Commit bfc569bc98

daurnimator <quae@daurnimator.com>
2020-01-15 09:15:24
std: add os.fstatat
1 parent 627618a
Changed files (2)
lib
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;
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,