Skip to content

Commit 46d7348

Browse files
Linux: Always use time64 APIs
`std.os.linux` has been reworked to use 64-bit time APIs on all targets. This required auditing all types used by the Kernel ABI for each of the supported targets, along with other some rewrites in `std.posix`. = `std.os.linux` The `Stat` structures for each target are now merged together into the `KernelStat` struct that switches on the target, similar to existing types. Targets that have a `stat64` structure have been modified to make that it's default, and all definitions have been re-written to match the kernel headers exactly using the `c_` int types. Of course, newer linux ports don't even implement the `stat(2)` family, instead requiring userspace to wrap it using `statx(2)`. Thus, a new `Stat` type has been created to hold information from both APIs. The new public variable `has_fstatat` has also been introduced, so that callers can check if the current target at least implements `fstatat(2)`, and to use `statx(2)` if not. The `major`, `minor` and `makedev` functions have also been ported over to make the translation from `statx(2)` possible. == `timespec` The KernelStat `(a|c|m)time` fields are no longer defined as `timespecs`, since their signedness and bit size vary by target. Instead, the new `timespec.makeTimespec` function is used, which does some comptime checks on the time types before performing `@intCasts` on each field. Speaking of, the `timespec` type has been redefined to be the same as `__kernel_timespec`, as it is the modern 64-bit type that the kernel is using going forward. Since some syscalls (e.g. `timerfd_(get|set)time`) require the `timespec64` type, it has been added as well. Note that the only difference between it and `__kernel_timespec` is that `ts_nsec` is defined as a `c_long`, thus explicit padding fields are added and zeroed out for 32-bit targets to avoid issued with uninitialised memory. == Misc. - The VDSO `clock_gettime` symbol now points to the proper 64-bit verrsion for each arch. - The `Time64` struct has been created to hold all the proper `time64` syscalls for each target. = `std.posix` - Add `fstatatLinux` that either uses `fstatat` or `statx` depending on the value of `linux.has_fstatat`. - Move `std.os.fstat(at)_wasi` into the `std.posix.fstat(at)Wasi` in light of #21023. - Move the libc path for `fstatat` into the new function `fstatatC`. - Mark `fstatatZ` as `inline` since the logic is simplified.
1 parent 7188153 commit 46d7348

22 files changed

+886
-799
lines changed

lib/std/fs/Dir.zig

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,10 +2694,9 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
26942694
defer file.close();
26952695
return file.stat();
26962696
}
2697-
if (native_os == .wasi and !builtin.link_libc) {
2698-
const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true });
2699-
return Stat.fromWasi(st);
2700-
}
2697+
if (native_os == .wasi and !builtin.link_libc)
2698+
return Stat.fromWasi(try posix.fstatatWasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true }));
2699+
27012700
if (native_os == .linux) {
27022701
const sub_path_c = try posix.toPosixPath(sub_path);
27032702
var stx = std.mem.zeroes(linux.Statx);

lib/std/fs/File.zig

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -522,10 +522,8 @@ pub fn stat(self: File) StatError!Stat {
522522
};
523523
}
524524

525-
if (builtin.os.tag == .wasi and !builtin.link_libc) {
526-
const st = try std.os.fstat_wasi(self.handle);
527-
return Stat.fromWasi(st);
528-
}
525+
if (builtin.os.tag == .wasi and !builtin.link_libc)
526+
return Stat.fromWasi(try posix.fstatWasi(self.handle));
529527

530528
if (builtin.os.tag == .linux) {
531529
var stx = std.mem.zeroes(linux.Statx);
@@ -1090,7 +1088,7 @@ pub fn metadata(self: File) MetadataError!Metadata {
10901088
.statx = stx,
10911089
};
10921090
},
1093-
.wasi => .{ .stat = try std.os.fstat_wasi(self.handle) },
1091+
.wasi => .{ .stat = try posix.fstatWasi(self.handle) },
10941092
else => .{ .stat = try posix.fstat(self.handle) },
10951093
},
10961094
};

lib/std/os.zig

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -237,37 +237,3 @@ pub fn getFdPath(fd: std.posix.fd_t, out_buffer: *[max_path_bytes]u8) std.posix.
237237
else => unreachable, // made unreachable by isGetFdPathSupportedOnTarget above
238238
}
239239
}
240-
241-
/// WASI-only. Same as `fstatat` but targeting WASI.
242-
/// `pathname` should be encoded as valid UTF-8.
243-
/// See also `fstatat`.
244-
pub fn fstatat_wasi(dirfd: posix.fd_t, pathname: []const u8, flags: wasi.lookupflags_t) posix.FStatAtError!wasi.filestat_t {
245-
var stat: wasi.filestat_t = undefined;
246-
switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) {
247-
.SUCCESS => return stat,
248-
.INVAL => unreachable,
249-
.BADF => unreachable, // Always a race condition.
250-
.NOMEM => return error.SystemResources,
251-
.ACCES => return error.AccessDenied,
252-
.FAULT => unreachable,
253-
.NAMETOOLONG => return error.NameTooLong,
254-
.NOENT => return error.FileNotFound,
255-
.NOTDIR => return error.FileNotFound,
256-
.NOTCAPABLE => return error.AccessDenied,
257-
.ILSEQ => return error.InvalidUtf8,
258-
else => |err| return posix.unexpectedErrno(err),
259-
}
260-
}
261-
262-
pub fn fstat_wasi(fd: posix.fd_t) posix.FStatError!wasi.filestat_t {
263-
var stat: wasi.filestat_t = undefined;
264-
switch (wasi.fd_filestat_get(fd, &stat)) {
265-
.SUCCESS => return stat,
266-
.INVAL => unreachable,
267-
.BADF => unreachable, // Always a race condition.
268-
.NOMEM => return error.SystemResources,
269-
.ACCES => return error.AccessDenied,
270-
.NOTCAPABLE => return error.AccessDenied,
271-
else => |err| return posix.unexpectedErrno(err),
272-
}
273-
}

0 commit comments

Comments
 (0)