| ... | @@ -5131,20 +5131,54 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | ... | @@ -5131,20 +5131,54 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { |
| 5131 | return target; | 5131 | return target; |
| 5132 | }, | 5132 | }, |
| 5133 | .freebsd => { | 5133 | .freebsd => { |
| 5134 | comptime if (builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0 }) == .lt) | 5134 | if (comptime builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0 }) == .gt) { |
| 5135 | @compileError("querying for canonical path of a handle is unsupported on FreeBSD 12 and below"); | 5135 | var kfile: system.kinfo_file = undefined; |
| 5136 | | 5136 | kfile.structsize = system.KINFO_FILE_SIZE; |
| 5137 | var kfile: system.kinfo_file = undefined; | 5137 | switch (errno(system.fcntl(fd, system.F.KINFO, @ptrToInt(&kfile)))) { |
| 5138 | kfile.structsize = system.KINFO_FILE_SIZE; | 5138 | .SUCCESS => {}, |
| 5139 | switch (errno(system.fcntl(fd, system.F.KINFO, @ptrToInt(&kfile)))) { | 5139 | .BADF => return error.FileNotFound, |
| 5140 | .SUCCESS => {}, | 5140 | else => |err| return unexpectedErrno(err), |
| 5141 | .BADF => return error.FileNotFound, | 5141 | } |
| 5142 | else => |err| return unexpectedErrno(err), | 5142 | const len = mem.indexOfScalar(u8, &kfile.path, 0) orelse MAX_PATH_BYTES; |
| | 5143 | mem.copy(u8, out_buffer, kfile.path[0..len]); |
| | 5144 | return out_buffer[0..len]; |
| | 5145 | } else { |
| | 5146 | // This fallback implementation reimplements libutil's `kinfo_getfile()`. |
| | 5147 | // The motivation is to avoid linking -lutil when building zig or general |
| | 5148 | // user executables. |
| | 5149 | var mib = [4]c_int{ CTL.KERN, KERN.PROC, KERN.PROC_FILEDESC, system.getpid() }; |
| | 5150 | var len: usize = undefined; |
| | 5151 | sysctl(&mib, null, &len, null, 0) catch |err| switch (err) { |
| | 5152 | error.PermissionDenied => unreachable, |
| | 5153 | error.SystemResources => return error.SystemResources, |
| | 5154 | error.NameTooLong => unreachable, |
| | 5155 | error.UnknownName => unreachable, |
| | 5156 | else => return error.Unexpected, |
| | 5157 | }; |
| | 5158 | len = len * 4 / 3; |
| | 5159 | const buf = std.heap.c_allocator.alloc(u8, len) catch return error.SystemResources; |
| | 5160 | defer std.heap.c_allocator.free(buf); |
| | 5161 | len = buf.len; |
| | 5162 | sysctl(&mib, &buf[0], &len, null, 0) catch |err| switch (err) { |
| | 5163 | error.PermissionDenied => unreachable, |
| | 5164 | error.SystemResources => return error.SystemResources, |
| | 5165 | error.NameTooLong => unreachable, |
| | 5166 | error.UnknownName => unreachable, |
| | 5167 | else => return error.Unexpected, |
| | 5168 | }; |
| | 5169 | var i: usize = 0; |
| | 5170 | while (i < len) { |
| | 5171 | const kf: *align(1) system.kinfo_file = @ptrCast(*align(1) system.kinfo_file, &buf[i]); |
| | 5172 | if (kf.fd == fd) { |
| | 5173 | len = mem.indexOfScalar(u8, &kf.path, 0) orelse MAX_PATH_BYTES; |
| | 5174 | if (len == 0) return error.NameTooLong; |
| | 5175 | mem.copy(u8, out_buffer, kf.path[0..len]); |
| | 5176 | return out_buffer[0..len]; |
| | 5177 | } |
| | 5178 | i += @intCast(usize, kf.structsize); |
| | 5179 | } |
| | 5180 | return error.InvalidHandle; |
| 5143 | } | 5181 | } |
| 5144 | | | |
| 5145 | const len = mem.indexOfScalar(u8, &kfile.path, 0) orelse MAX_PATH_BYTES; | | |
| 5146 | mem.copy(u8, out_buffer, kfile.path[0..len]); | | |
| 5147 | return out_buffer[0..len]; | | |
| 5148 | }, | 5182 | }, |
| 5149 | else => @compileError("querying for canonical path of a handle is unsupported on this host"), | 5183 | else => @compileError("querying for canonical path of a handle is unsupported on this host"), |
| 5150 | } | 5184 | } |