zerofs-client
An async, path-based Rust client for a ZeroFS
server. It speaks the private 9P2000.L.Z dialect over TCP or a unix
socket.
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.
The client asserts its uid at connect time and assumes a trusted network.
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
For an HA pair, pass both nodes as one comma-separated string:
let fs = connect.await?;
The client races the targets to find the serving leader and re-probes the set
after a disconnect. The initially negotiated msize is retained for the
logical session, and reconnect candidates that negotiate another value are
skipped. Every node in an HA or rolling deployment must therefore accept the
session's established msize. Rust callers that already hold separate strings
can use Client::connect_multi(&targets).
Use Client::connect_with for explicit identity (uid/gid/uname), the
attach subtree (aname), msize, and connect_timeout_ms.
Lifecycles
- Close and drop.
close()marks the handle closed and is idempotent and non-blocking. Dropping the handle schedules its server fid for release and recycling. Dropping an open handle performs the same cleanup. - Cancellation. Dropping a Rust operation future releases any temporary
fids it owns. If it is dropped while a fid-state request is dispatched and
unsettled, the client retires the connection that carried the request. If it
is still current, the session reconnects and replays before other operations
resume. A dispatched mutation may still complete, leaving an ambiguous
outcome.
zerofs-ffitimeouts abandon the caller's wait without cancelling the Rust operation. - Connection loss. The session reconnects with backoff and restores fids
and locks before accepting requests. Undispatched calls wait while no server
is reachable. In-flight mutations retain their operation envelope across
resends. Resends stop at the 120-second protocol horizon; unresolved outcomes
return an ambiguous connection failure. Reconnect requires the established
msize. An open-unlinked handle cannot be replayed and returnsESTALEafter connection loss; other handles remain usable.
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
Feature-gated additions are Rust-only and are excluded from 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