From 30bfe8143c5e3840275880d77e9765cf94910ee1 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Wed, 30 Sep 2026 14:05:41 -0300 Subject: A tag write over the limit is refused "no space: over 4096 bytes", so its err record says tag: once The refusal's text began with "tag: ", and the log's err record puts the file's name before the reason. So the record read `err - col/1/tag: tag: no space: over 4096 bytes`. The text is now the reason alone, as the control-character refusal's is, and the record names the file once. Co-Authored-By: Claude Opus 5.5 --- docs/fs.md | 2 +- src/ninep/cols.zig | 5 ++++- src/ninep/pane.zig | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/fs.md b/docs/fs.md index c7ef0857..7a4ce0b3 100644 --- a/docs/fs.md +++ b/docs/fs.md @@ -349,7 +349,7 @@ blank matters; `echo` would start a second line). A pane tag may hold several lines; a column or workspace tag is one, a newline written into it becoming a space. Control characters other than tab, DEL, C1 controls and non-UTF-8 bytes are refused (`invalid tag text`). The editable text is at -most 4096 bytes (`tag: no space: over 4096 bytes`, ENOSPC). All three kinds +most 4096 bytes (`no space: over 4096 bytes`, ENOSPC; the log says `err tag: no space: ...`). All three kinds take the same checks, whole or not at all, and a `>` whose write is refused changes nothing: its truncation is done with the write that fits, or at the close (or a read) when none came. A clear is an ordinary edit diff --git a/src/ninep/cols.zig b/src/ninep/cols.zig index 24fb590c..9185a2bc 100644 --- a/src/ninep/cols.zig +++ b/src/ninep/cols.zig @@ -500,7 +500,10 @@ test "a refused write after a truncation leaves every kind of tag as it was, and const h = th.call(p, .{ .tag = 2, .op = .open, .node = node, .omode = 1 }).reply.handle; const r = th.call(p, .{ .tag = 3, .op = .write, .node = node, .handle = h, .data = big }); try testing.expectEqual(E.NOSPC, r.errno()); - try testing.expectEqualStrings("tag: no space: over 4096 bytes", r.reply.ename); + try testing.expectEqualStrings("no space: over 4096 bytes", r.reply.ename); + // Its err record names the file once: `tag: no space`, never `tag: tag:`. + try testing.expect(th.logHas(p, "tag: no space: over 4096 bytes")); + try testing.expect(!th.logHas(p, "tag: tag:")); _ = th.call(p, .{ .tag = 4, .op = .release, .node = node, .handle = h, .opened = true }); try testing.expectEqualStrings(before, th.rd(p, node, 0, 1 << 16).bytes); // A control character is refused the same way on every kind. diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig index de7f7cd4..dc8b4b10 100644 --- a/src/ninep/pane.zig +++ b/src/ninep/pane.zig @@ -639,7 +639,7 @@ pub fn tagFault(data: []const u8) ?[]const u8 { /// A tag write's limit, the same for a pane's, a column's and the /// workspace's: whole or not at all. -pub const e_tag_over = std.fmt.comptimePrint("tag: no space: over {d} bytes", .{limits.max_tag_tail}); +pub const e_tag_over = std.fmt.comptimePrint("no space: over {d} bytes", .{limits.max_tag_tail}); fn writeTag(p: *Pardes, req: Req, pane: *Pane) Reply { if (req.data.len == 0) return .{ .tag = req.tag, .written = 0 }; @@ -1314,7 +1314,7 @@ test "a tag write past the limit is refused whole, naming the limit" { try testing.expectEqual(E.NOSPC, r.errno()); // `no space` is what 9ns maps to ENOSPC, so a shell through a mount // sees the errno the tree gives. - try testing.expect(std.mem.startsWith(u8, r.reply.ename, "tag: no space: over ")); + try testing.expect(std.mem.startsWith(u8, r.reply.ename, "no space: over ")); try testing.expectEqualStrings(before, rd(p, tag, 0, 1 << 16).bytes); } -- cgit v1.3