zerofs-client
An async, path-based Rust client for a ZeroFS server. It speaks 9P2000.L over TCP or a unix socket, and uses the ZeroFS fast-path extensions automatically when the server offers them.
The primary surface is one-shot path operations on a shared Client (read,
write, stat, rename, mkdir), with File and Dir handles where
statefulness pays off (chunked I/O, incremental listing, openat-style child
operations). Paths are bytes, as on POSIX and the 9P wire: every path parameter
is impl AsRef<Path>, so non-UTF-8 names work with no separate API.
This is a trusted-network client: you assert your uid at connect time, NFS-style.
Usage
use ;
async
Connection targets
Client::connect accepts:
unix:/path/to/sock: unix sockettcp://host:port: TCPhost:port/host: TCP (default port 5564)- a bare filesystem path (
/run/zerofs/9p.sock,./sock): unix socket
Use Client::connect_with for explicit identity (uid/gid/uname), the
attach subtree (aname), msize, and connect_timeout_ms.
Lifecycles
- Close & drop.
close()marks the handle closed immediately (later calls returnClosed); it always succeeds, is idempotent, and never hangs. A handle's server-side fid is released and its number recycled when the handle is dropped (for scope-bound use, right afterclose()); dropping a handle you never closed does the same. Fid numbers are always reused, so a long-running client never exhausts them. - Cancellation. Every public future is cancel-safe: dropping it at any
await point leaks nothing. There is no per-operation timeout parameter; bound
waits with
tokio::time::timeout. - Connection loss. The underlying session reconnects forever with backoff and replays its state; while the server is unreachable, calls block rather than fail. An op in flight at a disconnect is resent, so a non-idempotent op (rename, create, unlink) can apply twice across a reconnect.
Reads return Bytes
read, read_range, and File::read_at return [bytes::Bytes] (re-exported
as zerofs_client::Bytes): cheap to clone and slice, derefs to &[u8], and a
read served by a single round trip comes back with no copy. ZeroFsError
converts to std::io::Error (impl From), so client calls propagate with ?
in functions returning io::Result.
Features
All feature-gated additions are Rust-only and never cross the FFI boundary.
tokio-io(off by default):File::cursor()returning anio::FileCursorthat implementsAsyncRead + AsyncWrite + AsyncSeekover the positioned API, sotokio::io::copyand friends work.stream(off by default):Dir::entries()returning afutures::StreamofDirEntry, forStreamExtconsumers.serde(off by default):Serialize/Deserializeon the plain data records (Metadata,DirEntry,StatFs,Timestamp, ...).
SystemTime converts to/from Timestamp and into SetTime, so the standard
time types work directly with set_times and the metadata accessors.
License
AGPL-3.0