summaryrefslogtreecommitdiff
path: root/src/ninep/tree.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 18:07:08 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit01bf4ed09423b3c7e01598ff3a844cc3c12c3ff2 (patch)
tree62a6f8c331cd1d35c60a948a25a84319ae0d4b3b /src/ninep/tree.zig
parentf65cb652243bf0a63eecdd4d6c5cd8ccbc3fd2ea (diff)
downloadpardes-01bf4ed09423b3c7e01598ff3a844cc3c12c3ff2.tar.gz
pardes-01bf4ed09423b3c7e01598ff3a844cc3c12c3ff2.zip
A name written whole with no newline is checked with its write, as the docs now say, not at the close
Round 24's no-newline rule (uwzuqzxp) already covers name, a lines file; the 9P monkey's close_runs_only_line_files repros were from a binary before it. This pins it with a test and corrects docs/fs.md, which still said such a name waited for the close. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/tree.zig')
-rw-r--r--src/ninep/tree.zig9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/ninep/tree.zig b/src/ninep/tree.zig
index 6d09b9a6..94fa5d1e 100644
--- a/src/ninep/tree.zig
+++ b/src/ninep/tree.zig
@@ -1039,7 +1039,7 @@ fn linesFile(target: Target) bool {
.top => |f| f == .look or f == .exec or f == .ctl or f == .tagexec,
.col => |c| c.file == .ctl or c.file == .exec,
// `name` too: one name, however its writes cut it, applied once
- // its newline or its close comes.
+ // its newline comes, or with its write when that is whole.
.pane => |t| t.file == .look or t.file == .exec or t.file == .ctl or t.file == .tagexec or t.file == .name,
};
}
@@ -1634,6 +1634,13 @@ test "a write with no newline, whole in its Twrite, runs then and fails the writ
const r = call(p, .{ .tag = 7, .op = .open, .node = root_ctl, .omode = 1 }).reply.handle;
try testing.expectEqual(Status.err, call(p, .{ .tag = 8, .op = .write, .node = root_ctl, .handle = r, .data = "bogus" }).reply.status);
_ = call(p, .{ .tag = 9, .op = .release, .node = root_ctl, .handle = r, .opened = true });
+ // And a name: a bad one fails its write, not the close after it.
+ const name = Node.of(serial, .name);
+ const n = call(p, .{ .tag = 10, .op = .open, .node = name, .omode = 1 }).reply.handle;
+ const bad = call(p, .{ .tag = 11, .op = .write, .node = name, .handle = n, .data = "delete " });
+ try testing.expectEqual(Status.err, bad.reply.status);
+ try testing.expect(std.mem.indexOf(u8, bad.reply.ename, "a blank at its end") != null);
+ try testing.expectEqual(Status.ok, call(p, .{ .tag = 12, .op = .release, .node = name, .handle = n, .opened = true }).reply.status);
}
test "look and exec read back what their own open's write touched; a fresh open reads the session's last" {