Commit 40fc7a1fda

LemonBoy <thatlemon@gmail.com>
2019-10-12 14:55:02
Add support for the statx syscall
1 parent 8b45921
Changed files (3)
lib
std
lib/std/os/bits/linux.zig
@@ -1293,3 +1293,81 @@ pub const utsname = extern struct {
     domainname: [65]u8,
 };
 pub const HOST_NAME_MAX = 64;
+
+pub const STATX_TYPE = 0x0001;
+pub const STATX_MODE = 0x0002;
+pub const STATX_NLINK = 0x0004;
+pub const STATX_UID = 0x0008;
+pub const STATX_GID = 0x0010;
+pub const STATX_ATIME = 0x0020;
+pub const STATX_MTIME = 0x0040;
+pub const STATX_CTIME = 0x0080;
+pub const STATX_INO = 0x0100;
+pub const STATX_SIZE = 0x0200;
+pub const STATX_BLOCKS = 0x0400;
+pub const STATX_BASIC_STATS = 0x07ff;
+
+pub const STATX_BTIME = 0x0800;
+
+pub const STATX_ATTR_COMPRESSED = 0x0004;
+pub const STATX_ATTR_IMMUTABLE = 0x0010;
+pub const STATX_ATTR_APPEND = 0x0020;
+pub const STATX_ATTR_NODUMP = 0x0040;
+pub const STATX_ATTR_ENCRYPTED = 0x0800;
+pub const STATX_ATTR_AUTOMOUNT = 0x1000;
+
+pub const statx_timestamp = extern struct {
+    tv_sec: i64,
+    tv_nsec: u32,
+    __pad1: u32,
+};
+
+pub const Statx = extern struct {
+    // Mask of bits indicating filled fields
+    stx_mask: u32,
+    // Block size for filesystem I/O
+    stx_blksize: u32,
+    // Extra file attribute indicators
+    stx_attributes: u64,
+    // Number of hard links
+    stx_nlink: u32,
+    // User ID of owner
+    stx_uid: u32,
+    // Group ID of owner
+    stx_gid: u32,
+    // File type and mode
+    stx_mode: u16,
+    __pad1: u16,
+    // Inode number
+    stx_ino: u64,
+    // Total size in bytes
+    stx_size: u64,
+    // Number of 512B blocks allocated
+    stx_blocks: u64,
+    // Mask to show what's supported in stx_attributes
+    stx_attributes_mask: u64,
+
+    // The following fields are file timestamps
+    // Last access
+    stx_atime: statx_timestamp,
+    // Creation
+    stx_btime: statx_timestamp,
+    // Last status change
+    stx_ctime: statx_timestamp,
+    // Last modification
+    stx_mtime: statx_timestamp,
+
+    // If this file represents a device, then the next two fields contain the ID of the device
+    // Major ID
+    stx_rdev_major: u32,
+    // Minor ID
+    stx_rdev_minor: u32,
+
+    // The next two fields contain the ID of the device containing the filesystem where the file resides
+    // Major ID
+    stx_dev_major: u32,
+    // Minor ID
+    stx_dev_minor: u32,
+
+    __pad2: [14]u64,
+};
lib/std/os/linux/test.zig
@@ -44,3 +44,35 @@ test "timer" {
     // TODO implicit cast from *[N]T to [*]T
     err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
 }
+
+const File = std.fs.File;
+
+test "statx" {
+    const tmp_file_name = "just_a_temporary_file.txt";
+    var file = try File.openWrite(tmp_file_name);
+    defer {
+        file.close();
+        std.fs.deleteFile(tmp_file_name) catch {};
+    }
+
+    var statx_buf: linux.Statx = undefined;
+    switch (linux.getErrno(linux.statx(file.handle, c"", linux.AT_EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
+        0 => {},
+        // The statx syscall was only introduced in linux 4.11
+        linux.ENOSYS => return error.SkipZigTest,
+        else => unreachable,
+    }
+
+    var stat_buf: linux.Stat = undefined;
+    switch (linux.getErrno(linux.fstatat(file.handle, c"", &stat_buf, linux.AT_EMPTY_PATH))) {
+        0 => {},
+        else => unreachable,
+    }
+
+    expect(stat_buf.mode == statx_buf.stx_mode);
+    expect(@bitCast(u32, stat_buf.uid) == statx_buf.stx_uid);
+    expect(@bitCast(u32, stat_buf.gid) == statx_buf.stx_gid);
+    expect(@bitCast(u64, i64(stat_buf.size)) == statx_buf.stx_size);
+    expect(@bitCast(u64, i64(stat_buf.blksize)) == statx_buf.stx_blksize);
+    expect(@bitCast(u64, i64(stat_buf.blocks)) == statx_buf.stx_blocks);
+}
lib/std/os/linux.zig
@@ -860,6 +860,20 @@ pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize
     }
 }
 
+pub fn statx(dirfd: i32, path: [*]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize {
+    if (@hasDecl(@This(), "SYS_statx")) {
+        return syscall5(
+            SYS_statx,
+            @bitCast(usize, isize(dirfd)),
+            @ptrToInt(path),
+            flags,
+            mask,
+            @ptrToInt(statx_buf),
+        );
+    }
+    return @bitCast(usize, isize(-ENOSYS));
+}
+
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn listxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
     return syscall3(SYS_listxattr, @ptrToInt(path), @ptrToInt(list), size);