mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
std.fs.Dir.statFile: use fstatat
This avoids extra syscalls.
This commit is contained in:
parent
4af305b30a
commit
f65cdef7c8
@ -2598,14 +2598,26 @@ pub const Dir = struct {
|
||||
return file.stat();
|
||||
}
|
||||
|
||||
pub const StatFileError = File.OpenError || StatError;
|
||||
pub const StatFileError = File.OpenError || File.StatError || os.FStatAtError;
|
||||
|
||||
// TODO: improve this to use the fstatat syscall instead of making 2 syscalls here.
|
||||
pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!File.Stat {
|
||||
var file = try self.openFile(sub_path, .{});
|
||||
defer file.close();
|
||||
/// Provides info on a file (File.Stat) for any file in the opened directory,
|
||||
/// with a single syscall (fstatat), except on Windows.
|
||||
/// Currently on Windows, files are opened then closed (implying several syscalls, unfortunately).
|
||||
/// Symlinks are not followed on linux, haiku, solaris and *BSDs.
|
||||
/// Other OSs have a default behavior (they currently lack an os.AT.SYMLINK_NOFOLLOW flag).
|
||||
pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
|
||||
if (builtin.os.tag == .windows) {
|
||||
var file = try self.openFile(sub_path, .{});
|
||||
defer file.close();
|
||||
return file.stat();
|
||||
}
|
||||
|
||||
return file.stat();
|
||||
const flags = switch (builtin.os.tag) {
|
||||
.linux, .haiku, .solaris, .freebsd, .netbsd, .dragonfly, .openbsd => os.AT.SYMLINK_NOFOLLOW,
|
||||
else => 0, // TODO: correct flags not yet implemented
|
||||
};
|
||||
|
||||
return Stat.fromSystemStat(try os.fstatat(self.fd, sub_path, flags));
|
||||
}
|
||||
|
||||
const Permissions = File.Permissions;
|
||||
|
||||
@ -313,6 +313,57 @@ pub const File = struct {
|
||||
mtime: i128,
|
||||
/// Creation time in nanoseconds, relative to UTC 1970-01-01.
|
||||
ctime: i128,
|
||||
|
||||
pub fn systemStatKindToFsKind(st: os.system.Stat) Kind {
|
||||
const kind: File.Kind = if (builtin.os.tag == .wasi and !builtin.link_libc)
|
||||
switch (st.filetype) {
|
||||
.BLOCK_DEVICE => Kind.BlockDevice,
|
||||
.CHARACTER_DEVICE => Kind.CharacterDevice,
|
||||
.DIRECTORY => Kind.Directory,
|
||||
.SYMBOLIC_LINK => Kind.SymLink,
|
||||
.REGULAR_FILE => Kind.File,
|
||||
.SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
|
||||
else => Kind.Unknown,
|
||||
}
|
||||
else blk: {
|
||||
const m = st.mode & os.S.IFMT;
|
||||
switch (m) {
|
||||
os.S.IFBLK => break :blk Kind.BlockDevice,
|
||||
os.S.IFCHR => break :blk Kind.CharacterDevice,
|
||||
os.S.IFDIR => break :blk Kind.Directory,
|
||||
os.S.IFIFO => break :blk Kind.NamedPipe,
|
||||
os.S.IFLNK => break :blk Kind.SymLink,
|
||||
os.S.IFREG => break :blk Kind.File,
|
||||
os.S.IFSOCK => break :blk Kind.UnixDomainSocket,
|
||||
else => {},
|
||||
}
|
||||
if (builtin.os.tag == .solaris) switch (m) {
|
||||
os.S.IFDOOR => break :blk Kind.Door,
|
||||
os.S.IFPORT => break :blk Kind.EventPort,
|
||||
else => {},
|
||||
};
|
||||
|
||||
break :blk .Unknown;
|
||||
};
|
||||
return kind;
|
||||
}
|
||||
|
||||
pub fn fromSystemStat(st: os.system.Stat) File.StatError!Stat {
|
||||
const atime = st.atime();
|
||||
const mtime = st.mtime();
|
||||
const ctime = st.ctime();
|
||||
const kind = systemStatKindToFsKind(st);
|
||||
|
||||
return Stat{
|
||||
.inode = st.ino,
|
||||
.size = @bitCast(u64, st.size),
|
||||
.mode = st.mode,
|
||||
.kind = kind,
|
||||
.atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
|
||||
.mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
|
||||
.ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const StatError = os.FStatError;
|
||||
|
||||
@ -4137,14 +4137,19 @@ pub fn populateBuiltinFile(mod: *Module) !void {
|
||||
};
|
||||
}
|
||||
} else |err| switch (err) {
|
||||
error.BadPathName => unreachable, // it's always "builtin.zig"
|
||||
error.NameTooLong => unreachable, // it's always "builtin.zig"
|
||||
error.PipeBusy => unreachable, // it's not a pipe
|
||||
error.WouldBlock => unreachable, // not asking for non-blocking I/O
|
||||
|
||||
error.FileNotFound => try writeBuiltinFile(file, builtin_pkg),
|
||||
|
||||
else => |e| return e,
|
||||
else => |e| {
|
||||
if (builtin.os.tag == .windows) {
|
||||
switch (e) {
|
||||
error.BadPathName => unreachable, // it's always "builtin.zig"
|
||||
error.PipeBusy => unreachable, // it's not a pipe
|
||||
error.WouldBlock => unreachable, // not asking for non-blocking I/O
|
||||
else => return e,
|
||||
}
|
||||
}
|
||||
return e;
|
||||
},
|
||||
}
|
||||
|
||||
file.tree = try std.zig.parse(gpa, file.source);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user