reorg: move vfs-protocol to library/protocol + direct import

vfs-protocol -> library/protocol/vfs/vfs-protocol.zig. fat, its only consumer,
now imports the module directly (const vfs_protocol = @import("vfs-protocol"))
instead of through runtime.vfs_protocol, and the runtime re-export is deleted.
The runtime's own client (runtime.fs) still imports the module by name.

zig build + test green; vfs, fat-mount pass.
This commit is contained in:
Daniel Samson
2026-07-22 20:52:09 +01:00
parent f90dc6c121
commit 25cc4d610e
4 changed files with 26 additions and 27 deletions
+23 -23
View File
@@ -13,7 +13,7 @@ const std = @import("std");
const runtime = @import("runtime");
const engine = @import("engine.zig");
const on_disk = @import("on-disk.zig");
const protocol = runtime.vfs_protocol;
const vfs_protocol = @import("vfs-protocol");
const dma = runtime.dma;
const mount_point = "/mnt/usb";
@@ -69,11 +69,11 @@ fn openAt(id: u64) ?*OpenNode {
return if (o.used) o else null;
}
fn writeReply(out: []u8, reply: protocol.Reply, payload: []const u8) usize {
@memcpy(out[0..protocol.reply_size], std.mem.asBytes(&reply));
const n = @min(payload.len, out.len - protocol.reply_size);
@memcpy(out[protocol.reply_size..][0..n], payload[0..n]);
return protocol.reply_size + n;
fn writeReply(out: []u8, reply: vfs_protocol.Reply, payload: []const u8) usize {
@memcpy(out[0..vfs_protocol.reply_size], std.mem.asBytes(&reply));
const n = @min(payload.len, out.len - vfs_protocol.reply_size);
@memcpy(out[vfs_protocol.reply_size..][0..n], payload[0..n]);
return vfs_protocol.reply_size + n;
}
fn fail(out: []u8) usize {
@@ -183,7 +183,7 @@ fn splitParent(path: []const u8) ParentLeaf {
fn handleOpen(out: []u8, path: []const u8, flags: u32, sender: u32) usize {
var node = filesystem.resolve(path);
if (node == null and flags & protocol.create != 0) {
if (node == null and flags & vfs_protocol.create != 0) {
const split = splitParent(path);
const parent = filesystem.resolve(split.parent) orelse return fail(out);
node = filesystem.createFile(parent, split.leaf);
@@ -191,7 +191,7 @@ fn handleOpen(out: []u8, path: []const u8, flags: u32, sender: u32) usize {
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) {
if (flags & vfs_protocol.truncate != 0 and !resolved.is_directory) {
filesystem.truncate(&resolved);
}
const index = allocOpen() orelse return fail(out);
@@ -202,9 +202,9 @@ fn handleOpen(out: []u8, path: []const u8, flags: u32, sender: u32) usize {
fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.ipc.Handle) usize {
_ = capability;
if (!mounted) return fail(out); // storage not up (yet): fail politely, clients retry
if (message.len < protocol.request_size) return fail(out);
const request = std.mem.bytesToValue(protocol.Request, message[0..protocol.request_size]);
const payload = message[protocol.request_size..];
if (message.len < vfs_protocol.request_size) return fail(out);
const request = std.mem.bytesToValue(vfs_protocol.Request, message[0..vfs_protocol.request_size]);
const payload = message[vfs_protocol.request_size..];
// Stamp create/write with the current wall-clock time (mtime). Cheap, and it
// keeps the engine pure (it takes the time as data, not a syscall).
@@ -214,7 +214,7 @@ fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.i
.open => return handleOpen(out, payload[0..@min(payload.len, request.len)], request.flags, sender),
.read => {
const o = openAt(request.node) orelse return fail(out);
var buffer: [protocol.maximum_payload]u8 = undefined;
var buffer: [vfs_protocol.maximum_payload]u8 = undefined;
const want = @min(@as(usize, request.len), buffer.len);
const n = filesystem.readFile(o.node, @intCast(request.offset), buffer[0..want]);
return writeReply(out, .{ .status = 0, .len = @intCast(n) }, buffer[0..n]);
@@ -227,21 +227,21 @@ fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.i
},
.status => {
const o = openAt(request.node) orelse return fail(out);
const kind: protocol.NodeKind = if (o.node.is_directory) .directory else .regular;
const status = protocol.FileStatus{ .size = o.node.size, .kind = @intFromEnum(kind), .mtime = o.node.mtime };
return writeReply(out, .{ .status = 0, .len = @sizeOf(protocol.FileStatus) }, std.mem.asBytes(&status));
const kind: vfs_protocol.NodeKind = if (o.node.is_directory) .directory else .regular;
const status = vfs_protocol.FileStatus{ .size = o.node.size, .kind = @intFromEnum(kind), .mtime = o.node.mtime };
return writeReply(out, .{ .status = 0, .len = @sizeOf(vfs_protocol.FileStatus) }, std.mem.asBytes(&status));
},
.readdir => {
const o = openAt(request.node) orelse return fail(out);
if (!o.node.is_directory) return writeReply(out, .{ .status = 0, .len = 0 }, &.{});
const listing = filesystem.listEntry(o.node, @intCast(request.offset)) orelse return writeReply(out, .{ .status = 0, .len = 0 }, &.{});
const kind: protocol.NodeKind = if (listing.is_directory) .directory else .regular;
const header = protocol.DirectoryEntry{ .kind = @intFromEnum(kind), .name_len = @intCast(listing.name_len), .size = listing.size };
var buffer: [protocol.maximum_payload]u8 = undefined;
@memcpy(buffer[0..protocol.directory_entry_size], std.mem.asBytes(&header));
const nlen = @min(listing.name_len, buffer.len - protocol.directory_entry_size);
@memcpy(buffer[protocol.directory_entry_size..][0..nlen], listing.name_buffer[0..nlen]);
const total = protocol.directory_entry_size + nlen;
const kind: vfs_protocol.NodeKind = if (listing.is_directory) .directory else .regular;
const header = vfs_protocol.DirectoryEntry{ .kind = @intFromEnum(kind), .name_len = @intCast(listing.name_len), .size = listing.size };
var buffer: [vfs_protocol.maximum_payload]u8 = undefined;
@memcpy(buffer[0..vfs_protocol.directory_entry_size], std.mem.asBytes(&header));
const nlen = @min(listing.name_len, buffer.len - vfs_protocol.directory_entry_size);
@memcpy(buffer[vfs_protocol.directory_entry_size..][0..nlen], listing.name_buffer[0..nlen]);
const total = vfs_protocol.directory_entry_size + nlen;
return writeReply(out, .{ .status = 0, .len = @intCast(total) }, buffer[0..total]);
},
.close => {
@@ -287,7 +287,7 @@ fn onMessage(message: []const u8, out: []u8, sender: u32, capability: ?runtime.i
}
pub fn main() void {
runtime.service.run(protocol.message_maximum, .{
runtime.service.run(vfs_protocol.message_maximum, .{
.service = .fat,
.init = initialise,
.on_message = onMessage,