Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syscall: use statx to provide functionality of fstat/fstatat if they are not provided. #18772

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions lib/std/os/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1556,9 +1556,10 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag
pub fn fstat(fd: i32, stat_buf: *Stat) usize {
if (@hasField(SYS, "fstat64")) {
return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));
} else {
} else if (@hasField(SYS, "fstat")) {
return syscall2(.fstat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));
}
return fstatat(fd, "", stat_buf, AT.EMPTY_PATH);
}

pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
Expand All @@ -1580,9 +1581,41 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize {
if (@hasField(SYS, "fstatat64")) {
return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);
} else {
} else if (@hasField(SYS, "fstatat")) {
return syscall4(.fstatat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);
} else if (@hasField(SYS, "statx")) {
var statx_buf: Statx = undefined;
const rc = syscall5(
.statx,
@as(usize, @bitCast(@as(isize, dirfd))),
@intFromPtr(path),
AT.NO_AUTOMOUNT | flags,
STATX_BASIC_STATS,
@intFromPtr(&statx_buf),
);
if (rc != 0) {
return rc;
}

// fill in stat_buf with statx_buf
stat_buf.dev = makedev(statx_buf.dev_major, statx_buf.dev_minor);
stat_buf.ino = @as(ino_t, statx_buf.ino);
stat_buf.mode = @as(mode_t, statx_buf.mode);
stat_buf.nlink = statx_buf.nlink;
stat_buf.uid = statx_buf.uid;
stat_buf.gid = statx_buf.gid;
stat_buf.rdev = makedev(statx_buf.rdev_major, statx_buf.rdev_minor);
// type conversions that might not be safe
stat_buf.size = @as(off_t, @bitCast(statx_buf.size));
stat_buf.blksize = @as(blksize_t, @bitCast(statx_buf.blksize));
stat_buf.blocks = @as(blkcnt_t, @bitCast(statx_buf.blocks));
stat_buf.atim = timespecFrom(statx_buf.atime);
stat_buf.mtim = timespecFrom(statx_buf.mtime);
stat_buf.ctim = timespecFrom(statx_buf.ctime);

return 0;
}
return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a compile error rather than ENOSYS at runtime. I suggest to retain the pattern that was here before, making the else block call statx.

}

pub fn statx(dirfd: i32, path: [*]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize {
Expand Down Expand Up @@ -4508,6 +4541,23 @@ pub const statx_timestamp = extern struct {
__pad1: u32,
};

// makedev calculates a Stat's dev_t based on Statx's dev major and dev minor.
fn makedev(major: u32, minor: u32) dev_t {
const majorH: dev_t = @as(dev_t, major >> 12);
const majorL: dev_t = @as(dev_t, major & 0xfff);
const minorH: dev_t = @as(dev_t, minor >> 8);
const minorL: dev_t = @as(dev_t, minor & 0xff);
return (majorH << 44) | (minorH << 20) | (majorL << 8) | minorL;
}

// timespecFrom creates a statx_timestamp to timespec.
fn timespecFrom(ts: statx_timestamp) timespec {
return timespec{
.tv_sec = @as(isize, @bitCast(ts.tv_sec)),
.tv_nsec = @as(isize, ts.tv_nsec),
};
}

/// Renamed to `Statx` to not conflict with the `statx` function.
pub const Statx = extern struct {
/// Mask of bits indicating filled fields
Expand Down
Loading