function FileSystem.copy
Copies the contents of one file to another. This function will also copy the permission bits of the original file to the destination file.
This function will overwrite the contents of to.
Note that if from and to both point to the same file, then the file will likely get truncated by this operation.
On success, the total number of bytes copied is returned and it is equal to the length of the to file as reported by metadata.
This function will return an error in the following situations, but is not limited to just these cases:
- from is neither a regular file nor a symlink to a regular file.
- from does not exist.
- The current process does not have the permission rights to read from or write to.
- The parent directory of to doesn’t exist.
function FileSystem.create
Creates (or truncates) a file for writing and returns it as a writable stream.
Mirrors
std::fs::File::create — the file is opened write-only and
truncated to zero length, or created if it does not exist.
function FileSystem.create_dir
Creates a new, empty directory at the provided path.
This function will return an error in the following situations, but is not limited to just these cases:
- User lacks permissions to create directory at path.
- A parent of the given path doesn’t exist. (To create a directory and all its missing parents at the same time, use the createidirlall function.)
- path already exists.
function FileSystem.create_dir_all
Recursively create a directory and all of its parent components if they are missing.
This function is not atomic. If it returns an error, any parent components it was able to create will remain.
If the empty path is passed to this function, it always succeeds without creating any directories.
The function will return an error if any directory specified in path does not exist and could not be created. There may be other error conditions; see create_dir for specifics.
function FileSystem.exists
Returns
true if the path points at an existing entity.
This function will traverse symbolic links to query information about the
destination file. In case of broken symbolic links this will return false.
Note that while this avoids some pitfalls of the exists() method, it still can not
prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
where those bugs are not an issue.
function FileSystem.hard_link
Creates a new hard link on the filesystem.
The link path will be a link pointing to the original path. Note that systems often require these two paths to both be located on the same filesystem.
If original names a symbolic link, it is platform-specific whether the symbolic link is followed. On platforms where it’s possible to not follow it, it is not followed, and the created hard link points to the symbolic link itself.
This function will return an error in the following situations, but is not limited to just these cases:
- The original path is not a file or doesn’t exist.
- The ‘link’ path already exists.
function FileSystem.is_dir
Returns true if this path is for a directory.
This function will return an error in the following situations, but is not limited to just these cases:
- The user lacks permissions to perform metadata call on path.
- path does not exist.
function FileSystem.is_file
Returns true if this path is for a regular file.
This function will return an error in the following situations, but is not limited to just these cases:
- The user lacks permissions to perform metadata call on path.
- path does not exist.
function FileSystem.metadata
Returns the metadata about the given file or directory.
This function will return an error in the following situations, but is not limited to just these cases:
- The user lacks permissions to perform metadata call on path.
- path does not exist.
function FileSystem.mkdtemp
Creates a new temporary directory with a unique name and returns its path.
The directory is created inside
parent (defaults to the system temp dir).
The caller is responsible for removing it when done.
function FileSystem.open
Opens a file for reading and returns it as a readable stream.
The returned stream can be passed directly as the
data argument to
ctx.http().post() or ctx.http().put() for streaming uploads, or
iterated over / read directly.
function FileSystem.poll_read_to_string
Reads the entire contents of a file into a string without ever blocking the caller for more than
timeout_ms, or returns None when the contents aren’t available yet.
Built for polling files on network-backed filesystems (e.g. a
bb_clientd FUSE mount materializing remote-cache blobs), where a read
can block indefinitely — a plain read_to_string would wedge the
task. The read runs on a background thread; the first call for a path
waits up to timeout_ms for it, and while that read is still in
flight, subsequent calls for the same path return None immediately
rather than starting another read. Whenever the read eventually
completes, the next call returns its result: the file contents, or
None on any I/O/UTF-8 error (including a missing file).
Callers are expected to poll until content or a caller-side deadline:
None always means “not readable yet”, never “empty file” (an empty
readable file returns "").
Pass expected_len (bytes) when the caller knows the file’s
authoritative size — e.g. File.length from a build event. A read
returning fewer bytes means the blob is still materializing, and is
reported as None so the caller retries instead of consuming a
truncated file. Omit it (or pass a negative value) to accept whatever
the read returns.
function FileSystem.read_dir
Returns an iterator over the entries within a directory.
This function will return an error in the following situations, but is not limited to just these cases:
- The provided path doesn’t exist.
- The process lacks permissions to view the contents.
- The path points at a non-directory file.
function FileSystem.read_link
Reads a symbolic link, returning the file that the link points to.
This function will return an error in the following situations, but is not limited to just these cases:
- path is not a symbolic link.
- path does not exist.
function FileSystem.read_to_string
Reads the entire contents of a file into a string.
This function will return an error under a number of different circumstances. Some of these error conditions are:
- The specified file does not exist.
- The user lacks permission to get the specified access rights for the file.
- The user lacks permission to open one of the directory components of the specified path.
function FileSystem.read_to_string_if_complete
Reads a file only if it is exactly
expected_len bytes, else None.
For local reads of a file that another process may still be writing or
downloading. Comparing the bytes actually read against the
authoritative length is the only reliable completeness test: a stat
taken before the read can be stale by the time the read runs, and one
taken after can have caught up with a writer that finished mid-read, so
either would accept a prefix. None means “not complete yet” — poll
again. A negative expected_len disables the check and accepts
whatever the read returns.
This is the non-blocking counterpart to poll_read_to_string, which
applies the same length gate to reads that can block indefinitely.
function FileSystem.remove_dir
Removes an empty directory.
If you want to remove a directory that is not empty, as well as all
of its contents recursively, consider using remove_dir_all instead.
This function will return an error in the following situations, but is not limited to just these cases:
- path doesn’t exist.
- path isn’t a directory.
- The user lacks permissions to remove the directory at the provided path.
- The directory isn’t empty.
function FileSystem.remove_dir_all
Removes a directory at this path, after removing all its contents. Use carefully!
This function does not follow symbolic links and it will simply remove the symbolic link itself.
See remove_file and remove_dir for possible errors.
function FileSystem.remove_file
Removes a file from the filesystem.
Note that there is no guarantee that the file is immediately deleted
(e.g., depending on platform, other open file descriptors may prevent immediate removal).
This function will return an error in the following situations, but is not limited to just these cases:
- path points to a directory.
- The file doesn’t exist.
- The user lacks permissions to remove the file.
function FileSystem.rename
Renames a file or directory to a new name, replacing the original file if to already exists.
This will not work if the new name is on a different mount point.
This function will return an error in the following situations, but is not limited to just these cases:
- from does not exist.
- The user lacks permissions to view contents.
- from and to are on separate filesystems.
function FileSystem.set_permissions
Sets the Unix permission bits of a file to
mode (e.g. 0o755).
On non-Unix platforms this is a no-op. Useful when writing a file with
fs.write (which uses the default umask) but the result must be
executable, e.g. a generated shell script or tool wrapper.
Returns an error if path does not exist or the user lacks permission to
change its mode (not an exhaustive list).
function FileSystem.symlink_metadata
Queries the metadata about a file without following symlinks.
This function will return an error in the following situations, but is not limited to just these cases:
- The user lacks permissions to perform metadata call on path.
- path does not exist.
function FileSystem.try_append
Appends a string to the end of a file, creating it if it does not exist.
Opens the file with
OpenOptions::append(true) so concurrent writers
see their bytes interleaved at record boundaries rather than racing.
POSIX O_APPEND is atomic for writes ≤ PIPE_BUF, which covers the
short single-line records this is designed for (the
runner_job_history lines fit comfortably). The parent directory
must exist; this function will not create intermediate directories.
Returns True on success and False on any I/O error (parent
directory missing, permissions denied, target is a directory, etc.).
Errors are swallowed because the primary caller is the runner job
history hook, where a write failure must never fail the task.
function FileSystem.try_read_to_string
Reads the entire contents of a file into a string, or returns
"" on any I/O error (missing file, permission denied, non-UTF-8 content, transient read failure). Companion to try_append: the silent fall-through lets callers handle never-fail invariants without try/except — e.g. the runner job history dedup read, where a failed read must degrade to “assume empty file” rather than fail the task.
function FileSystem.try_read_to_string_capped
Reads at most
max_bytes bytes from the start of a file into a string, or returns "" on any I/O error (missing file, permission denied, transient failure). Like try_read_to_string, the silent fall-through lets callers degrade rather than fail the task.
Only the capped prefix is read into memory — never the whole file — so a
multi-MB log can be summarized without spiking the heap. Non-UTF-8 bytes
are replaced (lossy), and the prefix may split a multi-byte sequence at
the cap; that final partial char is dropped rather than emitted as \u{FFFD}.
function FileSystem.watch
Starts a recursive file watch over
root (an absolute path) and returns a fs.Watch.
Poll it with try_pop(), which returns None until pending changes have
settled for debounce_ms (capped at max_delay_ms under sustained
churn), then a batch with events (a list) and rescan (True when the
watcher lost track of state and anything may have changed). Each event
is a fs.watch.CreatedEvent, fs.watch.ModifiedEvent, or
fs.watch.RemovedEvent, each carrying path relative to root.
Discriminate them with isinstance(event, std.fs.watch.CreatedEvent), etc. Events under any of the ignore path
prefixes (absolute) are dropped — pass the bazel convenience-symlink
paths (bazel-bin, bazel-out, …) there. Use drain() to discard pending
changes caused by our own writes.
The backend is chosen automatically: watchman when root contains a
.watchmanconfig file, otherwise an in-process OS watcher.
function FileSystem.write
Writes a string as the entire contents of a file.
This function will create a file if it does not exist, and will entirely replace its contents if it does.
Depending on the platform, this function may fail if the full directory path does not exist.
This is a convenience function for using fs.create and [write_all] with fewer imports.

