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.