Back to Microsandbox

Filesystem

docs/sdk/rust/filesystem.mdx

0.6.343.1 KB
Original Source

Read, write, list, and manipulate files inside a running sandbox. Obtained via sb.fs(). Every op dispatches through the same host-guest channel as command execution, so there is no SSH and no network involved. Path-style helpers are the usual choice; handle-style helpers are available for callers that need POSIX-like file descriptor reuse. For bulk file movement, prefer a volume that gives the guest direct filesystem access. See Filesystem for conceptual usage.

<div className="msb-glance"> <p className="msb-gl"><span className="msb-dot instance"></span>Read<span className="msb-ct">3</span></p> <a className="msb-row" href="#fs-read"><span className="msb-rn">fs.read()</span><span className="msb-rg">whole file as bytes</span></a> <a className="msb-row" href="#fs-read_to_string"><span className="msb-rn">fs.read_to_string()</span><span className="msb-rg">whole file as UTF-8</span></a> <a className="msb-row" href="#fs-read_stream"><span className="msb-rn">fs.read_stream()</span><span className="msb-rg">stream chunks in</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Write<span className="msb-ct">2</span></p> <a className="msb-row" href="#fs-write"><span className="msb-rn">fs.write()</span><span className="msb-rg">overwrite a file</span></a> <a className="msb-row" href="#fs-write_stream"><span className="msb-rn">fs.write_stream()</span><span className="msb-rg">stream chunks out</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Handles<span className="msb-ct">13</span></p> <a className="msb-row" href="#fs-open_file"><span className="msb-rn">fs.open_file()</span><span className="msb-rg">open a file handle</span></a> <a className="msb-row" href="#fs-open_dir"><span className="msb-rn">fs.open_dir()</span><span className="msb-rg">open a directory handle</span></a> <a className="msb-row" href="#fs-close_handle"><span className="msb-rn">fs.close_handle()</span><span className="msb-rg">close a handle</span></a> <a className="msb-row" href="#fs-read_handle"><span className="msb-rn">fs.read_handle()</span><span className="msb-rg">read by handle</span></a> <a className="msb-row" href="#fs-read_handle_stream"><span className="msb-rn">fs.read_handle_stream()</span><span className="msb-rg">stream by handle</span></a> <a className="msb-row" href="#fs-write_handle"><span className="msb-rn">fs.write_handle()</span><span className="msb-rg">write by handle</span></a> <a className="msb-row" href="#fs-write_handle_stream"><span className="msb-rn">fs.write_handle_stream()</span><span className="msb-rg">stream writes by handle</span></a> <a className="msb-row" href="#fs-read_dir_handle"><span className="msb-rn">fs.read_dir_handle()</span><span className="msb-rg">read directory entries</span></a> <a className="msb-row" href="#fs-read_dir"><span className="msb-rn">fs.read_dir()</span><span className="msb-rg">directory handle alias</span></a> <a className="msb-row" href="#fs-stat_handle"><span className="msb-rn">fs.stat_handle()</span><span className="msb-rg">metadata by handle</span></a> <a className="msb-row" href="#fs-fstat"><span className="msb-rn">fs.fstat()</span><span className="msb-rg">metadata alias</span></a> <a className="msb-row" href="#fs-set_stat_handle"><span className="msb-rn">fs.set_stat_handle()</span><span className="msb-rg">update metadata by handle</span></a> <a className="msb-row" href="#fs-fset_stat"><span className="msb-rn">fs.fset_stat()</span><span className="msb-rg">metadata update alias</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Directories<span className="msb-ct">4</span></p> <a className="msb-row" href="#fs-list"><span className="msb-rn">fs.list()</span><span className="msb-rg">children of a dir</span></a> <a className="msb-row" href="#fs-mkdir"><span className="msb-rn">fs.mkdir()</span><span className="msb-rg">create dir + parents</span></a> <a className="msb-row" href="#fs-remove_dir"><span className="msb-rn">fs.remove_dir()</span><span className="msb-rg">remove dir recursively</span></a> <a className="msb-row" href="#fs-remove_empty_dir"><span className="msb-rn">fs.remove_empty_dir()</span><span className="msb-rg">remove empty dir</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Files<span className="msb-ct">3</span></p> <a className="msb-row" href="#fs-remove"><span className="msb-rn">fs.remove()</span><span className="msb-rg">delete a single file</span></a> <a className="msb-row" href="#fs-copy"><span className="msb-rn">fs.copy()</span><span className="msb-rg">copy within sandbox</span></a> <a className="msb-row" href="#fs-rename"><span className="msb-rn">fs.rename()</span><span className="msb-rg">rename / move</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Metadata<span className="msb-ct">7</span></p> <a className="msb-row" href="#fs-stat"><span className="msb-rn">fs.stat()</span><span className="msb-rg">file metadata</span></a> <a className="msb-row" href="#fs-stat_with_follow"><span className="msb-rn">fs.stat_with_follow()</span><span className="msb-rg">stat, control symlinks</span></a> <a className="msb-row" href="#fs-set_stat"><span className="msb-rn">fs.set_stat()</span><span className="msb-rg">update metadata</span></a> <a className="msb-row" href="#fs-read_link"><span className="msb-rn">fs.read_link()</span><span className="msb-rg">resolve a symlink</span></a> <a className="msb-row" href="#fs-symlink"><span className="msb-rn">fs.symlink()</span><span className="msb-rg">create a symlink</span></a> <a className="msb-row" href="#fs-real_path"><span className="msb-rn">fs.real_path()</span><span className="msb-rg">canonicalize a path</span></a> <a className="msb-row" href="#fs-exists"><span className="msb-rn">fs.exists()</span><span className="msb-rg">does a path exist</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Host transfer<span className="msb-ct">2</span></p> <a className="msb-row" href="#fs-copy_from_host"><span className="msb-rn">fs.copy_from_host()</span><span className="msb-rg">host file -&gt; guest</span></a> <a className="msb-row" href="#fs-copy_to_host"><span className="msb-rn">fs.copy_to_host()</span><span className="msb-rg">guest file -&gt; host</span></a> <p className="msb-gl"><span className="msb-dot type"></span>Types</p> <div className="msb-chiprow"> <a className="msb-typepill" href="#sandboxfsops">SandboxFsOps</a> <a className="msb-typepill" href="#fsentry">FsEntry</a> <a className="msb-typepill" href="#fsentrykind">FsEntryKind</a> <a className="msb-typepill" href="#fsmetadata">FsMetadata</a> <a className="msb-typepill" href="#fsopenoptions">FsOpenOptions</a> <a className="msb-typepill" href="#fssetattrs">FsSetAttrs</a> <a className="msb-typepill" href="#fsreadstream">FsReadStream</a> <a className="msb-typepill" href="#fswritesink">FsWriteSink</a> <a className="msb-typepill" href="#fshandle">FsHandle</a> </div> </div> <p className="msb-label" id="typical-flow">Typical flow</p>
rust
use microsandbox::Sandbox;

