summaryrefslogtreecommitdiff
path: root/src/ninep/tree.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 13:48:35 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:16 -0300
commitca362e190825862d5c0a1451d163d3c00be68314 (patch)
tree41ba9702527092b4e8cbc482c79d6651d6918fa0 /src/ninep/tree.zig
parenta2e466a874502b665807f620eb8edefb37be1e8c (diff)
downloadpardes-ca362e190825862d5c0a1451d163d3c00be68314.tar.gz
pardes-ca362e190825862d5c0a1451d163d3c00be68314.zip
A second line written to name is refused EINVAL, in one write or on the same open
bash writes printf 'a\nb\n' a line at a time, so each line arrived as a whole name on the held open and renamed the pane twice. An open that has named its pane now refuses a further line, as a two-line write already was. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/tree.zig')
-rw-r--r--src/ninep/tree.zig10
1 files changed, 10 insertions, 0 deletions
diff --git a/src/ninep/tree.zig b/src/ninep/tree.zig
index 60778b9c..8c0e74a6 100644
--- a/src/ninep/tree.zig
+++ b/src/ninep/tree.zig
@@ -162,6 +162,9 @@ pub const Open = struct {
/// answered from it again: bash's `read` takes a chunk, keeps a line and
/// lseeks back to just past it, and a stream has already moved on.
replay: ?Replay = null,
+ /// A `name` open has named its pane: one name an open, so a second line
+ /// on it (bash writes `printf 'a\nb\n'` a line at a time) is refused.
+ named: bool = false,
pub const Replay = struct { off: u64, bytes: []u8 };
@@ -1071,6 +1074,13 @@ fn write(p: *Pardes, req: Req, target: Target) Reply {
o.pending.clearRetainingCapacity();
return failText(req.tag, E.INVAL, "a line or Edit block over 1 MiB");
}
+ if (target == .pane and target.pane.file == .name) {
+ if (o.named or std.mem.count(u8, o.pending.items[0..end], "\n") > 1) {
+ o.pending.clearRetainingCapacity();
+ return failText(req.tag, E.INVAL, "invalid file name: one name a write, on one line");
+ }
+ o.named = true;
+ }
const whole = p.scratch.allocator().dupe(u8, o.pending.items[0..end]) catch return Reply.fail(req.tag, E.NOMEM);
const rest = o.pending.items.len - end;
std.mem.copyForwards(u8, o.pending.items[0..rest], o.pending.items[end..]);