diff options
| -rw-r--r-- | src/ninep/ctl.zig | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 1fcd7a6d..1e274e0c 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -647,8 +647,14 @@ pub fn writePager(p: *Pardes, req: Req) Reply { var it = Messages.init(p, req.data); const line = it.next() orelse ""; if (it.next() != null) return tree.failText(req.tag, E.INVAL, "pager: one directory a write"); + const dir = std.mem.trim(u8, line, " \t"); + // A directory that is there, or none (the session's): never a +Pager + // named into one missing, nor a relative one quietly taken for none. + if (dir.len > 0 and dir[0] != '/') return refuseQuoting(p, req, "pager: the directory must be absolute", dir); + 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, std.mem.trim(u8, line, " \t")) catch |err| + 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", else => "pager: could not make a +Pager pane", @@ -4011,10 +4017,10 @@ test "pager answers its +Pager on the open that asked, whatever another client e const pager = @intFromEnum(tree.TopFile.pager); const exec = @intFromEnum(tree.TopFile.exec); const asked = call(p, .{ .tag = 1, .op = .open, .node = pager, .omode = 2 }).reply.handle; - try testing.expectEqual(Status.ok, call(p, .{ .tag = 2, .op = .write, .node = pager, .handle = asked, .data = "/tmp/pager-race\n" }).reply.status); + try testing.expectEqual(Status.ok, call(p, .{ .tag = 2, .op = .write, .node = pager, .handle = asked, .data = "/tmp\n" }).reply.status); const paged = for (p.panes) |slot| { const pn = slot orelse continue; - if (pn.file) |f| if (std.mem.eql(u8, f.path, "/tmp/pager-race/+Pager")) break pn.serial; + if (pn.file) |f| if (std.mem.eql(u8, f.path, "/tmp/+Pager")) break pn.serial; } else return error.NoPager; // Another client execs between the request and its read: a pane of its own. const racer = call(p, .{ .tag = 3, .op = .open, .node = exec, .omode = 2 }).reply.handle; @@ -4025,8 +4031,10 @@ 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); - // One directory a write. + // One directory a write, absolute, and there. try testing.expectEqual(E.INVAL, wr(p, pager, "/a\n/b\n").errno()); + try testing.expectEqual(E.INVAL, wr(p, pager, "relative\n").errno()); + try testing.expectEqual(E.NOENT, wr(p, pager, "/tmp/pardes-surely-missing-dir\n").errno()); } test "a command pane an exec open was answered is leased to it while it stays open: another client's command gets a pane of its own" { |