let sb = Sandbox::builder("api").image("python").create().await?;
let fs = sb.fs();

fs.write("/tmp/config.json", r#"{"debug": true}"#).await?;
let text = fs.read_to_string("/tmp/config.json").await?;
println!("{text}");

for entry in fs.list("/tmp").await? {
    println!("{} ({} bytes)", entry.path, entry.size);
}

sb.fs() is synchronous and just borrows the sandbox's backend and name; the work happens on the awaited methods below, every one of which is async.

Read operations


<span className="msb-recv">fs.</span><span className="msb-hn">read()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read(&self, path: &str) -> MicrosandboxResult<Bytes>

Read an entire file from the guest filesystem into memory as raw bytes.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest, e.g. <code>"/app/config.json"</code>.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">Bytes</span></div> <div className="msb-param-desc">File contents as raw bytes.</div> </div> </div> <Accordion title="Example">
rust
let bytes = sb.fs().read("/app/logo.png").await?;
println!("{} bytes", bytes.len());
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">read_to_string()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read_to_string(&self, path: &str) -> MicrosandboxResult<String>

Read an entire file and decode it as UTF-8. Errors if the contents are not valid UTF-8.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">String</span></div> <div className="msb-param-desc">File contents as a UTF-8 string.</div> </div> </div> <Accordion title="Example">
rust
let text = sb.fs().read_to_string("/etc/hostname").await?;
println!("{}", text.trim());
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">read_stream()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read_stream(&self, path: &str) -> MicrosandboxResult<FsReadStream>

Open a streaming reader that yields chunks of file data as they arrive. Use this for files too large to hold in memory, or to process data incrementally.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#fsreadstream">FsReadStream</a></div> <div className="msb-param-desc">Reader that yields chunks until the file is exhausted.</div> </div> </div> <Accordion title="Example">
rust
let mut stream = sb.fs().read_stream("/var/log/big.log").await?;
let mut total = 0;
while let Some(chunk) = stream.recv().await? {
    total += chunk.len();
}
println!("read {total} bytes");
</Accordion>

Write operations


<span className="msb-recv">fs.</span><span className="msb-hn">write()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn write(&self, path: &str, data: impl AsRef<[u8]>) -> MicrosandboxResult<()>

Write data to a file in the guest, creating it if it doesn't exist and truncating it if it does. Parent directories must already exist.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>data</code><span className="msb-type">impl AsRef&lt;[u8]&gt;</span></div> <div className="msb-param-desc">File content (bytes or a string).</div> </div> </div> <Accordion title="Example">
rust
sb.fs().write("/tmp/hello.txt", "hi there").await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">write_stream()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn write_stream(&self, path: &str) -> MicrosandboxResult<FsWriteSink>

Open a streaming writer for large files. Write chunks incrementally, then call FsWriteSink::close() to flush and finalize. The file is created if missing and truncated if it exists.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#fswritesink">FsWriteSink</a></div> <div className="msb-param-desc">Writer for sending chunks; must be closed to finalize.</div> </div> </div> <Accordion title="Example">
rust
let sink = sb.fs().write_stream("/tmp/out.bin").await?;
sink.write(&[0u8; 4096]).await?;
sink.write(&[1u8; 4096]).await?;
sink.close().await?;
</Accordion>

Handle operations

Handle operations expose agentd-side file and directory handles. Use them when you need repeated reads/writes against the same open file, directory iteration state, or handle-based metadata updates. They require Sandbox::fs() on a live local sandbox because agentd scopes handles to the relay client; SandboxFsOps::with_backend() can run path-style methods but returns Unsupported for handle methods.

<Accordion title="Example">
rust
use microsandbox::sandbox::FsOpenOptions;

let fs = sb.fs();
let handle = fs.open_file("/tmp/data.txt", FsOpenOptions {
    read: true,
    write: true,
    create: true,
    ..Default::default()
}).await?;

fs.write_handle(handle, 0, "hello").await?;
let bytes = fs.read_handle(handle, 0, None).await?;
fs.close_handle(handle).await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">open_file()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn open_file(&self, path: &str, options: FsOpenOptions) -> MicrosandboxResult<FsHandle>

Open a file inside the guest and return an agentd-side handle. Configure read/write/create/truncate behavior with FsOpenOptions.


<span className="msb-recv">fs.</span><span className="msb-hn">open_dir()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn open_dir(&self, path: &str) -> MicrosandboxResult<FsHandle>

Open a directory inside the guest and return an agentd-side handle that can be consumed with read_dir_handle().


<span className="msb-recv">fs.</span><span className="msb-hn">close_handle()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn close_handle(&self, handle: FsHandle) -> MicrosandboxResult<()>

Close an open file or directory handle. Always close handles you opened directly once you are done with them.


<span className="msb-recv">fs.</span><span className="msb-hn">read_handle()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read_handle(&self, handle: FsHandle, offset: u64, len: Option<u64>) -> MicrosandboxResult<Bytes>

Read from an open file handle at offset. Passing None for len reads through EOF.


<span className="msb-recv">fs.</span><span className="msb-hn">read_handle_stream()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read_handle_stream(&self, handle: FsHandle, offset: u64, len: Option<u64>) -> MicrosandboxResult<FsReadStream>

Stream bytes from an open file handle. Use this for large reads while preserving the same open-handle semantics as read_handle().


<span className="msb-recv">fs.</span><span className="msb-hn">write_handle()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn write_handle(&self, handle: FsHandle, offset: u64, data: impl AsRef<[u8]>) -> MicrosandboxResult<()>

Write bytes to an open file handle at offset.


<span className="msb-recv">fs.</span><span className="msb-hn">write_handle_stream()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn write_handle_stream(&self, handle: FsHandle, offset: u64, len: Option<u64>) -> MicrosandboxResult<FsWriteSink>

Stream writes to an open file handle at offset. Call FsWriteSink::close() to send EOF and wait for the guest to confirm the write.


<span className="msb-recv">fs.</span><span className="msb-hn">read_dir_handle()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read_dir_handle(&self, handle: FsHandle, limit: Option<u32>) -> MicrosandboxResult<Vec<FsEntry>>

Read the next batch of entries from an open directory handle. limit caps the batch size when set.


<span className="msb-recv">fs.</span><span className="msb-hn">read_dir()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read_dir(&self, handle: FsHandle, limit: Option<u32>) -> MicrosandboxResult<Vec<FsEntry>>

Compatibility alias for read_dir_handle().


<span className="msb-recv">fs.</span><span className="msb-hn">stat_handle()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn stat_handle(&self, handle: FsHandle) -> MicrosandboxResult<FsMetadata>

Return metadata for an open file or directory handle.


<span className="msb-recv">fs.</span><span className="msb-hn">fstat()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn fstat(&self, handle: FsHandle) -> MicrosandboxResult<FsMetadata>

Unix-style compatibility alias for stat_handle().


<span className="msb-recv">fs.</span><span className="msb-hn">set_stat_handle()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn set_stat_handle(&self, handle: FsHandle, attrs: FsSetAttrs) -> MicrosandboxResult<()>

Update metadata for an open file handle. Only the fields set on FsSetAttrs are changed.


<span className="msb-recv">fs.</span><span className="msb-hn">fset_stat()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn fset_stat(&self, handle: FsHandle, attrs: FsSetAttrs) -> MicrosandboxResult<()>

Unix-style compatibility alias for set_stat_handle().


Directory operations


<span className="msb-recv">fs.</span><span className="msb-hn">list()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn list(&self, path: &str) -> MicrosandboxResult<Vec<FsEntry>>

List the immediate children of a directory (non-recursive). Each entry carries its path, kind, size, mode, and modification time.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute directory path inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#fsentry">Vec&lt;FsEntry&gt;</a></div> <div className="msb-param-desc">Directory entries.</div> </div> </div> <Accordion title="Example">
rust
for entry in sb.fs().list("/app").await? {
    println!("{:?} {}", entry.kind, entry.path);
}
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">mkdir()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn mkdir(&self, path: &str) -> MicrosandboxResult<()>

Create a directory, including any missing parent directories.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute directory path inside the guest.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().mkdir("/app/data/cache").await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">remove_dir()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn remove_dir(&self, path: &str) -> MicrosandboxResult<()>

Remove a directory and everything under it, recursively. For a single file use remove().

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute directory path inside the guest.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().remove_dir("/app/data/cache").await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">remove_empty_dir()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn remove_empty_dir(&self, path: &str) -> MicrosandboxResult<()>

Remove an empty directory. Unlike remove_dir(), this does not remove child entries and fails when the directory is not empty.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute directory path inside the guest.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().remove_empty_dir("/app/data/empty").await?;
</Accordion>

File operations


<span className="msb-recv">fs.</span><span className="msb-hn">remove()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn remove(&self, path: &str) -> MicrosandboxResult<()>

Delete a single file. Use remove_dir() for directories.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute file path inside the guest.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().remove("/tmp/hello.txt").await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">copy()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn copy(&self, from: &str, to: &str) -> MicrosandboxResult<()>

Copy a file from one path to another within the sandbox.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>from</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Source path inside the guest.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>to</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Destination path inside the guest.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().copy("/app/config.json", "/app/config.bak.json").await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">rename()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn rename(&self, from: &str, to: &str) -> MicrosandboxResult<()>

Rename or move a file or directory within the sandbox.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>from</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Current path inside the guest.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>to</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">New path inside the guest.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().rename("/tmp/draft.txt", "/tmp/final.txt").await?;
</Accordion>

Metadata


<span className="msb-recv">fs.</span><span className="msb-hn">stat()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn stat(&self, path: &str) -> MicrosandboxResult<FsMetadata>

Get metadata for a file or directory: kind, size, mode, read-only flag, and timestamps. A final symlink is followed (equivalent to stat_with_follow(path, true)); use stat_with_follow() to control that.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#fsmetadata">FsMetadata</a></div> <div className="msb-param-desc">File metadata.</div> </div> </div> <Accordion title="Example">
rust
let meta = sb.fs().stat("/app/config.json").await?;
println!("{} bytes, mode {:o}", meta.size, meta.mode);
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">stat_with_follow()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn stat_with_follow(&self, path: &str, follow_symlink: bool) -> MicrosandboxResult<FsMetadata>

Get metadata, choosing whether to follow a final symlink. With follow_symlink = false you stat the link itself rather than its target. Local backend only; cloud returns Unsupported.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>follow_symlink</code><span className="msb-type">bool</span></div> <div className="msb-param-desc">When <code>false</code>, stat the symlink itself instead of its target.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#fsmetadata">FsMetadata</a></div> <div className="msb-param-desc">File metadata.</div> </div> </div> <Accordion title="Example">
rust
let link_meta = sb.fs().stat_with_follow("/app/current", false).await?;
println!("{:?}", link_meta.kind);
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">set_stat()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn set_stat(&self, path: &str, follow_symlink: bool, attrs: FsSetAttrs) -> MicrosandboxResult<()>

Update metadata on a file or directory: mode, owner uid/gid, size, and access/modification times. Only the fields you set on FsSetAttrs are applied. Local backend only; cloud returns Unsupported.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>follow_symlink</code><span className="msb-type">bool</span></div> <div className="msb-param-desc">When <code>false</code>, target the symlink itself instead of its target.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>attrs</code><a className="msb-type" href="#fssetattrs">FsSetAttrs</a></div> <div className="msb-param-desc">Attributes to change; unset fields are left untouched.</div> </div> </div> <Accordion title="Example">
rust
use microsandbox::sandbox::FsSetAttrs;

sb.fs().set_stat("/app/run.sh", true, FsSetAttrs {
    mode: Some(0o755),
    ..Default::default()
}).await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">read_link()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn read_link(&self, path: &str) -> MicrosandboxResult<String>

Read the target of a symbolic link, returning the literal target text. Local backend only; cloud returns Unsupported.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path of the symlink inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">String</span></div> <div className="msb-param-desc">The link's target path.</div> </div> </div> <Accordion title="Example">
rust
let target = sb.fs().read_link("/app/current").await?;
println!("-> {target}");
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">symlink()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn symlink(&self, target: &str, link_path: &str) -> MicrosandboxResult<()>

Create a symbolic link at link_path that points to target. Local backend only; cloud returns Unsupported.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>target</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">What the link points to (literal target text).</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>link_path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path of the symlink to create.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().symlink("/app/releases/v2", "/app/current").await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">real_path()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn real_path(&self, path: &str) -> MicrosandboxResult<String>

Resolve a path to its canonical absolute path inside the guest.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Path inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">String</span></div> <div className="msb-param-desc">Canonical absolute path.</div> </div> </div> <Accordion title="Example">
rust
let canonical = sb.fs().real_path("/app/../app/config.json").await?;
println!("{canonical}");
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">exists()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn exists(&self, path: &str) -> MicrosandboxResult<bool>

Check whether a file or directory exists at the given path in the guest. Implemented as a stat() probe: a successful stat yields true, a filesystem-op error yields false, and transport errors still propagate.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">bool</span></div> <div className="msb-param-desc"><code>true</code> if the path exists.</div> </div> </div> <Accordion title="Example">
rust
if sb.fs().exists("/app/config.json").await? {
    println!("config present");
}
</Accordion>

Host transfer


<span className="msb-recv">fs.</span><span className="msb-hn">copy_from_host()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn copy_from_host(&self, host_path: impl AsRef<Path>, guest_path: &str) -> MicrosandboxResult<()>

Copy a file from the host machine into the sandbox, streaming it in chunks. For transferring many files, consider a bind-mounted volume instead.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>host_path</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div> <div className="msb-param-desc">Path on the host filesystem.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>guest_path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Destination path inside the sandbox.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().copy_from_host("./local/model.bin", "/app/model.bin").await?;
</Accordion>

<span className="msb-recv">fs.</span><span className="msb-hn">copy_to_host()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn copy_to_host(&self, guest_path: &str, host_path: impl AsRef<Path>) -> MicrosandboxResult<()>

Copy a file from the sandbox to the host machine.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>guest_path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Path inside the sandbox.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>host_path</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div> <div className="msb-param-desc">Destination path on the host.</div> </div> </div> <Accordion title="Example">
rust
sb.fs().copy_to_host("/app/out/report.pdf", "./report.pdf").await?;
</Accordion>

Types

SandboxFsOps

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="/sdk/rust/sandbox#sb-fs">sb.fs()</a></p>

Filesystem operations handle for a running sandbox, borrowing the parent sandbox's backend and name (it is generic over a lifetime, SandboxFsOps<'a>). Every method dispatches through the same host-guest channel as command execution. Local routes to core.fs.* agent messages; cloud returns Unsupported per method until cloud guest-fs lands. All operations are listed in the sections above.

