Skip to content

Commit c2f5848

Browse files
authored
Merge pull request #11594 from KaneRoot/master
Dir.statFile now uses fstatat (fewer syscalls)
2 parents 4af305b + b911b54 commit c2f5848

8 files changed

Lines changed: 85 additions & 61 deletions

File tree

ci/aarch64-linux-debug.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ stage3-debug/bin/zig build test docs \
6767
--zig-lib-dir "$(pwd)/../lib"
6868

6969
# Look for HTML errors.
70-
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
70+
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7171

7272
# Produce the experimental std lib documentation.
7373
stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib

ci/aarch64-linux-release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ stage3-release/bin/zig build test docs \
6767
--zig-lib-dir "$(pwd)/../lib"
6868

6969
# Look for HTML errors.
70-
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
70+
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7171

7272
# Produce the experimental std lib documentation.
7373
stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib

ci/x86_64-linux-debug.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ stage3-debug/bin/zig build test docs \
6666
--zig-lib-dir "$(pwd)/../lib"
6767

6868
# Look for HTML errors.
69-
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
69+
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7070

7171
# Produce the experimental std lib documentation.
7272
stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib

ci/x86_64-linux-release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ stage3-release/bin/zig build test docs \
6767
--zig-lib-dir "$(pwd)/../lib"
6868

6969
# Look for HTML errors.
70-
tidy --drop-empty-elements no -qe ../zig-cache/langref.html
70+
tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7171

7272
# Produce the experimental std lib documentation.
7373
stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib

