pub struct NamedTempFile { /* private fields */ }Expand description
A temporary file that auto-deletes when dropped.
Companion to crate::TempDir. Where TempDir manages a
directory, NamedTempFile manages a single zero-byte file at a
fresh path under the OS temp location. The caller reopens the
path with std::fs::OpenOptions (or any other API) when ready
to write or read.
The default basename is .tmpfile-{pid}-{name12}, intentionally
distinct from TempDir’s .tmp-{pid}-{name12}
so an operator inspecting the OS temp location can tell the two
apart at a glance. The 12 trailing characters use the same
Crockford base32 generator as TempDir, so the optional
mod-rand feature controls both types in lockstep. The embedded
PID lets cleanup_orphans identify
files left behind by crashed processes.
§Example
use mod_tempdir::NamedTempFile;
use std::io::Write;
let f = NamedTempFile::new().unwrap();
let mut handle = std::fs::OpenOptions::new()
.write(true)
.open(f.path())
.unwrap();
handle.write_all(b"hello").unwrap();
drop(handle);
// `f` is deleted automatically when it goes out of scope.§Cleanup semantics
Drop calls std::fs::remove_file best-effort. A failure (file
already gone, permission denied, or a still-open handle on
Windows) is intentionally swallowed: a Drop impl must not
panic. Use NamedTempFile::persist to keep the file alive past
drop.
§Windows handle-lock caveat
On Windows, std::fs::remove_file returns
ERROR_SHARING_VIOLATION (surfaced in Rust as
std::io::ErrorKind::PermissionDenied) if any process still
holds an open handle to the file at the moment of Drop. The
library does not retry. Drop must not block, and retries cannot
force-close a caller-owned handle. The file is left on disk in
that case. Close any handles you open against
NamedTempFile::path before the NamedTempFile drops to
guarantee cleanup.
Implementations§
Source§impl NamedTempFile
impl NamedTempFile
Sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Create a new temporary file in the system’s temp location
(/tmp on Linux/macOS, %TEMP% on Windows).
The basename is .tmpfile-{pid}-{name12} where {pid} is
the current process ID (used by
cleanup_orphans to identify
entries left behind by crashed processes) and {name12} is a
12-character Crockford base32 string from the shared name
generator. The file is materialized via
std::fs::File::create; the returned File handle is
closed before this function returns, so the caller starts
from a clean slate.
With the mod-rand feature enabled, the name fragment comes
from mod_rand::tier2::unique_name. Without it, from the
same internal process-unique mixer as
TempDir::new.
§Errors
Returns the underlying io::Error from
std::fs::File::create if the file cannot be created.
§Example
use mod_tempdir::NamedTempFile;
let f = NamedTempFile::new().unwrap();
assert!(f.path().is_file());Sourcepub fn with_prefix(prefix: &str) -> Result<Self>
pub fn with_prefix(prefix: &str) -> Result<Self>
Create a new temporary file with the given prefix.
The final basename is {prefix}-{12-char-name}. The prefix
is joined verbatim and is the caller’s responsibility to
sanitize.
§Errors
Returns the underlying io::Error from
std::fs::File::create if the file cannot be created.
§Example
use mod_tempdir::NamedTempFile;
let f = NamedTempFile::with_prefix("my-fixture").unwrap();
assert!(f
.path()
.file_name()
.unwrap()
.to_string_lossy()
.starts_with("my-fixture-"));Sourcepub fn path(&self) -> &Path
pub fn path(&self) -> &Path
Return the path of this temporary file.
§Example
use mod_tempdir::NamedTempFile;
let f = NamedTempFile::new().unwrap();
let mut handle = std::fs::OpenOptions::new()
.write(true)
.open(f.path())
.unwrap();Sourcepub fn persist(self) -> PathBuf
pub fn persist(self) -> PathBuf
Consume this NamedTempFile and return the path, disabling
cleanup on drop. The file will persist.
Use this when you want to inspect contents after a test fails.
§Example
use mod_tempdir::NamedTempFile;
let f = NamedTempFile::new().unwrap();
let kept = f.persist();
// `kept` survives past the original `f` going out of scope.Sourcepub fn cleanup_on_drop(&self) -> bool
pub fn cleanup_on_drop(&self) -> bool
Return true if the file will be deleted on drop.
§Example
use mod_tempdir::NamedTempFile;
let f = NamedTempFile::new().unwrap();
assert!(f.cleanup_on_drop());Sourcepub fn persist_atomic(
self,
target: impl AsRef<Path>,
) -> Result<PathBuf, PersistAtomicError>
pub fn persist_atomic( self, target: impl AsRef<Path>, ) -> Result<PathBuf, PersistAtomicError>
Atomically move this file to target with crash-safety
guarantees, then disable cleanup on drop.
Performs the canonical “atomic durable write” sequence:
fsyncthe temp file contents to disk (std::fs::File::sync_all).- Atomically rename the temp file onto
targetviastd::fs::rename. On Unix this isrename(2); on Windows it isMoveFileExWwithMOVEFILE_REPLACE_EXISTING. Both are atomic within a single filesystem. - Best-effort
fsyncof the target’s parent directory so the rename itself survives a crash. Failures here are silent, matching the rest of the crate’s durability story.
On success, the temp file no longer exists at
path; the data lives at target. Cleanup on
drop is disabled and the consumed self does not attempt
removal.
§Errors
On any failure (fsync, rename, etc.), the temp file is
preserved on disk and returned to the caller via
PersistAtomicError::file. The caller can inspect the
underlying io::Error, optionally fix the cause (e.g.,
create the missing parent directory), and retry. This is
the standard tempfile-crate pattern and matches the
data-integrity guarantee that a failed atomic-persist must
never lose the source.
Common error causes:
- Target’s parent directory does not exist.
- Target’s parent is on a different filesystem (
EXDEVon Unix,ERROR_NOT_SAME_DEVICEon Windows). - Permission denied at the target location.
- Source temp file already removed (race with cleanup).
§Cross-filesystem behaviour
rename is atomic only within a single filesystem. If
target is on a different mount than the temp directory,
rename will return EXDEV on Unix or the equivalent on
Windows. Callers wanting cross-filesystem persistence must
either pick a target on the same filesystem as
std::env::temp_dir or do their own copy-and-delete.
§Example
use mod_tempdir::NamedTempFile;
use std::io::Write;
let f = NamedTempFile::new().unwrap();
{
let mut h = std::fs::OpenOptions::new()
.write(true)
.open(f.path())
.unwrap();
h.write_all(b"finalized payload").unwrap();
}
let target = std::env::temp_dir().join("finalized.bin");
let landed = f.persist_atomic(&target).unwrap();
assert_eq!(landed, target);Retry pattern on recoverable error:
use mod_tempdir::NamedTempFile;
let mut f = NamedTempFile::new().unwrap();
let target = std::env::temp_dir().join("retry-target");
loop {
match f.persist_atomic(&target) {
Ok(_landed) => break,
Err(e) => {
eprintln!("persist failed: {}", e.error);
// ... fix the underlying issue ...
f = e.file; // recover the temp file and try again
}
}
}