Phase 2a: FAT engine mutations + O_TRUNC (fix the overwrite corruption)
The FAT engine could create, read, write, and grow files, but never free clusters or make directories — so overwriting a shorter file left a stale tail (a real bug: corrupt boot-log re-flushes, and later corrupt compiler cache/.o files). This adds the mutation half of the engine, with the corruption fix wired all the way through. Engine (system/services/fat/engine.zig), all host-tested: - freeChain: return a cluster chain to the pool (bounded against a corrupt cycle) — the shared primitive under truncate and remove. - truncate: free the chain and zero the entry's size/first-cluster (O_TRUNC). - createDirectory (mkdir): allocate + initialise a cluster with "." and ".." and add the directory entry to the parent. - removeFile (unlink): free the chain and mark the 8.3 entry plus any preceding long-name entries deleted, so a reused slot can't inherit an orphaned long name. Refuses directories. - createFile now shares a common addEntry helper with createDirectory. O_TRUNC wired end to end: a truncate open-flag (vfs protocol) that the router already forwards; runtime.fs.OpenOptions.truncate; and fat's handleOpen calls engine.truncate on an existing file. The boot-log flush (log-flush + init) now opens with truncate, so a shorter log on a later boot of the same stick leaves no stale tail — closing the caveat from the boot-log work. mkdir/unlink are engine-complete and host-tested but not yet exposed as VFS operations / runtime.fs methods (they are new path-based ops needing router cases); rename and the richer stat (mtime/mode, blocked on wall-clock) remain. See docs/zig-self-hosting.md (Phase 2). Verified: zig build, zig build test (8 engine host tests, incl. truncate, the overwrite-no-stale-tail regression, remove, and mkdir), zig build check-fat-image, and a sequential QEMU sweep — fat-mount, log-flush (DANOS.LOG read back at 11804 bytes, clean, with the truncate-based final flush), vfs, vfs-client-death, usb-storage, orderly-shutdown, initial-ramdisk, smoke — all green.
This commit is contained in:
@@ -82,11 +82,15 @@ pub const reply_size: usize = @sizeOf(Reply);
|
||||
/// Largest inline payload that still fits one IPC message alongside a header.
|
||||
pub const maximum_payload: usize = message_maximum - request_size;
|
||||
|
||||
/// Open flags (danos-native; the POSIX layer maps `O_CREAT` onto `create`).
|
||||
/// Open flags (danos-native; `runtime.fs.OpenOptions` maps its booleans onto these).
|
||||
pub const create: u32 = 1;
|
||||
/// Open a directory (for readdir) rather than a file. A mounted backend uses
|
||||
/// this to open a directory node; the flat ramfs ignores it.
|
||||
pub const directory: u32 = 2;
|
||||
/// Truncate the file to zero length on open (O_TRUNC): replace its contents rather
|
||||
/// than overwriting in place, so a shorter new file leaves no stale tail. A mounted
|
||||
/// backend frees the old cluster chain; the flat ramfs ignores it.
|
||||
pub const truncate: u32 = 4;
|
||||
|
||||
test "protocol struct sizes and node kinds" {
|
||||
const std = @import("std");
|
||||
|
||||
Reference in New Issue
Block a user