feature. See also
. The project being documented here (as the example) is the Zig library itself.
Threaded.realPathPosix
fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize
File
Code
fn realPathPosix(fd: posix.fd_t, out_buffer: []u8) File.RealPathError!usize {
switch (native_os) {
.dragonfly, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => {
var sufficient_buffer: [posix.PATH_MAX]u8 = undefined;
@memset(&sufficient_buffer, 0);
const syscall: Syscall = try .start();
while (true) {
switch (posix.errno(posix.system.fcntl(fd, posix.F.GETPATH, &sufficient_buffer))) {
.SUCCESS => {
syscall.finish();
break;
},
.INTR => {
try syscall.checkCancel();
continue;
},
else => |e| {
syscall.finish();
switch (e) {
.ACCES => return error.AccessDenied,
.BADF => return error.FileNotFound,
.NOENT => return error.FileNotFound,
.NOMEM => return error.SystemResources,
.NOSPC => return error.NameTooLong,
.RANGE => return error.NameTooLong,
else => |err| return posix.unexpectedErrno(err),
}
},
}
}
const n = std.mem.indexOfScalar(u8, &sufficient_buffer, 0) orelse sufficient_buffer.len;
if (n > out_buffer.len) return error.NameTooLong;
@memcpy(out_buffer[0..n], sufficient_buffer[0..n]);
return n;
},
.linux, .serenity, .illumos => {
var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined;
const template = if (native_os == .illumos) "/proc/self/path/{d}" else "/proc/self/fd/{d}";
const proc_path = std.fmt.bufPrintSentinel(&procfs_buf, template, .{fd}, 0) catch unreachable;
const syscall: Syscall = try .start();
while (true) {
const rc = posix.system.readlink(proc_path, out_buffer.ptr, out_buffer.len);
switch (posix.errno(rc)) {
.SUCCESS => {
syscall.finish();
const len: usize = @bitCast(rc);
return len;
},
.INTR => {
try syscall.checkCancel();
continue;
},
else => |e| {
syscall.finish();
switch (e) {
.ACCES => return error.AccessDenied,
.FAULT => |err| return errnoBug(err),
.IO => return error.FileSystem,
.LOOP => return error.SymLinkLoop,
.NAMETOOLONG => return error.NameTooLong,
.NOENT => return error.FileNotFound,
.NOMEM => return error.SystemResources,
.NOTDIR => return error.NotDir,
.ILSEQ => |err| return errnoBug(err),
else => |err| return posix.unexpectedErrno(err),
}
},
}
}
},
.freebsd => {
var k_file: std.c.kinfo_file = undefined;
k_file.structsize = std.c.KINFO_FILE_SIZE;
const syscall: Syscall = try .start();
while (true) {
switch (posix.errno(std.c.fcntl(fd, std.c.F.KINFO, @intFromPtr(&k_file)))) {
.SUCCESS => {
syscall.finish();
break;
},
.INTR => {
try syscall.checkCancel();
continue;
},
.BADF => {
syscall.finish();
return error.FileNotFound;
},
else => |err| {
syscall.finish();
return posix.unexpectedErrno(err);
},
}
}
const len = std.mem.findScalar(u8, &k_file.path, 0) orelse k_file.path.len;
if (len == 0) return error.NameTooLong;
@memcpy(out_buffer[0..len], k_file.path[0..len]);
return len;
},
else => return error.OperationUnsupported,
}
comptime unreachable;
}