diff options
| -rw-r--r-- | src/ninep/ctl.zig | 16 | ||||
| -rw-r--r-- | src/ninep/pane.zig | 11 |
2 files changed, 22 insertions, 5 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index fa6310bb..1bf916a9 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -991,6 +991,10 @@ pub fn writePane(p: *Pardes, req: Req, pane: *Pane) Reply { if (apply) _ = p.answerQuestion(id, if (choice[0] == '-') null else choice[0]); } else if (!apply) { if (checkBuiltin(p, req, line, .pane)) |refusal| return refusal; + // Edit on a pane with no text is the refusal a data write + // there gets, EINVAL, before anything runs. + if (std.mem.startsWith(u8, line, "Edit") and pane_files.fileOf(p.panes[p.paneBySerial(serial).?].?) == null) + return tree.failText(req.tag, E.INVAL, pane_files.e_no_text); } else if (runBuiltin(p, req, p.paneBySerial(serial).?, line)) |refusal| { return refusal; } @@ -4133,3 +4137,15 @@ test "a Rename that reaches other files previews them, says so, and is the pane try testing.expectEqual(preview.serial, p.fs.lsp_result.?); try testing.expect(th.logHas(p, "Rename: 2 edit(s) across files, previewed, not applied")); } + +test "Edit on an image pane is refused as a data write there is, EINVAL, before it runs" { + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + const doc = try p.newDocPane(p.freeSlot().?); + doc.image = .{ .path = try p.gpa.dupe(u8, "/tmp/pardes-pic.ppm") }; + const edit = wr(p, Node.of(doc.serial, .ctl), "Edit ,d\n"); + const data = wr(p, Node.of(doc.serial, .data), "x"); + try testing.expectEqual(E.INVAL, edit.errno()); + try testing.expectEqualStrings(data.reply.ename, edit.reply.ename); + try testing.expectEqual(E.INVAL, wr(p, Node.of(doc.serial, .name), "/tmp/other.ppm\n").errno()); +} diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig index f69813b0..48c2888e 100644 --- a/src/ninep/pane.zig +++ b/src/ninep/pane.zig @@ -936,10 +936,11 @@ fn writeName(p: *Pardes, req: Req, id: usize, pane: *Pane) Reply { const name = if (std.mem.endsWith(u8, req.data, "\n")) req.data[0 .. req.data.len - 1] else req.data; if (name.len == 0) return tree.failText(req.tag, E.INVAL, e_name_char ++ ": an empty name"); if (nameFault(name)) |why| return tree.failText(req.tag, E.INVAL, why); - if (fileOf(pane) == null) return tree.failText(req.tag, E.PERM, if (pane.isTerminal()) - "rename not allowed: a terminal is named by its shell's directory; cd there, or Tty in another" + // Words 9ns maps to EINVAL, as every refusal of a name here. + if (fileOf(pane) == null) return tree.failText(req.tag, E.INVAL, if (pane.isTerminal()) + "invalid rename: a terminal is named by its shell's directory; cd there, or Tty in another" else - "rename not allowed: an image or PDF is named by the file it shows"); + "invalid rename: an image or PDF is named by the file it shows"); var home_buf: [4096]u8 = undefined; const full = std.fs.path.resolvePosix(p.scratch.allocator(), &.{ pardes.Pardes.paneDir(pane), fs.expandHome(name, &home_buf) }) catch return Reply.fail(req.tag, E.NOMEM); @@ -1126,8 +1127,8 @@ test "a terminal is listed as term with its directory as name" { ) != null); try testing.expectEqualStrings("/work/dir\n", rd(p, Node.of(pane.serial, .name), 0, 4096).bytes); const refused = wr(p, Node.of(pane.serial, .name), "/elsewhere\n"); - try testing.expectEqual(E.PERM, refused.errno()); - try testing.expect(std.mem.startsWith(u8, refused.reply.ename, "rename not allowed: a terminal is named")); + try testing.expectEqual(E.INVAL, refused.errno()); + try testing.expect(std.mem.startsWith(u8, refused.reply.ename, "invalid rename: a terminal is named")); } test "body reads at any offset and writes append" { |
