Skip to content

ARCHITECTURE · 15

Image formats.

Every payload image is a file. Its format answers exactly one question, how to read these bytes, and nothing else; what a payload is, whether it is a runtime, and where its entrypoint lives are manifest semantics that never touch the format id.

Note

Six in-tree formats are shipped, with LimniFS the default write format since v0.2.0 and magic detection authoritative.

The pure-Rust runtime line (backend-limnifs only) is a recorded goal on its own release line, and it is planned.

The format_id axis

The format_id is a 32-bit field in each trailer slot record, and it is a hint. Magic detection on the actual bytes is authoritative; a slot stamped 5 whose bytes do not open with LMFS mounts as what the magic says. Ids ≥ 6 are unallocated.

ID FORMAT READER TOOLCHAIN STATUS

0

auto

Magic detection decides.

—

It is the hint value that defers to the bytes.

1

dwarfs

dwarfs-t (FlatBuffers metadata)

C++ (vcpkg/cmake)

It is a first-class read backend, with an explicit --format dwarfs write opt-in.

2

squashfs

squashfs-tools-ng

C (POSIX-only today)

It is a read backend.

3

zip

pure Rust

none

It is a read backend.

4

—

It is never mounted.

—

It is a legacy runtime-role wart: never reused and never given new meaning.

5

limnifs

limnifs-core, #![forbid(unsafe_code)]

pure Rust, zero system deps

It is the default write format, and it reads everywhere.

Id 4 is the v1 wart: a runtime role smuggled into the format field so that v1 loaders skip handing the runtime slot over as a mount. It is kept for backward compatibility and never reused; roles live in manifests, and new semantics are never again smuggled into the format axis. The documented deviation is locked: the reference C99 reader keeps its bound at 4 and rejects a format-5 slot with its named invalid error, which is fail-closed and correct, since a v1-era reader cannot read limnifs bytes.

Detection: strong magic first, weak heuristics last

Detection uses one 512-byte sniff window and one locked probe order. Every mount, a host file, memory, a file-region (offset+length), or a VFS-file-region (an image addressed by a path inside an existing mount, read through the owning mount’s pread), serves one byte-slice core.

# MAGIC FORMAT

1

PK\x03\x04 / PK\x05\x06

zip

2

DWARFS

dwarfs

3

hsqs

squashfs

4

LMFS

limnifs — disjoint 4-byte prefix against every arm above

5

\x1f\x8b\x08 · \x28\xb5\x2f\xfd

tar envelopes (gzip, zstd)

6

header-checksum heuristic

tar — always LAST (weak)

7

—

Unknown magic answers EINVAL at mount.

Compile separation: a build ships exactly the formats it must read

Backends compile in per cargo feature. The enc transform feature is orthogonal, and it stacks over any backend.

FEATURE BACKEND TOOLCHAIN

backend-dwarfs-t

dwarfs-t (FlatBuffers)

C++ (vcpkg/cmake via dwarfs-t-rs)

backend-squashfs

squashfs

C (squashfs-tools-ng; POSIX-only today)

backend-zip

zip

pure Rust

backend-tar

tar (+ gz/zst envelopes)

pure Rust

backend-limnifs

limnifs

pure Rust, #![forbid(unsafe_code)], no system deps

The per-product defaults are the following: the packager and human tools (tebako-cli, tfs-cli, tebako-pkg) ship all backends; the driver inside every runtime exe and the preload shim ship all backends, so any package runs on any runtime; and the bootstrap ships no backend, ever, because it never mounts, stays format-agnostic, and stays inside its size gate. The compiled-out rule is locked: a mount whose detected format has no compiled-in backend fails with the named ENOTSUP, naming the format, and there is never a silent re-route, a partial read, or a crash.

Why LimniFS is the default

The default is the format every payload takes when the operator says nothing, so it must be the one with the least toolchain exposure, the least build cost, and no loss of capability.

1. Pure Rust, #![forbid(unsafe_code)], zero system dependencies —
   reading AND writing the default format needs no C++ toolchain,
   no vcpkg, no cmake
2. Build wall-clock: limnifs-core compiles everywhere Rust compiles,
   semver-pinned from crates.io — the dwarfs-t vcpkg ports were the
   CI cost driver (per-target C++ cross-compilation)
3. Content-addressed: every drop is BLAKE3(plaintext) — image-internal
   integrity and dedup come from the format, not bolted-on machinery
4. Read efficiency: on-demand per-class decompression; inline drops
   serve small files straight from the metadata blob, no slab access
5. Unambiguous detection: the strong LMFS magic is disjoint from
   every existing probe arm
6. Nothing else changes: existing dwarfs packages, runtimes, and
   payload artifacts are untouched; dwarfs stays a first-class
   explicit --format dwarfs opt-in and a supported read backend
   forever

Both writer entry points, tfs mkimage and tebako press, default to limnifs and work fully in-process, with no limni or mkdwarfs binary, no PATH lookup, and no shell-out. While the published runtime fleet’s readers span pre-fix limnifs lines, the writers pin a floor-safe recipe (no shared-inline dedup, lz4-HC metadata, lz4-or-store content drops), and every constraint names its lift condition, a factory runtime cut whose link unit carries limnifs-core ≥ 0.2.53. A payload written outside the constraints is not rejected; it is simply below the floor’s guarantee, so it may mount on newer readers and fail closed, by name, on older ones.

Read-only at runtime, forever

The transforms law binds every backend: no format backend learns to write, creation-time writers are the only write path, and COW and ENC stack above as transforms. Writes to a read-only mount fail EROFS at the mode gate, above the backend, and TEBAKO_MOUNT_RW stays ENOTSUP in-tree. LimniFS’s own AEAD-sealed images are an image-format concern; a mount of one without key support fails ENOTSUP by name, and tebako-side encryption stays the stacking transform. The in-image manifest never names a format: payload artifacts stay .tfs-named and byte-identical with the registry artifact whatever the backend.