authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:07:31-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 22:15:12-08:00
logfa79d346744308250c165519f842fedfc26a1c14
tree21a007127f3199bca0334c0e959480f5cb7dd0eb
parent98e9716c082aa7e134e11ed14db8c2f631fedc8a

std: add changing cur dir back

There's a good argument to not have this in the std lib but it's more work to remove it than to leave it in, and this branch is already 20,000+ lines changed.

12 files changed, 229 insertions(+), 116 deletions(-)

lib/std/Io.zig+1
......@@ -718,6 +718,7 @@ pub const VTable = struct {
718718 lockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!LockedStderr,
719719 tryLockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!?LockedStderr,
720720 unlockStderr: *const fn (?*anyopaque) void,
721 processSetCurrentDir: *const fn (?*anyopaque, Dir) std.process.SetCurrentDirError!void,
721722
722723 now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,
723724 sleep: *const fn (?*anyopaque, Timeout) SleepError!void,
lib/std/Io/Threaded.zig+71-3
......@@ -648,7 +648,7 @@ pub fn init(
648648 .main_thread = .{
649649 .signal_id = Thread.currentSignalId(),
650650 .current_closure = null,
651 .cancel_protection = undefined,
651 .cancel_protection = .unblocked,
652652 },
653653 .argv0 = options.argv0,
654654 .environ = options.environ,
......@@ -689,7 +689,7 @@ pub const init_single_threaded: Threaded = .{
689689 .main_thread = .{
690690 .signal_id = undefined,
691691 .current_closure = null,
692 .cancel_protection = undefined,
692 .cancel_protection = .unblocked,
693693 },
694694 .robust_cancel = .disabled,
695695 .argv0 = .{},
......@@ -742,7 +742,7 @@ fn worker(t: *Threaded) void {
742742 var thread: Thread = .{
743743 .signal_id = Thread.currentSignalId(),
744744 .current_closure = null,
745 .cancel_protection = undefined,
745 .cancel_protection = .unblocked,
746746 };
747747 Thread.current = &thread;
748748
......@@ -844,6 +844,7 @@ pub fn io(t: *Threaded) Io {
844844 .lockStderr = lockStderr,
845845 .tryLockStderr = tryLockStderr,
846846 .unlockStderr = unlockStderr,
847 .processSetCurrentDir = processSetCurrentDir,
847848
848849 .now = now,
849850 .sleep = sleep,
......@@ -979,6 +980,7 @@ pub fn ioBasic(t: *Threaded) Io {
979980 .lockStderr = lockStderr,
980981 .tryLockStderr = tryLockStderr,
981982 .unlockStderr = unlockStderr,
983 .processSetCurrentDir = processSetCurrentDir,
982984
983985 .now = now,
984986 .sleep = sleep,
......@@ -7370,6 +7372,7 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex
73707372 };
73717373 defer w.CloseHandle(h_file);
73727374
7375 // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks
73737376 const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &path_name_w_buf.data);
73747377
73757378 const len = std.unicode.calcWtf8Len(wide_slice);
......@@ -10796,6 +10799,71 @@ fn unlockStderr(userdata: ?*anyopaque) void {
1079610799 std.process.stderr_thread_mutex.unlock();
1079710800}
1079810801
10802fn processSetCurrentDir(userdata: ?*anyopaque, dir: Dir) std.process.SetCurrentDirError!void {
10803 if (native_os == .wasi) return error.OperationUnsupported;
10804 const t: *Threaded = @ptrCast(@alignCast(userdata));
10805 const current_thread = Thread.getCurrent(t);
10806
10807 if (is_windows) {
10808 try current_thread.checkCancel();
10809 var dir_path_buffer: [windows.PATH_MAX_WIDE]u16 = undefined;
10810 // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks
10811 const dir_path = try windows.GetFinalPathNameByHandle(dir.handle, .{}, &dir_path_buffer);
10812 const path_len_bytes = std.math.cast(u16, dir_path.len * 2) orelse return error.NameTooLong;
10813 try current_thread.checkCancel();
10814 var nt_name: windows.UNICODE_STRING = .{
10815 .Length = path_len_bytes,
10816 .MaximumLength = path_len_bytes,
10817 .Buffer = @constCast(dir_path.ptr),
10818 };
10819 switch (windows.ntdll.RtlSetCurrentDirectory_U(&nt_name)) {
10820 .SUCCESS => return,
10821 .OBJECT_NAME_INVALID => return error.BadPathName,
10822 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
10823 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
10824 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
10825 .INVALID_PARAMETER => |err| return windows.statusBug(err),
10826 .ACCESS_DENIED => return error.AccessDenied,
10827 .OBJECT_PATH_SYNTAX_BAD => |err| return windows.statusBug(err),
10828 .NOT_A_DIRECTORY => return error.NotDir,
10829 else => |status| return windows.unexpectedStatus(status),
10830 }
10831 }
10832
10833 if (dir.handle == posix.AT.FDCWD) return;
10834
10835 try current_thread.beginSyscall();
10836 while (true) {
10837 switch (posix.errno(posix.system.fchdir(dir.handle))) {
10838 .SUCCESS => return current_thread.endSyscall(),
10839 .INTR => {
10840 try current_thread.checkCancel();
10841 continue;
10842 },
10843 .ACCES => {
10844 current_thread.endSyscall();
10845 return error.AccessDenied;
10846 },
10847 .BADF => |err| {
10848 current_thread.endSyscall();
10849 return errnoBug(err);
10850 },
10851 .NOTDIR => {
10852 current_thread.endSyscall();
10853 return error.NotDir;
10854 },
10855 .IO => {
10856 current_thread.endSyscall();
10857 return error.FileSystem;
10858 },
10859 else => |err| {
10860 current_thread.endSyscall();
10861 return posix.unexpectedErrno(err);
10862 },
10863 }
10864 }
10865}
10866
1079910867pub const PosixAddress = extern union {
1080010868 any: posix.sockaddr,
1080110869 in: posix.sockaddr.in,
lib/std/os/windows.zig-34
......@@ -2939,40 +2939,6 @@ pub fn WriteFile(
29392939 return bytes_written;
29402940}
29412941
2942pub const SetCurrentDirectoryError = error{
2943 NameTooLong,
2944 FileNotFound,
2945 NotDir,
2946 AccessDenied,
2947 NoDevice,
2948 BadPathName,
2949 Unexpected,
2950};
2951
2952pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void {
2953 const path_len_bytes = math.cast(u16, path_name.len * 2) orelse return error.NameTooLong;
2954
2955 var nt_name: UNICODE_STRING = .{
2956 .Length = path_len_bytes,
2957 .MaximumLength = path_len_bytes,
2958 .Buffer = @constCast(path_name.ptr),
2959 };
2960
2961 const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
2962 switch (rc) {
2963 .SUCCESS => {},
2964 .OBJECT_NAME_INVALID => return error.BadPathName,
2965 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
2966 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
2967 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
2968 .INVALID_PARAMETER => unreachable,
2969 .ACCESS_DENIED => return error.AccessDenied,
2970 .OBJECT_PATH_SYNTAX_BAD => unreachable,
2971 .NOT_A_DIRECTORY => return error.NotDir,
2972 else => return unexpectedStatus(rc),
2973 }
2974}
2975
29762942pub const GetCurrentDirectoryError = error{
29772943 NameTooLong,
29782944 Unexpected,
lib/std/posix.zig+4-17
......@@ -1171,11 +1171,9 @@ pub const ChangeCurDirError = error{
11711171/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
11721172pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
11731173 if (native_os == .wasi and !builtin.link_libc) {
1174 @compileError("WASI does not support os.chdir");
1174 @compileError("unsupported OS");
11751175 } else if (native_os == .windows) {
1176 var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
1177 const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path);
1178 return chdirW(wtf16_dir_path[0..len]);
1176 @compileError("unsupported OS");
11791177 } else {
11801178 const dir_path_c = try toPosixPath(dir_path);
11811179 return chdirZ(&dir_path_c);
......@@ -1188,12 +1186,9 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
11881186/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
11891187pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
11901188 if (native_os == .windows) {
1191 const dir_path_span = mem.span(dir_path);
1192 var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
1193 const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path_span);
1194 return chdirW(wtf16_dir_path[0..len]);
1189 @compileError("unsupported OS");
11951190 } else if (native_os == .wasi and !builtin.link_libc) {
1196 return chdir(mem.span(dir_path));
1191 @compileError("unsupported OS");
11971192 }
11981193 switch (errno(system.chdir(dir_path))) {
11991194 .SUCCESS => return,
......@@ -1210,14 +1205,6 @@ pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
12101205 }
12111206}
12121207
1213/// Windows-only. Same as `chdir` except the parameter is WTF16 LE encoded.
1214pub fn chdirW(dir_path: []const u16) ChangeCurDirError!void {
1215 windows.SetCurrentDirectory(dir_path) catch |err| switch (err) {
1216 error.NoDevice => return error.FileSystem,
1217 else => |e| return e,
1218 };
1219}
1220
12211208pub const FchdirError = error{
12221209 AccessDenied,
12231210 NotDir,
lib/std/process.zig+25
......@@ -2304,3 +2304,28 @@ pub fn exit(status: u8) noreturn {
23042304 else => posix.system.exit(status),
23052305 }
23062306}
2307
2308pub const SetCurrentDirError = error{
2309 AccessDenied,
2310 BadPathName,
2311 FileNotFound,
2312 FileSystem,
2313 NameTooLong,
2314 NoDevice,
2315 NotDir,
2316 OperationUnsupported,
2317 UnrecognizedVolume,
2318} || Io.Cancelable || Io.UnexpectedError;
2319
2320/// Changes the current working directory to the open directory handle.
2321/// Corresponds to "fchdir" in libc.
2322///
2323/// This modifies global process state and can have surprising effects in
2324/// multithreaded applications. Most applications and especially libraries
2325/// should not call this function as a general rule, however it can have use
2326/// cases in, for example, implementing a shell, or child process execution.
2327///
2328/// Calling this function makes code less portable and less reusable.
2329pub fn setCurrentDir(io: Io, dir: Io.Dir) !void {
2330 return io.vtable.processSetCurrentDir(io.userdata, dir);
2331}
lib/std/testing.zig+1
......@@ -629,6 +629,7 @@ pub const TmpDir = struct {
629629};
630630
631631pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir {
632 comptime assert(builtin.is_test);
632633 var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
633634 std.crypto.random.bytes(&random_bytes);
634635 var sub_path: [TmpDir.sub_path_len]u8 = undefined;
test/standalone/posix/cwd.zig+59-13
......@@ -1,6 +1,10 @@
1const std = @import("std");
21const builtin = @import("builtin");
32
3const std = @import("std");
4const Io = std.Io;
5const Allocator = std.mem.Allocator;
6const assert = std.debug.assert;
7
48const path_max = std.fs.max_path_bytes;
59
610pub fn main() !void {
......@@ -9,13 +13,17 @@ pub fn main() !void {
913 return;
1014 }
1115
12 var Allocator = std.heap.DebugAllocator(.{}){};
13 const a = Allocator.allocator();
14 defer std.debug.assert(Allocator.deinit() == .ok);
16 var debug_allocator: std.heap.DebugAllocator(.{}) = .{};
17 defer assert(debug_allocator.deinit() == .ok);
18 const gpa = debug_allocator.allocator();
19
20 var threaded: std.Io.Threaded = .init(gpa, .{});
21 defer threaded.deinit();
22 const io = threaded.io();
1523
1624 try test_chdir_self();
1725 try test_chdir_absolute();
18 try test_chdir_relative(a);
26 try test_chdir_relative(gpa, io);
1927}
2028
2129// get current working directory and expect it to match given path
......@@ -46,20 +54,20 @@ fn test_chdir_absolute() !void {
4654 try expect_cwd(parent);
4755}
4856
49fn test_chdir_relative(a: std.mem.Allocator) !void {
50 var tmp = std.testing.tmpDir(.{});
51 defer tmp.cleanup();
57fn test_chdir_relative(gpa: Allocator, io: Io) !void {
58 var tmp = tmpDir(io, .{});
59 defer tmp.cleanup(io);
5260
5361 // Use the tmpDir parent_dir as the "base" for the test. Then cd into the child
54 try tmp.parent_dir.setAsCwd();
62 try std.process.setCurrentDir(io, tmp.parent_dir);
5563
5664 // Capture base working directory path, to build expected full path
5765 var base_cwd_buf: [path_max]u8 = undefined;
5866 const base_cwd = try std.posix.getcwd(base_cwd_buf[0..]);
5967
6068 const relative_dir_name = &tmp.sub_path;
61 const expected_path = try std.fs.path.resolve(a, &.{ base_cwd, relative_dir_name });
62 defer a.free(expected_path);
69 const expected_path = try std.fs.path.resolve(gpa, &.{ base_cwd, relative_dir_name });
70 defer gpa.free(expected_path);
6371
6472 // change current working directory to new test directory
6573 try std.posix.chdir(relative_dir_name);
......@@ -68,8 +76,46 @@ fn test_chdir_relative(a: std.mem.Allocator) !void {
6876 const new_cwd = try std.posix.getcwd(new_cwd_buf[0..]);
6977
7078 // On Windows, fs.path.resolve returns an uppercase drive letter, but the drive letter returned by getcwd may be lowercase
71 const resolved_cwd = try std.fs.path.resolve(a, &.{new_cwd});
72 defer a.free(resolved_cwd);
79 const resolved_cwd = try std.fs.path.resolve(gpa, &.{new_cwd});
80 defer gpa.free(resolved_cwd);
7381
7482 try std.testing.expectEqualStrings(expected_path, resolved_cwd);
7583}
84
85pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir {
86 var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
87 std.crypto.random.bytes(&random_bytes);
88 var sub_path: [TmpDir.sub_path_len]u8 = undefined;
89 _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
90
91 const cwd = Io.Dir.cwd();
92 var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch
93 @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir");
94 defer cache_dir.close(io);
95 const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch
96 @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir");
97 const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch
98 @panic("unable to make tmp dir for testing: unable to make and open the tmp dir");
99
100 return .{
101 .dir = dir,
102 .parent_dir = parent_dir,
103 .sub_path = sub_path,
104 };
105}
106
107pub const TmpDir = struct {
108 dir: Io.Dir,
109 parent_dir: Io.Dir,
110 sub_path: [sub_path_len]u8,
111
112 const random_bytes_count = 12;
113 const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count);
114
115 pub fn cleanup(self: *TmpDir, io: Io) void {
116 self.dir.close(io);
117 self.parent_dir.deleteTree(io, &self.sub_path) catch {};
118 self.parent_dir.close(io);
119 self.* = undefined;
120 }
121};
test/standalone/posix/relpaths.zig+56-35
......@@ -14,21 +14,21 @@ pub fn main() !void {
1414 const gpa = debug_allocator.allocator();
1515 defer std.debug.assert(debug_allocator.deinit() == .ok);
1616
17 const io = std.Io.Threaded.global_single_threaded.ioBasic();
17 var threaded: std.Io.Threaded = .init(gpa, .{});
18 defer threaded.deinit();
19 const io = threaded.io();
1820
19 // TODO this API isn't supposed to be used outside of unit testing. make it compilation error if used
20 // outside of unit testing.
21 var tmp = std.testing.tmpDir(.{});
22 defer tmp.cleanup();
21 var tmp = tmpDir(io, .{});
22 defer tmp.cleanup(io);
2323
2424 // Want to test relative paths, so cd into the tmpdir for these tests
25 try tmp.dir.setAsCwd();
25 try std.process.setCurrentDir(io, tmp.dir);
2626
2727 try test_symlink(gpa, io, tmp);
2828 try test_link(io, tmp);
2929}
3030
31fn test_symlink(gpa: Allocator, io: Io, tmp: std.testing.TmpDir) !void {
31fn test_symlink(gpa: Allocator, io: Io, tmp: TmpDir) !void {
3232 const target_name = "symlink-target";
3333 const symlink_name = "symlinker";
3434
......@@ -47,32 +47,15 @@ fn test_symlink(gpa: Allocator, io: Io, tmp: std.testing.TmpDir) !void {
4747 else => return err,
4848 };
4949 } else {
50 try std.posix.symlink(target_name, symlink_name);
50 try Io.Dir.cwd().symLink(io, target_name, symlink_name, .{});
5151 }
5252
5353 var buffer: [std.fs.max_path_bytes]u8 = undefined;
54 const given = try std.posix.readlink(symlink_name, buffer[0..]);
54 const given = buffer[0..try Io.Dir.cwd().readLink(io, symlink_name, &buffer)];
5555 try std.testing.expectEqualStrings(target_name, given);
5656}
5757
58fn getLinkInfo(fd: std.posix.fd_t) !struct { std.posix.ino_t, std.posix.nlink_t } {
59 if (builtin.target.os.tag == .linux) {
60 const stx = try std.os.linux.wrapped.statx(
61 fd,
62 "",
63 std.posix.AT.EMPTY_PATH,
64 .{ .INO = true, .NLINK = true },
65 );
66 std.debug.assert(stx.mask.INO);
67 std.debug.assert(stx.mask.NLINK);
68 return .{ stx.ino, stx.nlink };
69 }
70
71 const st = try std.posix.fstat(fd);
72 return .{ st.ino, st.nlink };
73}
74
75fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
58fn test_link(io: Io, tmp: TmpDir) !void {
7659 switch (builtin.target.os.tag) {
7760 .linux, .illumos => {},
7861 else => return,
......@@ -84,7 +67,7 @@ fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
8467 try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" });
8568
8669 // Test 1: create the relative link from inside tmp
87 try std.posix.link(target_name, link_name);
70 try Io.Dir.hardLink(.cwd(), target_name, .cwd(), link_name, io, .{});
8871
8972 // Verify
9073 const efd = try tmp.dir.openFile(io, target_name, .{});
......@@ -94,16 +77,54 @@ fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
9477 defer nfd.close(io);
9578
9679 {
97 const eino, _ = try getLinkInfo(efd.handle);
98 const nino, const nlink = try getLinkInfo(nfd.handle);
99 try std.testing.expectEqual(eino, nino);
100 try std.testing.expectEqual(@as(std.posix.nlink_t, 2), nlink);
80 const e_stat = try efd.stat(io);
81 const n_stat = try nfd.stat(io);
82 try std.testing.expectEqual(e_stat.inode, n_stat.inode);
83 try std.testing.expectEqual(2, n_stat.nlink);
10184 }
10285
10386 // Test 2: Remove the link and see the stats update
104 try std.posix.unlink(link_name);
87 try Io.Dir.cwd().deleteFile(io, link_name);
10588 {
106 _, const elink = try getLinkInfo(efd.handle);
107 try std.testing.expectEqual(@as(std.posix.nlink_t, 1), elink);
89 const e_stat = try efd.stat(io);
90 try std.testing.expectEqual(1, e_stat.nlink);
10891 }
10992}
93
94pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir {
95 var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
96 std.crypto.random.bytes(&random_bytes);
97 var sub_path: [TmpDir.sub_path_len]u8 = undefined;
98 _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
99
100 const cwd = Io.Dir.cwd();
101 var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch
102 @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir");
103 defer cache_dir.close(io);
104 const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch
105 @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir");
106 const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch
107 @panic("unable to make tmp dir for testing: unable to make and open the tmp dir");
108
109 return .{
110 .dir = dir,
111 .parent_dir = parent_dir,
112 .sub_path = sub_path,
113 };
114}
115
116pub const TmpDir = struct {
117 dir: Io.Dir,
118 parent_dir: Io.Dir,
119 sub_path: [sub_path_len]u8,
120
121 const random_bytes_count = 12;
122 const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count);
123
124 pub fn cleanup(self: *TmpDir, io: Io) void {
125 self.dir.close(io);
126 self.parent_dir.deleteTree(io, &self.sub_path) catch {};
127 self.parent_dir.close(io);
128 self.* = undefined;
129 }
130};
test/standalone/windows_bat_args/fuzz.zig+2-2
......@@ -44,8 +44,8 @@ pub fn main() anyerror!void {
4444 var tmp = std.testing.tmpDir(.{});
4545 defer tmp.cleanup();
4646
47 try tmp.dir.setAsCwd();
48 defer tmp.parent_dir.setAsCwd() catch {};
47 try std.process.setCurrentDir(io, tmp.dir);
48 defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
4949
5050 // `child_exe_path_orig` might be relative; make it relative to our new cwd.
5151 const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig });
test/standalone/windows_bat_args/test.zig+2-2
......@@ -18,8 +18,8 @@ pub fn main() anyerror!void {
1818 var tmp = std.testing.tmpDir(.{});
1919 defer tmp.cleanup();
2020
21 try tmp.dir.setAsCwd();
22 defer tmp.parent_dir.setAsCwd() catch {};
21 try std.process.setCurrentDir(io, tmp.dir);
22 defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
2323
2424 // `child_exe_path_orig` might be relative; make it relative to our new cwd.
2525 const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig });
test/standalone/windows_spawn/main.zig+3-3
......@@ -127,8 +127,8 @@ pub fn main() anyerror!void {
127127 try testExecError(error.FileNotFound, gpa, "goodbye");
128128
129129 // Now let's set the tmp dir as the cwd and set the path only include the "something" sub dir
130 try tmp.dir.setAsCwd();
131 defer tmp.parent_dir.setAsCwd() catch {};
130 try std.process.setCurrentDir(io, tmp.dir);
131 defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
132132 const something_subdir_abs_path = try std.mem.concatWithSentinel(gpa, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0);
133133 defer gpa.free(something_subdir_abs_path);
134134
......@@ -191,7 +191,7 @@ pub fn main() anyerror!void {
191191 defer subdir_cwd.close(io);
192192
193193 try renameExe(tmp.dir, "something/goodbye.exe", "hello.exe");
194 try subdir_cwd.setAsCwd();
194 try std.process.setCurrentDir(io, subdir_cwd);
195195
196196 // clear the PATH again
197197 std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
tools/fetch_them_macos_headers.zig+5-7
......@@ -4,7 +4,6 @@ const Dir = std.Io.Dir;
44const mem = std.mem;
55const process = std.process;
66const assert = std.debug.assert;
7const tmpDir = std.testing.tmpDir;
87const fatal = std.process.fatal;
98const info = std.log.info;
109
......@@ -111,15 +110,14 @@ pub fn main() anyerror!void {
111110 const os_ver: OsVer = @enumFromInt(version.major);
112111 info("found SDK deployment target macOS {f} aka '{t}'", .{ version, os_ver });
113112
114 var tmp = tmpDir(.{});
115 defer tmp.cleanup();
113 const tmp_dir: Io.Dir = .cwd();
116114
117115 for (&[_]Arch{ .aarch64, .x86_64 }) |arch| {
118116 const target: Target = .{
119117 .arch = arch,
120118 .os_ver = os_ver,
121119 };
122 try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp);
120 try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp_dir);
123121 }
124122}
125123
......@@ -130,11 +128,11 @@ fn fetchTarget(
130128 sysroot: []const u8,
131129 target: Target,
132130 ver: Version,
133 tmp: std.testing.TmpDir,
131 tmp_dir: Io.Dir,
134132) !void {
135133 const tmp_filename = "macos-headers";
136134 const headers_list_filename = "macos-headers.o.d";
137 const tmp_path = try tmp.dir.realPathFileAlloc(io, ".", arena);
135 const tmp_path = try tmp_dir.realPathFileAlloc(io, ".", arena);
138136 const tmp_file_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, tmp_filename });
139137 const headers_list_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, headers_list_filename });
140138
......@@ -173,7 +171,7 @@ fn fetchTarget(
173171 }
174172
175173 // Read in the contents of `macos-headers.o.d`
176 const headers_list_file = try tmp.dir.openFile(io, headers_list_filename, .{});
174 const headers_list_file = try tmp_dir.openFile(io, headers_list_filename, .{});
177175 defer headers_list_file.close(io);
178176
179177 var headers_dir = Dir.cwd().openDir(io, headers_source_prefix, .{}) catch |err| switch (err) {