fatd is the private FAT filesystem provider daemon for EriX
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Erik Inkinen 6c6f1bdf75
All checks were successful
CI / markdown (push) Successful in 12s
CI / test (push) Successful in 1m57s
chore: Merge native CLI development into main
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: 30f974d061
Selected feature: 7685c07da6

Publish this integration point following the requested cross-repository merge. Preserve the feature branch and immutable dependency objects for reproducibility; do not squash, rebase or rewrite existing commits.
2026-09-12 08:28:43 +03:00
.github build: Pin dependency and CI helper source commits 2026-09-12 07:37:08 +03:00
src fix: Distinguish storage failures from missing FAT paths 2026-09-08 05:42:12 +03:00
.editorconfig Initial commit 2026-04-26 08:06:37 +02:00
.gitignore Initial commit 2026-04-26 08:06:37 +02:00
.markdownlint-cli2.yaml Tighten CI markdown policy 2026-05-22 15:10:01 +03:00
ARCHITECTURE.md fix: Distinguish storage failures from missing FAT paths 2026-09-08 05:42:12 +03:00
Cargo.toml build: Pin dependency and CI helper source commits 2026-09-12 07:37:08 +03:00
CODE_OF_CONDUCT.md docs: Synchronize shared contribution and review policies 2026-09-12 06:38:11 +03:00
CONTRIBUTING.md build: Pin dependency and CI helper source commits 2026-09-12 07:37:08 +03:00
LICENSE Initial commit 2026-04-26 08:06:37 +02:00
linker.ld fix: keep filesystem state below the process stack 2026-07-29 08:39:37 +03:00
README.md build: Pin dependency and CI helper source commits 2026-09-12 07:37:08 +03:00
ROADMAP.md fix: Distinguish storage failures from missing FAT paths 2026-09-08 05:42:12 +03:00
rustfmt.toml Initial commit 2026-04-26 08:06:37 +02:00
SECURITY.md docs: Synchronize shared contribution and review policies 2026-09-12 06:38:11 +03:00

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 blockd endpoint
  • keep provider authority private with no named entry 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 blockd endpoint.
  • It never exposes a public named service endpoint or peer-provider authority.

Authority Boundaries

  • fatd receives only its provider endpoint and provider-local blockd endpoint.
  • 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.