std.tempfile
Owned temporary files and directories, with automatic cleanup and explicit
fallible cleanup methods. Prefer this module for scratch storage; use
std.fs for descriptor-rooted staging and atomic publication.
import std.fs
import std.path as path
import std.tempfile as tempfile
def main() -> Result[(), AllocError | IoError | std.fs.FsError]:
parent = path.from_text(".")?
with tempfile.directory(&parent, prefix="build-")? as scratch:
note = scratch.path().join(&path.from_text("note.txt")?)?
write_text(¬e.to_text()?, "draft")?
print(read_text(¬e.to_text()?)?)?
scratch.cleanup()?
print(std.fs.metadata(scratch.path()).is_err())?
Ok(())
draft
True
Constructors
| Function | Result | Defaults |
|---|---|---|
default_dir() | Result[Path, IoError] | First nonempty TMPDIR, TEMP, TMP; otherwise /tmp |
file(parent: &Path = default_dir()?) | Result[TemporaryFile, IoError] | Unnamed file |
named_file(parent, prefix="plenty-", suffix="") | Result[NamedTemporaryFile, FsError] | Parent is default_dir() |
directory(parent, prefix="plenty-", max_entries: Positive[i64] = 100000, max_depth: Positive[i64] = 64) | Result[TemporaryDirectory, FsError] | Parent is default_dir() |
parent is a borrowed Path; prefix and suffix are borrowed strings. Explicit
parents bypass environment selection. Relative parents are resolved against the
current directory. Environment paths preserve native bytes. Selection is fresh
on every call, without caching or a trial file: an unusable configured directory
causes construction to fail, rather than silently falling back elsewhere.
Named resources use 16 random bytes encoded as 32 hexadecimal characters, between
the prefix and suffix. Prefix and suffix together may occupy at most 200 UTF-8
bytes and must contain neither / nor NUL. These are byte limits, not scalar
counts; invalid components or a combined length above 200 return
FsError.InvalidInput before creating a resource. Directories accept only a prefix.
Creation retries up to 16 name collisions. Files are created with owner-only
permissions, directories with owner-only access (subject to the process umask).
No API returns an uncreated, supposedly unique filename.
Files
TemporaryFile.stream() lends a mutable std.io.FileStream. Its context manager
also yields that stream. close() returns Result[(), StreamError]; dropping the
owner closes the descriptor. The file has no pathname.
NamedTemporaryFile.path() returns a borrowed absolute Path, usable by another
program while the owner is alive. The file supports read, write, flush,
sync, and seek with the same signatures as FileStream, and works with
std.io reader/writer helpers. Its context manager yields the named
owner itself. The underlying descriptor stays private for cleanup identity checks.
close() returns Result[(), FsError]: it removes the name, then closes the
stream. An already removed name is accepted. A different file at that name is
rejected; a failed removal leaves the owner armed for another cleanup attempt.
keep() returns Result[Path, AllocError] and disarms removal after successfully
copying the path. The stream remains open until closed or dropped. Call keep()
before cleanup; it does not recreate an already removed file.
Directories
TemporaryDirectory.path() returns a borrowed absolute Path; root() borrows
its descriptor-rooted std.fs.Root. Its context manager yields the directory
owner. cleanup() returns Result[(), FsError] and recursively removes contents
and the directory. Successful cleanup is idempotent. keep() returns an owned
path and disarms cleanup, allocating the path before changing ownership policy.
Each cleanup attempt is bounded by max_entries and max_depth, both
Positive[i64]; directory traps on a max_depth above 64. The root directory counts toward both budgets. A limit or I/O failure
can leave a partially removed tree; cleanup remains armed for a later attempt.
Symlinks are removed without traversing their targets. Before traversal, the
parent entry must still identify the owned directory; otherwise cleanup returns
FsError.Replaced without traversing the replacement.
Cleanup and platform limits
Context exits and destructors perform best-effort cleanup. Use explicit
close()? or cleanup()? inside the context when failure must be reported.
Normal return and ? propagation run cleanup; process termination and runtime
traps do not promise destructor execution. Cleanup itself can fail to allocate.
These APIs currently use the Linux facilities of std.fs: unnamed and named
files require filesystem O_TMPFILE support; named publication additionally
requires /proc/self/fd. There is no fallback that exposes an intermediate
predictable name. Memory-to-disk spooling is not provided.
Parents must be trusted against concurrent hostile mutation. Identity checks detect replaced entries, but are not atomic with deletion; they do not make cleanup safe against an attacker racing renames. Named files may also be removed by external temporary-directory cleaners. Keep the owner alive while another program uses its path.
See the temporary-resource tutorial for complete examples.