authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-16 17:11:22-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-10-16 17:11:22-04:00
log312880f10243b3074c3f176fbea6b9994e733f56
tree440391f85a19f8414c0e49218f62c697fbb6db17
parent3af2202ea4a5950541ee369a005f8e4484d544ab
parentead9630c135b86c77de9774635f7b5c55ce62f41
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3439 from LemonBoy/statx

Add support for the statx syscall

4 files changed, 142 insertions(+), 9 deletions(-)

lib/std/os/bits/linux.zig+78
......@@ -1293,3 +1293,81 @@ pub const utsname = extern struct {
12931293 domainname: [65]u8,
12941294};
12951295pub const HOST_NAME_MAX = 64;
1296
1297pub const STATX_TYPE = 0x0001;
1298pub const STATX_MODE = 0x0002;
1299pub const STATX_NLINK = 0x0004;
1300pub const STATX_UID = 0x0008;
1301pub const STATX_GID = 0x0010;
1302pub const STATX_ATIME = 0x0020;
1303pub const STATX_MTIME = 0x0040;
1304pub const STATX_CTIME = 0x0080;
1305pub const STATX_INO = 0x0100;
1306pub const STATX_SIZE = 0x0200;
1307pub const STATX_BLOCKS = 0x0400;
1308pub const STATX_BASIC_STATS = 0x07ff;
1309
1310pub const STATX_BTIME = 0x0800;
1311
1312pub const STATX_ATTR_COMPRESSED = 0x0004;
1313pub const STATX_ATTR_IMMUTABLE = 0x0010;
1314pub const STATX_ATTR_APPEND = 0x0020;
1315pub const STATX_ATTR_NODUMP = 0x0040;
1316pub const STATX_ATTR_ENCRYPTED = 0x0800;
1317pub const STATX_ATTR_AUTOMOUNT = 0x1000;
1318
1319pub const statx_timestamp = extern struct {
1320 tv_sec: i64,
1321 tv_nsec: u32,
1322 __pad1: u32,
1323};
1324
1325pub const Statx = extern struct {
1326 // Mask of bits indicating filled fields
1327 stx_mask: u32,
1328 // Block size for filesystem I/O
1329 stx_blksize: u32,
1330 // Extra file attribute indicators
1331 stx_attributes: u64,
1332 // Number of hard links
1333 stx_nlink: u32,
1334 // User ID of owner
1335 stx_uid: u32,
1336 // Group ID of owner
1337 stx_gid: u32,
1338 // File type and mode
1339 stx_mode: u16,
1340 __pad1: u16,
1341 // Inode number
1342 stx_ino: u64,
1343 // Total size in bytes
1344 stx_size: u64,
1345 // Number of 512B blocks allocated
1346 stx_blocks: u64,
1347 // Mask to show what's supported in stx_attributes
1348 stx_attributes_mask: u64,
1349
1350 // The following fields are file timestamps
1351 // Last access
1352 stx_atime: statx_timestamp,
1353 // Creation
1354 stx_btime: statx_timestamp,
1355 // Last status change
1356 stx_ctime: statx_timestamp,
1357 // Last modification
1358 stx_mtime: statx_timestamp,
1359
1360 // If this file represents a device, then the next two fields contain the ID of the device
1361 // Major ID
1362 stx_rdev_major: u32,
1363 // Minor ID
1364 stx_rdev_minor: u32,
1365
1366 // The next two fields contain the ID of the device containing the filesystem where the file resides
1367 // Major ID
1368 stx_dev_major: u32,
1369 // Minor ID
1370 stx_dev_minor: u32,
1371
1372 __pad2: [14]u64,
1373};
lib/std/os/bits/linux/arm-eabi.zig+18-9
......@@ -6,6 +6,8 @@ const iovec = linux.iovec;
66const iovec_const = linux.iovec_const;
77const stack_t = linux.stack_t;
88const sigset_t = linux.sigset_t;
9const uid_t = linux.uid_t;
10const gid_t = linux.gid_t;
911
1012pub const SYS_restart_syscall = 0;
1113pub const SYS_exit = 1;
......@@ -512,7 +514,14 @@ pub const msghdr_const = extern struct {
512514 msg_flags: i32,
513515};
514516
517pub const blksize_t = i32;
518pub const nlink_t = u32;
519pub const time_t = isize;
520pub const mode_t = u32;
515521pub const off_t = i64;
522pub const ino_t = u64;
523pub const dev_t = u64;
524pub const blkcnt_t = i64;
516525
517526/// Renamed to Stat to not conflict with the stat function.
518527/// atime, mtime, and ctime have functions to return `timespec`,
......@@ -521,22 +530,22 @@ pub const off_t = i64;
521530/// in C, macros are used to hide the differences. Here we use
522531/// methods to accomplish this.
523532pub const Stat = extern struct {
524 dev: u64,
533 dev: dev_t,
525534 __dev_padding: u32,
526535 __ino_truncated: u32,
527 mode: u32,
528 nlink: u32,
529 uid: u32,
530 gid: u32,
531 rdev: u64,
536 mode: mode_t,
537 nlink: nlink_t,
538 uid: uid_t,
539 gid: gid_t,
540 rdev: dev_t,
532541 __rdev_padding: u32,
533542 size: off_t,
534 blksize: i32,
535 blocks: u64,
543 blksize: blksize_t,
544 blocks: blkcnt_t,
536545 atim: timespec,
537546 mtim: timespec,
538547 ctim: timespec,
539 ino: u64,
548 ino: ino_t,
540549
541550 pub fn atime(self: Stat) timespec {
542551 return self.atim;
lib/std/os/linux.zig+14
......@@ -860,6 +860,20 @@ pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize
860860 }
861861}
862862
863pub fn statx(dirfd: i32, path: [*]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize {
864 if (@hasDecl(@This(), "SYS_statx")) {
865 return syscall5(
866 SYS_statx,
867 @bitCast(usize, isize(dirfd)),
868 @ptrToInt(path),
869 flags,
870 mask,
871 @ptrToInt(statx_buf),
872 );
873 }
874 return @bitCast(usize, isize(-ENOSYS));
875}
876
863877// TODO https://github.com/ziglang/zig/issues/265
864878pub fn listxattr(path: [*]const u8, list: [*]u8, size: usize) usize {
865879 return syscall3(SYS_listxattr, @ptrToInt(path), @ptrToInt(list), size);
lib/std/os/linux/test.zig+32
......@@ -44,3 +44,35 @@ test "timer" {
4444 // TODO implicit cast from *[N]T to [*]T
4545 err = linux.epoll_wait(@intCast(i32, epoll_fd), @ptrCast([*]linux.epoll_event, &events), 8, -1);
4646}
47
48const File = std.fs.File;
49
50test "statx" {
51 const tmp_file_name = "just_a_temporary_file.txt";
52 var file = try File.openWrite(tmp_file_name);
53 defer {
54 file.close();
55 std.fs.deleteFile(tmp_file_name) catch {};
56 }
57
58 var statx_buf: linux.Statx = undefined;
59 switch (linux.getErrno(linux.statx(file.handle, c"", linux.AT_EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
60 0 => {},
61 // The statx syscall was only introduced in linux 4.11
62 linux.ENOSYS => return error.SkipZigTest,
63 else => unreachable,
64 }
65
66 var stat_buf: linux.Stat = undefined;
67 switch (linux.getErrno(linux.fstatat(file.handle, c"", &stat_buf, linux.AT_EMPTY_PATH))) {
68 0 => {},
69 else => unreachable,
70 }
71
72 expect(stat_buf.mode == statx_buf.stx_mode);
73 expect(@bitCast(u32, stat_buf.uid) == statx_buf.stx_uid);
74 expect(@bitCast(u32, stat_buf.gid) == statx_buf.stx_gid);
75 expect(@bitCast(u64, i64(stat_buf.size)) == statx_buf.stx_size);
76 expect(@bitCast(u64, i64(stat_buf.blksize)) == statx_buf.stx_blksize);
77 expect(@bitCast(u64, i64(stat_buf.blocks)) == statx_buf.stx_blocks);
78}