Phase 2c: rename, wired through the VFS to runtime.fs
Completes the Phase 2 FAT mutation set (truncate, mkdir, unlink, rename). - engine: rename(dir, old_name, new_name) rewrites an existing entry's 8.3 name in place within the same directory. Refuses a missing source, a non-8.3 target, or a name that already exists; drops any long-name entries on the old file (it takes its new 8.3 name), LFN-aware like removeFile. Cross-directory and long-name- preserving rename are noted limitations. Host-tested (rename keeps contents; collision, non-8.3, and missing-source are refused). - vfs protocol: a `rename` operation whose payload is old-path, a 0x00 separator, then new-path. - VFS router: a forwardRename helper + a `.rename` case that requires both paths under the same mount (cross-filesystem rename is refused) and forwards the mount-relative old+new. - fat server: a `.rename` handler that requires the same parent directory and calls engine.rename. - runtime.fs: rename(old_path, new_path). - fat-test now renames the file it created (before removing it) and asserts the old name is gone, behind a new `fat-rename` QEMU case. Verified: zig build, zig build test (the engine rename unit test), zig build check-fat-image, and a sequential QEMU sweep — fat-mount, fat-mutations, fat-rename, vfs, vfs-client-death, log-flush, orderly-shutdown, initial-ramdisk, smoke — green.
This commit is contained in:
@@ -202,6 +202,17 @@ fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.i
|
||||
if (!filesystem.removeFile(parent, split.leaf)) return fail(out);
|
||||
return writeReply(out, .{ .status = 0 }, &.{});
|
||||
},
|
||||
.rename => {
|
||||
const both = payload[0..@min(payload.len, request.len)];
|
||||
const sep = std.mem.indexOfScalar(u8, both, 0) orelse return fail(out);
|
||||
const old_split = splitParent(both[0..sep]);
|
||||
const new_split = splitParent(both[sep + 1 ..]);
|
||||
// Same-directory rename only.
|
||||
if (!std.mem.eql(u8, old_split.parent, new_split.parent)) return fail(out);
|
||||
const parent = filesystem.resolve(old_split.parent) orelse return fail(out);
|
||||
if (!filesystem.rename(parent, old_split.leaf, new_split.leaf)) return fail(out);
|
||||
return writeReply(out, .{ .status = 0 }, &.{});
|
||||
},
|
||||
// A backend is never itself a mount target.
|
||||
.mount, .unmount => return fail(out),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user