mirror of
https://github.com/ziglang/zig.git
synced 2025-12-27 16:43:07 +00:00
Merge pull request #11594 from KaneRoot/master
Dir.statFile now uses fstatat (fewer syscalls)
This commit is contained in:
commit
c2f5848fe4
@ -67,7 +67,7 @@ stage3-debug/bin/zig build test docs \
|
||||
--zig-lib-dir "$(pwd)/../lib"
|
||||
|
||||
# Look for HTML errors.
|
||||
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
|
||||
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
|
||||
|
||||
# Produce the experimental std lib documentation.
|
||||
stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
|
||||
|
||||
@ -67,7 +67,7 @@ stage3-release/bin/zig build test docs \
|
||||
--zig-lib-dir "$(pwd)/../lib"
|
||||
|
||||
# Look for HTML errors.
|
||||
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
|
||||
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
|
||||
|
||||
# Produce the experimental std lib documentation.
|
||||
stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
|
||||
|
||||
@ -66,7 +66,7 @@ stage3-debug/bin/zig build test docs \
|
||||
--zig-lib-dir "$(pwd)/../lib"
|
||||
|
||||
# Look for HTML errors.
|
||||
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
|
||||
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
|
||||
|
||||
# Produce the experimental std lib documentation.
|
||||
stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
|
||||
|
||||
@ -67,7 +67,7 @@ stage3-release/bin/zig build test docs \
|
||||
--zig-lib-dir "$(pwd)/../lib"
|
||||
|
||||
# Look for HTML errors.
|
||||
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
|
||||
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
|
||||
|
||||
# Produce the experimental std lib documentation.
|
||||
stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
|
||||
|
||||
@ -229,7 +229,7 @@ pub const EAI = enum(c_int) {
|
||||
pub extern "c" fn fallocate64(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int;
|
||||
pub extern "c" fn fopen64(noalias filename: [*:0]const u8, noalias modes: [*:0]const u8) ?*FILE;
|
||||
pub extern "c" fn fstat64(fd: fd_t, buf: *Stat) c_int;
|
||||
pub extern "c" fn fstatat64(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, flags: u32) c_int;
|
||||
pub extern "c" fn fstatat64(dirfd: fd_t, noalias path: [*:0]const u8, noalias stat_buf: *Stat, flags: u32) c_int;
|
||||
pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int;
|
||||
pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int;
|
||||
pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64;
|
||||
|
||||
@ -150,7 +150,6 @@ pub fn copyFileAbsolute(source_path: []const u8, dest_path: []const u8, args: Co
|
||||
return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args);
|
||||
}
|
||||
|
||||
/// TODO update this API to avoid a getrandom syscall for every operation.
|
||||
pub const AtomicFile = struct {
|
||||
file: File,
|
||||
// TODO either replace this with rand_buf or use []u16 on Windows
|
||||
@ -2598,14 +2597,32 @@ 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();
|
||||
|
||||
return file.stat();
|
||||
/// 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 {
|
||||
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 Permissions = File.Permissions;
|
||||
|
||||
@ -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,
|
||||
@ -313,6 +316,50 @@ pub const File = struct {
|
||||
mtime: i128,
|
||||
/// Creation time in nanoseconds, relative to UTC 1970-01-01.
|
||||
ctime: i128,
|
||||
|
||||
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,
|
||||
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,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const StatError = os.FStatError;
|
||||
@ -342,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;
|
||||
|
||||
@ -4156,7 +4156,7 @@ pub fn populateBuiltinFile(mod: *Module) !void {
|
||||
file.status = .success_zir;
|
||||
}
|
||||
|
||||
pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
|
||||
fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
|
||||
var af = try builtin_pkg.root_src_directory.handle.atomicFile(builtin_pkg.root_src_path, .{});
|
||||
defer af.deinit();
|
||||
try af.file.writeAll(file.source);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user