Expand description
ferrosys — pure-Rust, userspace filesystem tooling.
The crate creates and reads filesystem images entirely in userspace, over ordinary byte streams, in self-contained, safe Rust. On-disk types serialize through explicit little-endian byte accessors, so the byte layout is spelled out at every field.
§Structure
The crate root holds what is true of a filesystem whatever family it is, and each family lives in a module of its own behind a feature of its own.
Finding one, and opening it.
detectreads an image and reports theFilesystemfamily it holds, anddetect_withdoes the same at an offset within the source, for a partition or a region a carver located;DetectErrortells an unreadable source from an unrecognized one.OpenOptions,ReadPolicy, andLimitssay where to look, how strictly, and within what bounds a read may allocate.opendetects and hands back the matching family’s reader, as anFsReader— an enum of concrete readers rather than a common interface, so a caller that has matched its way to one has that family’s whole surface.
Describing a tree, and draining one. A directory tree is not any family’s concept, so the vocabulary for one is here and every family consumes it unchanged.
Source,SourceEntry,EntryKind,Metadata,FileContent,Xattr, andTimestampdescribe what to write;TreeBuilderandLayeredSourcebuild one programmatically.FsTreeis the other direction, and the one behavioural trait the families share: walk the names, stat one, stream a file’s bytes, resolve a link. It is what lets a sink drain any family without knowing which.
Saying what was lost, and what was found.
FidelityReportnames every property a format could not hold and every value a read had to invent, andSynthesisis what a read invents them from — with conservative defaults, because a tree extracted from a format with no permission bits must not land world-writable because nothing was named. A build that would lose a property fails until the caller names it in anAcceptedLoss, so nothing is dropped unacknowledged.Findingis what a scan reports, carrying aSeverity, a byte offset, theFamilythat found it, and that family’s own words for the rest. Each family keeps its own typed taxonomy and projects into this, so there is one document shape and one severity scale however many families a build carries.printablerenders a name that came off an image as text a terminal will not act on, andpush_json_stringdoes the same into a JSON document. Every message and every finding this crate produces has already been through them; they are public for a caller whose own output names the same untrusted bytes.crc32cis the reflected CRC-32C primitive filesystem metadata checksums are built from. Theextmodule implements the ext2/ext3/ext4 family — theformatwriter, theReaderopened over anyRead + Seeksource, and the byte-exact on-disk structures — and is on by default. Its images are byte-reproducible: the UUID, hash seed, and timestamps are inputs, never read from the clock or a random source. It re-exports the root vocabulary above, so a caller formatting an ext image names one namespace rather than two. Thefatmodule implements the FAT12/FAT16/FAT32 family — theformatwriter, theReader, theplan_layoutgeometry planner, and the byte-exact on-disk structures underfat::ondisk. Which of the three a volume is follows from its cluster count and from nothing else, so the type is derived rather than chosen, and the arithmetic that derives it is the format’s real contract. Its images are byte-reproducible: the volume serial number and the times a directory entry carries are inputs, and the date conversion is UTC, so nothing about the machine that wrote an image reaches it. The reader reads any conformant volume with one or two allocation tables, whatever wrote it, and takes one input no other family has —ShortNameCharset, since nothing in a FAT volume records the code page its short names are written in and this crate does not guess one. Theexfatmodule implements the exFAT family — theformatwriter, theplan_layoutgeometry planner, and the byte-exact on-disk structures underexfat::ondisk. It shares a name with FAT and no bytes: a different boot region, a different directory entry format, a different name encoding, and an allocation bitmap FAT has no equivalent of. Three of its structures carry a checksum and a fourth carries a hash, and every one is recomputed rather than copied. Its images are byte-reproducible, and cost one input to be so — the volume serial number, since an empty exFAT volume records no time anywhere. Thebtrfsmodule implements the btrfs family, over the two layers the format has. AVolumeopens one over anyRead + Seeksource and gives the lower one: the superblock and every mirror of it the device holds, the chunk map that turns a logical address into a place on the device, and aTreeover any of the filesystem’s B-trees — searched by the key tuple, iterated in key order, with every block’s checksum verified as it is read. AReaderis the filesystem view built on that, andFormatPlanwrites one, subvolumes included. Reading a file whose bytes are compressed takes the decoder for its algorithm; verifying one takes none, the checksums covering the bytes on the volume. The byte-exact on-disk structures are underbtrfs::ondisk.
§Features
A build takes the filesystem families it names. ext is on by default; a build that
turns off every family compiles the root substrate and no family code at all, and
detect then recognizes nothing. Granularity is per family rather than
per format — ext is ext2, ext3, and ext4 together, and fat is FAT12, FAT16, and
FAT32 together, since each set is one lineage sharing its on-disk structures.
Cargo unifies features across a dependency graph, so selecting a subset is a property of
a leaf application rather than of a library deep in someone’s tree: anything else in the
build that pulls this crate with a family turns that family on for everyone in it —
including the answers detect then gives.
Nine more features are off by default, so a build that wants none of them depends only
on thiserror. Each stands alone and none implies a family — the two ends of a tree are
the root’s vocabulary, so a source feeds whichever family is being written and a sink
drains whichever one was opened, and a decoder undoes an encoding whichever family
stored a run of bytes in it:
fatadds the FAT12/FAT16/FAT32 family. It has no dependencies of its own.exfatadds the exFAT family, which shares a name with the one above and none of its structures. It has no dependencies of its own.btrfsadds the btrfs family, over a format built out of B-trees and a logical address space. It has no dependencies of its own.zlib,lzoandzstdeach add a decoder, so that a file whose extents are stored in that encoding reads as the file rather than as a refusal naming the algorithm. btrfs is the family here that stores runs that way, and a decoder reaches bytes only through a family that stores some — name one besidebtrfs, as--features btrfs,zstd; alone it compiles its dependency and decodes nothing, since no reachable read stores runs that way.lzotakes no dependency, its decoder being in this crate; the other two depend onminiz_oxideandruzstd. None of them is needed to verify a filesystem: the checksums it records cover the bytes it stored, so a compressed extent is checked without being expanded.taradds the tar/PAX archive source and sink: a filesystem built from an archive, and one written back out as one. It depends ontar.diradds the host-directory source and sink: a filesystem built by walking a tree on this machine, and one written back out as a tree, with modes, ownership, times, hard links, special files, and extended attributes. It depends onrustixfor the directory, node, ownership and extended-attribute calls the standard library has no equivalent of, and is present on Linux.serdeaddsSerializeto the findings taxonomy, every family’s planned geometry, and the ext feature model, for embedding them in a document of your own. It depends onserde.
Modules§
- btrfs
- The btrfs family: the logical address space, the B-trees over it, and the byte-exact on-disk structures both are made of.
- exfat
- The exFAT family: the formatter, the geometry planner, the byte-exact on-disk structures,
and the classifier
detectanswersFilesystem::ExFatwith. - ext
- The ext2/ext3/ext4 family: the formatter, the reader, and the byte-exact on-disk structures.
- fat
- The FAT12/FAT16/FAT32 family: the formatter, the geometry planner, and the byte-exact on-disk structures.
- json
- Building a JSON document: objects, arrays, and the value kinds a report carries.
Structs§
- Accepted
Loss - Which properties a build may lose without being refused.
- Acl
- A POSIX access control list: a canonically ordered, validated set of entries.
- AclEntry
- One ACL entry: a qualifier and the read/write/execute bits it grants.
- Archive
Sink - Writes a filesystem’s contents out as a tar archive with PAX extensions.
- Archive
Source - A
Sourcethat yields the entries parsed from a tar archive. - Attributes
- Everything a sink records about one node beyond what the walk carried.
- Civil
- A civil date and time of day, UTC: what an instant reads as on a calendar.
- Detect
Options - Where to look for a filesystem, and anything else detection needs to be told.
- Directory
Sink - Writes a filesystem’s contents out as a directory tree on this host.
- Directory
Source - A
Sourcethat yields the entries walked from a directory on the host. - DosTimestamp
- An instant in the DOS date and time encoding: two sixteen-bit words counting years from 1980 and seconds in units of two, and a companion field of hundredths.
- Extract
Report - What an extraction wrote, and what it left out.
- Fidelity
Record - One property that did not survive, and the entry it belonged to.
- Fidelity
Report - Everything a build could not carry and everything a read had to invent.
- File
Range - A range of bytes within a file on the host, read at the moment the content is placed.
- Finding
- A typed deviation from what a family’s writer would emit, carrying its severity, where it sits, and that family’s own description.
- Finding
Report - A set of findings and what the scan that produced them managed to look at.
- Layered
Source - Several sources composed into one, where a later layer’s entry replaces an earlier layer’s at the same path.
- Limits
- Caps on what one read of an untrusted image may allocate.
- Metadata
- Ownership, permission bits, and timestamps for one entry.
- Open
Options - How an image is opened without naming its family: where it begins, how strictly it is read, and what it may allocate.
- Scan
Report - What a whole-filesystem scan found: every
Deviationit met, in the order it walked them. - Source
Entry - One thing to place in the filesystem: where it goes, what it is, its metadata, and any extended attributes.
- Synthesis
- What a read records for a property the source filesystem has no field for.
- Timestamp
- An instant: seconds since the Unix epoch, plus a nanosecond fraction.
- Tree
Builder - An in-memory, programmatic source: add entries, then hand it to the model.
- Tree
Entry - One name a walk reached: where it is, what is there, and the family’s own handle to it.
- Xattr
- One extended attribute: a fully-qualified name (namespace prefix included, e.g.
b"security.capability") and its raw value bytes.
Enums§
- AclError
- A failure encoding or decoding an ACL.
- AclQualifier
- Who an
AclEntrygrants permissions to. - Archive
Error - A failure reading or interpreting a tar archive.
- Detect
Error - A failure detecting the filesystem in an image.
- Direction
- Which way a fidelity record runs.
- Entry
Kind - What an entry is: a regular file, directory, symlink, hard link, device node, FIFO, or socket — the full set of POSIX file types ext4 represents.
- Family
- Which filesystem family reported a finding.
- File
Content - A regular file’s contents: either bytes in memory, or a range of a file on the host read at the moment it is placed.
- Filesystem
- The filesystem family an image holds, as
detectclassifies it. - FsReader
- An open filesystem, as whichever family claimed the image.
- Host
Error - A failure walking a host directory tree.
- Node
Kind - What a node in a filesystem tree is, as an extraction sees it.
- Open
Error - A failure opening an image whose family is not known in advance.
- Property
- A property of an entry that a filesystem may or may not record.
- Read
Policy - The conformance-strictness policy a read applies: a threshold over
Severity. - Severity
- How serious a deviation from what this crate emits is, ordered least to most serious so a policy can set a fatal threshold over it.
- Slack
- Room to leave beyond what the source needs, when a filesystem is sized to fit one.
- Tree
Error - A failure reading a filesystem through the extraction surface.
Constants§
- FINDINGS_
SCHEMA_ VERSION - The version of the emitted findings schema — the JSON a report renders and the record each finding renders within it.
- MAX_
SYMLINK_ HOPS - The most symbolic links a path resolution follows before calling it a loop, matching the
kernel’s
MAXSYMLINKS.
Traits§
- Deviation
- A family’s own typed deviation from what its writer emits, and how it reaches the shared frame.
- FsTree
- The four operations an extraction needs of a filesystem, whichever family it is.
- Named
Choice - A closed set of variants a caller names, in whichever direction it is being read.
- Source
- Something that produces the entries to write into a filesystem.
Functions§
- crc32c
- crc32c of
data, continued fromseed. - detect
- Detect the filesystem family at the start of an image.
- detect_
with - Detect the filesystem family an image holds under
options. - hex
bytesas lower-case hexadecimal, two digits each and no separator.- open
- Open the filesystem at the start of an image, whatever family it is.
- open_
with - Open the filesystem an image holds under
options, whatever family it is. - printable
- Text for
bytes, with everything a terminal would act on rendered as an escape. - push_
json_ string - Append
stooutas a JSON string literal, quotes included, escaping what the grammar requires and what a terminal acts on.
Type Aliases§
- Coordinate
- One named coordinate a family locates a finding by:
("group", 3),("inode", 12),("cluster", 57).