volume-manager: the volumes query verb — read a volume's id, path, and label (S2)

The mechanism the id/label split needs: a `volumes` verb whose reply packs the
mounted volume's {id, mount_path, label} into the tail (VolumeInfo.encode/decode
— three length-prefixed strings). Software keys on the id (the mount path is
/volumes/<id>); a shell or file manager shows the label — the database id/name
split made a query. The VM's onVolumes answers from the mounted volume, empty
reply if none. Two host round-trip tests (encode/decode; too-small buffer and
short-tail rejection). No runtime consumer yet — the first is a userspace shell;
the hello handshake is unaffected (fat-mount/volume-probe green).
This commit is contained in:
Daniel Samson
2026-08-10 00:17:22 +01:00
parent 167e9c7a9e
commit f1e79d0eeb
2 changed files with 97 additions and 1 deletions
@@ -348,7 +348,24 @@ fn onHello(_: void, invocation: Invocation(volume_manager_protocol.Hello), _: An
return 0;
}
const handlers = Serve.Handlers{ .hello = onHello };
/// Answer a `volumes` query with the mounted volume's descriptor — its id (its
/// mount path is /volumes/<id> unless overridden), its actual mount path, and
/// its display label. This is how a shell or file manager reads a volume's
/// friendly name: software keys on the id, a UI shows the label. An empty reply
/// means no volume is mounted.
fn onVolumes(_: void, _: Invocation(volume_manager_protocol.Volumes), answer: Answer(void)) isize {
const v = volume orelse return 0;
var id_buf: [volume_map.id_maximum]u8 = undefined;
const info = volume_manager_protocol.VolumeInfo{
.id = volume_map.idString(v.identity, &id_buf),
.mount_path = v.mount_prefix,
.label = v.identity.labelSlice(),
};
const encoded = info.encode(answer.tail()) orelse return 0;
return @intCast(encoded.len);
}
const handlers = Serve.Handlers{ .hello = onHello, .volumes = onVolumes };
fn onMessage(message: []const u8, out: []u8, sender: u32, arrived: *ipc.Arrival) usize {
// No verb takes a capability up, so the turn closes whatever arrives.