summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ninep/pane.zig19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig
index d3c1b907..78bec09f 100644
--- a/src/ninep/pane.zig
+++ b/src/ninep/pane.zig
@@ -883,6 +883,11 @@ fn writeName(p: *Pardes, req: Req, id: usize, pane: *Pane) Reply {
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);
if (!std.fs.path.isAbsolute(full) or full.len >= 4096) return tree.failText(req.tag, E.INVAL, "invalid file name: longer than a path may be");
+ // A directory (`~`, `/`, `foo/`) is no file to name a pane after: a
+ // Save could only fail. Said now, EISDIR.
+ const is_dir = name[name.len - 1] == '/' or std.mem.eql(u8, full, "/") or
+ (if (comptime pardes.hosted) (if (fs.localPath(full)) |local| exec.isDirectory(local) else false) else false);
+ if (is_dir) return tree.failText(req.tag, E.ISDIR, std.fmt.bufPrint(&p.fs.ename, "name: {s} is a directory, not a file", .{full[0..@min(full.len, 256)]}) catch "name: is a directory, not a file");
nameBuffer(p, id, full, false) catch |err| return Reply.fail(req.tag, switch (err) {
error.OutOfMemory => E.NOMEM,
else => E.INVAL,
@@ -1415,6 +1420,20 @@ test "an addr pair out of order or out of range is refused as the address form i
try testing.expectEqual(State.Range{ .q0 = 2, .q1 = 4 }, p.panes[p.paneBySerial(serial).?].?.fs.addr);
}
+test "name refuses a directory, EISDIR, and leaves the name as it was" {
+ const p = try withFile(testing.allocator, "x\n");
+ defer p.deinit();
+ const serial = serialOf(p);
+ const node = Node.of(serial, .name);
+ for ([_][]const u8{ "/\n", "/tmp/\n", "sub/\n", "/tmp\n" }) |dir| {
+ if (comptime !pardes.hosted) if (std.mem.eql(u8, dir, "/tmp\n")) continue;
+ const r = wr(p, node, dir);
+ try testing.expectEqual(E.ISDIR, r.errno());
+ try testing.expect(std.mem.indexOf(u8, r.reply.ename, "is a directory") != null);
+ }
+ try testing.expectEqualStrings("/test.txt", nameOf(p, p.panes[p.paneBySerial(serial).?].?));
+}
+
test "a write of two lines to name is refused EINVAL, on a held open or not" {
const p = try withFile(testing.allocator, "x\n");
defer p.deinit();