diff --git a/lib/std/c.zig b/lib/std/c.zig index 84a9e92dee..7c01908540 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -75,6 +75,7 @@ pub extern "c" fn isatty(fd: fd_t) c_int; pub extern "c" fn close(fd: fd_t) c_int; pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int; pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int; +pub extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, flags: u32) c_int; pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t; pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int; pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int; diff --git a/lib/std/os.zig b/lib/std/os.zig index 7563a34f21..a74a2343a6 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2371,6 +2371,29 @@ pub fn fstat(fd: fd_t) FStatError!Stat { } } +const FStatAtError = FStatError || error{NameTooLong}; + +pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError![]Stat { + const pathname_c = try toPosixPath(pathname); + return fstatatC(dirfd, &pathname_c, flags); +} + +pub fn fstatatC(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat { + var stat: Stat = undefined; + switch (errno(system.fstatat(dirfd, pathname, &stat, flags))) { + 0 => return stat, + EINVAL => unreachable, + EBADF => unreachable, // Always a race condition. + ENOMEM => return error.SystemResources, + EACCES => return error.AccessDenied, + EFAULT => unreachable, + ENAMETOOLONG => return error.NameTooLong, + ENOENT => return error.FileNotFound, + ENOTDIR => return error.FileNotFound, + else => |err| return unexpectedErrno(err), + } +} + pub const KQueueError = error{ /// The per-process limit on the number of open file descriptors has been reached. ProcessFdQuotaExceeded,