summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.agents/skills/pardes-9p/SKILL.md2
-rw-r--r--docs/fs.md6
-rw-r--r--src/ninep/addr.zig3
-rw-r--r--src/ninep/pane.zig12
4 files changed, 13 insertions, 10 deletions
diff --git a/.agents/skills/pardes-9p/SKILL.md b/.agents/skills/pardes-9p/SKILL.md
index cc129d5c..feb4f703 100644
--- a/.agents/skills/pardes-9p/SKILL.md
+++ b/.agents/skills/pardes-9p/SKILL.md
@@ -234,7 +234,7 @@ and a search that backtracks
past a step budget (about 300 ms) fails with `regular expression search
gave up, ...`. A failed address says
why (`no match for regexp`, `address out of range`) and leaves no address:
-`data` refuses until the next good one, so a missed target is never
+`addr` reads empty and `data` refuses until the next good one, so a missed target is never
written at the old one. Moving `dot` scrolls the pane to it. `limit` bounds
only the end of a forward search, as in acme, and reads empty until set;
truncate it to lift it. In `12:5` the column counts bytes from 1 and clamps
diff --git a/docs/fs.md b/docs/fs.md
index c9d5356d..fc5a8586 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -563,9 +563,9 @@ expression`, `regular expression search gave up, ...`, or sam's
`addresses out of order` for a range that ends before it starts
(`#100,#50`), which acme lets through. A failed write to `addr` leaves no
address at all, where acme
-keeps the old one: until a good address is written,
-reading `addr`, and reading, writing or truncating `data` and `xdata`, fail
-with `no address: the last one written to addr failed`, so a script that
+keeps the old one: until a good address is written, `addr` reads empty
+(as an unset `limit` does), and reading, writing or truncating `data` and
+`xdata` fail with `no address: the last one written to addr failed`, so a script that
missed its target cannot then write at the last one.
The three flag files `dirty`, `mark` and `scroll` read `0` or `1` and take
diff --git a/src/ninep/addr.zig b/src/ninep/addr.zig
index e731ba24..15f23a55 100644
--- a/src/ninep/addr.zig
+++ b/src/ninep/addr.zig
@@ -373,7 +373,8 @@ test "a failed address leaves none, so data refuses rather than act at the last
try testing.expectEqualStrings(e_no_match, th.wr(p, addr, "/zzz/").reply.ename);
try testing.expectEqualStrings(pane_files.e_addr_failed, th.wr(p, data, "ONE").reply.ename);
try testing.expectEqualStrings(pane_files.e_addr_failed, th.rd(p, data, 0, 64).reply.ename);
- try testing.expectEqualStrings(pane_files.e_addr_failed, th.rd(p, addr, 0, 64).reply.ename);
+ try testing.expectEqual(Status.ok, th.rd(p, addr, 0, 64).reply.status);
+ try testing.expectEqualStrings("", th.rd(p, addr, 0, 64).bytes);
try testing.expectEqual(E.INVAL, th.call(p, .{ .tag = 1, .op = .setattr, .node = Node.of(serial, .xdata), .truncate = true }).errno());
try testing.expectEqualStrings("one\ntwo\n", p.panes[0].?.file.?.content);
// A good address gives it one again; truncating addr does not.
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig
index e7b72c88..3307eb47 100644
--- a/src/ninep/pane.zig
+++ b/src/ninep/pane.zig
@@ -250,7 +250,8 @@ pub fn fileSize(p: *Pardes, id: usize, f: PaneFile) u64 {
const d = dotOf(pane);
break :sel @max(d.q0, d.q1) - d.q0;
},
- .addr, .dot => range_len,
+ .addr => if (pf.addr_failed) 0 else range_len,
+ .dot => range_len,
.limit => if (pf.limit == null) 0 else range_len,
.dirty, .mark, .scroll => 2,
.look, .exec => ctl.resultsLen(p),
@@ -308,11 +309,12 @@ pub fn read(p: *Pardes, req: Req, id: usize, pane: *Pane, file: PaneFile) Reply
break :tag tree.stagedReply(p, req);
},
.ctl => ctl.readPane(p, req, pane),
- .addr => addr: {
- if (pf.addr_failed) break :addr tree.failText(req.tag, E.INVAL, e_addr_failed);
+ // A failed address reads empty, as an unset limit does: there is
+ // none. data and xdata are what refuse.
+ .addr => readRange(p, req, if (pf.addr_failed) null else addr: {
clampAddr(pf, bodyOf(pane).len);
- break :addr readRange(p, req, pf.addr);
- },
+ break :addr pf.addr;
+ }),
.dot => readRange(p, req, dotOf(pane)),
.limit => readRange(p, req, pf.limit),
.data => readData(req, id, pane, pf, false),