authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 23:31:47-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-23 23:31:47-08:00
loga901e9241396a11f807bf40bbd548e25f120deab
tree9213c467a66e4ff9f6df940f398448e5fb10912a
parent2708a3c1ac9f63cce10b70c780dd7b1530d9c26b

std.Io.Threaded: implement process executable path on darwin


2 files changed, 32 insertions(+), 13 deletions(-)

lib/std/Io/Threaded.zig+31-12
......@@ -7152,7 +7152,30 @@ fn processExecutableOpen(userdata: ?*anyopaque, flags: File.OpenFlags) std.proce
71527152 const prefixed_path_w = try windows.wToPrefixedFileW(null, image_path_name);
71537153 return dirOpenFileWtf16(t, null, prefixed_path_w.span(), flags);
71547154 },
7155 else => @panic("TODO implement processExecutableOpen"),
7155 .driverkit,
7156 .ios,
7157 .maccatalyst,
7158 .macos,
7159 .tvos,
7160 .visionos,
7161 .watchos,
7162 => {
7163 // _NSGetExecutablePath() returns a path that might be a symlink to
7164 // the executable. Here it does not matter since we open it.
7165 var symlink_path_buf: [posix.PATH_MAX + 1]u8 = undefined;
7166 var n: u32 = symlink_path_buf.len;
7167 const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &n);
7168 if (rc != 0) return error.NameTooLong;
7169 const symlink_path = std.mem.sliceTo(&symlink_path_buf, 0);
7170 return dirOpenFilePosix(t, .cwd(), symlink_path, flags);
7171 },
7172 else => {
7173 var buffer: [Dir.max_path_bytes]u8 = undefined;
7174 const n = try processExecutablePath(t, &buffer);
7175 buffer[n] = 0;
7176 const executable_path = buffer[0..n :0];
7177 return dirOpenFilePosix(t, .cwd(), executable_path, flags);
7178 },
71567179 }
71577180}
71587181
......@@ -7168,21 +7191,17 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex
71687191 .visionos,
71697192 .watchos,
71707193 => {
7171 // Note that _NSGetExecutablePath() will return "a path" to
7172 // the executable not a "real path" to the executable.
7173 var symlink_path_buf: [posix.PATH_MAX:0]u8 = undefined;
7174 var u32_len: u32 = posix.PATH_MAX + 1; // include the sentinel
7175 const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len);
7194 // _NSGetExecutablePath() returns a path that might be a symlink to
7195 // the executable.
7196 var symlink_path_buf: [posix.PATH_MAX + 1]u8 = undefined;
7197 var n: u32 = symlink_path_buf.len;
7198 const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &n);
71767199 if (rc != 0) return error.NameTooLong;
7177
7178 var real_path_buf: [posix.PATH_MAX]u8 = undefined;
7179 const n = Io.Dir.realPathFileAbsolute(ioBasic(t), &symlink_path_buf, &real_path_buf) catch |err| switch (err) {
7200 const symlink_path = std.mem.sliceTo(&symlink_path_buf, 0);
7201 return Io.Dir.realPathFileAbsolute(ioBasic(t), symlink_path, out_buffer) catch |err| switch (err) {
71807202 error.NetworkNotFound => unreachable, // Windows-only
71817203 else => |e| return e,
71827204 };
7183 if (n > out_buffer.len) return error.NameTooLong;
7184 @memcpy(out_buffer[0..n], real_path_buf[0..n]);
7185 return n;
71867205 },
71877206 .linux, .serenity => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/exe", out_buffer) catch |err| switch (err) {
71887207 error.UnsupportedReparsePointType => unreachable, // Windows-only
lib/std/c/darwin.zig+1-1
......@@ -349,7 +349,7 @@ pub const VM = struct {
349349pub const exception_type_t = c_int;
350350
351351pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
352pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
352pub extern "c" fn _NSGetExecutablePath(buf: [*]u8, bufsize: *u32) c_int;
353353pub extern "c" fn _dyld_image_count() u32;
354354pub extern "c" fn _dyld_get_image_header(image_index: u32) ?*mach_header;
355355pub extern "c" fn _dyld_get_image_vmaddr_slide(image_index: u32) usize;