| ... | ... | @@ -2162,7 +2162,7 @@ pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File { |
| 2162 | 2162 | return openFileAbsoluteZ(buf[0..self_exe_path.len :0].ptr, flags); |
| 2163 | 2163 | } |
| 2164 | 2164 | |
| 2165 | | pub const SelfExePathError = os.ReadLinkError || os.SysCtlError; |
| 2165 | pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathError; |
| 2166 | 2166 | |
| 2167 | 2167 | /// `selfExePath` except allocates the result on the heap. |
| 2168 | 2168 | /// Caller owns returned memory. |
| ... | ... | @@ -2190,10 +2190,18 @@ pub fn selfExePathAlloc(allocator: *Allocator) ![]u8 { |
| 2190 | 2190 | /// TODO make the return type of this a null terminated pointer |
| 2191 | 2191 | pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { |
| 2192 | 2192 | if (is_darwin) { |
| 2193 | | var u32_len: u32 = @intCast(u32, math.min(out_buffer.len, math.maxInt(u32))); |
| 2194 | | const rc = std.c._NSGetExecutablePath(out_buffer.ptr, &u32_len); |
| 2193 | // Note that _NSGetExecutablePath() will return "a path" to |
| 2194 | // the executable not a "real path" to the executable. |
| 2195 | var symlink_path_buf: [MAX_PATH_BYTES]u8 = undefined; |
| 2196 | var u32_len: u32 = MAX_PATH_BYTES; |
| 2197 | const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len); |
| 2195 | 2198 | if (rc != 0) return error.NameTooLong; |
| 2196 | | return mem.spanZ(@ptrCast([*:0]u8, out_buffer)); |
| 2199 | |
| 2200 | var real_path_buf: [MAX_PATH_BYTES]u8 = undefined; |
| 2201 | const real_path = try std.os.realpathZ(@ptrCast([*:0]u8, &symlink_path_buf), &real_path_buf); |
| 2202 | if (real_path.len > out_buffer.len) return error.NameTooLong; |
| 2203 | std.mem.copy(u8, out_buffer, real_path); |
| 2204 | return out_buffer[0..real_path.len]; |
| 2197 | 2205 | } |
| 2198 | 2206 | switch (builtin.os.tag) { |
| 2199 | 2207 | .linux => return os.readlinkZ("/proc/self/exe", out_buffer), |