summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-10-01 06:26:46 -0300
committerGabriel Schneider <[email protected]>2026-10-01 07:16:43 -0300
commita88139a012939be9394014f483f6920a6e6d3a53 (patch)
treed1748fcf3aa0ed576954e076955ac202f65ff83c
parent4195c285e860435b1251d010422831ec137d7e60 (diff)
downloadpardes-a88139a012939be9394014f483f6920a6e6d3a53.tar.gz
pardes-a88139a012939be9394014f483f6920a6e6d3a53.zip
A refused /pager write leaves its open no answer, not the +Pager it answered before
writePager emptied the answer only once the directory had passed, so a read after a refused write on the same open still gave the last write's serial. It is emptied first, as a refused look or exec leaves none. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/ninep/ctl.zig6
1 files changed, 5 insertions, 1 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index f0dab28d..89d438df 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -648,6 +648,8 @@ pub fn readRoot(p: *Pardes, req: Req) Reply {
/// session's) gets its one +Pager, made or emptied; the serial is what a
/// read of this same open answers, never another client's.
pub fn writePager(p: *Pardes, req: Req) Reply {
+ // A refused write leaves its open no answer, not the last one's.
+ p.fs.results_len = 0;
var it = Messages.init(p, req.data);
const line = it.next() orelse "";
// Words 9ns maps back to EINVAL (`invalid`), as every refusal here.
@@ -661,7 +663,6 @@ pub fn writePager(p: *Pardes, req: Req) Reply {
}
if (comptime pardes.hosted) if (dir.len > 0) if (pardes.filesystem.localPath(dir)) |local| if (!exec_line.isDirectory(local))
return tree.failText(req.tag, E.NOENT, std.fmt.bufPrint(&p.fs.ename, "pager: {s}: no such directory", .{dir[0..@min(dir.len, 256)]}) catch "pager: no such directory");
- p.fs.results_len = 0;
const id = pardes.panes.Output.openPager(p, p.active, dir) catch |err|
return tree.failText(req.tag, if (err == error.NoPaneRoom or err == error.NoPaneSlots) E.NOSPC else E.IO, switch (err) {
error.NoPaneRoom, error.NoPaneSlots => "pager: no space for a +Pager pane",
@@ -4045,6 +4046,9 @@ test "pager answers its +Pager on the open that asked, whatever another client e
// `pardes -` once read, and wrote its text into.
try testing.expect(!std.mem.eql(u8, want, rd(p, exec, 0, 64).bytes));
try testing.expectEqualStrings(want, call(p, .{ .tag = 5, .op = .read, .node = pager, .handle = asked, .size = 64 }).bytes);
+ // Refused, the same open answers nothing, not its last answer.
+ try testing.expectEqual(E.INVAL, call(p, .{ .tag = 6, .op = .write, .node = pager, .handle = asked, .data = "relative\n" }).errno());
+ try testing.expectEqualStrings("", call(p, .{ .tag = 7, .op = .read, .node = pager, .handle = asked, .size = 64 }).bytes);
// One directory a write, absolute, and there.
try testing.expectEqual(E.INVAL, wr(p, pager, "/a\n/b\n").errno());
const relative = wr(p, pager, "relative\n");