commit fa79d346744308250c165519f842fedfc26a1c14 (tree)
parent 98e9716c082aa7e134e11ed14db8c2f631fedc8a
Author: Andrew Kelley <andrew@ziglang.org>
Date: Tue, 23 Dec 2025 22:07:31 -0800
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.
Diffstat:
12 files changed, 229 insertions(+), 116 deletions(-)
diff --git a/lib/std/Io.zig b/lib/std/Io.zig
@@ -718,6 +718,7 @@ pub const VTable = struct {
lockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!LockedStderr,
tryLockStderr: *const fn (?*anyopaque, buffer: []u8, ?Terminal.Mode) Cancelable!?LockedStderr,
unlockStderr: *const fn (?*anyopaque) void,
+ processSetCurrentDir: *const fn (?*anyopaque, Dir) std.process.SetCurrentDirError!void,
now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp,
sleep: *const fn (?*anyopaque, Timeout) SleepError!void,
diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig
@@ -648,7 +648,7 @@ pub fn init(
.main_thread = .{
.signal_id = Thread.currentSignalId(),
.current_closure = null,
- .cancel_protection = undefined,
+ .cancel_protection = .unblocked,
},
.argv0 = options.argv0,
.environ = options.environ,
@@ -689,7 +689,7 @@ pub const init_single_threaded: Threaded = .{
.main_thread = .{
.signal_id = undefined,
.current_closure = null,
- .cancel_protection = undefined,
+ .cancel_protection = .unblocked,
},
.robust_cancel = .disabled,
.argv0 = .{},
@@ -742,7 +742,7 @@ fn worker(t: *Threaded) void {
var thread: Thread = .{
.signal_id = Thread.currentSignalId(),
.current_closure = null,
- .cancel_protection = undefined,
+ .cancel_protection = .unblocked,
};
Thread.current = &thread;
@@ -844,6 +844,7 @@ pub fn io(t: *Threaded) Io {
.lockStderr = lockStderr,
.tryLockStderr = tryLockStderr,
.unlockStderr = unlockStderr,
+ .processSetCurrentDir = processSetCurrentDir,
.now = now,
.sleep = sleep,
@@ -979,6 +980,7 @@ pub fn ioBasic(t: *Threaded) Io {
.lockStderr = lockStderr,
.tryLockStderr = tryLockStderr,
.unlockStderr = unlockStderr,
+ .processSetCurrentDir = processSetCurrentDir,
.now = now,
.sleep = sleep,
@@ -7370,6 +7372,7 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex
};
defer w.CloseHandle(h_file);
+ // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks
const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &path_name_w_buf.data);
const len = std.unicode.calcWtf8Len(wide_slice);
@@ -10796,6 +10799,71 @@ fn unlockStderr(userdata: ?*anyopaque) void {
std.process.stderr_thread_mutex.unlock();
}
+fn processSetCurrentDir(userdata: ?*anyopaque, dir: Dir) std.process.SetCurrentDirError!void {
+ if (native_os == .wasi) return error.OperationUnsupported;
+ const t: *Threaded = @ptrCast(@alignCast(userdata));
+ const current_thread = Thread.getCurrent(t);
+
+ if (is_windows) {
+ try current_thread.checkCancel();
+ var dir_path_buffer: [windows.PATH_MAX_WIDE]u16 = undefined;
+ // TODO move GetFinalPathNameByHandle logic into std.Io.Threaded and add cancel checks
+ const dir_path = try windows.GetFinalPathNameByHandle(dir.handle, .{}, &dir_path_buffer);
+ const path_len_bytes = std.math.cast(u16, dir_path.len * 2) orelse return error.NameTooLong;
+ try current_thread.checkCancel();
+ var nt_name: windows.UNICODE_STRING = .{
+ .Length = path_len_bytes,
+ .MaximumLength = path_len_bytes,
+ .Buffer = @constCast(dir_path.ptr),
+ };
+ switch (windows.ntdll.RtlSetCurrentDirectory_U(&nt_name)) {
+ .SUCCESS => return,
+ .OBJECT_NAME_INVALID => return error.BadPathName,
+ .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
+ .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .NO_MEDIA_IN_DEVICE => return error.NoDevice,
+ .INVALID_PARAMETER => |err| return windows.statusBug(err),
+ .ACCESS_DENIED => return error.AccessDenied,
+ .OBJECT_PATH_SYNTAX_BAD => |err| return windows.statusBug(err),
+ .NOT_A_DIRECTORY => return error.NotDir,
+ else => |status| return windows.unexpectedStatus(status),
+ }
+ }
+
+ if (dir.handle == posix.AT.FDCWD) return;
+
+ try current_thread.beginSyscall();
+ while (true) {
+ switch (posix.errno(posix.system.fchdir(dir.handle))) {
+ .SUCCESS => return current_thread.endSyscall(),
+ .INTR => {
+ try current_thread.checkCancel();
+ continue;
+ },
+ .ACCES => {
+ current_thread.endSyscall();
+ return error.AccessDenied;
+ },
+ .BADF => |err| {
+ current_thread.endSyscall();
+ return errnoBug(err);
+ },
+ .NOTDIR => {
+ current_thread.endSyscall();
+ return error.NotDir;
+ },
+ .IO => {
+ current_thread.endSyscall();
+ return error.FileSystem;
+ },
+ else => |err| {
+ current_thread.endSyscall();
+ return posix.unexpectedErrno(err);
+ },
+ }
+ }
+}
+
pub const PosixAddress = extern union {
any: posix.sockaddr,
in: posix.sockaddr.in,
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
@@ -2939,40 +2939,6 @@ pub fn WriteFile(
return bytes_written;
}
-pub const SetCurrentDirectoryError = error{
- NameTooLong,
- FileNotFound,
- NotDir,
- AccessDenied,
- NoDevice,
- BadPathName,
- Unexpected,
-};
-
-pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void {
- const path_len_bytes = math.cast(u16, path_name.len * 2) orelse return error.NameTooLong;
-
- var nt_name: UNICODE_STRING = .{
- .Length = path_len_bytes,
- .MaximumLength = path_len_bytes,
- .Buffer = @constCast(path_name.ptr),
- };
-
- const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
- switch (rc) {
- .SUCCESS => {},
- .OBJECT_NAME_INVALID => return error.BadPathName,
- .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
- .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
- .NO_MEDIA_IN_DEVICE => return error.NoDevice,
- .INVALID_PARAMETER => unreachable,
- .ACCESS_DENIED => return error.AccessDenied,
- .OBJECT_PATH_SYNTAX_BAD => unreachable,
- .NOT_A_DIRECTORY => return error.NotDir,
- else => return unexpectedStatus(rc),
- }
-}
-
pub const GetCurrentDirectoryError = error{
NameTooLong,
Unexpected,
diff --git a/lib/std/posix.zig b/lib/std/posix.zig
@@ -1171,11 +1171,9 @@ pub const ChangeCurDirError = error{
/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
if (native_os == .wasi and !builtin.link_libc) {
- @compileError("WASI does not support os.chdir");
+ @compileError("unsupported OS");
} else if (native_os == .windows) {
- var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
- const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path);
- return chdirW(wtf16_dir_path[0..len]);
+ @compileError("unsupported OS");
} else {
const dir_path_c = try toPosixPath(dir_path);
return chdirZ(&dir_path_c);
@@ -1188,12 +1186,9 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
/// On other platforms, `dir_path` is an opaque sequence of bytes with no particular encoding.
pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
if (native_os == .windows) {
- const dir_path_span = mem.span(dir_path);
- var wtf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined;
- const len = try windows.wtf8ToWtf16Le(&wtf16_dir_path, dir_path_span);
- return chdirW(wtf16_dir_path[0..len]);
+ @compileError("unsupported OS");
} else if (native_os == .wasi and !builtin.link_libc) {
- return chdir(mem.span(dir_path));
+ @compileError("unsupported OS");
}
switch (errno(system.chdir(dir_path))) {
.SUCCESS => return,
@@ -1210,14 +1205,6 @@ pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
}
}
-/// Windows-only. Same as `chdir` except the parameter is WTF16 LE encoded.
-pub fn chdirW(dir_path: []const u16) ChangeCurDirError!void {
- windows.SetCurrentDirectory(dir_path) catch |err| switch (err) {
- error.NoDevice => return error.FileSystem,
- else => |e| return e,
- };
-}
-
pub const FchdirError = error{
AccessDenied,
NotDir,
diff --git a/lib/std/process.zig b/lib/std/process.zig
@@ -2304,3 +2304,28 @@ pub fn exit(status: u8) noreturn {
else => posix.system.exit(status),
}
}
+
+pub const SetCurrentDirError = error{
+ AccessDenied,
+ BadPathName,
+ FileNotFound,
+ FileSystem,
+ NameTooLong,
+ NoDevice,
+ NotDir,
+ OperationUnsupported,
+ UnrecognizedVolume,
+} || Io.Cancelable || Io.UnexpectedError;
+
+/// Changes the current working directory to the open directory handle.
+/// Corresponds to "fchdir" in libc.
+///
+/// This modifies global process state and can have surprising effects in
+/// multithreaded applications. Most applications and especially libraries
+/// should not call this function as a general rule, however it can have use
+/// cases in, for example, implementing a shell, or child process execution.
+///
+/// Calling this function makes code less portable and less reusable.
+pub fn setCurrentDir(io: Io, dir: Io.Dir) !void {
+ return io.vtable.processSetCurrentDir(io.userdata, dir);
+}
diff --git a/lib/std/testing.zig b/lib/std/testing.zig
@@ -629,6 +629,7 @@ pub const TmpDir = struct {
};
pub fn tmpDir(opts: Io.Dir.OpenOptions) TmpDir {
+ comptime assert(builtin.is_test);
var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
std.crypto.random.bytes(&random_bytes);
var sub_path: [TmpDir.sub_path_len]u8 = undefined;
diff --git a/test/standalone/posix/cwd.zig b/test/standalone/posix/cwd.zig
@@ -1,6 +1,10 @@
-const std = @import("std");
const builtin = @import("builtin");
+const std = @import("std");
+const Io = std.Io;
+const Allocator = std.mem.Allocator;
+const assert = std.debug.assert;
+
const path_max = std.fs.max_path_bytes;
pub fn main() !void {
@@ -9,13 +13,17 @@ pub fn main() !void {
return;
}
- var Allocator = std.heap.DebugAllocator(.{}){};
- const a = Allocator.allocator();
- defer std.debug.assert(Allocator.deinit() == .ok);
+ var debug_allocator: std.heap.DebugAllocator(.{}) = .{};
+ defer assert(debug_allocator.deinit() == .ok);
+ const gpa = debug_allocator.allocator();
+
+ var threaded: std.Io.Threaded = .init(gpa, .{});
+ defer threaded.deinit();
+ const io = threaded.io();
try test_chdir_self();
try test_chdir_absolute();
- try test_chdir_relative(a);
+ try test_chdir_relative(gpa, io);
}
// get current working directory and expect it to match given path
@@ -46,20 +54,20 @@ fn test_chdir_absolute() !void {
try expect_cwd(parent);
}
-fn test_chdir_relative(a: std.mem.Allocator) !void {
- var tmp = std.testing.tmpDir(.{});
- defer tmp.cleanup();
+fn test_chdir_relative(gpa: Allocator, io: Io) !void {
+ var tmp = tmpDir(io, .{});
+ defer tmp.cleanup(io);
// Use the tmpDir parent_dir as the "base" for the test. Then cd into the child
- try tmp.parent_dir.setAsCwd();
+ try std.process.setCurrentDir(io, tmp.parent_dir);
// Capture base working directory path, to build expected full path
var base_cwd_buf: [path_max]u8 = undefined;
const base_cwd = try std.posix.getcwd(base_cwd_buf[0..]);
const relative_dir_name = &tmp.sub_path;
- const expected_path = try std.fs.path.resolve(a, &.{ base_cwd, relative_dir_name });
- defer a.free(expected_path);
+ const expected_path = try std.fs.path.resolve(gpa, &.{ base_cwd, relative_dir_name });
+ defer gpa.free(expected_path);
// change current working directory to new test directory
try std.posix.chdir(relative_dir_name);
@@ -68,8 +76,46 @@ fn test_chdir_relative(a: std.mem.Allocator) !void {
const new_cwd = try std.posix.getcwd(new_cwd_buf[0..]);
// On Windows, fs.path.resolve returns an uppercase drive letter, but the drive letter returned by getcwd may be lowercase
- const resolved_cwd = try std.fs.path.resolve(a, &.{new_cwd});
- defer a.free(resolved_cwd);
+ const resolved_cwd = try std.fs.path.resolve(gpa, &.{new_cwd});
+ defer gpa.free(resolved_cwd);
try std.testing.expectEqualStrings(expected_path, resolved_cwd);
}
+
+pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir {
+ var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
+ std.crypto.random.bytes(&random_bytes);
+ var sub_path: [TmpDir.sub_path_len]u8 = undefined;
+ _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
+
+ const cwd = Io.Dir.cwd();
+ var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch
+ @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir");
+ defer cache_dir.close(io);
+ const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch
+ @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir");
+ const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch
+ @panic("unable to make tmp dir for testing: unable to make and open the tmp dir");
+
+ return .{
+ .dir = dir,
+ .parent_dir = parent_dir,
+ .sub_path = sub_path,
+ };
+}
+
+pub const TmpDir = struct {
+ dir: Io.Dir,
+ parent_dir: Io.Dir,
+ sub_path: [sub_path_len]u8,
+
+ const random_bytes_count = 12;
+ const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count);
+
+ pub fn cleanup(self: *TmpDir, io: Io) void {
+ self.dir.close(io);
+ self.parent_dir.deleteTree(io, &self.sub_path) catch {};
+ self.parent_dir.close(io);
+ self.* = undefined;
+ }
+};
diff --git a/test/standalone/posix/relpaths.zig b/test/standalone/posix/relpaths.zig
@@ -14,21 +14,21 @@ pub fn main() !void {
const gpa = debug_allocator.allocator();
defer std.debug.assert(debug_allocator.deinit() == .ok);
- const io = std.Io.Threaded.global_single_threaded.ioBasic();
+ var threaded: std.Io.Threaded = .init(gpa, .{});
+ defer threaded.deinit();
+ const io = threaded.io();
- // TODO this API isn't supposed to be used outside of unit testing. make it compilation error if used
- // outside of unit testing.
- var tmp = std.testing.tmpDir(.{});
- defer tmp.cleanup();
+ var tmp = tmpDir(io, .{});
+ defer tmp.cleanup(io);
// Want to test relative paths, so cd into the tmpdir for these tests
- try tmp.dir.setAsCwd();
+ try std.process.setCurrentDir(io, tmp.dir);
try test_symlink(gpa, io, tmp);
try test_link(io, tmp);
}
-fn test_symlink(gpa: Allocator, io: Io, tmp: std.testing.TmpDir) !void {
+fn test_symlink(gpa: Allocator, io: Io, tmp: TmpDir) !void {
const target_name = "symlink-target";
const symlink_name = "symlinker";
@@ -47,32 +47,15 @@ fn test_symlink(gpa: Allocator, io: Io, tmp: std.testing.TmpDir) !void {
else => return err,
};
} else {
- try std.posix.symlink(target_name, symlink_name);
+ try Io.Dir.cwd().symLink(io, target_name, symlink_name, .{});
}
var buffer: [std.fs.max_path_bytes]u8 = undefined;
- const given = try std.posix.readlink(symlink_name, buffer[0..]);
+ const given = buffer[0..try Io.Dir.cwd().readLink(io, symlink_name, &buffer)];
try std.testing.expectEqualStrings(target_name, given);
}
-fn getLinkInfo(fd: std.posix.fd_t) !struct { std.posix.ino_t, std.posix.nlink_t } {
- if (builtin.target.os.tag == .linux) {
- const stx = try std.os.linux.wrapped.statx(
- fd,
- "",
- std.posix.AT.EMPTY_PATH,
- .{ .INO = true, .NLINK = true },
- );
- std.debug.assert(stx.mask.INO);
- std.debug.assert(stx.mask.NLINK);
- return .{ stx.ino, stx.nlink };
- }
-
- const st = try std.posix.fstat(fd);
- return .{ st.ino, st.nlink };
-}
-
-fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
+fn test_link(io: Io, tmp: TmpDir) !void {
switch (builtin.target.os.tag) {
.linux, .illumos => {},
else => return,
@@ -84,7 +67,7 @@ fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" });
// Test 1: create the relative link from inside tmp
- try std.posix.link(target_name, link_name);
+ try Io.Dir.hardLink(.cwd(), target_name, .cwd(), link_name, io, .{});
// Verify
const efd = try tmp.dir.openFile(io, target_name, .{});
@@ -94,16 +77,54 @@ fn test_link(io: Io, tmp: std.testing.TmpDir) !void {
defer nfd.close(io);
{
- const eino, _ = try getLinkInfo(efd.handle);
- const nino, const nlink = try getLinkInfo(nfd.handle);
- try std.testing.expectEqual(eino, nino);
- try std.testing.expectEqual(@as(std.posix.nlink_t, 2), nlink);
+ const e_stat = try efd.stat(io);
+ const n_stat = try nfd.stat(io);
+ try std.testing.expectEqual(e_stat.inode, n_stat.inode);
+ try std.testing.expectEqual(2, n_stat.nlink);
}
// Test 2: Remove the link and see the stats update
- try std.posix.unlink(link_name);
+ try Io.Dir.cwd().deleteFile(io, link_name);
{
- _, const elink = try getLinkInfo(efd.handle);
- try std.testing.expectEqual(@as(std.posix.nlink_t, 1), elink);
+ const e_stat = try efd.stat(io);
+ try std.testing.expectEqual(1, e_stat.nlink);
}
}
+
+pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir {
+ var random_bytes: [TmpDir.random_bytes_count]u8 = undefined;
+ std.crypto.random.bytes(&random_bytes);
+ var sub_path: [TmpDir.sub_path_len]u8 = undefined;
+ _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes);
+
+ const cwd = Io.Dir.cwd();
+ var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch
+ @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir");
+ defer cache_dir.close(io);
+ const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch
+ @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir");
+ const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch
+ @panic("unable to make tmp dir for testing: unable to make and open the tmp dir");
+
+ return .{
+ .dir = dir,
+ .parent_dir = parent_dir,
+ .sub_path = sub_path,
+ };
+}
+
+pub const TmpDir = struct {
+ dir: Io.Dir,
+ parent_dir: Io.Dir,
+ sub_path: [sub_path_len]u8,
+
+ const random_bytes_count = 12;
+ const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count);
+
+ pub fn cleanup(self: *TmpDir, io: Io) void {
+ self.dir.close(io);
+ self.parent_dir.deleteTree(io, &self.sub_path) catch {};
+ self.parent_dir.close(io);
+ self.* = undefined;
+ }
+};
diff --git a/test/standalone/windows_bat_args/fuzz.zig b/test/standalone/windows_bat_args/fuzz.zig
@@ -44,8 +44,8 @@ pub fn main() anyerror!void {
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
- try tmp.dir.setAsCwd();
- defer tmp.parent_dir.setAsCwd() catch {};
+ try std.process.setCurrentDir(io, tmp.dir);
+ defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
// `child_exe_path_orig` might be relative; make it relative to our new cwd.
const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig });
diff --git a/test/standalone/windows_bat_args/test.zig b/test/standalone/windows_bat_args/test.zig
@@ -18,8 +18,8 @@ pub fn main() anyerror!void {
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
- try tmp.dir.setAsCwd();
- defer tmp.parent_dir.setAsCwd() catch {};
+ try std.process.setCurrentDir(io, tmp.dir);
+ defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
// `child_exe_path_orig` might be relative; make it relative to our new cwd.
const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig });
diff --git a/test/standalone/windows_spawn/main.zig b/test/standalone/windows_spawn/main.zig
@@ -127,8 +127,8 @@ pub fn main() anyerror!void {
try testExecError(error.FileNotFound, gpa, "goodbye");
// Now let's set the tmp dir as the cwd and set the path only include the "something" sub dir
- try tmp.dir.setAsCwd();
- defer tmp.parent_dir.setAsCwd() catch {};
+ try std.process.setCurrentDir(io, tmp.dir);
+ defer std.process.setCurrentDir(io, tmp.parent_dir) catch {};
const something_subdir_abs_path = try std.mem.concatWithSentinel(gpa, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0);
defer gpa.free(something_subdir_abs_path);
@@ -191,7 +191,7 @@ pub fn main() anyerror!void {
defer subdir_cwd.close(io);
try renameExe(tmp.dir, "something/goodbye.exe", "hello.exe");
- try subdir_cwd.setAsCwd();
+ try std.process.setCurrentDir(io, subdir_cwd);
// clear the PATH again
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
diff --git a/tools/fetch_them_macos_headers.zig b/tools/fetch_them_macos_headers.zig
@@ -4,7 +4,6 @@ const Dir = std.Io.Dir;
const mem = std.mem;
const process = std.process;
const assert = std.debug.assert;
-const tmpDir = std.testing.tmpDir;
const fatal = std.process.fatal;
const info = std.log.info;
@@ -111,15 +110,14 @@ pub fn main() anyerror!void {
const os_ver: OsVer = @enumFromInt(version.major);
info("found SDK deployment target macOS {f} aka '{t}'", .{ version, os_ver });
- var tmp = tmpDir(.{});
- defer tmp.cleanup();
+ const tmp_dir: Io.Dir = .cwd();
for (&[_]Arch{ .aarch64, .x86_64 }) |arch| {
const target: Target = .{
.arch = arch,
.os_ver = os_ver,
};
- try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp);
+ try fetchTarget(allocator, io, argv.items, sysroot_path, target, version, tmp_dir);
}
}
@@ -130,11 +128,11 @@ fn fetchTarget(
sysroot: []const u8,
target: Target,
ver: Version,
- tmp: std.testing.TmpDir,
+ tmp_dir: Io.Dir,
) !void {
const tmp_filename = "macos-headers";
const headers_list_filename = "macos-headers.o.d";
- const tmp_path = try tmp.dir.realPathFileAlloc(io, ".", arena);
+ const tmp_path = try tmp_dir.realPathFileAlloc(io, ".", arena);
const tmp_file_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, tmp_filename });
const headers_list_path = try Dir.path.join(arena, &[_][]const u8{ tmp_path, headers_list_filename });
@@ -173,7 +171,7 @@ fn fetchTarget(
}
// Read in the contents of `macos-headers.o.d`
- const headers_list_file = try tmp.dir.openFile(io, headers_list_filename, .{});
+ const headers_list_file = try tmp_dir.openFile(io, headers_list_filename, .{});
defer headers_list_file.close(io);
var headers_dir = Dir.cwd().openDir(io, headers_source_prefix, .{}) catch |err| switch (err) {