summaryrefslogtreecommitdiff
path: root/src/ninep/ctl.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 23:03:35 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commita628330543d1c2a0b29062036f23b1c74e4ccc6e (patch)
tree69a223c58586130d1c37b96debed58cddc0131d8 /src/ninep/ctl.zig
parent1ab1d412e2768d9fe56a9e97ab60716a6d31063a (diff)
downloadpardes-a628330543d1c2a0b29062036f23b1c74e4ccc6e.tar.gz
pardes-a628330543d1c2a0b29062036f23b1c74e4ccc6e.zip
A builtin refused when its record is written back through event fails that write, EIO and its err, as fs.md says
A Del refused over unsaved text, written back by an event reader, said so on the message row and answered the write ok, so the script that wrote it could not tell. The write-back now captures failures as an exec write does: the first one fails the write with its words and the errno they read as. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/ctl.zig')
-rw-r--r--src/ninep/ctl.zig21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 31265a94..aa309ad1 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -296,7 +296,7 @@ pub fn captured(p: *Pardes, req: Req, id: usize, exec: bool, text: []const u8, i
/// The errno a builtin's failure answers with: ENOENT for what is not
/// there (`no such`, `not found`, the words 9ns reads as ENOENT too), else
/// EIO.
-fn failureErrno(failure: []const u8) u16 {
+pub fn failureErrno(failure: []const u8) u16 {
if (std.mem.indexOf(u8, failure, "no such") != null or std.mem.indexOf(u8, failure, "not found") != null) return E.NOENT;
// A pattern refused (Edit's too) is malformed input, as 9ns reads it;
// so is a word this build has not (`invalid: acme's Put ...`).
@@ -1760,6 +1760,25 @@ test "exec Save writes the named file through the host" {
try testing.expectEqualStrings(pane.file.?.content, p.fallback.get("/tmp/renamed.txt").?);
}
+test "a refused Del written back through event fails that write, EIO, with its err" {
+ const gpa = testing.allocator;
+ const p = try withFile(gpa, "text\n");
+ defer p.deinit();
+ const serial = serialOf(p);
+ try testing.expectEqual(Status.ok, wr(p, Node.of(serial, .body), "more\n").reply.status); // unsaved
+ const event = Node.of(serial, .event);
+ const h = call(p, .{ .tag = 1, .op = .open, .node = event }).reply.handle;
+ defer _ = call(p, .{ .tag = 9, .op = .release, .node = event, .handle = h });
+ try testing.expectEqual(Status.ok, wr(p, Node.of(serial, .exec), "Del\n").reply.status);
+ const record = call(p, .{ .tag = 2, .op = .read, .node = event, .handle = h, .size = 256 }).bytes;
+ var copy: [256]u8 = undefined;
+ @memcpy(copy[0..record.len], record);
+ const back = wr(p, event, copy[0..record.len]);
+ try testing.expectEqual(E.IO, back.errno());
+ try testing.expect(std.mem.indexOf(u8, back.reply.ename, "Modified") != null);
+ try testing.expect(p.paneBySerial(serial) != null);
+}
+
test "a pane's own look and exec go to the event reader holding it, which writes them back to act" {
const gpa = testing.allocator;
const p = try withFile(gpa, "Msg routed\n");