with_backend(backend, name) is a public constructor for FFI shims that re-assemble a SandboxFsOps per call; most callers obtain one via sb.fs().

FsEntry

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#fs-list">list()</a></p>

Metadata for a single entry returned from a directory listing.

FieldTypeDescription
pathStringPath of the entry
kindFsEntryKindKind of entry
sizeu64Size in bytes
modeu32Unix permission bits (e.g. 0o644)
uidu32Owner user ID
gidu32Owner group ID
accessedOption<DateTime<Utc>>Last access time
modifiedOption<DateTime<Utc>>Last modification time

FsEntryKind

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div> <p className="msb-backref">Used by <a href="#fsentry">FsEntry.kind</a> · <a href="#fsmetadata">FsMetadata.kind</a></p>

The kind of a filesystem entry. Derives Copy, PartialEq, and Eq.

VariantDescription
FileRegular file
DirectoryDirectory
SymlinkSymbolic link
OtherOther entry type (device, socket, etc.)

FsMetadata

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#fs-stat">stat()</a> · <a href="#fs-stat_with_follow">stat_with_follow()</a></p>

Detailed metadata for a file or directory.

FieldTypeDescription
kindFsEntryKindKind of entry
sizeu64Size in bytes
modeu32Unix permission bits
uidu32Owner user ID
gidu32Owner group ID
readonlyboolWhether the entry is read-only (no owner write bit)
accessedOption<DateTime<Utc>>Last access time
modifiedOption<DateTime<Utc>>Last modification time
createdOption<DateTime<Utc>>Creation time (not populated by guest stat, currently always None)

