pub trait Filesystem {
Show 30 methods
// Required methods
fn create_file(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
src: FileSource,
meta: FileMeta,
) -> Result<()>;
fn create_dir(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
meta: FileMeta,
) -> Result<()>;
fn create_symlink(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
target: &Path,
meta: FileMeta,
) -> Result<()>;
fn create_device(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
kind: DeviceKind,
major: u32,
minor: u32,
meta: FileMeta,
) -> Result<()>;
fn remove(&mut self, dev: &mut dyn BlockDevice, path: &Path) -> Result<()>;
fn list(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
) -> Result<Vec<DirEntry>>;
fn read_file<'a>(
&'a mut self,
dev: &'a mut dyn BlockDevice,
path: &Path,
) -> Result<Box<dyn Read + 'a>>;
fn flush(&mut self, dev: &mut dyn BlockDevice) -> Result<()>;
// Provided methods
fn streams_immediately(&self) -> bool { ... }
fn create_file_streaming(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
body: &mut dyn Read,
len: u64,
meta: FileMeta,
) -> Result<()> { ... }
fn open_file_ro<'a>(
&'a mut self,
_dev: &'a mut dyn BlockDevice,
_path: &Path,
) -> Result<Box<dyn FileReadHandle + 'a>> { ... }
fn open_file_rw<'a>(
&'a mut self,
_dev: &'a mut dyn BlockDevice,
_path: &Path,
_flags: OpenFlags,
_meta: Option<FileMeta>,
) -> Result<Box<dyn FileHandle + 'a>> { ... }
fn image_len(&self) -> Option<u64> { ... }
fn mutation_capability(&self) -> MutationCapability { ... }
fn supports_mutation(&self) -> bool { ... }
fn clone_capability(&self) -> CloneCapability { ... }
fn clone_file(
&mut self,
dev: &mut dyn BlockDevice,
src: &Path,
dst: &Path,
) -> Result<()> { ... }
fn clone_range(
&mut self,
_dev: &mut dyn BlockDevice,
_src: &Path,
_src_off: u64,
_dst: &Path,
_dst_off: u64,
_len: u64,
) -> Result<()> { ... }
fn read_symlink(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
) -> Result<PathBuf> { ... }
fn getattr(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
) -> Result<FileAttrs> { ... }
fn set_attrs(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_attrs: SetAttrs,
) -> Result<()> { ... }
fn truncate(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_new_size: u64,
) -> Result<()> { ... }
fn rename(
&mut self,
_dev: &mut dyn BlockDevice,
_old_path: &Path,
_new_path: &Path,
) -> Result<()> { ... }
fn hardlink(
&mut self,
_dev: &mut dyn BlockDevice,
_target_path: &Path,
_new_path: &Path,
) -> Result<()> { ... }
fn list_xattrs(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
) -> Result<Vec<XattrPair>> { ... }
fn set_xattr(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_name: &str,
_value: &[u8],
) -> Result<()> { ... }
fn set_xattrs(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
xattrs: &[XattrPair],
) -> Result<()> { ... }
fn remove_xattr(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_name: &str,
) -> Result<()> { ... }
fn statfs(&mut self, _dev: &mut dyn BlockDevice) -> Result<StatFs> { ... }
fn total_file_bytes(&mut self, dev: &mut dyn BlockDevice) -> Result<u64> { ... }
}Expand description
Top-level dyn-compatible API every filesystem implements. The
format / open factory methods live on the sibling
FilesystemFactory trait so this one stays object-safe — the
generic walker in crate::repack can hold a &mut dyn Filesystem and drive any of Ext / Fat32 / HfsPlus / Ntfs
/ F2fs / Squashfs / Xfs through the same create_* /
remove / list / read_file / flush entry points.
Required Methods§
Sourcefn create_file(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
src: FileSource,
meta: FileMeta,
) -> Result<()>
fn create_file( &mut self, dev: &mut dyn BlockDevice, path: &Path, src: FileSource, meta: FileMeta, ) -> Result<()>
Create a regular file at path populated from src with metadata meta.
Sourcefn create_dir(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
meta: FileMeta,
) -> Result<()>
fn create_dir( &mut self, dev: &mut dyn BlockDevice, path: &Path, meta: FileMeta, ) -> Result<()>
Create a directory at path.
Sourcefn create_symlink(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
target: &Path,
meta: FileMeta,
) -> Result<()>
fn create_symlink( &mut self, dev: &mut dyn BlockDevice, path: &Path, target: &Path, meta: FileMeta, ) -> Result<()>
Create a symbolic link at path pointing at target.
Sourcefn create_device(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
kind: DeviceKind,
major: u32,
minor: u32,
meta: FileMeta,
) -> Result<()>
fn create_device( &mut self, dev: &mut dyn BlockDevice, path: &Path, kind: DeviceKind, major: u32, minor: u32, meta: FileMeta, ) -> Result<()>
Create a device node / FIFO / socket.
Sourcefn remove(&mut self, dev: &mut dyn BlockDevice, path: &Path) -> Result<()>
fn remove(&mut self, dev: &mut dyn BlockDevice, path: &Path) -> Result<()>
Remove a file, directory, or special entry. Returns
Error::InvalidArgument for a
non-empty directory.
Sourcefn list(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
) -> Result<Vec<DirEntry>>
fn list( &mut self, dev: &mut dyn BlockDevice, path: &Path, ) -> Result<Vec<DirEntry>>
List the entries of a directory.
Sourcefn read_file<'a>(
&'a mut self,
dev: &'a mut dyn BlockDevice,
path: &Path,
) -> Result<Box<dyn Read + 'a>>
fn read_file<'a>( &'a mut self, dev: &'a mut dyn BlockDevice, path: &Path, ) -> Result<Box<dyn Read + 'a>>
Open a regular file for reading. Returns a boxed streaming reader
that borrows both self (for filesystem metadata) and dev (for
actual block reads), so it must outlive both.
Sourcefn flush(&mut self, dev: &mut dyn BlockDevice) -> Result<()>
fn flush(&mut self, dev: &mut dyn BlockDevice) -> Result<()>
Persist outstanding dirty state to the device.
Provided Methods§
Sourcefn streams_immediately(&self) -> bool
fn streams_immediately(&self) -> bool
Create a regular file at path streaming exactly len bytes from
body. Unlike create_file’s
FileSource::Reader (which needs an owned ReadSeek + Send),
body is a plain borrowed Read — so a body borrowed from
another open filesystem can be piped straight through without an
intermediate tempfile or a Seek/Send bound. Implementations
MUST NOT retain body past the call.
Default: spool body into a tempfile and delegate to
create_file(FileSource::HostPath(..)) — correct everywhere, so
no backend regresses. Backends whose writer already consumes a
&mut dyn Read (ext, FAT32, the archive core, …) override this
for true zero-copy streaming.
Whether create_file consumes its
FileSource synchronously (true) rather than storing it to read
later at flush (false — e.g. SquashFS / ISO 9660 / GRF, which
keep every source until they serialise). Immediate backends let
create_file_streaming buffer small
files in memory instead of spilling each one to a temp file.
fn create_file_streaming( &mut self, dev: &mut dyn BlockDevice, path: &Path, body: &mut dyn Read, len: u64, meta: FileMeta, ) -> Result<()>
Sourcefn open_file_ro<'a>(
&'a mut self,
_dev: &'a mut dyn BlockDevice,
_path: &Path,
) -> Result<Box<dyn FileReadHandle + 'a>>
fn open_file_ro<'a>( &'a mut self, _dev: &'a mut dyn BlockDevice, _path: &Path, ) -> Result<Box<dyn FileReadHandle + 'a>>
Open a regular file for random-access reads with no
writes. The returned handle is Read + Seek and reports the
file’s total length via len(). Every backend that can
surface file contents should implement this — including the
immutable formats (ISO 9660 / SquashFS / tar / GRF) where
open_file_rw is unsupported but seeking inside a file is
still meaningful.
Default: returns Unsupported. Implementations override —
most can do so by reusing the same extent / runlist walker
that powers Self::read_file.
Sourcefn open_file_rw<'a>(
&'a mut self,
_dev: &'a mut dyn BlockDevice,
_path: &Path,
_flags: OpenFlags,
_meta: Option<FileMeta>,
) -> Result<Box<dyn FileHandle + 'a>>
fn open_file_rw<'a>( &'a mut self, _dev: &'a mut dyn BlockDevice, _path: &Path, _flags: OpenFlags, _meta: Option<FileMeta>, ) -> Result<Box<dyn FileHandle + 'a>>
Open a regular file for in-place reads + writes at byte
granularity. The returned handle is Read + Write + Seek;
dropping it persists any pending bytes (each implementation
chooses whether Write::write is eager or buffered).
Filesystems whose on-disk format requires journaling to be
safe across crash boundaries should refuse this method until
their journal is wired — partial writes that bypass a journal
leave the FS in a “needs fsck” state on next mount, which
is a worse default than a clear Unsupported error.
Default: returns Unsupported. Implementations override only
when they can produce a result that survives a clean unmount
without external repair.
Sourcefn image_len(&self) -> Option<u64>
fn image_len(&self) -> Option<u64>
For archive / streaming writers backed by a pre-sized device:
the exact number of bytes the output occupies after flush.
The backing file is provisioned generously (and sparsely), so
the caller truncates it to this length — an archive must be
exactly its own size, not padded with a zero tail.
Default None: filesystem images keep their provisioned size.
Only the archive backends (zip/cpio/ar) override this.
Sourcefn mutation_capability(&self) -> MutationCapability
fn mutation_capability(&self) -> MutationCapability
Capability of this filesystem with respect to mutating an already-flushed image. Three cases:
MutationCapability::Mutable: full in-place edits viacreate_*/remove(ext, FAT32, F2FS).MutationCapability::Streaming: writer is sequential only — adding to an existing image means producing a new one from scratch (tar).MutationCapability::Immutable: writer can seek but the on-disk format has no in-place mutation hooks (ISO 9660, SquashFS).repackrebuilds.
Default: Mutable. Override on backends that aren’t.
Sourcefn supports_mutation(&self) -> bool
fn supports_mutation(&self) -> bool
Convenience shortcut: can this filesystem satisfy
create_file / remove? Equivalent to
mutation_capability().supports_add_remove(). Returns true
for both MutationCapability::Mutable and
MutationCapability::WholeFileOnly — callers that need
finer detail (e.g. “can I patch byte N?”) should query
Self::mutation_capability directly.
Sourcefn clone_capability(&self) -> CloneCapability
fn clone_capability(&self) -> CloneCapability
Reflink / clone capability of this filesystem — does it natively share extents, and at what granularity?
Default: CloneCapability::None — clone_file will byte-copy
and clone_range will return Unsupported. Reflink-capable
backends (XFS once the REFLINK feature is on, APFS clones,
Btrfs) override to surface the right variant.
Sourcefn clone_file(
&mut self,
dev: &mut dyn BlockDevice,
src: &Path,
dst: &Path,
) -> Result<()>
fn clone_file( &mut self, dev: &mut dyn BlockDevice, src: &Path, dst: &Path, ) -> Result<()>
Clone the file at src into a new file at dst. Reflink-capable
backends share extents (zero data copy, refcount-btree updates);
everything else falls back to the default byte-copy.
Default behaviour. Spools src to a host tempfile so the
read-borrow on self is dropped, then runs create_file(dst, FileSource::TempFile, ...). Best-effort metadata via
Self::getattr (mode / uid / gid / mtime); falls back to
FileMeta::default when the source backend has no getattr
implementation.
Contracts.
srcmust exist;dstmust not already exist.dst’s parent directory must exist.- The result is observable through
read_file/getattrregardless of whether extents were shared — callers needn’t inspectclone_capabilityto use this method.
Returns Err(Unsupported) only when neither sharing nor the
default fallback can satisfy the call (e.g. an immutable
backend can’t create files at all).
Sourcefn clone_range(
&mut self,
_dev: &mut dyn BlockDevice,
_src: &Path,
_src_off: u64,
_dst: &Path,
_dst_off: u64,
_len: u64,
) -> Result<()>
fn clone_range( &mut self, _dev: &mut dyn BlockDevice, _src: &Path, _src_off: u64, _dst: &Path, _dst_off: u64, _len: u64, ) -> Result<()>
Clone an arbitrary byte range src[src_off..src_off+len] into
dst[dst_off..dst_off+len]. Reflink-capable backends share the
underlying extents (BTRFS_IOC_CLONE_RANGE / FICLONERANGE
semantics: writes through either side trigger COW).
Default: crate::Error::Unsupported. Sub-file extent
sharing is fundamentally a refcount-btree operation; backends
without that machinery cannot satisfy it (a byte-copy would
have different semantics — writes through src after the
“clone” would NOT propagate, defeating the point).
Contracts (when supported):
srcanddstmust both exist (dstmay equalsrc).src_off + lenmust not exceedsrc’s size;dst_offmay extenddst(the backend grows it).- Offsets and length must be aligned to the backend’s allocation unit (typically the cluster / block size); the backend’s docs specify the exact rule.
Sourcefn read_symlink(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
) -> Result<PathBuf>
fn read_symlink( &mut self, _dev: &mut dyn BlockDevice, _path: &Path, ) -> Result<PathBuf>
Read a symbolic link’s target. Default returns Unsupported
— filesystems that have symlinks (ext, tar, xfs, hfs+, ntfs,
squashfs, iso 9660 via Rock Ridge) override.
Sourcefn getattr(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
) -> Result<FileAttrs>
fn getattr( &mut self, dev: &mut dyn BlockDevice, path: &Path, ) -> Result<FileAttrs>
Full attributes for path. Used by the FUSE adapter to populate
getattr and lookup replies; also handy for any consumer that
wants a complete stat-like result without juggling
Self::list + the file handle.
Default: best-effort. We list the parent and find the entry
— that gives kind, size, and inode. The rest (mode, uid,
gid, times) are defaulted by FileAttrs::defaults_for (mode
0o755 for dirs, 0o644 for files, 0o777 for symlinks; all
times 0). Backends with per-file metadata (ext, hfs+, ntfs,
xfs, …) should override.
Sourcefn set_attrs(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_attrs: SetAttrs,
) -> Result<()>
fn set_attrs( &mut self, _dev: &mut dyn BlockDevice, _path: &Path, _attrs: SetAttrs, ) -> Result<()>
Update attributes on path. Fields set to None in attrs
are left unchanged. Backends that can’t change a given field
silently ignore it (FAT, for example, has no uid/gid concept).
Default: returns Unsupported. Read-only and metadata-poor
backends keep this default; mutable backends override.
Sourcefn truncate(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_new_size: u64,
) -> Result<()>
fn truncate( &mut self, _dev: &mut dyn BlockDevice, _path: &Path, _new_size: u64, ) -> Result<()>
Resize path to new_size bytes. Equivalent to
FileHandle::set_len reached through a path. Growing fills
with zeros; shrinking discards trailing bytes and frees blocks.
Default: returns Unsupported. Mutable backends override.
Sourcefn rename(
&mut self,
_dev: &mut dyn BlockDevice,
_old_path: &Path,
_new_path: &Path,
) -> Result<()>
fn rename( &mut self, _dev: &mut dyn BlockDevice, _old_path: &Path, _new_path: &Path, ) -> Result<()>
Rename old_path to new_path. Cross-directory moves and
directory renames are both in scope — the operation must
preserve the target inode (so hardlinks survive).
Default: returns Unsupported. Mutable backends override.
Sourcefn hardlink(
&mut self,
_dev: &mut dyn BlockDevice,
_target_path: &Path,
_new_path: &Path,
) -> Result<()>
fn hardlink( &mut self, _dev: &mut dyn BlockDevice, _target_path: &Path, _new_path: &Path, ) -> Result<()>
Add a new directory entry at new_path that points at the
existing inode at target_path — a POSIX hard link.
Default: returns Unsupported. Only ext implements this today.
Sourcefn list_xattrs(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
) -> Result<Vec<XattrPair>>
fn list_xattrs( &mut self, _dev: &mut dyn BlockDevice, _path: &Path, ) -> Result<Vec<XattrPair>>
List the extended attributes attached to path, with both
names and values. The FUSE adapter splits this into
listxattr / getxattr itself; we surface both at once so
backends don’t need two parallel walkers.
Default: empty vec. Backends with xattr storage (ext, ntfs, hfs+) override.
Sourcefn set_xattr(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_name: &str,
_value: &[u8],
) -> Result<()>
fn set_xattr( &mut self, _dev: &mut dyn BlockDevice, _path: &Path, _name: &str, _value: &[u8], ) -> Result<()>
Write or replace the xattr name on path. Returns
Unsupported when the backend can’t store xattrs.
Sourcefn set_xattrs(
&mut self,
dev: &mut dyn BlockDevice,
path: &Path,
xattrs: &[XattrPair],
) -> Result<()>
fn set_xattrs( &mut self, dev: &mut dyn BlockDevice, path: &Path, xattrs: &[XattrPair], ) -> Result<()>
Write a whole set of xattrs onto path at once, replacing any
existing set. Backends that store xattrs in a single on-disk
structure (ext’s external attribute block) override this to write
them atomically — applying them one at a time via set_xattr
would orphan the previous block on each call. The default applies
them individually.
Sourcefn remove_xattr(
&mut self,
_dev: &mut dyn BlockDevice,
_path: &Path,
_name: &str,
) -> Result<()>
fn remove_xattr( &mut self, _dev: &mut dyn BlockDevice, _path: &Path, _name: &str, ) -> Result<()>
Remove the xattr name from path. Returns Unsupported
when the backend can’t store xattrs.
Sourcefn statfs(&mut self, _dev: &mut dyn BlockDevice) -> Result<StatFs>
fn statfs(&mut self, _dev: &mut dyn BlockDevice) -> Result<StatFs>
Filesystem-level capacity stats. The FUSE adapter calls this
to answer statfs; the CLI’s info command could too.
Default: StatFs::default — 4 KiB block size, zero counts,
name_max = 255. Backends with real superblock data override.
Sourcefn total_file_bytes(&mut self, dev: &mut dyn BlockDevice) -> Result<u64>
fn total_file_bytes(&mut self, dev: &mut dyn BlockDevice) -> Result<u64>
Recursive sum of all regular-file sizes in the filesystem.
Uses the size field on DirEntry returned by Self::list
— filesystems that don’t surface size from a listing return 0
for those entries, in which case the total is best-effort.
Skips the special names ".", "..", and "lost+found" so
the walk doesn’t loop / double-count ext’s reserved tree.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
impl Filesystem for Affs
impl Filesystem for Apfs
Filesystem adapter for APFS. An Apfs opened via
Apfs::open is read-only — mutation calls return Unsupported.
An Apfs returned by Apfs::format is in pending-write mode:
create_file / create_dir / create_symlink buffer operations
in memory and flush drains them into a fresh image through
write::ApfsWriter. After flush the Apfs is in read mode
and behaves like a freshly-opened image.
impl Filesystem for ArFs
impl Filesystem for ArcFs
impl Filesystem for ArchiveFs
impl Filesystem for CabFs
impl Filesystem for CpioFs
impl Filesystem for Exfat
Filesystem adapter so inspect::open(dev) can return a
Box<dyn Filesystem> that walks and mutates an exFAT image. Symlinks
and device nodes have no representation in exFAT and return
Unsupported. The caller must call flush to persist FAT + bitmap
changes before dropping the volume.
impl Filesystem for Ext
impl Filesystem for F2fs
impl Filesystem for Fat32
impl Filesystem for Grf
impl Filesystem for Hfs
impl Filesystem for HfsPlus
impl Filesystem for Iso9660
impl Filesystem for LhaFs
impl Filesystem for LzxFs
impl Filesystem for Ntfs
impl Filesystem for Ramfs
impl Filesystem for RarFs
impl Filesystem for SevenZFs
impl Filesystem for SitFs
impl Filesystem for Squashfs
impl Filesystem for Tar
Read-only Filesystem adapter so inspect::open(dev) can return a
Box<dyn Filesystem> that walks a tar archive. Writes return
Unsupported — tar archives are sequential and repack is the
only way to produce a new one.