lib/std/c/linux.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ pub const EAI = enum(c_int) {
229229
pub extern "c" fn fallocate64(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int;
230230
pub extern "c" fn fopen64(noalias filename: [*:0]const u8, noalias modes: [*:0]const u8) ?*FILE;
231231
pub extern "c" fn fstat64(fd: fd_t, buf: *Stat) c_int;
232-
pub extern "c" fn fstatat64(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, flags: u32) c_int;
232+
pub extern "c" fn fstatat64(dirfd: fd_t, noalias path: [*:0]const u8, noalias stat_buf: *Stat, flags: u32) c_int;
233233
pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int;
234234
pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int;
235235
pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64;

lib/std/fs.zig

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ pub fn copyFileAbsolute(source_path: []const u8, dest_path: []const u8, args: Co
150150
return Dir.copyFile(my_cwd, source_path, my_cwd, dest_path, args);
151151
}
152152

153-
/// TODO update this API to avoid a getrandom syscall for every operation.
154153
pub const AtomicFile = struct {
155154
file: File,
156155
// TODO either replace this with rand_buf or use []u16 on Windows
@@ -2598,14 +2597,32 @@ pub const Dir = struct {
25982597
return file.stat();
25992598
}
26002599

2601-
pub const StatFileError = File.OpenError || StatError;
2600+
pub const StatFileError = File.OpenError || File.StatError || os.FStatAtError;
26022601

2603-
// TODO: improve this to use the fstatat syscall instead of making 2 syscalls here.
2604-
pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!File.Stat {
2605-
var file = try self.openFile(sub_path, .{});
2606-
defer file.close();
2607-
2608-
return file.stat();
2602+
/// Returns metadata for a file inside the directory.
2603+
///
2604+
/// On Windows, this requires three syscalls. On other operating systems, it
2605+
/// only takes one.
2606+
///
2607+
/// Symlinks are followed.
2608+
///
2609+
/// `sub_path` may be absolute, in which case `self` is ignored.
2610+
pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
2611+
switch (builtin.os.tag) {
2612+
.windows => {
2613+
var file = try self.openFile(sub_path, .{});
2614+
defer file.close();
2615+
return file.stat();
2616+
},
2617+
.wasi => {
2618+
const st = try os.fstatatWasi(self.fd, sub_path, os.wasi.LOOKUP_SYMLINK_FOLLOW);
2619+
return Stat.fromSystem(st);
2620+
},
2621+
else => {
2622+
const st = try os.fstatat(self.fd, sub_path, 0);
2623+
return Stat.fromSystem(st);
2624+
},
2625+
}
26092626
}
26102627

26112628
const Permissions = File.Permissions;

lib/std/fs/file.zig

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,17 @@ pub const File = struct {
294294
}
295295

296296
pub const Stat = struct {
297-
/// A number that the system uses to point to the file metadata. This number is not guaranteed to be
298-
/// unique across time, as some file systems may reuse an inode after its file has been deleted.
299-
/// Some systems may change the inode of a file over time.
297+
/// A number that the system uses to point to the file metadata. This
298+
/// number is not guaranteed to be unique across time, as some file
299+
/// systems may reuse an inode after its file has been deleted. Some
300+
/// systems may change the inode of a file over time.
300301
///
301-
/// On Linux, the inode is a structure that stores the metadata, and the inode _number_ is what
302-
/// you see here: the index number of the inode.
302+
/// On Linux, the inode is a structure that stores the metadata, and
303+
/// the inode _number_ is what you see here: the index number of the
304+
/// inode.
303305
///
304-
/// The FileIndex on Windows is similar. It is a number for a file that is unique to each filesystem.
306+
/// The FileIndex on Windows is similar. It is a number for a file that
307+
/// is unique to each filesystem.
305308
inode: INode,
306309
size: u64,
307310
mode: Mode,
@@ -313,6 +316,50 @@ pub const File = struct {
313316
mtime: i128,
314317
/// Creation time in nanoseconds, relative to UTC 1970-01-01.
315318
ctime: i128,
319+
320+
pub fn fromSystem(st: os.system.Stat) Stat {
321+
const atime = st.atime();
322+
const mtime = st.mtime();
323+
const ctime = st.ctime();
324+
const kind: Kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) {
325+
.BLOCK_DEVICE => Kind.BlockDevice,
326+
.CHARACTER_DEVICE => Kind.CharacterDevice,
327+
.DIRECTORY => Kind.Directory,
328+
.SYMBOLIC_LINK => Kind.SymLink,
329+
.REGULAR_FILE => Kind.File,
330+
.SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
331+
else => Kind.Unknown,
332+
} else blk: {
333+
const m = st.mode & os.S.IFMT;
334+
switch (m) {
335+
os.S.IFBLK => break :blk Kind.BlockDevice,
336+
os.S.IFCHR => break :blk Kind.CharacterDevice,
337+
os.S.IFDIR => break :blk Kind.Directory,
338+
os.S.IFIFO => break :blk Kind.NamedPipe,
339+
os.S.IFLNK => break :blk Kind.SymLink,
340+
os.S.IFREG => break :blk Kind.File,
341+
os.S.IFSOCK => break :blk Kind.UnixDomainSocket,
342+
else => {},
343+
}
344+
if (builtin.os.tag == .solaris) switch (m) {
345+
os.S.IFDOOR => break :blk Kind.Door,
346+
os.S.IFPORT => break :blk Kind.EventPort,
347+
else => {},
348+
};
349+
350+
break :blk .Unknown;
351+
};
352+
353+
return Stat{
354+
.inode = st.ino,
355+
.size = @bitCast(u64, st.size),
356+
.mode = st.mode,
357+
.kind = kind,
358+
.atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
359+
.mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
360+
.ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
361+
};
362+
}
316363
};
317364

318365
pub const StatError = os.FStatError;
@@ -342,47 +389,7 @@ pub const File = struct {
342389
}
343390

344391
const st = try os.fstat(self.handle);
345-
const atime = st.atime();
346-
const mtime = st.mtime();
347-
const ctime = st.ctime();
348-
const kind: Kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) {
349-
.BLOCK_DEVICE => Kind.BlockDevice,
350-
.CHARACTER_DEVICE => Kind.CharacterDevice,
351-
.DIRECTORY => Kind.Directory,
352-
.SYMBOLIC_LINK => Kind.SymLink,
353-
.REGULAR_FILE => Kind.File,
354-
.SOCKET_STREAM, .SOCKET_DGRAM => Kind.UnixDomainSocket,
355-
else => Kind.Unknown,
356-
} else blk: {
357-
const m = st.mode & os.S.IFMT;
358-
switch (m) {
359-
os.S.IFBLK => break :blk Kind.BlockDevice,
360-
os.S.IFCHR => break :blk Kind.CharacterDevice,
361-
os.S.IFDIR => break :blk Kind.Directory,
362-
os.S.IFIFO => break :blk Kind.NamedPipe,
363-
os.S.IFLNK => break :blk Kind.SymLink,
364-
os.S.IFREG => break :blk Kind.File,
365-
os.S.IFSOCK => break :blk Kind.UnixDomainSocket,
366-
else => {},
367-
}
368-
if (builtin.os.tag == .solaris) switch (m) {
369-
os.S.IFDOOR => break :blk Kind.Door,
370-
os.S.IFPORT => break :blk Kind.EventPort,
371-
else => {},
372-
};
373-
374-
break :blk .Unknown;
375-
};
376-
377-
return Stat{
378-
.inode = st.ino,
379-
.size = @bitCast(u64, st.size),
380-
.mode = st.mode,
381-
.kind = kind,
382-
.atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
383-
.mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
384-
.ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
385-
};
392+
return Stat.fromSystem(st);
386393
}
387394

388395
pub const ChmodError = std.os.FChmodError;

src/Module.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4156,7 +4156,7 @@ pub fn populateBuiltinFile(mod: *Module) !void {
41564156
file.status = .success_zir;
41574157
}
41584158

4159-
pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
4159+
fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
41604160
var af = try builtin_pkg.root_src_directory.handle.atomicFile(builtin_pkg.root_src_path, .{});
41614161
defer af.deinit();
41624162
try af.file.writeAll(file.source);

0 commit comments

Comments
 (0)