FsOpenOptions

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Used by <a href="#fs-open_file">open_file()</a></p>

Options accepted by open_file(). Re-exported from microsandbox_protocol::fs. Derives Default, so set only the flags you need.

FieldTypeDescription
readboolOpen for reading
writeboolOpen for writing
appendboolAppend writes to the end
createboolCreate the file if it is missing
truncateboolTruncate the file after opening
create_newboolCreate a new file and fail if it already exists
modeOption<u32>Permission bits to set on creation

FsSetAttrs

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Used by <a href="#fs-set_stat">set_stat()</a> · <a href="#fs-set_stat_handle">set_stat_handle()</a> · <a href="#fs-fset_stat">fset_stat()</a></p>

Attributes accepted by set_stat(). Re-exported from microsandbox_protocol::fs. Derives Default, so set only the fields you want to change and spread the rest with ..Default::default(). Each field is Option: None leaves that attribute unchanged.

FieldTypeDescription
modeOption<u32>Unix permission bits
uidOption<u32>Owner user ID
gidOption<u32>Owner group ID
sizeOption<u64>File size (truncate or extend)
atimeOption<i64>Access time as Unix timestamp seconds
mtimeOption<i64>Modification time as Unix timestamp seconds

FsReadStream

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#fs-read_stream">read_stream()</a> · <a href="#fs-read_handle_stream">read_handle_stream()</a></p>

