diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.zig | 6 | ||||
| -rw-r--r-- | src/fs.zig | 22 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 16 |
3 files changed, 43 insertions, 1 deletions
diff --git a/src/builtins.zig b/src/builtins.zig index 6aabba8d..6688d05f 100644 --- a/src/builtins.zig +++ b/src/builtins.zig @@ -666,7 +666,11 @@ pub const Restore = struct { pub const scope: Scope = .session; pub const takes_arg = true; pub fn run(c: Ctx) void { - const path = c.arg orelse (c.p.last_dump orelse return c.p.reportFailure(c.id, "Restore: no dump yet; name one")); + const typed = c.arg orelse (c.p.last_dump orelse return c.p.reportFailure(c.id, "Restore: no dump yet; name one")); + // The file it reads, whole (`~`, the DumpDir, the directory it runs + // in): what the log's `restore` record and every message name. + var full_buf: [4096]u8 = undefined; + const path = if (comptime pardes.hosted) @import("fs.zig").restorePath(typed, c.p.settings.dump_dir.get(), &full_buf) else typed; if (path.len > c.p.restore_buf.len) return c.p.reportFailure(c.id, "Restore: that name is too long"); // A dump that cannot be read is said now, and fails a ctl write: the // host reads it only after this step, where nobody hears. First, @@ -1232,6 +1232,28 @@ pub fn readRestore(gpa: std.mem.Allocator, typed: []const u8, dir_setting: []con return readRestoreIn(gpa, path, dir); } +/// The file a Restore of `typed` reads, whole: `~` expanded, a relative name +/// the DumpDir's when one is there, else the current directory's. What the +/// log and the message say, not the name as typed. `typed` itself (home +/// expanded) when nothing resolves: the read then says why. +pub fn restorePath(typed: []const u8, dir_setting: []const u8, out: *[4096]u8) []const u8 { + var home_buf: [4096]u8 = undefined; + const path = expandHome(typed, &home_buf); + if (!std.fs.path.isAbsolute(path)) { + var dir_buf: [4096]u8 = undefined; + if (@import("dump.zig").directory(&dir_buf, dir_setting)) |base| { + var buf: [4096]u8 = undefined; + if (std.fmt.bufPrint(&buf, "{s}/{s}", .{ base, path })) |candidate| { + if (resolveOs(candidate, out)) |r| if (!r.dir) return r.path; + } else |_| {} + } + } + if (resolveOs(path, out)) |r| return r.path; + const n = @min(path.len, out.len); + @memcpy(out[0..n], path[0..n]); + return out[0..n]; +} + fn readRestoreIn(gpa: std.mem.Allocator, path: []const u8, dir: ?[]const u8) ![]u8 { if (!std.fs.path.isAbsolute(path)) { if (dir) |base| { diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index aebd07e2..fdc83da8 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -2589,6 +2589,22 @@ test "a focus moved over 9P tells the programs that asked for focus reports, as try testing.expectEqualStrings("\x1b[O\x1b[I", moved.pty_buf[0..moved.pty_len]); } +test "a Restore of a name in the DumpDir asks for, and logs, the whole path it reads" { + if (comptime !pardes.hosted) return error.SkipZigTest; + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + try pardes.dump.dumpState(p); + var tmp = testing.tmpDir(.{}); + defer tmp.cleanup(); + try tmp.dir.writeFile(testing.io, .{ .sub_path = "x.dump.zon", .data = p.dump_out.? }); + var buf: [4096]u8 = undefined; + const dir = buf[0..try tmp.dir.realPath(testing.io, &buf)]; + try testing.expect(p.settings.dump_dir.set(dir)); + try testing.expectEqual(Status.ok, wr(p, @intFromEnum(tree.TopFile.ctl), "Restore x.dump.zon\n").reply.status); + var want: [4200]u8 = undefined; + try testing.expectEqualStrings(try std.fmt.bufPrint(&want, "{s}/x.dump.zon", .{dir}), p.restore_req.?); +} + test "a line starting with # runs as nothing at an exec or a ctl, silently" { const p = try withFile(testing.allocator, "x\n"); defer p.deinit(); |
