Commit a62c8d36d5
Changed files (3)
src
lib/std/fs/file.zig
@@ -294,14 +294,17 @@ pub const File = struct {
}
pub const Stat = struct {
- /// A number that the system uses to point to the file metadata. This number is not guaranteed to be
- /// unique across time, as some file systems may reuse an inode after its file has been deleted.
- /// Some systems may change the inode of a file over time.
+ /// A number that the system uses to point to the file metadata. This
+ /// number is not guaranteed to be unique across time, as some file
+ /// systems may reuse an inode after its file has been deleted. Some
+ /// systems may change the inode of a file over time.
///
- /// On Linux, the inode is a structure that stores the metadata, and the inode _number_ is what
- /// you see here: the index number of the inode.
+ /// On Linux, the inode is a structure that stores the metadata, and
+ /// the inode _number_ is what you see here: the index number of the
+ /// inode.
///
- /// The FileIndex on Windows is similar. It is a number for a file that is unique to each filesystem.
+ /// The FileIndex on Windows is similar. It is a number for a file that
+ /// is unique to each filesystem.
inode: INode,
size: u64,
mode: Mode,
@@ -314,18 +317,19 @@ pub const File = struct {
/// 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: {
+ pub fn fromSystem(st: os.system.Stat) Stat {
+ const atime = st.atime();
+ const mtime = st.mtime();
+ const ctime = st.ctime();
+ const kind: 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,
@@ -345,14 +349,6 @@ pub const File = struct {
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,
@@ -393,47 +389,7 @@ pub const File = struct {
}
const st = try os.fstat(self.handle);
- const atime = st.atime();
- const mtime = st.mtime();
- const ctime = st.ctime();
- const kind: 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 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,
- };
+ return Stat.fromSystem(st);
}
pub const ChmodError = std.os.FChmodError;
lib/std/fs.zig
@@ -2600,24 +2600,30 @@ pub const Dir = struct {
pub const StatFileError = File.OpenError || File.StatError || os.FStatAtError;
- /// 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).
+ /// Returns metadata for a file inside the directory.
+ ///
+ /// On Windows, this requires three syscalls. On other operating systems, it
+ /// only takes one.
+ ///
+ /// Symlinks are followed.
+ ///
+ /// `sub_path` may be absolute, in which case `self` is ignored.
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();
+ switch (builtin.os.tag) {
+ .windows => {
+ var file = try self.openFile(sub_path, .{});
+ defer file.close();
+ return file.stat();
+ },
+ .wasi => {
+ const st = try os.fstatatWasi(self.fd, sub_path, os.wasi.LOOKUP_SYMLINK_FOLLOW);
+ return Stat.fromSystem(st);
+ },
+ else => {
+ const st = try os.fstatat(self.fd, sub_path, 0);
+ return Stat.fromSystem(st);
+ },
}
-
- 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;
src/Module.zig
@@ -4137,19 +4137,14 @@ 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| {
- 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;
- },
+
+ else => |e| return e,
}
file.tree = try std.zig.parse(gpa, file.source);