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:
@@ -124,7 +124,12 @@ fn handleOpen(out: []u8, path: []const u8, flags: u32) usize {
|
||||
const parent = filesystem.resolve(parent_path) orelse return fail(out);
|
||||
node = filesystem.createFile(parent, leaf);
|
||||
}
|
||||
const resolved = node orelse return fail(out);
|
||||
var resolved = node orelse return fail(out);
|
||||
// O_TRUNC: replace an existing file's contents rather than overwriting in place
|
||||
// (frees the old chain, so a shorter rewrite leaves no stale tail).
|
||||
if (flags & protocol.truncate != 0 and !resolved.is_directory) {
|
||||
filesystem.truncate(&resolved);
|
||||
}
|
||||
const index = allocOpen() orelse return fail(out);
|
||||
open_nodes[index] = .{ .used = true, .node = resolved };
|
||||
return writeReply(out, .{ .status = 0, .node = index }, &.{});
|
||||
|
||||
Reference in New Issue
Block a user