summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 09:59:34 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:16 -0300
commit6046b8c67bf6894824d2b7f72c476b9dfd5daa72 (patch)
tree835675bf66e05a11486d867e88527688de18ca14
parent8bc8bc2289e3e33903f9008b3513d0bd9c3f7311 (diff)
downloadpardes-6046b8c67bf6894824d2b7f72c476b9dfd5daa72.tar.gz
pardes-6046b8c67bf6894824d2b7f72c476b9dfd5daa72.zip
Errnos that fit: a Dump into a missing DumpDir and a shell that is not there are ENOENT, a GUI-only setting EINVAL
A Dump into a DumpDir not there failed EIO `file not found`; `no shell "x"` read as EIO through a mount; and a GUI-only setting on a terminal, EINVAL in the reply, had no word 9ns reads as EINVAL. Each says so in the words that give its errno: `no such directory`, `not found`, `invalid here`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--docs/fs.md5
-rw-r--r--src/host_io.zig3
-rw-r--r--src/ninep/ctl.zig10
-rw-r--r--src/pardes.zig9
-rw-r--r--test/snapshots/shellset.golden2
5 files changed, 21 insertions, 8 deletions
diff --git a/docs/fs.md b/docs/fs.md
index 8f50a45b..c53f83d6 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -243,7 +243,10 @@ and reads every setting there is, one a line, in the words a write of it
takes (`Verbose on`, `WindowOpacity 70`, `PanelSlide off`, `DumpDir
<the directory in effect>`, `LocationsConfig ...`), so writing what it reads
back changes nothing; a setting the frontend cannot show (`Lift`,
-`GripWidth` on a terminal) is refused as `Lift is GUI-only`; platform and startup facts are `/status`'s and the
+`GripWidth` on a terminal) is refused as `Lift is GUI-only, invalid here`
+(EINVAL: a request this build cannot take); a `Shell` or `Tty` naming no
+shell says `no shell "x", not found` (ENOENT); a Dump into a `DumpDir`
+that is not there says `Dump <path>: no such directory` (ENOENT); platform and startup facts are `/status`'s and the
Config window's, not settings. A pane's `ctl` takes the builtins that act on
a pane (`Del`, or `Del k`/`Del j` to give its rows to the pane above or
below, `Save f`, `Collapse`, which folds that pane, `Undo` and
diff --git a/src/host_io.zig b/src/host_io.zig
index fbdfb703..913930ac 100644
--- a/src/host_io.zig
+++ b/src/host_io.zig
@@ -867,7 +867,8 @@ pub const Shell = struct {
buf[bin.len] = 0;
if (isDirectory(@ptrCast(&buf))) return std.fmt.bufPrint(said, "not a shell: {s} is a directory", .{bin}) catch "not a shell: a directory";
}
- return std.fmt.bufPrint(said, "no shell \"{s}\" (a name on the usual paths, or a path to one)", .{bin}) catch "no such shell";
+ // "not found": the words a mount reads as ENOENT.
+ return std.fmt.bufPrint(said, "no shell \"{s}\", not found (a name on the usual paths, or a path to one)", .{bin}) catch "no such shell";
}
fn fallback(buf: *[std.fs.max_path_bytes]u8) [*:0]const u8 {
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 5f26a181..a474c781 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -386,7 +386,9 @@ fn checkBuiltin(p: *Pardes, req: Req, line: []const u8, scope: builtins.Scope) ?
// terminal) is known, and says so rather than sound misspelt.
if (config.Runtime.find(word) != null) {
var why: [64]u8 = undefined;
- return refuse(p, req, std.fmt.bufPrint(&why, "{s} is GUI-only", .{word}) catch "GUI-only", line);
+ // EINVAL, a request this build cannot take, in words 9ns reads
+ // as that: `invalid`.
+ return refuse(p, req, std.fmt.bufPrint(&why, "{s} is GUI-only, invalid here", .{word}) catch "GUI-only, invalid here", line);
}
return refuse(p, req, "unknown control message", line);
};
@@ -1653,7 +1655,7 @@ test "a Restore of a file that is no dump fails the write before any warning, an
p.fs.late_failure_len = 0;
p.dumpFailed("/nowhere/pardes.dump.zon", error.FileNotFound);
- try testing.expectEqualStrings("Dump /nowhere/pardes.dump.zon: file not found", p.fs.late_failure[0..p.fs.late_failure_len]);
+ try testing.expectEqualStrings("Dump /nowhere/pardes.dump.zon: no such directory", p.fs.late_failure[0..p.fs.late_failure_len]);
}
test "a setting this frontend cannot show says GUI-only, and DumpDir reads back the directory in effect" {
@@ -1661,8 +1663,8 @@ test "a setting this frontend cannot show says GUI-only, and DumpDir reads back
defer p.deinit();
const root_ctl = @intFromEnum(tree.TopFile.ctl);
if (!builtins.capabilities.lift) {
- try testing.expectEqualStrings("Lift is GUI-only \"Lift on\"", wr(p, root_ctl, "Lift on\n").reply.ename);
- try testing.expectEqualStrings("GripWidth is GUI-only \"GripWidth 120\"", wr(p, root_ctl, "GripWidth 120\n").reply.ename);
+ try testing.expectEqualStrings("Lift is GUI-only, invalid here \"Lift on\"", wr(p, root_ctl, "Lift on\n").reply.ename);
+ try testing.expectEqualStrings("GripWidth is GUI-only, invalid here \"GripWidth 120\"", wr(p, root_ctl, "GripWidth 120\n").reply.ename);
}
try testing.expectEqualStrings("unknown control message \"Liftt on\"", wr(p, root_ctl, "Liftt on\n").reply.ename);
var buf: [900]u8 = undefined;
diff --git a/src/pardes.zig b/src/pardes.zig
index 35b44871..225dbf9e 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -5302,7 +5302,14 @@ pub const Pardes = struct {
pub fn dumpFailed(p: *Pardes, path: []const u8, err: anyerror) void {
var what: [limits.host_path_cap + 8]u8 = undefined;
const operation = std.fmt.bufPrint(&what, "Dump {s}", .{path}) catch "Dump";
- p.reportError(p.active, operation, err);
+ // Into a DumpDir that is not there: said so, ENOENT, as a Save is.
+ const parent = std.fs.path.dirname(path) orelse "/";
+ const no_dir = err == error.FileNotFound or err == error.NotDir or
+ (if (comptime hosted) (if (filesystem.localPath(parent)) |local| !exec.isDirectory(local) else false) else false);
+ if (no_dir) {
+ var said: [limits.host_path_cap + 48]u8 = undefined;
+ p.reportFailure(p.active, std.fmt.bufPrint(&said, "{s}: no such directory", .{operation}) catch "Dump: no such directory");
+ } else p.reportError(p.active, operation, err);
// In the words the message row has, so the write's err is the one
// record of it (its msg goes: 9p_io, dropMessage).
const said = if (p.panes[p.active]) |pane| pane.msg[0..pane.msg_len] else "Dump failed";
diff --git a/test/snapshots/shellset.golden b/test/snapshots/shellset.golden
index e2830801..db72bfc8 100644
--- a/test/snapshots/shellset.golden
+++ b/test/snapshots/shellset.golden
@@ -4,7 +4,7 @@
| /tmp/pardes-snap/shellset/cwd/cmd.txt Save Tty Collapse Del
| 1 Shell zznosuchshell
== snap builtin-ran grid=90x21 cursor=25,3
-|3: 1 Shel Shell: no shell "zznosuchshell" (a name on the usual paths, or a path to one)
+|3: hell: no shell "zznosuchshell", not found (a name on the usual paths, or a path to one)
== snap fallback-shell grid=90x21 cursor=49,6
|1: New Tty Find Grep Joincol Delcol New Tty Find Grep Joincol Delcol
|2: /tmp/pardes-snap/shellset/cwd/cmd.txt Save /tmp/pardes-snap/shellset/cwd Tty+bash Sav