authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-14 20:54:04-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-14 20:54:04-05:00
logc2f5848fe4dc3d3ffbebdbaaf8ff55fa2a9eb286
tree714af317059e20a7c8f6f075c946a3a2f30fe5c6
parent4af305b30acdefb9da380b21b446d2b31b5a6295
parentb911b54aeb45d2d2d7a8d616af5df04ad230bcc3
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11594 from KaneRoot/master

Dir.statFile now uses fstatat (fewer syscalls)

8 files changed, 85 insertions(+), 61 deletions(-)

ci/aarch64-linux-debug.sh+1-1
......@@ -67,7 +67,7 @@ stage3-debug/bin/zig build test docs \
6767 --zig-lib-dir "$(pwd)/../lib"
6868
6969# Look for HTML errors.
70tidy --drop-empty-elements no -qe ../zig-cache/langref.html
70tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7171
7272# Produce the experimental std lib documentation.
7373stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
ci/aarch64-linux-release.sh+1-1
......@@ -67,7 +67,7 @@ stage3-release/bin/zig build test docs \
6767 --zig-lib-dir "$(pwd)/../lib"
6868
6969# Look for HTML errors.
70tidy --drop-empty-elements no -qe ../zig-cache/langref.html
70tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7171
7272# Produce the experimental std lib documentation.
7373stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
ci/x86_64-linux-debug.sh+1-1
......@@ -66,7 +66,7 @@ stage3-debug/bin/zig build test docs \
6666 --zig-lib-dir "$(pwd)/../lib"
6767
6868# Look for HTML errors.
69tidy --drop-empty-elements no -qe ../zig-cache/langref.html
69tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7070
7171# Produce the experimental std lib documentation.
7272stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
ci/x86_64-linux-release.sh+1-1
......@@ -67,7 +67,7 @@ stage3-release/bin/zig build test docs \
6767 --zig-lib-dir "$(pwd)/../lib"
6868
6969# Look for HTML errors.
70tidy --drop-empty-elements no -qe ../zig-cache/langref.html
70tidy --drop-empty-elements no -qe "$ZIG_LOCAL_CACHE_DIR/langref.html"
7171
7272# Produce the experimental std lib documentation.
7373stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
lib/std/c/linux.zig+1-1
......@@ -229,7 +229,7 @@ pub const EAI = enum(c_int) {
229229pub extern "c" fn fallocate64(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int;
230230pub extern "c" fn fopen64(noalias filename: [*:0]const u8, noalias modes: [*:0]const u8) ?*FILE;
231231pub extern "c" fn fstat64(fd: fd_t, buf: *Stat) c_int;
232pub extern "c" fn fstatat64(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, flags: u32) c_int;
232pub extern "c" fn fstatat64(dirfd: fd_t, noalias path: [*:0]const u8, noalias stat_buf: *Stat, flags: u32) c_int;
233233pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int;
234234pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int;
235235pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64;
lib/std/fs.zig+25-8
......@@ -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.
154153pub 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+54-47
......@@ -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+1-1
......@@ -4156,7 +4156,7 @@ pub fn populateBuiltinFile(mod: *Module) !void {
41564156 file.status = .success_zir;
41574157}
41584158
4159pub fn writeBuiltinFile(file: *File, builtin_pkg: *Package) !void {
4159fn 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);