Streaming reader for file data from the sandbox. Obtained via read_stream() or read_handle_stream().

MethodSignatureDescription
recv()recv(&mut self) -> MicrosandboxResult<Option<Bytes>>Receive the next chunk; None once the file is fully read. Errors if the guest reports a failure.
collect()collect(self) -> MicrosandboxResult<Bytes>Consume the stream and collect all remaining chunks into a single buffer.

FsWriteSink

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#fs-write_stream">write_stream()</a> · <a href="#fs-write_handle_stream">write_handle_stream()</a></p>

Streaming writer for file data to the sandbox. Obtained via write_stream() or write_handle_stream().

MethodSignatureDescription
write()write(&self, data: impl AsRef<[u8]>) -> MicrosandboxResult<()>Write a chunk of data.
close()close(self) -> MicrosandboxResult<()>Send EOF and wait for confirmation. Must be called to finalize the write; errors if the guest reports a write failure.

FsHandle

<div className="msb-tags"><span className="msb-tag is-type">type</span></div> <p className="msb-backref">Returned by <a href="#fs-open_file">open_file()</a> · <a href="#fs-open_dir">open_dir()</a></p>

Type alias for an agentd-side filesystem handle. Handles are valid only for the live relay client that opened them; close directly opened handles with close_handle().

rust
pub type FsHandle = u64;