getFdPath
Return canonical path of handle fd.
This function is very host-specific and is not universally supported by all hosts. For example, while it generally works on Linux, macOS, FreeBSD or Windows, it is unsupported on WASI.
- On Windows, the result is encoded as WTF-8.
- On other platforms, the result is an opaque sequence of bytes with no particular encoding.
Calling this function is usually a bug.
Function parameters
Parameters
- fd:std.posix.fd_t
- out_buffer:*[max_path_bytes]u8
Type definitions in this namespace
Types
Call from Windows-specific code if you already have a WTF-16LE encoded, null terminated string.
Functions
- accessW
- Call from Windows-specific code if you already have a WTF-16LE encoded, null terminated string.
- getFdPath
- Return canonical path of handle `fd`.
- fstatat_wasi
- WASI-only.
See also `getenv`.
Values
Source
Implementation
pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.RealPathError![]u8 {
if (!comptime isGetFdPathSupportedOnTarget(builtin.os)) {
@compileError("querying for canonical path of a handle is unsupported on this host");
}
switch (native_os) {
.windows => {
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
const wide_slice = try windows.GetFinalPathNameByHandle(fd, .{}, wide_buf[0..]);
const end_index = std.unicode.wtf16LeToWtf8(out_buffer, wide_slice);
return out_buffer[0..end_index];
},
.macos, .ios, .watchos, .tvos, .visionos => {
// On macOS, we can use F.GETPATH fcntl command to query the OS for
// the path to the file descriptor.
@memset(out_buffer[0..max_path_bytes], 0);
switch (posix.errno(posix.system.fcntl(fd, posix.F.GETPATH, out_buffer))) {
.SUCCESS => {},
.BADF => return error.FileNotFound,
.NOSPC => return error.NameTooLong,
.NOENT => return error.FileNotFound,
// TODO man pages for fcntl on macOS don't really tell you what
// errno values to expect when command is F.GETPATH...
else => |err| return posix.unexpectedErrno(err),
}
const len = mem.indexOfScalar(u8, out_buffer[0..], 0) orelse max_path_bytes;
return out_buffer[0..len];
},
.linux, .serenity => {
var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;
const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/fd/{d}", .{fd}) catch unreachable;
const target = posix.readlinkZ(proc_path, out_buffer) catch |err| {
switch (err) {
error.NotLink => unreachable,
error.BadPathName => unreachable,
error.InvalidUtf8 => unreachable, // WASI-only
error.InvalidWtf8 => unreachable, // Windows-only
error.UnsupportedReparsePointType => unreachable, // Windows-only
error.NetworkNotFound => unreachable, // Windows-only
else => |e| return e,
}
};
return target;
},
.solaris, .illumos => {
var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined;
const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/path/{d}", .{fd}) catch unreachable;
const target = posix.readlinkZ(proc_path, out_buffer) catch |err| switch (err) {
error.UnsupportedReparsePointType => unreachable,
error.NotLink => unreachable,
error.InvalidUtf8 => unreachable, // WASI-only
else => |e| return e,
};
return target;
},
.freebsd => {
var kfile: std.c.kinfo_file = undefined;
kfile.structsize = std.c.KINFO_FILE_SIZE;
switch (posix.errno(std.c.fcntl(fd, std.c.F.KINFO, @intFromPtr(&kfile)))) {
.SUCCESS => {},
.BADF => return error.FileNotFound,
else => |err| return posix.unexpectedErrno(err),
}
const len = mem.indexOfScalar(u8, &kfile.path, 0) orelse max_path_bytes;
if (len == 0) return error.NameTooLong;
const result = out_buffer[0..len];
@memcpy(result, kfile.path[0..len]);
return result;
},
.dragonfly => {
@memset(out_buffer[0..max_path_bytes], 0);
switch (posix.errno(std.c.fcntl(fd, posix.F.GETPATH, out_buffer))) {
.SUCCESS => {},
.BADF => return error.FileNotFound,
.RANGE => return error.NameTooLong,
else => |err| return posix.unexpectedErrno(err),
}
const len = mem.indexOfScalar(u8, out_buffer[0..], 0) orelse max_path_bytes;
return out_buffer[0..len];
},
.netbsd => {
@memset(out_buffer[0..max_path_bytes], 0);
switch (posix.errno(std.c.fcntl(fd, posix.F.GETPATH, out_buffer))) {
.SUCCESS => {},
.ACCES => return error.AccessDenied,
.BADF => return error.FileNotFound,
.NOENT => return error.FileNotFound,
.NOMEM => return error.SystemResources,
.RANGE => return error.NameTooLong,
else => |err| return posix.unexpectedErrno(err),
}
const len = mem.indexOfScalar(u8, out_buffer[0..], 0) orelse max_path_bytes;
return out_buffer[0..len];
},
else => unreachable, // made unreachable by isGetFdPathSupportedOnTarget above
}
}