summaryrefslogtreecommitdiff
path: root/src/host_io.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/host_io.zig')
-rw-r--r--src/host_io.zig34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/host_io.zig b/src/host_io.zig
index 1db0dac9..10bcf0d7 100644
--- a/src/host_io.zig
+++ b/src/host_io.zig
@@ -1286,7 +1286,14 @@ pub fn shellCwd(pid: libc.pid_t, buf: []u8) ?[]const u8 {
const path = std.fmt.bufPrintSentinel(&pbuf, "/proc/{d}/cwd", .{pid}, 0) catch return null;
const n = libc.readlink(path, buf.ptr, buf.len);
if (n <= 0 or n >= buf.len) return null;
- return buf[0..@intCast(n)];
+ const link = buf[0..@intCast(n)];
+ // A directory removed under the shell reads `<path> (deleted)`:
+ // no directory to be named by, so the name it had stays, and a
+ // restart works there once it is back.
+ if (std.mem.endsWith(u8, link, " (deleted)")) {
+ _ = std.Io.Dir.cwd().statFile(std.Io.Threaded.global_single_threaded.io(), link, .{}) catch return null;
+ }
+ return link;
},
.macos, .ios, .tvos, .watchos, .visionos => {
var info: proc_vnodepathinfo = undefined;
@@ -1330,6 +1337,31 @@ test "shell cwd rejects truncation and preserves an owned child path longer than
try std.testing.expectEqualStrings(directory, shellCwd(child.pid, &result) orelse return error.MissingCwd);
}
+test "a shell whose directory was removed is not named `... (deleted)`" {
+ if (comptime builtin.os.tag != .linux) return error.SkipZigTest;
+ if (!haveFile("/bin/sh")) return error.SkipZigTest;
+ const io = std.testing.io;
+ var tmp = std.testing.tmpDir(.{});
+ defer tmp.cleanup();
+ try tmp.dir.createDirPath(io, "gone");
+ var path_buf: [4096]u8 = undefined;
+ const directory = path_buf[0..try tmp.dir.realPathFile(io, "gone", &path_buf)];
+ const rcs: Shell.PromptFiles = .{};
+ const child = try forkShell(null, 0, &rcs, "/bin/sh", directory, 24, 80, null);
+ defer {
+ _ = libc.kill(child.pid, libc.SIG.KILL);
+ _ = libc.waitpid(child.pid, null, 0);
+ _ = libc.close(child.file.handle);
+ }
+ var sh: TestShell = .{ .master = child.file.handle, .pid = child.pid };
+ try std.testing.expect(writeFd(child.file.handle, "printf '\\160ardes-cwd-ready\\n'\n"));
+ try std.testing.expect(sh.waitText("pardes-cwd-ready", 5_000));
+ var result: [4096]u8 = undefined;
+ try std.testing.expectEqualStrings(directory, shellCwd(child.pid, &result) orelse return error.MissingCwd);
+ try tmp.dir.deleteDir(io, "gone");
+ try std.testing.expect(shellCwd(child.pid, &result) == null);
+}
+
extern "c" fn tcgetpgrp(fd: c_int) libc.pid_t;
const occ_max_depth: u8 = 8;