diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/9p_io.zig | 4 | ||||
| -rw-r--r-- | src/builtins.zig | 13 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 24 |
3 files changed, 36 insertions, 5 deletions
diff --git a/src/9p_io.zig b/src/9p_io.zig index e199dea9..dd755f82 100644 --- a/src/9p_io.zig +++ b/src/9p_io.zig @@ -1427,6 +1427,7 @@ test "TCP addresses are numeric and normalize mapped IPv4" { try testing.expectError(error.BadDial, Client.validateDial("unix!work")); try testing.expectError(error.BadDial, Client.validateDial("nowhere!x")); try Client.validateDial("/tmp/odd!name.sock"); + try testing.expectError(error.BadDial, Client.validateDial("rel/dir.sock")); try testing.expectError(error.BadDial, Client.validateDial("unix!")); try testing.expectError(error.BadDial, Client.validateDial("unix!/tmp/a\x00b")); try testing.expectError(error.BadDial, Client.validateDial("tcp!localhost!5640")); @@ -2086,6 +2087,9 @@ pub const Client = struct { const path = if (explicit_unix) dial[5..] else dial; if (explicit_unix and !std.mem.startsWith(u8, path, "/")) return error.BadDial; if (std.mem.indexOfScalar(u8, path, '/') != null) { + // A socket's path is absolute: a relative one would mean wherever + // the editor happens to run. + if (path[0] != '/') return error.BadDial; if (std.mem.indexOfScalar(u8, path, 0) != null) return error.BadDial; return .{ .unix = std.fmt.bufPrintSentinel(buf, "{s}", .{path}, 0) catch return error.BadDial }; } diff --git a/src/builtins.zig b/src/builtins.zig index ca80be26..907650bd 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -804,9 +804,20 @@ pub const Mount = struct { if (dial.len == 0) return c.p.reportFailure(c.id, e_args); c.p.fs.mount(c.p.gpa, name, dial) catch |err| { var said: [200]u8 = undefined; - if (err == error.BadDial) return c.p.reportFailure(c.id, std.fmt.bufPrint(&said, "Mount: bad dial address: {s} (unix!/path, tcp!host!port, or a session name)", .{dial[0..@min(dial.len, 100)]}) catch "Mount: bad dial address"); + if (err == error.BadDial) return c.p.reportFailure(c.id, std.fmt.bufPrint(&said, "Mount: bad dial address: {s} (unix!/path, /path, tcp!<numeric-ip>!<port>, or a session name)", .{dial[0..@min(dial.len, 100)]}) catch "Mount: bad dial address"); return c.p.reportError(c.id, "Mount", err); }; + // A socket path that is not there: said so (ENOENT), not a dial + // that went unanswered. + const sock_path: ?[]const u8 = if (std.mem.startsWith(u8, dial, "unix!")) dial[5..] else if (dial.len > 0 and dial[0] == '/') dial else null; + if (sock_path) |path| if (@import("exec.zig").kindOf(path) == null) { + if (c.p.fs.mounts.pop()) |gone| { + c.p.gpa.free(gone.name); + c.p.gpa.free(gone.dial); + } + var said: [200]u8 = undefined; + return c.p.reportFailure(c.id, std.fmt.bufPrint(&said, "Mount {s}: {s}: no such socket", .{ name, path[0..@min(path.len, 100)] }) catch "Mount: no such socket"); + }; // A mount that cannot be reached is said now, and taken back, not // found out by the first look through it. const reached = reached: { diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 4fb5bf41..06eb8cdd 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -1363,8 +1363,8 @@ test "the root ctl reads the settings as a write takes them, and takes the sessi // A builtin that fails as it runs fails the write, quoting its error and // its line; the lines before it have taken effect, as in acme. const failed = wr(p, root_ctl, "Verbose on\nMount x /tmp/pardes-no-such-sock-zz\nVerbose off"); - try testing.expectEqual(E.IO, failed.errno()); - try testing.expectStringStartsWith(failed.reply.ename, "Mount x /tmp/pardes-no-such-sock-zz: dial failed"); + try testing.expectEqual(E.NOENT, failed.errno()); + try testing.expectStringStartsWith(failed.reply.ename, "Mount x: /tmp/pardes-no-such-sock-zz: no such socket"); try testing.expect(p.settings.verbose); try testing.expect(!p.fs.no_prompt); try testing.expectEqual(Status.ok, wr(p, root_ctl, "Verbose off").reply.status); @@ -2458,9 +2458,14 @@ test "Mount dials its peer and fails, mounting nothing, when none answers; a loo defer p.deinit(); const root_ctl = @intFromEnum(tree.TopFile.ctl); const dead = "/tmp/pardes-test-no-such-peer.sock"; - const refused = wr(p, root_ctl, "Mount dead " ++ dead ++ "\n"); + // A socket path not there is said so; one there that does not answer + // (a directory here) is a dial that failed. + const missing = wr(p, root_ctl, "Mount dead " ++ dead ++ "\n"); + try testing.expectEqual(E.NOENT, missing.errno()); + try testing.expectEqualStrings("Mount dead: " ++ dead ++ ": no such socket", missing.reply.ename); + const refused = wr(p, root_ctl, "Mount dead /tmp\n"); try testing.expectEqual(E.IO, refused.errno()); - try testing.expectEqualStrings("Mount dead " ++ dead ++ ": dial failed: no answer", refused.reply.ename); + try testing.expectEqualStrings("Mount dead /tmp: dial failed: no answer", refused.reply.ename); try testing.expectEqual(@as(usize, 0), p.fs.mounts.items.len); // A pane of a peer gone since: get says so too. try p.fs.mounts.append(p.gpa, .{ .name = try p.gpa.dupe(u8, "away"), .dial = try p.gpa.dupe(u8, dead) }); @@ -4438,3 +4443,14 @@ test "an unsaved pane from a dump that says nothing of its disk asks at its firs pardes.exec.saveFile(p, id); try testing.expect(th.logHas(p, "modified on disk since read (Save again to overwrite)")); } + +test "a Mount of a socket path that is not there says no such socket, ENOENT" { + if (comptime !pardes.hosted) return; + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + const r = wr(p, @intFromEnum(tree.TopFile.ctl), "Mount peer unix!/tmp/pardes-surely-no-socket\n"); + try testing.expectEqual(E.NOENT, r.errno()); + try testing.expect(std.mem.indexOf(u8, r.reply.ename, "no such socket") != null); + try testing.expectEqual(@as(usize, 0), p.fs.mounts.items.len); + try testing.expectEqual(E.INVAL, wr(p, @intFromEnum(tree.TopFile.ctl), "Mount peer rel/x.sock\n").errno()); +} |
