Commit 13945548fc
lib/std/fs/Dir.zig
@@ -334,7 +334,6 @@ pub const Iterator = switch (native_os) {
first_iter: bool,
const Self = @This();
- const linux = std.os.linux;
pub const Error = IteratorError;
@@ -2690,8 +2689,33 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true });
return Stat.fromWasi(st);
}
+ if (native_os == .linux) {
+ const sub_path_c = try posix.toPosixPath(sub_path);
+ var stx = std.mem.zeroes(linux.Statx);
+
+ const rc = linux.statx(
+ self.fd,
+ &sub_path_c,
+ linux.AT.NO_AUTOMOUNT,
+ linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
+ &stx,
+ );
+
+ return switch (linux.E.init(rc)) {
+ .SUCCESS => Stat.fromLinux(stx),
+ .ACCES => error.AccessDenied,
+ .BADF => unreachable,
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ .LOOP => error.SymLinkLoop,
+ .NAMETOOLONG => unreachable, // Handled by posix.toPosixPath() above.
+ .NOENT, .NOTDIR => error.FileNotFound,
+ .NOMEM => error.SystemResources,
+ else => |err| posix.unexpectedErrno(err),
+ };
+ }
const st = try posix.fstatat(self.fd, sub_path, 0);
- return Stat.fromSystem(st);
+ return Stat.fromPosix(st);
}
pub const ChmodError = File.ChmodError;
@@ -2751,6 +2775,7 @@ const path = fs.path;
const fs = std.fs;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
+const linux = std.os.linux;
const windows = std.os.windows;
const native_os = builtin.os.tag;
const have_flock = @TypeOf(posix.system.flock) != void;
lib/std/fs/File.zig
@@ -342,7 +342,7 @@ pub fn seekTo(self: File, offset: u64) SeekError!void {
return posix.lseek_SET(self.handle, offset);
}
-pub const GetSeekPosError = posix.SeekError || posix.FStatError;
+pub const GetSeekPosError = posix.SeekError || StatError;
/// TODO: integrate with async I/O
pub fn getPos(self: File) GetSeekPosError!u64 {
@@ -357,7 +357,7 @@ pub fn getEndPos(self: File) GetSeekPosError!u64 {
return (try self.stat()).size;
}
-pub const ModeError = posix.FStatError;
+pub const ModeError = StatError;
/// TODO: integrate with async I/O
pub fn mode(self: File) ModeError!Mode {
@@ -392,7 +392,7 @@ pub const Stat = struct {
/// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01.
ctime: i128,
- pub fn fromSystem(st: posix.Stat) Stat {
+ pub fn fromPosix(st: posix.Stat) Stat {
const atime = st.atime();
const mtime = st.mtime();
const ctime = st.ctime();
@@ -426,6 +426,31 @@ pub const Stat = struct {
};
}
+ pub fn fromLinux(stx: linux.Statx) Stat {
+ const atime = stx.atime;
+ const mtime = stx.mtime;
+ const ctime = stx.ctime;
+
+ return .{
+ .inode = stx.ino,
+ .size = stx.size,
+ .mode = stx.mode,
+ .kind = switch (stx.mode & linux.S.IFMT) {
+ linux.S.IFDIR => .directory,
+ linux.S.IFCHR => .character_device,
+ linux.S.IFBLK => .block_device,
+ linux.S.IFREG => .file,
+ linux.S.IFIFO => .named_pipe,
+ linux.S.IFLNK => .sym_link,
+ linux.S.IFSOCK => .unix_domain_socket,
+ else => .unknown,
+ },
+ .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec,
+ .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec,
+ .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec,
+ };
+ }
+
pub fn fromWasi(st: std.os.wasi.filestat_t) Stat {
return .{
.inode = st.ino,
@@ -502,8 +527,34 @@ pub fn stat(self: File) StatError!Stat {
return Stat.fromWasi(st);
}
+ if (builtin.os.tag == .linux) {
+ var stx = std.mem.zeroes(linux.Statx);
+
+ const rc = linux.statx(
+ self.handle,
+ "",
+ linux.AT.EMPTY_PATH,
+ linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
+ &stx,
+ );
+
+ return switch (linux.E.init(rc)) {
+ .SUCCESS => Stat.fromLinux(stx),
+ .ACCES => unreachable,
+ .BADF => unreachable,
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ .LOOP => unreachable,
+ .NAMETOOLONG => unreachable,
+ .NOENT => unreachable,
+ .NOMEM => error.SystemResources,
+ .NOTDIR => unreachable,
+ else => |err| posix.unexpectedErrno(err),
+ };
+ }
+
const st = try posix.fstat(self.handle);
- return Stat.fromSystem(st);
+ return Stat.fromPosix(st);
}
pub const ChmodError = posix.FChmodError;
@@ -1009,16 +1060,29 @@ pub fn metadata(self: File) MetadataError!Metadata {
};
},
.linux => blk: {
- const l = std.os.linux;
- var stx = std.mem.zeroes(l.Statx);
- const rcx = l.statx(self.handle, "\x00", l.AT.EMPTY_PATH, l.STATX_TYPE |
- l.STATX_MODE | l.STATX_ATIME | l.STATX_MTIME | l.STATX_BTIME, &stx);
-
- switch (posix.errno(rcx)) {
+ var stx = std.mem.zeroes(linux.Statx);
+
+ // We are gathering information for Metadata, which is meant to contain all the
+ // native OS information about the file, so use all known flags.
+ const rc = linux.statx(
+ self.handle,
+ "",
+ linux.AT.EMPTY_PATH,
+ linux.STATX_BASIC_STATS | linux.STATX_BTIME,
+ &stx,
+ );
+
+ switch (posix.errno(rc)) {
.SUCCESS => {},
+ .ACCES => unreachable,
.BADF => unreachable,
.FAULT => unreachable,
+ .INVAL => unreachable,
+ .LOOP => unreachable,
+ .NAMETOOLONG => unreachable,
+ .NOENT => unreachable,
.NOMEM => return error.SystemResources,
+ .NOTDIR => unreachable,
else => |err| return posix.unexpectedErrno(err),
}
@@ -1712,6 +1776,7 @@ const posix = std.posix;
const io = std.io;
const math = std.math;
const assert = std.debug.assert;
+const linux = std.os.linux;
const windows = std.os.windows;
const Os = std.builtin.Os;
const maxInt = std.math.maxInt;