danos/docs/file-system-development/file-system-hierarchy.md

8.3 KiB

The danos file-system hierarchy

danos is not unix, and its tree does not follow the unix FHS. Paths are the system's universal namespace — files, the device inventory, and protocol endpoints all live in one tree — but what a path yields differs by subtree: bytes, facts, or a connection. Root path resolution is provided by the kernel-resident VFS root (fs_resolve, system/kernel/vfs.zig); mounted backends serve the subtrees they own.

Naming follows the codebase conventions: kebab-case, full words, no abbreviations. Every top-level name says what its subtree is.

The tree

Path What it is
/ The root of the one namespace.
/applications Installed applications, one directory per application — the directory is the identity, the same rule as source sub-projects. (Planned; empty today.)
/protocol The contract namespace: one protocol node per contract, grouped into directories by domain (/protocol/display, /protocol/networking/ip). Synthetic — no bytes; opening a name yields a connection to the current provider. See protocol-namespace.md.
/system The operating system — what danos is. Its program subtrees mirror the source tree exactly.
/system/kernel The kernel image.
/system/drivers Driver binaries, one per sub-project (/system/drivers/pci-bus, /system/drivers/ps2-bus).
/system/services System-service binaries (/system/services/init, /system/services/fat).
/system/devices The device inventory: every node hardware discovery found, with its resources and parent — the structures of the devices module, as a browsable virtual tree. Informational only; you read about hardware here and talk to it through /protocol. (Planned; served by device-manager.)
/system/configuration Machine configuration (init.csv, devices.csv). Writable, served from the boot volume.
/system/logs Per-boot logs: /system/logs/<boot-stamp>/<binary-path>.log. Writable, served from the boot volume.
/test Test fixtures for the QEMU integration suite. Read-only and initrd-backed like the program subtrees of /system, mirroring the repo's test/ directory. Present on development and test images; a volume without it still boots.
/volumes Attached storage volumes, one directory per volume (/volumes/usb). A volume's own tree appears beneath its name.

Read-only and writable halves of /system: the program subtrees (kernel, drivers, services) and the future devices are immutable at runtime — initrd-backed or synthetic — while configuration and logs are mutable machine state served by the boot-volume FAT backend. The kernel's reserved-prefix rule (no mount may shadow /system, /test, or /protocol) needs a carve-out for exactly these two writable subtrees; that lands with the path migration below.

Deliberately not defined yet: a temporary-files location and per-application mutable storage. Both belong to the /applications design and will be specified there, not guessed at here.

Node kinds

What a path resolves to. These fill FileStatus.kind and DirectoryEntry.kind in the vfs protocol (library/protocol/vfs/vfs-protocol.zig); enum values are append-only.

Kind Meaning
regular An ordinary file: an uninterpreted byte stream, positional reads and writes, grows on demand.
directory A container mapping names to nodes; modified only through directory operations.
character_device A node whose read/write have stream semantics: unseekable, reads block until bytes exist, size is meaningless. The console and every tty-shaped node (character-devices-and-tty.md); what a POSIX layer's isatty detects.
block_device A node addressed in fixed-size sectors — a raw volume. Reserved: recognized, nothing serves one yet.
symbolic_link Reserved: a recognized value, not implemented by any backend.
fifo Reserved for the future pipe object (wanted by the POSIX compatibility layer); not implemented.
protocol A node naming a contract: open yields an IPC connection (an endpoint capability) instead of a file id — the kind of every leaf under /protocol. (Being added; see protocol-namespace.md.)

Note the layering: protocol says what opening the name does (you get a conversation); character_device/block_device say what read and write mean on a node a provider serves you. The two compose — /protocol/console is a protocol node in the registry, and the node opened over that connection reports character_device, which is what gives it stream semantics. Only socket is retired (its value stays reserved for wire stability): a named rendezvous point is exactly what a protocol node is.

What is deliberately absent

There is no /bin, /boot, /dev, /etc, /home, /lib, /mnt, /sbin, /srv, /tmp, /usr, or /var. These encode unix history — the binary/library split of small disks, configuration-as-scattered-text, devices as magic files — that danos does not carry. A POSIX compatibility layer (the Python track's mini-libc) may present whichever of these its programs expect, mapped onto the real tree; the tree itself stays danos-native.

Migration

The tree above is the specification; some code still writes the unix paths it replaced. The flag-day converting them:

Today (in code) Becomes Where
/etc/init.csv /system/configuration/init.csv system/services/init/init.zig
/etc/devices.csv /system/configuration/devices.csv system/services/device-manager/device-manager.zig
/var/log/... /system/logs/... system/services/logger/logger.zig, the FAT server's /var mount
/mnt/usb /volumes/usb system/services/fat/fat.zig, the fat/vfs tests
ServiceId lookup resolve + open under /protocol every service and client; protocol-namespace.md

The boot-image builder and the on-volume directory layout move in the same change, so a freshly written image and the paths the services expect never disagree.