Skip to main content

Crate ferrosys

Crate ferrosys 

Source
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.

  • detect reads an image and reports the Filesystem family it holds, and detect_with does the same at an offset within the source, for a partition or a region a carver located; DetectError tells an unreadable source from an unrecognized one.
  • OpenOptions, ReadPolicy, and Limits say where to look, how strictly, and within what bounds a read may allocate.
  • open detects and hands back the matching family’s reader, as an FsReader — 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.

Saying what was lost, and what was found.

  • FidelityReport names every property a format could not hold and every value a read had to invent, and Synthesis is 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 an AcceptedLoss, so nothing is dropped unacknowledged.
  • Finding is what a scan reports, carrying a Severity, a byte offset, the Family that 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.
  • printable renders a name that came off an image as text a terminal will not act on, and push_json_string does 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.
  • crc32c is the reflected CRC-32C primitive filesystem metadata checksums are built from. The ext module implements the ext2/ext3/ext4 family — the format writer, the Reader opened over any Read + Seek source, 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. The fat module implements the FAT12/FAT16/FAT32 family — the format writer, the Reader, the plan_layout geometry planner, and the byte-exact on-disk structures under fat::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. The exfat module implements the exFAT family — the format writer, the plan_layout geometry planner, and the byte-exact on-disk structures under exfat::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. The btrfs module implements the btrfs family, over the two layers the format has. A Volume opens one over any Read + Seek source 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 a Tree over 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. A Reader is the filesystem view built on that, and FormatPlan writes 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 under btrfs::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:

  • fat adds the FAT12/FAT16/FAT32 family. It has no dependencies of its own.
  • exfat adds the exFAT family, which shares a name with the one above and none of its structures. It has no dependencies of its own.
  • btrfs adds the btrfs family, over a format built out of B-trees and a logical address space. It has no dependencies of its own.
  • zlib, lzo and zstd each 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 beside btrfs, as --features btrfs,zstd; alone it compiles its dependency and decodes nothing, since no reachable read stores runs that way. lzo takes no dependency, its decoder being in this crate; the other two depend on miniz_oxide and ruzstd. 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.
  • tar adds the tar/PAX archive source and sink: a filesystem built from an archive, and one written back out as one. It depends on tar.
  • dir adds 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 on rustix for the directory, node, ownership and extended-attribute calls the standard library has no equivalent of, and is present on Linux.
  • serde adds Serialize to the findings taxonomy, every family’s planned geometry, and the ext feature model, for embedding them in a document of your own. It depends on serde.

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 detect answers Filesystem::ExFat with.
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§

AcceptedLoss
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.
ArchiveSink
Writes a filesystem’s contents out as a tar archive with PAX extensions.
ArchiveSource
A Source that 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.
DetectOptions
Where to look for a filesystem, and anything else detection needs to be told.
DirectorySink
Writes a filesystem’s contents out as a directory tree on this host.
DirectorySource
A Source that 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.
ExtractReport
What an extraction wrote, and what it left out.
FidelityRecord
One property that did not survive, and the entry it belonged to.
FidelityReport
Everything a build could not carry and everything a read had to invent.
FileRange
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.
FindingReport
A set of findings and what the scan that produced them managed to look at.
LayeredSource
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.
OpenOptions
How an image is opened without naming its family: where it begins, how strictly it is read, and what it may allocate.
ScanReport
What a whole-filesystem scan found: every Deviation it met, in the order it walked them.
SourceEntry
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.
TreeBuilder
An in-memory, programmatic source: add entries, then hand it to the model.
TreeEntry
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 AclEntry grants permissions to.
ArchiveError
A failure reading or interpreting a tar archive.
DetectError
A failure detecting the filesystem in an image.
Direction
Which way a fidelity record runs.
EntryKind
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.
FileContent
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 detect classifies it.
FsReader
An open filesystem, as whichever family claimed the image.
HostError
A failure walking a host directory tree.
NodeKind
What a node in a filesystem tree is, as an extraction sees it.
OpenError
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.
ReadPolicy
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.
TreeError
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.
NamedChoice
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 from seed.
detect
Detect the filesystem family at the start of an image.
detect_with
Detect the filesystem family an image holds under options.
hex
bytes as 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 s to out as 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).