- Rust 99.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Merge the selected feature/native-cli history with an explicit two-parent commit so main retains the development lineage and the validated source snapshot. The resulting tree is identical to the selected feature commit; no dependency pins or runtime behavior are changed by this merge. Previous main: |
||
| .github | ||
| src | ||
| .editorconfig | ||
| .gitignore | ||
| .markdownlint-cli2.yaml | ||
| ARCHITECTURE.md | ||
| Cargo.toml | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| linker.ld | ||
| README.md | ||
| ROADMAP.md | ||
| rustfmt.toml | ||
| SECURITY.md | ||
fatd
fatd is the private FAT-family filesystem provider daemon behind vfsd. It is
started by rootd after e2fsd and before vfsd, and it is reachable only
through the provider endpoint delegated to vfsd.
EriX is a clean-room, capability-based microkernel operating system written entirely in Rust.
Technical requirements are tracked in the EriX requirements, conventions, and project documentation.
See:
- docs for design documents, specifications, and development plans.
- Related architecture repositories for kernel, services, libraries, drivers, and integration tooling.
Purpose of This Repository
Private cwd component opens retain FAT/exFAT directories beneath an existing provider handle, with independent close lifetimes and live-only object identity. They grant no new mount or namespace authority; FAT-family link reads fail explicitly because these formats do not implement symbolic links.
This repository implements the EriX FAT-family filesystem provider. Its purpose
in EriX is to serve validated FAT and exFAT media behind vfsd without exposing
a public service.
Functionally, it parses FAT-family media, validates directory/allocation state, and implements provider file/directory operations. The repository keeps the implementation, interface contracts, tests, and documentation for that behavior in one reviewable ownership boundary.
The maintained responsibilities are:
- serve FAT-family and exFAT filesystems only through the private filesystem-provider ABI
- validate boot sectors, allocation metadata, directory entries, and name state before exposing mounts
- implement persistent file and directory operations through the assigned
blockdendpoint - keep provider authority private with no
namedentry or public client endpoint
Clean-Room Policy
EriX follows a strict clean-room philosophy:
- No external source code may be copied.
- No external Rust crates are allowed.
- No code generation tools that embed third-party code.
- All code must be authored within the project.
Violations will result in rejection of the contribution.
License
All EriX repositories are licensed under the ISC License.
Development Model
EriX development is modular, deterministic, reproducible, authority-explicit, security-first, and self-hosting oriented.
This repository follows the project roadmap and the validation rules documented in its own roadmap.
Current Status
Private OPEN reports an unknown mount as INVALID_ARGUMENT, not file absence.
NOT_FOUND from path resolution beneath a live mount remains unchanged, while
underlying storage absence becomes INTERNAL. This distinction grants no
create authority and changes no other operation's errors.
The private directory-entry metadata operation accepts one retained directory
handle and one validated immediate basename. It returns current no-follow
metadata without reopening a parent pathname, following a symbolic link, or
granting file-content access. Closed handles, non-directory objects, and path
selectors fail closed; public authorization remains owned by vfsd.
The provider service, startup validation, generic ABI dispatch, CI, and
block-backed FAT12/FAT16/FAT32/exFAT media engine are present. Mount reads
device metadata and the boot sector through the private blockd endpoint, uses
the shared callback-driven lib-block filesystem client, and keeps the
call-message, block-transfer, mount-validation, directory-scan, and FAT table
scratch state in service-static buffers instead of large stack frames. Sector
scratch follows
the FAT/exFAT format maximum of 4,096 bytes rather than a block-library
transfer constant; BlockClient fragments at the smaller of caller transfer
storage and the canonical IPC transport envelope, retries transient
backpressure without a service-local ceiling, and retains accepted call
storage through the authoritative reply. It batches mount-time FAT
sector reads through bounded caches, classifies FAT12/FAT16/FAT32 by
cluster-count thresholds, validates exFAT BPB, allocation bitmap, compressed
upcase-table checksum, coverage, and mandatory mapping metadata for EXFAT
provider-kind mounts, validates exFAT main and backup boot-region checksums
before trusting BPB fields, checks mirrored FATs before accepting a FAT12/16/32
mount, safely repairs exactly one divergent FAT mirror when a writable volume
has at least three mirrors and the remaining mirrors agree, validates FAT32
FSInfo signatures and range fields, parses FAT32 extended flags and backup
boot-sector metadata, and validates FAT reserved entries, clean/dirty state,
hard-error state, and volume ID/label/type metadata. fatd rejects read-write
FAT16/FAT32 mounts when the format clean-shutdown or no-hard-error bit is clear,
while read-only mounts proceed only after bounded boot-sector, backup-sector,
reserved-FAT, FSInfo-shape, active-root-chain, and one-pass root-directory
syntax validation. Full FAT free-space, mirror, and stackless directory-tree
scans remain writable-mount checks. The FAT tree walk descends through child
records, validates each directory's format-required . and .. links, returns
through .., and rescans the parent for its next child. Valid media depth is
therefore bounded by the media rather than by a fixed recursion or scratch
limit. It also rejects read-write FAT32 mounts with
stale FSInfo counts or inconsistent primary/backup boot metadata. exFAT
boot-region disagreement is fail-closed
except for backup VolumeFlags and PercentInUse, which the format treats as
stale. exFAT uses the primary VolumeFlags active-FAT selector to choose both
the FAT and allocation bitmap; dirty or media-failure volumes are
read-only-only, invalid reserved flag state fails closed, and successful
writable metadata operations refresh primary PercentInUse from the active
allocation bitmap with bounded bitmap-stream reads and clear the dirty bit
before returning, while leaving backup checksum-excluded stale fields alone.
First-free cluster selection for exFAT allocation also uses bounded active
bitmap stream reads before touching the selected FAT and allocation bitmap.
exFAT root metadata validation rejects
malformed allocation-bitmap entries, duplicate bitmap/upcase critical entries,
bad upcase tables, and corrupt directory entry sets fail-closed before the mount
is exposed. It parses Volume Label and Volume GUID entries as root metadata,
preserves inert TexFAT padding and no-allocation benign vendor/unknown
secondaries, rejects vendor allocation and unknown critical entry types, and
treats every in-use benign metadata slot as occupied during allocation.
Runtime state stores only mount records and open handles; file and directory
operations resolve media directory entries on demand. Packaging derives the
mount-record count from exact provider = "fat" deployment rows and takes the
handle-record count from explicit runtime policy. It authenticates both counts
and their target layouts in the signed service image, then expands one writable
NOBITS arena to the exact page-rounded size. fatd carves only typed mount
and handle slices from that arena and retains neither a general allocator nor
access to alignment or page padding. Mount and create requests reserve their
required records before assigning an ID or mutating media, so capacity
exhaustion cannot consume an identifier or leave residual filesystem state.
The FAT engine supports
FAT12 12-bit entries, FAT16 fixed root directories, FAT32 cluster-root/FSInfo
metadata, exFAT allocation bitmap/upcase-table/directory-entry-set metadata,
exFAT upcase-table filename keys and stream NameHash validation, VFAT
long-name decode/write with strict ordinal/checksum/termination validation,
media short-alias validation that accepts OEM bytes only behind valid VFAT LFN
records, ASCII-only standalone short-name decoding, escaped leading 0xE5
rejection, deterministic 8.3 alias generation with duplicate-alias rejection, NT
lowercase direct short entries, Unicode casefold lookup through lib-fs-name,
mirrored FAT entry updates, exFAT bitmap/FAT updates, cluster
allocation/freeing, malformed-chain rejection, mount-time referenced-chain
validation for file and directory loops, bad cluster markers, out-of-range
starts, and cross-linked chains, plus exFAT allocation-bitmap reconciliation
across reachable FAT-chain and no-FAT-chain file/directory streams, metadata
streams, duplicate ownership, leaked clusters, bitmap/FAT mismatches, loops, and
out-of-range clusters using bounded bitmap-stream scans, bounded exFAT
first-free allocation scans, active-FAT selection when FAT32 mirroring is disabled,
safe single mirror repair, persistent file data writeback, and FAT regular-file
truncate with allocation shrink/free, zero-filled growth, and coherent cached
metadata in every matching live handle. FAT and exFAT
directory-entry metadata is decoded and preserved for create/access/modify
timestamps, read-only/hidden/system/archive attributes, directory type bits, and
other primary-entry fields that the provider does not own. FAT additionally
preserves volume-label entries and NT lowercase short-name flags. V1
create/mkdir still use the FAT epoch in UTC because fatd has no ambient
wall-clock authority; caller-supplied v1 set_metadata timestamps remain
explicit UTC date/time values. Additive v2 private-provider calls accept only a
descriptive trusted hardware-RTC or degraded timestamp from vfsd; fatd
receives neither a timed endpoint nor RTC authority. V2 create, successful
read/readdir, nonempty write, truncate, namespace, metadata, and exact-entry
operations apply automatic times to each representable surviving entry. FAT
access is date-only and FAT modification is two-second precision; FAT creation
and exFAT creation/modification use 10 ms increments, while exFAT access uses
two-second precision. FAT and exFAT have no independent inode-change-time
field, so reported changed remains an alias of stored mtime: ctime-only events
preserve that field, while representable explicit atime and historical mtime
updates are accepted independently. Timestamp values selected for an on-media
field must represent UTC years 1980 through 2107; out-of-range values, including
Unix epoch zero, are rejected before a media write. A trusted current change
timestamp is still shape-validated when the operation has no independent ctime
field, but it is not fabricated into mtime. Root-directory automatic time is
omitted because neither format has a parent directory entry for the root.
FAT and exFAT do not provide a rollback transaction. Timestamped mutations
prevalidate time and metadata representation, then conservatively track block
writes. Any error after the first write attempt is publication uncertainty and
causes fail-stop without a provider reply; the implementation does not claim
rollback across durable block-I/O uncertainty. exFAT continues to use its dirty
volume flag around metadata updates. Unit coverage includes FAT12 entry
packing, FAT16 fixed-root create/write/read, FAT reserved-entry validation,
dirty/error read-only-only policy, reserved-entry writeback preservation, FAT
timestamp encoding, attribute preservation/mutation, lowercase short-name flags,
valid VFAT LFN records with OEM-byte aliases, invalid attribute-combination
rejection, malformed standalone short-name byte and NT flag rejection, ambiguous
LFN/short visible-name rejection, FAT rename metadata preservation, compatible
file and empty-directory replacement, cycle and non-empty-directory replacement
rejection, FAT truncate coverage for shrink-to-zero, in-cluster shrink,
cross-cluster shrink, zero-filled growth, FAT32 FSInfo update, and active-FAT
policy, FAT32 active-FAT selection, missing/corrupt backup boot sectors, exFAT
mount validation, active-FAT/active-bitmap selection, dirty/media-failure
policy, clean dirty-bit writeback, malformed upcase rejection, exFAT NameHash
validation, duplicate upcase-equivalent name rejection, malformed UTF-16 name
rejection, exFAT create/write/read/readdir/unlink/rename persistence, exFAT
compatible rename replacement with no-FAT-chain destination cleanup, Unicode
casefold lookups, alias collision handling including dense suffix growth, strict
VFAT malformed-chain rejection, duplicate short-alias rejection, exact valid
UTF-16 payload preservation, fragmented multi-cluster files, directory
growth/deep paths, open-target unlink denial, read-only write denial, and single
divergent mirror repair. The VM and host-media corpus covers FAT12 and FAT16 ESP
media in addition to primary-only, mirrored, active-FAT, and malformed-backup
FAT32 fixtures plus clean, dirty, hard-error, and malformed reserved-entry FAT32
metadata fixtures and FAT12/FAT16/FAT32 directory-metadata fixtures verified
with host FAT tools, plus a focused FAT32 metadata-set fixture that validates
host-created timestamps and VFS-updated atime/mtime/attribute fields with
mtools and direct directory-entry checks. FAT-04 adds host-tool-generated VFAT
Unicode/dense-alias media plus patched ordinal, orphan-chain, duplicate-alias,
short-byte, NT-flag, and ambiguous-LFN negative media; FAT-05 adds fragmented
allocation, grown-directory/free-slot reuse, sparse-looking writeback,
cross-linked-file, looped-chain, bad-cluster, out-of-range-chain, and
inconsistent-FSInfo coverage; focused FAT12/FAT16/FAT32 truncate VM scenarios
verify shrink/grow/zero-fill through vfsd and post-VM host mtools,
fsck.fat, and direct FAT/FSInfo checks; exFAT now has deterministic ESP media
generation, one-FAT/two-FAT active-state scenario definitions, boot-region
positive/negative coverage, upcase-table Unicode lookup and NameHash
positive/negative coverage, allocation-reconciliation positive/negative
coverage, stream ValidDataLength/DataLength coverage, path truncate support,
no-FAT-chain growth conversion, sparse-valid-data reads, fragmented-stream
fixtures, and host-side image verification in integration. The provider
dispatch also parses the expanded generic filesystem-provider ABI for rename,
truncate, symlink/readlink, hard-link, and metadata-update requests. FAT and
exFAT exact-entry operations use one provider-private handle that retains the
parent directory identity, target directory-entry location or absence, and
admitted operation. Exact stat re-reads only that retained location. Exact
touch additionally checks the vfsd-derived basename, supports a proven-absent
no-create result or regular-file creation, and applies only selected atime and
mtime fields. Neither follow-up accepts a mount, namespace, parent, or path
selector, and ordinary operations reject the exact handle. FAT and
exFAT media implement rename, regular-file path truncate with live-handle
coherence, and flagged metadata updates for supported attribute and timestamp
fields; unsupported
symlink/readlink, hard-link, and UID/GID ownership requests return explicit
DENIED responses. exFAT media validates file-primary attributes, timestamp
increments, and UTC offsets fail-closed, enforces read-only attributes across
open/write/truncate/unlink paths, and preserves unsupported primary-entry fields
across supported mutations.
Validation
cargo fmt --all -- --check- strict
cargo clippy --all-targets --all-features -- -D warnings cargo test --all-targets --all-features- warning-denied host and freestanding builds and Rustdoc
- source-size, dependency-pin, Markdown, and diff hygiene gates
- integration image builds through the Filesystem provider work fixture path
Dynamic Boot Artifact Evidence
The runtime image contract documents fatd as a dynamic boot artifact.
The image build
packages the FAT filesystem provider as an ELF64 x86_64 ET_DYN executable
with .erix_dynlink metadata in the signed dynlink-store and mirrors it
under /lib/erix/dynlink with its required shared objects.
Startup remains rootd through procd staged dynamic creation before dynlinkd;
authority remains explicit block and VFS peers. Dynamic packaging and
filesystem mirror records are evidence and launch inputs only; they do not
grant filesystem, loader, object-store, service-discovery, provider-bypass,
block-device, or dynlinkd authority. fatd receives only the documented
startup endpoints, peers, and capabilities for its role.
The authenticated startup rendezvous and private provider loop wait without daemon-local tick deadlines. Calls must be authority-free; complete unwanted capability receipts are retired through the shared backpressure-safe local-slot helper before rejection. Uncertain cleanup or terminal retained reply delivery requests process teardown, preventing accepted-call or provider authority from remaining in a quarantined task.
Governance Principles
fatd governance is scoped to private FAT-family and exFAT filesystem service
behind vfsd.
The scoped governance rules are:
- It serves FAT-family media only through the generic private provider ABI.
- It must reject malformed boot sectors, unsafe mirror divergence, invalid allocation metadata, and unsupported partial mounts.
- It performs media mutation only through the provider-local
blockdendpoint. - It never exposes a public
namedservice endpoint or peer-provider authority.
Authority Boundaries
fatdreceives only its provider endpoint and provider-localblockdendpoint.- It does not receive
keyd,deviced, driver, or peer-filesystem authority. - It retains accepted replies through delivery, retires unwanted incoming capability receipts completely, and fails stop through process teardown when cleanup state is uncertain.
Contact
Development occurs in EriX organization and discussions happen in issues and design documents.
No decisions are considered valid without documented rationale.
Maintainers can be reached via email: admin@erikinkinen.fi.