| author | |
| committer | |
| log | 2f2b09757682d4c3624d8e6d470852b1d1d6264d |
| tree | 127627d7a0c5d5336df3296fe45755609b86e04e |
| parent | c13857e504f5893cabf182dde1e826131f2acf24 |
| parent | aec7bfb09219e32389ad666906166f690a158fbe |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30122
Reviewed-by: Alex Rønne Petersen <alex@alexrp.com>29 files changed, 358 insertions(+), 1083 deletions(-)
lib/std/Io/Threaded.zig+16-2| ... | ... | @@ -1533,12 +1533,19 @@ fn dirStatPathLinux( |
| 1533 | 1533 | dir.handle, |
| 1534 | 1534 | sub_path_posix, |
| 1535 | 1535 | flags, |
| 1536 | linux.STATX_INO | linux.STATX_SIZE | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, | |
| 1536 | .{ .TYPE = true, .MODE = true, .ATIME = true, .MTIME = true, .CTIME = true, .INO = true, .SIZE = true }, | |
| 1537 | 1537 | &statx, |
| 1538 | 1538 | ); |
| 1539 | 1539 | switch (linux.errno(rc)) { |
| 1540 | 1540 | .SUCCESS => { |
| 1541 | 1541 | current_thread.endSyscall(); |
| 1542 | assert(statx.mask.TYPE); | |
| 1543 | assert(statx.mask.MODE); | |
| 1544 | assert(statx.mask.ATIME); | |
| 1545 | assert(statx.mask.MTIME); | |
| 1546 | assert(statx.mask.CTIME); | |
| 1547 | assert(statx.mask.INO); | |
| 1548 | assert(statx.mask.SIZE); | |
| 1542 | 1549 | return statFromLinux(&statx); |
| 1543 | 1550 | }, |
| 1544 | 1551 | .INTR => { |
| ... | ... | @@ -1725,12 +1732,19 @@ fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File |
| 1725 | 1732 | file.handle, |
| 1726 | 1733 | "", |
| 1727 | 1734 | linux.AT.EMPTY_PATH, |
| 1728 | linux.STATX_INO | linux.STATX_SIZE | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, | |
| 1735 | .{ .TYPE = true, .MODE = true, .ATIME = true, .MTIME = true, .CTIME = true, .INO = true, .SIZE = true }, | |
| 1729 | 1736 | &statx, |
| 1730 | 1737 | ); |
| 1731 | 1738 | switch (linux.errno(rc)) { |
| 1732 | 1739 | .SUCCESS => { |
| 1733 | 1740 | current_thread.endSyscall(); |
| 1741 | assert(statx.mask.TYPE); | |
| 1742 | assert(statx.mask.MODE); | |
| 1743 | assert(statx.mask.ATIME); | |
| 1744 | assert(statx.mask.MTIME); | |
| 1745 | assert(statx.mask.CTIME); | |
| 1746 | assert(statx.mask.INO); | |
| 1747 | assert(statx.mask.SIZE); | |
| 1734 | 1748 | return statFromLinux(&statx); |
| 1735 | 1749 | }, |
| 1736 | 1750 | .INTR => { |
lib/std/c.zig+5-163| ... | ... | @@ -7586,166 +7586,6 @@ pub const EAI = if (builtin.abi.isAndroid()) enum(c_int) { |
| 7586 | 7586 | pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.c) c_int; |
| 7587 | 7587 | |
| 7588 | 7588 | pub const Stat = switch (native_os) { |
| 7589 | .linux => switch (native_arch) { | |
| 7590 | .sparc64 => extern struct { | |
| 7591 | dev: u64, | |
| 7592 | __pad1: u16, | |
| 7593 | ino: ino_t, | |
| 7594 | mode: u32, | |
| 7595 | nlink: u32, | |
| 7596 | ||
| 7597 | uid: u32, | |
| 7598 | gid: u32, | |
| 7599 | rdev: u64, | |
| 7600 | __pad2: u16, | |
| 7601 | ||
| 7602 | size: off_t, | |
| 7603 | blksize: isize, | |
| 7604 | blocks: i64, | |
| 7605 | ||
| 7606 | atim: timespec, | |
| 7607 | mtim: timespec, | |
| 7608 | ctim: timespec, | |
| 7609 | __reserved: [2]usize, | |
| 7610 | ||
| 7611 | pub fn atime(self: @This()) timespec { | |
| 7612 | return self.atim; | |
| 7613 | } | |
| 7614 | ||
| 7615 | pub fn mtime(self: @This()) timespec { | |
| 7616 | return self.mtim; | |
| 7617 | } | |
| 7618 | ||
| 7619 | pub fn ctime(self: @This()) timespec { | |
| 7620 | return self.ctim; | |
| 7621 | } | |
| 7622 | }, | |
| 7623 | .mips, .mipsel => if (builtin.target.abi.isMusl()) extern struct { | |
| 7624 | dev: dev_t, | |
| 7625 | __pad0: [2]i32, | |
| 7626 | ino: ino_t, | |
| 7627 | mode: mode_t, | |
| 7628 | nlink: nlink_t, | |
| 7629 | uid: uid_t, | |
| 7630 | gid: gid_t, | |
| 7631 | rdev: dev_t, | |
| 7632 | __pad1: [2]i32, | |
| 7633 | size: off_t, | |
| 7634 | atim: timespec, | |
| 7635 | mtim: timespec, | |
| 7636 | ctim: timespec, | |
| 7637 | blksize: blksize_t, | |
| 7638 | __pad3: i32, | |
| 7639 | blocks: blkcnt_t, | |
| 7640 | __pad4: [14]i32, | |
| 7641 | ||
| 7642 | pub fn atime(self: @This()) timespec { | |
| 7643 | return self.atim; | |
| 7644 | } | |
| 7645 | ||
| 7646 | pub fn mtime(self: @This()) timespec { | |
| 7647 | return self.mtim; | |
| 7648 | } | |
| 7649 | ||
| 7650 | pub fn ctime(self: @This()) timespec { | |
| 7651 | return self.ctim; | |
| 7652 | } | |
| 7653 | } else extern struct { | |
| 7654 | dev: u32, | |
| 7655 | __pad0: [3]u32, | |
| 7656 | ino: ino_t, | |
| 7657 | mode: mode_t, | |
| 7658 | nlink: nlink_t, | |
| 7659 | uid: uid_t, | |
| 7660 | gid: gid_t, | |
| 7661 | rdev: u32, | |
| 7662 | __pad1: [3]u32, | |
| 7663 | size: off_t, | |
| 7664 | atim: timespec, | |
| 7665 | mtim: timespec, | |
| 7666 | ctim: timespec, | |
| 7667 | blksize: blksize_t, | |
| 7668 | __pad3: u32, | |
| 7669 | blocks: blkcnt_t, | |
| 7670 | __pad4: [14]u32, | |
| 7671 | ||
| 7672 | pub fn atime(self: @This()) timespec { | |
| 7673 | return self.atim; | |
| 7674 | } | |
| 7675 | ||
| 7676 | pub fn mtime(self: @This()) timespec { | |
| 7677 | return self.mtim; | |
| 7678 | } | |
| 7679 | ||
| 7680 | pub fn ctime(self: @This()) timespec { | |
| 7681 | return self.ctim; | |
| 7682 | } | |
| 7683 | }, | |
| 7684 | .mips64, .mips64el => if (builtin.target.abi.isMusl()) extern struct { | |
| 7685 | dev: dev_t, | |
| 7686 | __pad0: [3]i32, | |
| 7687 | ino: ino_t, | |
| 7688 | mode: mode_t, | |
| 7689 | nlink: nlink_t, | |
| 7690 | uid: uid_t, | |
| 7691 | gid: gid_t, | |
| 7692 | rdev: dev_t, | |
| 7693 | __pad1: [2]u32, | |
| 7694 | size: off_t, | |
| 7695 | __pad2: i32, | |
| 7696 | atim: timespec, | |
| 7697 | mtim: timespec, | |
| 7698 | ctim: timespec, | |
| 7699 | blksize: blksize_t, | |
| 7700 | __pad3: u32, | |
| 7701 | blocks: blkcnt_t, | |
| 7702 | __pad4: [14]i32, | |
| 7703 | ||
| 7704 | pub fn atime(self: @This()) timespec { | |
| 7705 | return self.atim; | |
| 7706 | } | |
| 7707 | ||
| 7708 | pub fn mtime(self: @This()) timespec { | |
| 7709 | return self.mtim; | |
| 7710 | } | |
| 7711 | ||
| 7712 | pub fn ctime(self: @This()) timespec { | |
| 7713 | return self.ctim; | |
| 7714 | } | |
| 7715 | } else extern struct { | |
| 7716 | dev: dev_t, | |
| 7717 | __pad0: [3]u32, | |
| 7718 | ino: ino_t, | |
| 7719 | mode: mode_t, | |
| 7720 | nlink: nlink_t, | |
| 7721 | uid: uid_t, | |
| 7722 | gid: gid_t, | |
| 7723 | rdev: dev_t, | |
| 7724 | __pad1: [3]u32, | |
| 7725 | size: off_t, | |
| 7726 | atim: timespec, | |
| 7727 | mtim: timespec, | |
| 7728 | ctim: timespec, | |
| 7729 | blksize: blksize_t, | |
| 7730 | __pad3: u32, | |
| 7731 | blocks: blkcnt_t, | |
| 7732 | __pad4: [14]i32, | |
| 7733 | ||
| 7734 | pub fn atime(self: @This()) timespec { | |
| 7735 | return self.atim; | |
| 7736 | } | |
| 7737 | ||
| 7738 | pub fn mtime(self: @This()) timespec { | |
| 7739 | return self.mtim; | |
| 7740 | } | |
| 7741 | ||
| 7742 | pub fn ctime(self: @This()) timespec { | |
| 7743 | return self.ctim; | |
| 7744 | } | |
| 7745 | }, | |
| 7746 | ||
| 7747 | else => std.os.linux.Stat, // libc stat is the same as kernel stat. | |
| 7748 | }, | |
| 7749 | 7589 | .emscripten => emscripten.Stat, |
| 7750 | 7590 | .wasi => extern struct { |
| 7751 | 7591 | // Match wasi-libc's `struct stat` in lib/libc/include/wasm-wasi-musl/__struct_stat.h |
| ... | ... | @@ -10422,6 +10262,7 @@ pub const fstat = switch (native_os) { |
| 10422 | 10262 | else => private.fstat, |
| 10423 | 10263 | }, |
| 10424 | 10264 | .netbsd => private.__fstat50, |
| 10265 | .linux => {}, | |
| 10425 | 10266 | else => private.fstat, |
| 10426 | 10267 | }; |
| 10427 | 10268 | |
| ... | ... | @@ -10430,8 +10271,12 @@ pub const fstatat = switch (native_os) { |
| 10430 | 10271 | .x86_64 => private.@"fstatat$INODE64", |
| 10431 | 10272 | else => private.fstatat, |
| 10432 | 10273 | }, |
| 10274 | .linux => {}, | |
| 10433 | 10275 | else => private.fstatat, |
| 10434 | 10276 | }; |
| 10277 | ||
| 10278 | pub extern "c" fn statx(dirfd: fd_t, path: [*:0]const u8, flags: u32, mask: linux.STATX, buf: *linux.Statx) c_int; | |
| 10279 | ||
| 10435 | 10280 | pub extern "c" fn getpwent() ?*passwd; |
| 10436 | 10281 | pub extern "c" fn endpwent() void; |
| 10437 | 10282 | pub extern "c" fn setpwent() void; |
| ... | ... | @@ -10505,8 +10350,6 @@ pub extern "c" fn inotify_init1(flags: c_uint) c_int; |
| 10505 | 10350 | pub extern "c" fn inotify_add_watch(fd: fd_t, pathname: [*:0]const u8, mask: u32) c_int; |
| 10506 | 10351 | pub extern "c" fn inotify_rm_watch(fd: fd_t, wd: c_int) c_int; |
| 10507 | 10352 | |
| 10508 | pub extern "c" fn fstat64(fd: fd_t, buf: *Stat) c_int; | |
| 10509 | pub extern "c" fn fstatat64(dirfd: fd_t, noalias path: [*:0]const u8, noalias stat_buf: *Stat, flags: u32) c_int; | |
| 10510 | 10353 | pub extern "c" fn fallocate64(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int; |
| 10511 | 10354 | pub extern "c" fn fopen64(noalias filename: [*:0]const u8, noalias modes: [*:0]const u8) ?*FILE; |
| 10512 | 10355 | pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int; |
| ... | ... | @@ -11552,7 +11395,6 @@ const private = struct { |
| 11552 | 11395 | extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 11553 | 11396 | extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int; |
| 11554 | 11397 | extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int; |
| 11555 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int; | |
| 11556 | 11398 | extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; |
| 11557 | 11399 | extern "c" fn sysconf(sc: c_int) c_long; |
| 11558 | 11400 | extern "c" fn shm_open(name: [*:0]const u8, flag: c_int, mode: mode_t) c_int; |
lib/std/os/linux.zig+174-118| ... | ... | @@ -95,15 +95,14 @@ pub fn clone( |
| 95 | 95 | pub const ARCH = arch_bits.ARCH; |
| 96 | 96 | pub const HWCAP = arch_bits.HWCAP; |
| 97 | 97 | pub const SC = arch_bits.SC; |
| 98 | pub const Stat = arch_bits.Stat; | |
| 99 | 98 | pub const VDSO = arch_bits.VDSO; |
| 100 | pub const blkcnt_t = arch_bits.blkcnt_t; | |
| 101 | pub const blksize_t = arch_bits.blksize_t; | |
| 102 | pub const dev_t = arch_bits.dev_t; | |
| 103 | pub const ino_t = arch_bits.ino_t; | |
| 104 | pub const mode_t = arch_bits.mode_t; | |
| 105 | pub const nlink_t = arch_bits.nlink_t; | |
| 106 | pub const off_t = arch_bits.off_t; | |
| 99 | pub const blkcnt_t = u64; | |
| 100 | pub const blksize_t = u32; | |
| 101 | pub const dev_t = u64; | |
| 102 | pub const ino_t = u64; | |
| 103 | pub const mode_t = u32; | |
| 104 | pub const nlink_t = u32; | |
| 105 | pub const off_t = i64; | |
| 107 | 106 | pub const time_t = arch_bits.time_t; |
| 108 | 107 | pub const user_desc = arch_bits.user_desc; |
| 109 | 108 | |
| ... | ... | @@ -2199,61 +2198,13 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag |
| 2199 | 2198 | return syscall4(.accept4, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(addr), @intFromPtr(len), flags); |
| 2200 | 2199 | } |
| 2201 | 2200 | |
| 2202 | pub fn fstat(fd: i32, stat_buf: *Stat) usize { | |
| 2203 | if (native_arch == .riscv32 or native_arch.isLoongArch()) { | |
| 2204 | // riscv32 and loongarch have made the interesting decision to not implement some of | |
| 2205 | // the older stat syscalls, including this one. | |
| 2206 | @compileError("No fstat syscall on this architecture."); | |
| 2207 | } else if (@hasField(SYS, "fstat64")) { | |
| 2208 | return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf)); | |
| 2209 | } else { | |
| 2210 | return syscall2(.fstat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf)); | |
| 2211 | } | |
| 2212 | } | |
| 2213 | ||
| 2214 | pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize { | |
| 2215 | if (native_arch == .riscv32 or native_arch.isLoongArch()) { | |
| 2216 | // riscv32 and loongarch have made the interesting decision to not implement some of | |
| 2217 | // the older stat syscalls, including this one. | |
| 2218 | @compileError("No stat syscall on this architecture."); | |
| 2219 | } else if (@hasField(SYS, "stat64")) { | |
| 2220 | return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf)); | |
| 2221 | } else { | |
| 2222 | return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf)); | |
| 2223 | } | |
| 2224 | } | |
| 2225 | ||
| 2226 | pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize { | |
| 2227 | if (native_arch == .riscv32 or native_arch.isLoongArch()) { | |
| 2228 | // riscv32 and loongarch have made the interesting decision to not implement some of | |
| 2229 | // the older stat syscalls, including this one. | |
| 2230 | @compileError("No lstat syscall on this architecture."); | |
| 2231 | } else if (@hasField(SYS, "lstat64")) { | |
| 2232 | return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf)); | |
| 2233 | } else { | |
| 2234 | return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf)); | |
| 2235 | } | |
| 2236 | } | |
| 2237 | ||
| 2238 | pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize { | |
| 2239 | if (native_arch == .riscv32 or native_arch.isLoongArch()) { | |
| 2240 | // riscv32 and loongarch have made the interesting decision to not implement some of | |
| 2241 | // the older stat syscalls, including this one. | |
| 2242 | @compileError("No fstatat syscall on this architecture."); | |
| 2243 | } else if (@hasField(SYS, "fstatat64")) { | |
| 2244 | return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags); | |
| 2245 | } else { | |
| 2246 | return syscall4(.fstatat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags); | |
| 2247 | } | |
| 2248 | } | |
| 2249 | ||
| 2250 | pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize { | |
| 2201 | pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: STATX, statx_buf: *Statx) usize { | |
| 2251 | 2202 | return syscall5( |
| 2252 | 2203 | .statx, |
| 2253 | 2204 | @as(usize, @bitCast(@as(isize, dirfd))), |
| 2254 | 2205 | @intFromPtr(path), |
| 2255 | 2206 | flags, |
| 2256 | mask, | |
| 2207 | @as(u32, @bitCast(mask)), | |
| 2257 | 2208 | @intFromPtr(statx_buf), |
| 2258 | 2209 | ); |
| 2259 | 2210 | } |
| ... | ... | @@ -6940,96 +6891,161 @@ pub const utsname = extern struct { |
| 6940 | 6891 | }; |
| 6941 | 6892 | pub const HOST_NAME_MAX = 64; |
| 6942 | 6893 | |
| 6943 | pub const STATX_TYPE = 0x0001; | |
| 6944 | pub const STATX_MODE = 0x0002; | |
| 6945 | pub const STATX_NLINK = 0x0004; | |
| 6946 | pub const STATX_UID = 0x0008; | |
| 6947 | pub const STATX_GID = 0x0010; | |
| 6948 | pub const STATX_ATIME = 0x0020; | |
| 6949 | pub const STATX_MTIME = 0x0040; | |
| 6950 | pub const STATX_CTIME = 0x0080; | |
| 6951 | pub const STATX_INO = 0x0100; | |
| 6952 | pub const STATX_SIZE = 0x0200; | |
| 6953 | pub const STATX_BLOCKS = 0x0400; | |
| 6954 | pub const STATX_BASIC_STATS = 0x07ff; | |
| 6955 | ||
| 6956 | pub const STATX_BTIME = 0x0800; | |
| 6957 | ||
| 6958 | pub const STATX_ATTR_COMPRESSED = 0x0004; | |
| 6959 | pub const STATX_ATTR_IMMUTABLE = 0x0010; | |
| 6960 | pub const STATX_ATTR_APPEND = 0x0020; | |
| 6961 | pub const STATX_ATTR_NODUMP = 0x0040; | |
| 6962 | pub const STATX_ATTR_ENCRYPTED = 0x0800; | |
| 6963 | pub const STATX_ATTR_AUTOMOUNT = 0x1000; | |
| 6894 | /// Flags used to request specific members in `Statx` be filled out. | |
| 6895 | /// The `Statx.mask` member will be updated with what information the kernel | |
| 6896 | /// returned. Callers must check this field since support varies by kernel | |
| 6897 | /// version and filesystem. | |
| 6898 | pub const STATX = packed struct(u32) { | |
| 6899 | /// Want `mode & S.IFMT`. | |
| 6900 | TYPE: bool = false, | |
| 6901 | /// Want `mode & ~S.IFMT`. | |
| 6902 | MODE: bool = false, | |
| 6903 | /// Want the `nlink` member. | |
| 6904 | NLINK: bool = false, | |
| 6905 | /// Want the `uid` member. | |
| 6906 | UID: bool = false, | |
| 6907 | /// Want the `gid` member. | |
| 6908 | GID: bool = false, | |
| 6909 | /// Want the `atime` member. | |
| 6910 | ATIME: bool = false, | |
| 6911 | /// Want the `mtime` member. | |
| 6912 | MTIME: bool = false, | |
| 6913 | /// Want the `ctime` member. | |
| 6914 | CTIME: bool = false, | |
| 6915 | /// Want the `ino` member. | |
| 6916 | INO: bool = false, | |
| 6917 | /// Want the `size` member. | |
| 6918 | SIZE: bool = false, | |
| 6919 | /// Want the `blocks` member. | |
| 6920 | BLOCKS: bool = false, | |
| 6921 | /// Want the `btime` member. | |
| 6922 | BTIME: bool = false, | |
| 6923 | /// Want the `mnt_id` member. | |
| 6924 | MNT_ID: bool = false, | |
| 6925 | /// Want the `dio_mem_align` and `dio_offset_align` members. | |
| 6926 | DIOALIGN: bool = false, | |
| 6927 | /// Want the `stx_mnt_id` member. | |
| 6928 | MNT_ID_UNIQUE: bool = false, | |
| 6929 | /// Want the `sub` member. | |
| 6930 | SUBVOL: bool = false, | |
| 6931 | /// Want the `atomic_write_unit_min`, `atomic_write_unit_max` and | |
| 6932 | /// `atomic_write_segments_max` members. | |
| 6933 | WRITE_ATOMIC: bool = false, | |
| 6934 | /// Want the `dio_read_offset_align` member. | |
| 6935 | DIO_READ_ALIGN: bool = false, | |
| 6936 | __pad: u13 = 0, | |
| 6937 | /// Reserved for future expansion; must not be set. | |
| 6938 | __RESERVED: bool = false, | |
| 6939 | ||
| 6940 | pub const BASIC_STATS: STATX = @bitCast(@as(u32, 0x7ff)); | |
| 6941 | }; | |
| 6942 | ||
| 6943 | /// Attributes about the state or features of a file as a bitmask. | |
| 6944 | /// Flags marked [I] correspond to the `FS_IOC_SETFLAGS` values semantically. | |
| 6945 | /// See [FS_IOC_SETFLAGS(2const)](https://man7.org/linux/man-pages/man2/FS_IOC_GETFLAGS.2const.html) | |
| 6946 | /// for more. | |
| 6947 | pub const STATX_ATTR = packed struct(u64) { | |
| 6948 | __pad1: u3 = 0, | |
| 6949 | /// [I] File is compressed by the fs. | |
| 6950 | COMPRESSED: bool = false, | |
| 6951 | __pad2: u1 = 0, | |
| 6952 | /// [I] File is marked immutable. | |
| 6953 | IMMUTABLE: bool = false, | |
| 6954 | /// [I] File is append-only. | |
| 6955 | APPEND: bool = false, | |
| 6956 | /// [I] File is not to be dumped. | |
| 6957 | NODUMP: bool = false, | |
| 6958 | /// [I] File requires a key to decrypt in the filesystem. | |
| 6959 | ENCRYPTED: bool = false, | |
| 6960 | /// File names a directory that triggers an automount. | |
| 6961 | AUTOMOUNT: bool = false, | |
| 6962 | /// File names the root of a mount. | |
| 6963 | MOUNT_ROOT: bool = false, | |
| 6964 | /// [I] File is protected by the `dm-verity` device. | |
| 6965 | VERITY: bool = false, | |
| 6966 | /// File is currently in the CPU direct access state. | |
| 6967 | /// Does not correspond to the per-inode DAX flag that some filesystems support. | |
| 6968 | DAX: bool = false, | |
| 6969 | /// File supports atomic write operations. | |
| 6970 | WRITE_ATOMIC: bool = false, | |
| 6971 | __pad3: u50 = 0, | |
| 6972 | }; | |
| 6964 | 6973 | |
| 6965 | 6974 | pub const statx_timestamp = extern struct { |
| 6975 | /// Number of seconds before or after `1970-01-01T00:00:00Z`. | |
| 6966 | 6976 | sec: i64, |
| 6977 | /// Number of nanoseconds (0..999,999,999) after `sec`. | |
| 6967 | 6978 | nsec: u32, |
| 6979 | // Reserved for future increases in resolution. | |
| 6968 | 6980 | __pad1: u32, |
| 6969 | 6981 | }; |
| 6970 | 6982 | |
| 6971 | 6983 | /// Renamed to `Statx` to not conflict with the `statx` function. |
| 6972 | 6984 | pub const Statx = extern struct { |
| 6973 | /// Mask of bits indicating filled fields | |
| 6974 | mask: u32, | |
| 6975 | ||
| 6976 | /// Block size for filesystem I/O | |
| 6985 | /// Mask of bits indicating filled fields. | |
| 6986 | mask: STATX, | |
| 6987 | /// Block size for filesystem I/O. | |
| 6977 | 6988 | blksize: u32, |
| 6978 | ||
| 6979 | /// Extra file attribute indicators | |
| 6980 | attributes: u64, | |
| 6981 | ||
| 6982 | /// Number of hard links | |
| 6989 | /// Extra file attribute indicators. | |
| 6990 | attributes: STATX_ATTR, | |
| 6991 | /// Number of hard links. | |
| 6983 | 6992 | nlink: u32, |
| 6984 | ||
| 6985 | /// User ID of owner | |
| 6993 | /// User ID of owner. | |
| 6986 | 6994 | uid: uid_t, |
| 6987 | ||
| 6988 | /// Group ID of owner | |
| 6995 | /// Group ID of owner. | |
| 6989 | 6996 | gid: gid_t, |
| 6990 | ||
| 6991 | /// File type and mode | |
| 6997 | /// File type and mode. | |
| 6992 | 6998 | mode: u16, |
| 6993 | __pad1: u16, | |
| 6994 | ||
| 6995 | /// Inode number | |
| 6999 | __spare0: u16, | |
| 7000 | /// Inode number. | |
| 6996 | 7001 | ino: u64, |
| 6997 | ||
| 6998 | /// Total size in bytes | |
| 7002 | /// Total size in bytes. | |
| 6999 | 7003 | size: u64, |
| 7000 | ||
| 7001 | /// Number of 512B blocks allocated | |
| 7004 | /// Number of 512B blocks allocated. | |
| 7002 | 7005 | blocks: u64, |
| 7003 | ||
| 7004 | 7006 | /// Mask to show what's supported in `attributes`. |
| 7005 | attributes_mask: u64, | |
| 7006 | ||
| 7007 | /// Last access file timestamp | |
| 7007 | attributes_mask: STATX_ATTR, | |
| 7008 | /// Last access file timestamp. | |
| 7008 | 7009 | atime: statx_timestamp, |
| 7009 | ||
| 7010 | /// Creation file timestamp | |
| 7010 | /// Creation file timestamp. | |
| 7011 | 7011 | btime: statx_timestamp, |
| 7012 | ||
| 7013 | /// Last status change file timestamp | |
| 7012 | /// Last status change file timestamp. | |
| 7014 | 7013 | ctime: statx_timestamp, |
| 7015 | ||
| 7016 | /// Last modification file timestamp | |
| 7014 | /// Last modification file timestamp. | |
| 7017 | 7015 | mtime: statx_timestamp, |
| 7018 | ||
| 7019 | 7016 | /// Major ID, if this file represents a device. |
| 7020 | 7017 | rdev_major: u32, |
| 7021 | ||
| 7022 | 7018 | /// Minor ID, if this file represents a device. |
| 7023 | 7019 | rdev_minor: u32, |
| 7024 | ||
| 7025 | 7020 | /// Major ID of the device containing the filesystem where this file resides. |
| 7026 | 7021 | dev_major: u32, |
| 7027 | ||
| 7028 | 7022 | /// Minor ID of the device containing the filesystem where this file resides. |
| 7029 | 7023 | dev_minor: u32, |
| 7030 | ||
| 7031 | __pad2: [14]u64, | |
| 7032 | }; | |
| 7024 | /// Mount ID | |
| 7025 | mnt_id: u64, | |
| 7026 | /// Memory buffer alignment for direct I/O. | |
| 7027 | dio_mem_align: u32, | |
| 7028 | /// File offset alignment for direct I/O. | |
| 7029 | dio_offset_align: u32, | |
| 7030 | /// Subvolume identifier. | |
| 7031 | subvol: u64, | |
| 7032 | /// Min atomic write unit in bytes. | |
| 7033 | atomic_write_unit_min: u32, | |
| 7034 | /// Max atomic write unit in bytes. | |
| 7035 | atomic_write_unit_max: u32, | |
| 7036 | /// Max atomic write segment count. | |
| 7037 | atomic_write_segments_max: u32, | |
| 7038 | /// File offset alignment for direct I/O reads. | |
| 7039 | dio_read_offset_align: u32, | |
| 7040 | /// Optimised max atomic write unit in bytes. | |
| 7041 | atomic_write_unit_max_opt: u32, | |
| 7042 | __spare2: [1]u32, | |
| 7043 | __spare3: [8]u64, | |
| 7044 | }; | |
| 7045 | ||
| 7046 | comptime { | |
| 7047 | assert(@sizeOf(Statx) == 0x100); | |
| 7048 | } | |
| 7033 | 7049 | |
| 7034 | 7050 | pub const addrinfo = extern struct { |
| 7035 | 7051 | flags: AI, |
| ... | ... | @@ -9970,6 +9986,46 @@ pub const wrapped = struct { |
| 9970 | 9986 | } |
| 9971 | 9987 | } |
| 9972 | 9988 | |
| 9989 | pub const StatxError = std.posix.UnexpectedError || error{ | |
| 9990 | /// Search permission is denied for one of the directories in `path`. | |
| 9991 | AccessDenied, | |
| 9992 | /// Too many symbolic links were encountered traversing `path`. | |
| 9993 | SymLinkLoop, | |
| 9994 | /// `path` is too long. | |
| 9995 | NameTooLong, | |
| 9996 | /// One of: | |
| 9997 | /// - A component of `path` does not exist. | |
| 9998 | /// - A component of `path` is not a directory. | |
| 9999 | /// - `path` is a relative and `dirfd` is not a directory file descriptor. | |
| 10000 | FileNotFound, | |
| 10001 | /// Insufficient memory is available. | |
| 10002 | SystemResources, | |
| 10003 | }; | |
| 10004 | ||
| 10005 | pub fn statx(dirfd: fd_t, path: [*:0]const u8, flags: u32, mask: STATX) StatxError!Statx { | |
| 10006 | const use_c = std.c.versionCheck(if (builtin.abi.isAndroid()) | |
| 10007 | .{ .major = 30, .minor = 0, .patch = 0 } | |
| 10008 | else | |
| 10009 | .{ .major = 2, .minor = 28, .patch = 0 }); | |
| 10010 | const sys = if (use_c) std.c else std.os.linux; | |
| 10011 | ||
| 10012 | var stx = std.mem.zeroes(Statx); | |
| 10013 | const rc = sys.statx(dirfd, path, flags, mask, &stx); | |
| 10014 | return switch (sys.errno(rc)) { | |
| 10015 | .SUCCESS => stx, | |
| 10016 | .ACCES => error.AccessDenied, | |
| 10017 | .BADF => invalidApiUsage(), | |
| 10018 | .FAULT => invalidApiUsage(), | |
| 10019 | .INVAL => invalidApiUsage(), | |
| 10020 | .LOOP => error.SymLinkLoop, | |
| 10021 | .NAMETOOLONG => error.NameTooLong, | |
| 10022 | .NOENT => error.FileNotFound, | |
| 10023 | .NOTDIR => error.FileNotFound, | |
| 10024 | .NOMEM => error.SystemResources, | |
| 10025 | else => |err| unexpectedErrno(err), | |
| 10026 | }; | |
| 10027 | } | |
| 10028 | ||
| 9973 | 10029 | const unexpectedErrno = std.posix.unexpectedErrno; |
| 9974 | 10030 | |
| 9975 | 10031 | fn invalidApiUsage() error{Unexpected} { |
lib/std/os/linux/IoUring.zig+3-3| ... | ... | @@ -958,7 +958,7 @@ pub fn statx( |
| 958 | 958 | fd: linux.fd_t, |
| 959 | 959 | path: [:0]const u8, |
| 960 | 960 | flags: u32, |
| 961 | mask: u32, | |
| 961 | mask: linux.STATX, | |
| 962 | 962 | buf: *linux.Statx, |
| 963 | 963 | ) !*linux.io_uring_sqe { |
| 964 | 964 | const sqe = try self.get_sqe(); |
| ... | ... | @@ -2691,7 +2691,7 @@ test "statx" { |
| 2691 | 2691 | tmp.dir.fd, |
| 2692 | 2692 | path, |
| 2693 | 2693 | 0, |
| 2694 | linux.STATX_SIZE, | |
| 2694 | .{ .SIZE = true }, | |
| 2695 | 2695 | &buf, |
| 2696 | 2696 | ); |
| 2697 | 2697 | try testing.expectEqual(linux.IORING_OP.STATX, sqe.opcode); |
| ... | ... | @@ -2718,7 +2718,7 @@ test "statx" { |
| 2718 | 2718 | .flags = 0, |
| 2719 | 2719 | }, cqe); |
| 2720 | 2720 | |
| 2721 | try testing.expect(buf.mask & linux.STATX_SIZE == linux.STATX_SIZE); | |
| 2721 | try testing.expect(buf.mask.SIZE); | |
| 2722 | 2722 | try testing.expectEqual(@as(u64, 6), buf.size); |
| 2723 | 2723 | } |
| 2724 | 2724 |
lib/std/os/linux/aarch64.zig-39| ... | ... | @@ -143,43 +143,4 @@ pub const VDSO = struct { |
| 143 | 143 | pub const CGT_VER = "LINUX_2.6.39"; |
| 144 | 144 | }; |
| 145 | 145 | |
| 146 | pub const blksize_t = i32; | |
| 147 | pub const nlink_t = u32; | |
| 148 | 146 | pub const time_t = i64; |
| 149 | pub const mode_t = u32; | |
| 150 | pub const off_t = i64; | |
| 151 | pub const ino_t = u64; | |
| 152 | pub const dev_t = u64; | |
| 153 | pub const blkcnt_t = i64; | |
| 154 | ||
| 155 | // The `stat` definition used by the Linux kernel. | |
| 156 | pub const Stat = extern struct { | |
| 157 | dev: dev_t, | |
| 158 | ino: ino_t, | |
| 159 | mode: mode_t, | |
| 160 | nlink: nlink_t, | |
| 161 | uid: std.os.linux.uid_t, | |
| 162 | gid: std.os.linux.gid_t, | |
| 163 | rdev: dev_t, | |
| 164 | __pad: u64, | |
| 165 | size: off_t, | |
| 166 | blksize: blksize_t, | |
| 167 | __pad2: i32, | |
| 168 | blocks: blkcnt_t, | |
| 169 | atim: std.os.linux.timespec, | |
| 170 | mtim: std.os.linux.timespec, | |
| 171 | ctim: std.os.linux.timespec, | |
| 172 | __unused: [2]u32, | |
| 173 | ||
| 174 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 175 | return self.atim; | |
| 176 | } | |
| 177 | ||
| 178 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 179 | return self.mtim; | |
| 180 | } | |
| 181 | ||
| 182 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 183 | return self.ctim; | |
| 184 | } | |
| 185 | }; |
lib/std/os/linux/arm.zig-39| ... | ... | @@ -179,43 +179,4 @@ pub const HWCAP = struct { |
| 179 | 179 | pub const EVTSTRM = 1 << 21; |
| 180 | 180 | }; |
| 181 | 181 | |
| 182 | pub const blksize_t = i32; | |
| 183 | pub const nlink_t = u32; | |
| 184 | 182 | pub const time_t = i32; |
| 185 | pub const mode_t = u32; | |
| 186 | pub const off_t = i64; | |
| 187 | pub const ino_t = u64; | |
| 188 | pub const dev_t = u64; | |
| 189 | pub const blkcnt_t = i64; | |
| 190 | ||
| 191 | // The `stat` definition used by the Linux kernel. | |
| 192 | pub const Stat = extern struct { | |
| 193 | dev: dev_t, | |
| 194 | __dev_padding: u32, | |
| 195 | __ino_truncated: u32, | |
| 196 | mode: mode_t, | |
| 197 | nlink: nlink_t, | |
| 198 | uid: std.os.linux.uid_t, | |
| 199 | gid: std.os.linux.gid_t, | |
| 200 | rdev: dev_t, | |
| 201 | __rdev_padding: u32, | |
| 202 | size: off_t, | |
| 203 | blksize: blksize_t, | |
| 204 | blocks: blkcnt_t, | |
| 205 | atim: std.os.linux.timespec, | |
| 206 | mtim: std.os.linux.timespec, | |
| 207 | ctim: std.os.linux.timespec, | |
| 208 | ino: ino_t, | |
| 209 | ||
| 210 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 211 | return self.atim; | |
| 212 | } | |
| 213 | ||
| 214 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 215 | return self.mtim; | |
| 216 | } | |
| 217 | ||
| 218 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 219 | return self.ctim; | |
| 220 | } | |
| 221 | }; |
lib/std/os/linux/hexagon.zig-39| ... | ... | @@ -119,45 +119,6 @@ pub fn clone() callconv(.naked) u32 { |
| 119 | 119 | ); |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | pub const blksize_t = i32; | |
| 123 | pub const nlink_t = u32; | |
| 124 | 122 | pub const time_t = i64; |
| 125 | pub const mode_t = u32; | |
| 126 | pub const off_t = i64; | |
| 127 | pub const ino_t = u64; | |
| 128 | pub const dev_t = u64; | |
| 129 | pub const blkcnt_t = i64; | |
| 130 | ||
| 131 | // The `stat` definition used by the Linux kernel. | |
| 132 | pub const Stat = extern struct { | |
| 133 | dev: dev_t, | |
| 134 | ino: ino_t, | |
| 135 | mode: mode_t, | |
| 136 | nlink: nlink_t, | |
| 137 | uid: std.os.linux.uid_t, | |
| 138 | gid: std.os.linux.gid_t, | |
| 139 | rdev: dev_t, | |
| 140 | __pad: u32, | |
| 141 | size: off_t, | |
| 142 | blksize: blksize_t, | |
| 143 | __pad2: i32, | |
| 144 | blocks: blkcnt_t, | |
| 145 | atim: std.os.linux.timespec, | |
| 146 | mtim: std.os.linux.timespec, | |
| 147 | ctim: std.os.linux.timespec, | |
| 148 | __unused: [2]u32, | |
| 149 | ||
| 150 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 151 | return self.atim; | |
| 152 | } | |
| 153 | ||
| 154 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 155 | return self.mtim; | |
| 156 | } | |
| 157 | ||
| 158 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 159 | return self.ctim; | |
| 160 | } | |
| 161 | }; | |
| 162 | 123 | |
| 163 | 124 | pub const VDSO = void; |
lib/std/os/linux/io_uring_sqe.zig+2-2| ... | ... | @@ -420,10 +420,10 @@ pub const io_uring_sqe = extern struct { |
| 420 | 420 | fd: linux.fd_t, |
| 421 | 421 | path: [*:0]const u8, |
| 422 | 422 | flags: u32, |
| 423 | mask: u32, | |
| 423 | mask: linux.STATX, | |
| 424 | 424 | buf: *linux.Statx, |
| 425 | 425 | ) void { |
| 426 | sqe.prep_rw(.STATX, fd, @intFromPtr(path), mask, @intFromPtr(buf)); | |
| 426 | sqe.prep_rw(.STATX, fd, @intFromPtr(path), @as(u32, @bitCast(mask)), @intFromPtr(buf)); | |
| 427 | 427 | sqe.rw_flags = flags; |
| 428 | 428 | } |
| 429 | 429 |
lib/std/os/linux/loongarch64.zig-39| ... | ... | @@ -125,46 +125,7 @@ pub fn clone() callconv(.naked) u64 { |
| 125 | 125 | ); |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | pub const blksize_t = i32; | |
| 129 | pub const nlink_t = u32; | |
| 130 | 128 | pub const time_t = i64; |
| 131 | pub const mode_t = u32; | |
| 132 | pub const off_t = i64; | |
| 133 | pub const ino_t = u64; | |
| 134 | pub const dev_t = u32; | |
| 135 | pub const blkcnt_t = i64; | |
| 136 | ||
| 137 | // The `stat` definition used by the Linux kernel. | |
| 138 | pub const Stat = extern struct { | |
| 139 | dev: dev_t, | |
| 140 | ino: ino_t, | |
| 141 | mode: mode_t, | |
| 142 | nlink: nlink_t, | |
| 143 | uid: std.os.linux.uid_t, | |
| 144 | gid: std.os.linux.gid_t, | |
| 145 | rdev: dev_t, | |
| 146 | _pad1: u64, | |
| 147 | size: off_t, | |
| 148 | blksize: blksize_t, | |
| 149 | _pad2: i32, | |
| 150 | blocks: blkcnt_t, | |
| 151 | atim: std.os.linux.timespec, | |
| 152 | mtim: std.os.linux.timespec, | |
| 153 | ctim: std.os.linux.timespec, | |
| 154 | _pad3: [2]u32, | |
| 155 | ||
| 156 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 157 | return self.atim; | |
| 158 | } | |
| 159 | ||
| 160 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 161 | return self.mtim; | |
| 162 | } | |
| 163 | ||
| 164 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 165 | return self.ctim; | |
| 166 | } | |
| 167 | }; | |
| 168 | 129 | |
| 169 | 130 | pub const VDSO = struct { |
| 170 | 131 | pub const CGT_SYM = "__vdso_clock_gettime"; |
lib/std/os/linux/m68k.zig-38| ... | ... | @@ -142,45 +142,7 @@ pub fn restore_rt() callconv(.naked) noreturn { |
| 142 | 142 | ); |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | pub const blksize_t = i32; | |
| 146 | pub const nlink_t = u32; | |
| 147 | 145 | pub const time_t = i32; |
| 148 | pub const mode_t = u32; | |
| 149 | pub const off_t = i64; | |
| 150 | pub const ino_t = u64; | |
| 151 | pub const dev_t = u64; | |
| 152 | pub const blkcnt_t = i64; | |
| 153 | ||
| 154 | pub const Stat = extern struct { | |
| 155 | dev: dev_t, | |
| 156 | __pad: i16, | |
| 157 | __ino_truncated: i32, | |
| 158 | mode: mode_t, | |
| 159 | nlink: nlink_t, | |
| 160 | uid: std.os.linux.uid_t, | |
| 161 | gid: std.os.linux.gid_t, | |
| 162 | rdev: dev_t, | |
| 163 | __pad2: i16, | |
| 164 | size: off_t, | |
| 165 | blksize: blksize_t, | |
| 166 | blocks: blkcnt_t, | |
| 167 | atim: std.os.linux.timespec, | |
| 168 | mtim: std.os.linux.timespec, | |
| 169 | ctim: std.os.linux.timespec, | |
| 170 | ino: ino_t, | |
| 171 | ||
| 172 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 173 | return self.atim; | |
| 174 | } | |
| 175 | ||
| 176 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 177 | return self.mtim; | |
| 178 | } | |
| 179 | ||
| 180 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 181 | return self.ctim; | |
| 182 | } | |
| 183 | }; | |
| 184 | 146 | |
| 185 | 147 | // No VDSO used as of glibc 112a0ae18b831bf31f44d81b82666980312511d6. |
| 186 | 148 | pub const VDSO = void; |
lib/std/os/linux/mips.zig-39| ... | ... | @@ -230,43 +230,4 @@ pub const VDSO = struct { |
| 230 | 230 | pub const CGT_VER = "LINUX_2.6"; |
| 231 | 231 | }; |
| 232 | 232 | |
| 233 | pub const blksize_t = u32; | |
| 234 | pub const nlink_t = u32; | |
| 235 | 233 | pub const time_t = i32; |
| 236 | pub const mode_t = u32; | |
| 237 | pub const off_t = i64; | |
| 238 | pub const ino_t = u64; | |
| 239 | pub const dev_t = u64; | |
| 240 | pub const blkcnt_t = i64; | |
| 241 | ||
| 242 | // The `stat64` definition used by the Linux kernel. | |
| 243 | pub const Stat = extern struct { | |
| 244 | dev: dev_t, | |
| 245 | __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). | |
| 246 | ino: ino_t, | |
| 247 | mode: mode_t, | |
| 248 | nlink: nlink_t, | |
| 249 | uid: std.os.linux.uid_t, | |
| 250 | gid: std.os.linux.gid_t, | |
| 251 | rdev: dev_t, | |
| 252 | __pad1: [2]u32, | |
| 253 | size: off_t, | |
| 254 | atim: std.os.linux.timespec, | |
| 255 | mtim: std.os.linux.timespec, | |
| 256 | ctim: std.os.linux.timespec, | |
| 257 | blksize: blksize_t, | |
| 258 | __pad3: u32, | |
| 259 | blocks: blkcnt_t, | |
| 260 | ||
| 261 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 262 | return self.atim; | |
| 263 | } | |
| 264 | ||
| 265 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 266 | return self.mtim; | |
| 267 | } | |
| 268 | ||
| 269 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 270 | return self.ctim; | |
| 271 | } | |
| 272 | }; |
lib/std/os/linux/mips64.zig-51| ... | ... | @@ -184,55 +184,4 @@ pub const VDSO = struct { |
| 184 | 184 | pub const CGT_VER = "LINUX_2.6"; |
| 185 | 185 | }; |
| 186 | 186 | |
| 187 | pub const blksize_t = u32; | |
| 188 | pub const nlink_t = u32; | |
| 189 | 187 | pub const time_t = i32; |
| 190 | pub const mode_t = u32; | |
| 191 | pub const off_t = i64; | |
| 192 | pub const ino_t = u64; | |
| 193 | pub const dev_t = u64; | |
| 194 | pub const blkcnt_t = i64; | |
| 195 | ||
| 196 | // The `stat` definition used by the Linux kernel. | |
| 197 | pub const Stat = extern struct { | |
| 198 | dev: dev_t, | |
| 199 | __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). | |
| 200 | ino: ino_t, | |
| 201 | mode: mode_t, | |
| 202 | nlink: nlink_t, | |
| 203 | uid: std.os.linux.uid_t, | |
| 204 | gid: std.os.linux.gid_t, | |
| 205 | rdev: dev_t, | |
| 206 | __pad1: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). | |
| 207 | size: off_t, | |
| 208 | atim: u32, | |
| 209 | atim_nsec: u32, | |
| 210 | mtim: u32, | |
| 211 | mtim_nsec: u32, | |
| 212 | ctim: u32, | |
| 213 | ctim_nsec: u32, | |
| 214 | blksize: blksize_t, | |
| 215 | __pad3: u32, | |
| 216 | blocks: blkcnt_t, | |
| 217 | ||
| 218 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 219 | return .{ | |
| 220 | .sec = self.atim, | |
| 221 | .nsec = self.atim_nsec, | |
| 222 | }; | |
| 223 | } | |
| 224 | ||
| 225 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 226 | return .{ | |
| 227 | .sec = self.mtim, | |
| 228 | .nsec = self.mtim_nsec, | |
| 229 | }; | |
| 230 | } | |
| 231 | ||
| 232 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 233 | return .{ | |
| 234 | .sec = self.ctim, | |
| 235 | .nsec = self.ctim_nsec, | |
| 236 | }; | |
| 237 | } | |
| 238 | }; |
lib/std/os/linux/mipsn32.zig-51| ... | ... | @@ -184,55 +184,4 @@ pub const VDSO = struct { |
| 184 | 184 | pub const CGT_VER = "LINUX_2.6"; |
| 185 | 185 | }; |
| 186 | 186 | |
| 187 | pub const blksize_t = u32; | |
| 188 | pub const nlink_t = u32; | |
| 189 | 187 | pub const time_t = i32; |
| 190 | pub const mode_t = u32; | |
| 191 | pub const off_t = i64; | |
| 192 | pub const ino_t = u64; | |
| 193 | pub const dev_t = u64; | |
| 194 | pub const blkcnt_t = i64; | |
| 195 | ||
| 196 | // The `stat` definition used by the Linux kernel. | |
| 197 | pub const Stat = extern struct { | |
| 198 | dev: dev_t, | |
| 199 | __pad0: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). | |
| 200 | ino: ino_t, | |
| 201 | mode: mode_t, | |
| 202 | nlink: nlink_t, | |
| 203 | uid: std.os.linux.uid_t, | |
| 204 | gid: std.os.linux.gid_t, | |
| 205 | rdev: dev_t, | |
| 206 | __pad1: [2]u32, // -1 because our dev_t is u64 (kernel dev_t is really u32). | |
| 207 | size: off_t, | |
| 208 | atim: u32, | |
| 209 | atim_nsec: u32, | |
| 210 | mtim: u32, | |
| 211 | mtim_nsec: u32, | |
| 212 | ctim: u32, | |
| 213 | ctim_nsec: u32, | |
| 214 | blksize: blksize_t, | |
| 215 | __pad3: u32, | |
| 216 | blocks: blkcnt_t, | |
| 217 | ||
| 218 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 219 | return .{ | |
| 220 | .sec = self.atim, | |
| 221 | .nsec = self.atim_nsec, | |
| 222 | }; | |
| 223 | } | |
| 224 | ||
| 225 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 226 | return .{ | |
| 227 | .sec = self.mtim, | |
| 228 | .nsec = self.mtim_nsec, | |
| 229 | }; | |
| 230 | } | |
| 231 | ||
| 232 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 233 | return .{ | |
| 234 | .sec = self.ctim, | |
| 235 | .nsec = self.ctim_nsec, | |
| 236 | }; | |
| 237 | } | |
| 238 | }; |
lib/std/os/linux/or1k.zig-39| ... | ... | @@ -131,43 +131,4 @@ pub fn clone() callconv(.naked) u32 { |
| 131 | 131 | |
| 132 | 132 | pub const VDSO = void; |
| 133 | 133 | |
| 134 | pub const blksize_t = u32; | |
| 135 | pub const nlink_t = u32; | |
| 136 | 134 | pub const time_t = i32; |
| 137 | pub const mode_t = u32; | |
| 138 | pub const off_t = i64; | |
| 139 | pub const ino_t = u64; | |
| 140 | pub const dev_t = u64; | |
| 141 | pub const blkcnt_t = i64; | |
| 142 | ||
| 143 | // The `stat64` definition used by the Linux kernel. | |
| 144 | pub const Stat = extern struct { | |
| 145 | dev: dev_t, | |
| 146 | ino: ino_t, | |
| 147 | mode: mode_t, | |
| 148 | nlink: nlink_t, | |
| 149 | uid: std.os.linux.uid_t, | |
| 150 | gid: std.os.linux.gid_t, | |
| 151 | rdev: dev_t, | |
| 152 | _pad0: [2]u32, | |
| 153 | size: off_t, | |
| 154 | blksize: blksize_t, | |
| 155 | _pad1: u32, | |
| 156 | blocks: blkcnt_t, | |
| 157 | atim: std.os.linux.timespec, | |
| 158 | mtim: std.os.linux.timespec, | |
| 159 | ctim: std.os.linux.timespec, | |
| 160 | _pad2: [2]u32, | |
| 161 | ||
| 162 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 163 | return self.atim; | |
| 164 | } | |
| 165 | ||
| 166 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 167 | return self.mtim; | |
| 168 | } | |
| 169 | ||
| 170 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 171 | return self.ctim; | |
| 172 | } | |
| 173 | }; |
lib/std/os/linux/powerpc.zig-38| ... | ... | @@ -269,42 +269,4 @@ pub const VDSO = struct { |
| 269 | 269 | pub const CGT_VER = "LINUX_2.6.15"; |
| 270 | 270 | }; |
| 271 | 271 | |
| 272 | pub const blksize_t = i32; | |
| 273 | pub const nlink_t = u32; | |
| 274 | 272 | pub const time_t = i32; |
| 275 | pub const mode_t = u32; | |
| 276 | pub const off_t = i64; | |
| 277 | pub const ino_t = u64; | |
| 278 | pub const dev_t = u64; | |
| 279 | pub const blkcnt_t = i64; | |
| 280 | ||
| 281 | // The `stat` definition used by the Linux kernel. | |
| 282 | pub const Stat = extern struct { | |
| 283 | dev: dev_t, | |
| 284 | ino: ino_t, | |
| 285 | mode: mode_t, | |
| 286 | nlink: nlink_t, | |
| 287 | uid: std.os.linux.uid_t, | |
| 288 | gid: std.os.linux.gid_t, | |
| 289 | rdev: dev_t, | |
| 290 | __rdev_padding: i16, | |
| 291 | size: off_t, | |
| 292 | blksize: blksize_t, | |
| 293 | blocks: blkcnt_t, | |
| 294 | atim: std.os.linux.timespec, | |
| 295 | mtim: std.os.linux.timespec, | |
| 296 | ctim: std.os.linux.timespec, | |
| 297 | __unused: [2]u32, | |
| 298 | ||
| 299 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 300 | return self.atim; | |
| 301 | } | |
| 302 | ||
| 303 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 304 | return self.mtim; | |
| 305 | } | |
| 306 | ||
| 307 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 308 | return self.ctim; | |
| 309 | } | |
| 310 | }; |
lib/std/os/linux/powerpc64.zig-37| ... | ... | @@ -254,41 +254,4 @@ pub const VDSO = struct { |
| 254 | 254 | pub const CGT_VER = "LINUX_2.6.15"; |
| 255 | 255 | }; |
| 256 | 256 | |
| 257 | pub const blksize_t = i64; | |
| 258 | pub const nlink_t = u64; | |
| 259 | 257 | pub const time_t = i64; |
| 260 | pub const mode_t = u32; | |
| 261 | pub const off_t = i64; | |
| 262 | pub const ino_t = u64; | |
| 263 | pub const dev_t = u64; | |
| 264 | pub const blkcnt_t = i64; | |
| 265 | ||
| 266 | // The `stat` definition used by the Linux kernel. | |
| 267 | pub const Stat = extern struct { | |
| 268 | dev: dev_t, | |
| 269 | ino: ino_t, | |
| 270 | nlink: nlink_t, | |
| 271 | mode: mode_t, | |
| 272 | uid: std.os.linux.uid_t, | |
| 273 | gid: std.os.linux.gid_t, | |
| 274 | rdev: dev_t, | |
| 275 | size: off_t, | |
| 276 | blksize: blksize_t, | |
| 277 | blocks: blkcnt_t, | |
| 278 | atim: std.os.linux.timespec, | |
| 279 | mtim: std.os.linux.timespec, | |
| 280 | ctim: std.os.linux.timespec, | |
| 281 | __unused: [3]u64, | |
| 282 | ||
| 283 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 284 | return self.atim; | |
| 285 | } | |
| 286 | ||
| 287 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 288 | return self.mtim; | |
| 289 | } | |
| 290 | ||
| 291 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 292 | return self.ctim; | |
| 293 | } | |
| 294 | }; |
lib/std/os/linux/riscv32.zig-39| ... | ... | @@ -124,46 +124,7 @@ pub fn clone() callconv(.naked) u32 { |
| 124 | 124 | ); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | pub const blksize_t = i32; | |
| 128 | pub const nlink_t = u32; | |
| 129 | 127 | pub const time_t = i64; |
| 130 | pub const mode_t = u32; | |
| 131 | pub const off_t = i64; | |
| 132 | pub const ino_t = u64; | |
| 133 | pub const dev_t = u64; | |
| 134 | pub const blkcnt_t = i64; | |
| 135 | ||
| 136 | // The `stat` definition used by the Linux kernel. | |
| 137 | pub const Stat = extern struct { | |
| 138 | dev: dev_t, | |
| 139 | ino: ino_t, | |
| 140 | mode: mode_t, | |
| 141 | nlink: nlink_t, | |
| 142 | uid: std.os.linux.uid_t, | |
| 143 | gid: std.os.linux.gid_t, | |
| 144 | rdev: dev_t, | |
| 145 | __pad: u32, | |
| 146 | size: off_t, | |
| 147 | blksize: blksize_t, | |
| 148 | __pad2: i32, | |
| 149 | blocks: blkcnt_t, | |
| 150 | atim: std.os.linux.timespec, | |
| 151 | mtim: std.os.linux.timespec, | |
| 152 | ctim: std.os.linux.timespec, | |
| 153 | __unused: [2]u32, | |
| 154 | ||
| 155 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 156 | return self.atim; | |
| 157 | } | |
| 158 | ||
| 159 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 160 | return self.mtim; | |
| 161 | } | |
| 162 | ||
| 163 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 164 | return self.ctim; | |
| 165 | } | |
| 166 | }; | |
| 167 | 128 | |
| 168 | 129 | pub const VDSO = struct { |
| 169 | 130 | pub const CGT_SYM = "__vdso_clock_gettime"; |
lib/std/os/linux/riscv64.zig-39| ... | ... | @@ -124,46 +124,7 @@ pub fn clone() callconv(.naked) u64 { |
| 124 | 124 | ); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | pub const blksize_t = i32; | |
| 128 | pub const nlink_t = u32; | |
| 129 | 127 | pub const time_t = i64; |
| 130 | pub const mode_t = u32; | |
| 131 | pub const off_t = i64; | |
| 132 | pub const ino_t = u64; | |
| 133 | pub const dev_t = u64; | |
| 134 | pub const blkcnt_t = i64; | |
| 135 | ||
| 136 | // The `stat` definition used by the Linux kernel. | |
| 137 | pub const Stat = extern struct { | |
| 138 | dev: dev_t, | |
| 139 | ino: ino_t, | |
| 140 | mode: mode_t, | |
| 141 | nlink: nlink_t, | |
| 142 | uid: std.os.linux.uid_t, | |
| 143 | gid: std.os.linux.gid_t, | |
| 144 | rdev: dev_t, | |
| 145 | __pad: u64, | |
| 146 | size: off_t, | |
| 147 | blksize: blksize_t, | |
| 148 | __pad2: i32, | |
| 149 | blocks: blkcnt_t, | |
| 150 | atim: std.os.linux.timespec, | |
| 151 | mtim: std.os.linux.timespec, | |
| 152 | ctim: std.os.linux.timespec, | |
| 153 | __unused: [2]u32, | |
| 154 | ||
| 155 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 156 | return self.atim; | |
| 157 | } | |
| 158 | ||
| 159 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 160 | return self.mtim; | |
| 161 | } | |
| 162 | ||
| 163 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 164 | return self.ctim; | |
| 165 | } | |
| 166 | }; | |
| 167 | 128 | |
| 168 | 129 | pub const VDSO = struct { |
| 169 | 130 | pub const CGT_SYM = "__vdso_clock_gettime"; |
lib/std/os/linux/s390x.zig-37| ... | ... | @@ -152,44 +152,7 @@ pub fn restore_rt() callconv(.naked) noreturn { |
| 152 | 152 | ); |
| 153 | 153 | } |
| 154 | 154 | |
| 155 | pub const blksize_t = i64; | |
| 156 | pub const nlink_t = u64; | |
| 157 | 155 | pub const time_t = i64; |
| 158 | pub const mode_t = u32; | |
| 159 | pub const off_t = i64; | |
| 160 | pub const ino_t = u64; | |
| 161 | pub const dev_t = u64; | |
| 162 | pub const blkcnt_t = i64; | |
| 163 | ||
| 164 | // The `stat` definition used by the Linux kernel. | |
| 165 | pub const Stat = extern struct { | |
| 166 | dev: dev_t, | |
| 167 | ino: ino_t, | |
| 168 | nlink: nlink_t, | |
| 169 | mode: mode_t, | |
| 170 | uid: std.os.linux.uid_t, | |
| 171 | gid: std.os.linux.gid_t, | |
| 172 | rdev: dev_t, | |
| 173 | size: off_t, | |
| 174 | atim: std.os.linux.timespec, | |
| 175 | mtim: std.os.linux.timespec, | |
| 176 | ctim: std.os.linux.timespec, | |
| 177 | blksize: blksize_t, | |
| 178 | blocks: blkcnt_t, | |
| 179 | __unused: [3]c_ulong, | |
| 180 | ||
| 181 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 182 | return self.atim; | |
| 183 | } | |
| 184 | ||
| 185 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 186 | return self.mtim; | |
| 187 | } | |
| 188 | ||
| 189 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 190 | return self.ctim; | |
| 191 | } | |
| 192 | }; | |
| 193 | 156 | |
| 194 | 157 | pub const VDSO = struct { |
| 195 | 158 | pub const CGT_SYM = "__kernel_clock_gettime"; |
lib/std/os/linux/sparc64.zig-42| ... | ... | @@ -228,46 +228,4 @@ pub const VDSO = struct { |
| 228 | 228 | pub const CGT_VER = "LINUX_2.6"; |
| 229 | 229 | }; |
| 230 | 230 | |
| 231 | pub const off_t = i64; | |
| 232 | pub const ino_t = u64; | |
| 233 | 231 | pub const time_t = i64; |
| 234 | pub const mode_t = u32; | |
| 235 | pub const dev_t = u64; | |
| 236 | pub const nlink_t = u32; | |
| 237 | pub const blksize_t = i64; | |
| 238 | pub const blkcnt_t = i64; | |
| 239 | ||
| 240 | // The `stat64` definition used by the kernel. | |
| 241 | pub const Stat = extern struct { | |
| 242 | dev: dev_t, | |
| 243 | ino: ino_t, | |
| 244 | nlink: nlink_t, | |
| 245 | _pad: i32, | |
| 246 | ||
| 247 | mode: mode_t, | |
| 248 | uid: std.os.linux.uid_t, | |
| 249 | gid: std.os.linux.gid_t, | |
| 250 | __pad0: u32, | |
| 251 | ||
| 252 | rdev: dev_t, | |
| 253 | size: i64, | |
| 254 | blksize: blksize_t, | |
| 255 | blocks: blkcnt_t, | |
| 256 | ||
| 257 | atim: std.os.linux.timespec, | |
| 258 | mtim: std.os.linux.timespec, | |
| 259 | ctim: std.os.linux.timespec, | |
| 260 | __unused: [3]u64, | |
| 261 | ||
| 262 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 263 | return self.atim; | |
| 264 | } | |
| 265 | ||
| 266 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 267 | return self.mtim; | |
| 268 | } | |
| 269 | ||
| 270 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 271 | return self.ctim; | |
| 272 | } | |
| 273 | }; |
lib/std/os/linux/test.zig+12-18| ... | ... | @@ -10,8 +10,6 @@ const expectEqual = std.testing.expectEqual; |
| 10 | 10 | const fs = std.fs; |
| 11 | 11 | |
| 12 | 12 | test "fallocate" { |
| 13 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23809 | |
| 14 | ||
| 15 | 13 | var tmp = std.testing.tmpDir(.{}); |
| 16 | 14 | defer tmp.cleanup(); |
| 17 | 15 | |
| ... | ... | @@ -84,26 +82,22 @@ test "statx" { |
| 84 | 82 | var file = try tmp.dir.createFile(tmp_file_name, .{}); |
| 85 | 83 | defer file.close(); |
| 86 | 84 | |
| 87 | var statx_buf: linux.Statx = undefined; | |
| 88 | switch (linux.errno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) { | |
| 89 | .SUCCESS => {}, | |
| 90 | else => unreachable, | |
| 91 | } | |
| 92 | ||
| 93 | if (builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; // No fstatat, so the rest of the test is meaningless. | |
| 94 | ||
| 95 | var stat_buf: linux.Stat = undefined; | |
| 96 | switch (linux.errno(linux.fstatat(file.handle, "", &stat_buf, linux.AT.EMPTY_PATH))) { | |
| 85 | var buf: linux.Statx = undefined; | |
| 86 | switch (linux.errno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, .BASIC_STATS, &buf))) { | |
| 97 | 87 | .SUCCESS => {}, |
| 98 | 88 | else => unreachable, |
| 99 | 89 | } |
| 100 | 90 | |
| 101 | try expect(stat_buf.mode == statx_buf.mode); | |
| 102 | try expect(@as(u32, @bitCast(stat_buf.uid)) == statx_buf.uid); | |
| 103 | try expect(@as(u32, @bitCast(stat_buf.gid)) == statx_buf.gid); | |
| 104 | try expect(@as(u64, @bitCast(@as(i64, stat_buf.size))) == statx_buf.size); | |
| 105 | try expect(@as(u64, @bitCast(@as(i64, stat_buf.blksize))) == statx_buf.blksize); | |
| 106 | try expect(@as(u64, @bitCast(@as(i64, stat_buf.blocks))) == statx_buf.blocks); | |
| 91 | const uid = linux.getuid(); | |
| 92 | const gid = linux.getgid(); | |
| 93 | if (buf.mask.MODE) | |
| 94 | try expectEqual(@as(linux.mode_t, linux.S.IFREG), buf.mode & linux.S.IFMT); | |
| 95 | if (buf.mask.UID) | |
| 96 | try expectEqual(uid, buf.uid); | |
| 97 | if (buf.mask.GID) | |
| 98 | try expectEqual(gid, buf.gid); | |
| 99 | if (buf.mask.SIZE) | |
| 100 | try expectEqual(@as(u64, 0), buf.size); | |
| 107 | 101 | } |
| 108 | 102 | |
| 109 | 103 | test "user and group ids" { |
lib/std/os/linux/x32.zig-40| ... | ... | @@ -132,14 +132,7 @@ pub fn restore_rt() callconv(.naked) noreturn { |
| 132 | 132 | } |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | pub const mode_t = u32; | |
| 136 | 135 | pub const time_t = i32; |
| 137 | pub const nlink_t = u32; | |
| 138 | pub const blksize_t = i32; | |
| 139 | pub const blkcnt_t = i32; | |
| 140 | pub const off_t = i64; | |
| 141 | pub const ino_t = u64; | |
| 142 | pub const dev_t = u64; | |
| 143 | 136 | |
| 144 | 137 | pub const VDSO = struct { |
| 145 | 138 | pub const CGT_SYM = "__vdso_clock_gettime"; |
| ... | ... | @@ -155,36 +148,3 @@ pub const ARCH = struct { |
| 155 | 148 | pub const GET_FS = 0x1003; |
| 156 | 149 | pub const GET_GS = 0x1004; |
| 157 | 150 | }; |
| 158 | ||
| 159 | // The `stat` definition used by the Linux kernel. | |
| 160 | pub const Stat = extern struct { | |
| 161 | dev: dev_t, | |
| 162 | ino: ino_t, | |
| 163 | nlink: nlink_t, | |
| 164 | ||
| 165 | mode: mode_t, | |
| 166 | uid: std.os.linux.uid_t, | |
| 167 | gid: std.os.linux.gid_t, | |
| 168 | __pad0: u32, | |
| 169 | rdev: dev_t, | |
| 170 | size: off_t, | |
| 171 | blksize: blksize_t, | |
| 172 | blocks: i64, | |
| 173 | ||
| 174 | atim: std.os.linux.timespec, | |
| 175 | mtim: std.os.linux.timespec, | |
| 176 | ctim: std.os.linux.timespec, | |
| 177 | __unused: [3]i32, | |
| 178 | ||
| 179 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 180 | return self.atim; | |
| 181 | } | |
| 182 | ||
| 183 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 184 | return self.mtim; | |
| 185 | } | |
| 186 | ||
| 187 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 188 | return self.ctim; | |
| 189 | } | |
| 190 | }; |
lib/std/os/linux/x86.zig-39| ... | ... | @@ -195,46 +195,7 @@ pub const VDSO = struct { |
| 195 | 195 | pub const CGT_VER = "LINUX_2.6"; |
| 196 | 196 | }; |
| 197 | 197 | |
| 198 | pub const blksize_t = i32; | |
| 199 | pub const nlink_t = u32; | |
| 200 | 198 | pub const time_t = i32; |
| 201 | pub const mode_t = u32; | |
| 202 | pub const off_t = i64; | |
| 203 | pub const ino_t = u64; | |
| 204 | pub const dev_t = u64; | |
| 205 | pub const blkcnt_t = i64; | |
| 206 | ||
| 207 | // The `stat` definition used by the Linux kernel. | |
| 208 | pub const Stat = extern struct { | |
| 209 | dev: dev_t, | |
| 210 | __dev_padding: u32, | |
| 211 | __ino_truncated: u32, | |
| 212 | mode: mode_t, | |
| 213 | nlink: nlink_t, | |
| 214 | uid: std.os.linux.uid_t, | |
| 215 | gid: std.os.linux.gid_t, | |
| 216 | rdev: dev_t, | |
| 217 | __rdev_padding: u32, | |
| 218 | size: off_t, | |
| 219 | blksize: blksize_t, | |
| 220 | blocks: blkcnt_t, | |
| 221 | atim: std.os.linux.timespec, | |
| 222 | mtim: std.os.linux.timespec, | |
| 223 | ctim: std.os.linux.timespec, | |
| 224 | ino: ino_t, | |
| 225 | ||
| 226 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 227 | return self.atim; | |
| 228 | } | |
| 229 | ||
| 230 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 231 | return self.mtim; | |
| 232 | } | |
| 233 | ||
| 234 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 235 | return self.ctim; | |
| 236 | } | |
| 237 | }; | |
| 238 | 199 | |
| 239 | 200 | pub const user_desc = extern struct { |
| 240 | 201 | entry_number: u32, |
lib/std/os/linux/x86_64.zig-40| ... | ... | @@ -132,14 +132,7 @@ pub fn restore_rt() callconv(.naked) noreturn { |
| 132 | 132 | } |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | pub const mode_t = u64; | |
| 136 | 135 | pub const time_t = i64; |
| 137 | pub const nlink_t = u64; | |
| 138 | pub const blksize_t = i64; | |
| 139 | pub const blkcnt_t = i64; | |
| 140 | pub const off_t = i64; | |
| 141 | pub const ino_t = u64; | |
| 142 | pub const dev_t = u64; | |
| 143 | 136 | |
| 144 | 137 | pub const VDSO = struct { |
| 145 | 138 | pub const CGT_SYM = "__vdso_clock_gettime"; |
| ... | ... | @@ -155,36 +148,3 @@ pub const ARCH = struct { |
| 155 | 148 | pub const GET_FS = 0x1003; |
| 156 | 149 | pub const GET_GS = 0x1004; |
| 157 | 150 | }; |
| 158 | ||
| 159 | // The `stat` definition used by the Linux kernel. | |
| 160 | pub const Stat = extern struct { | |
| 161 | dev: dev_t, | |
| 162 | ino: ino_t, | |
| 163 | nlink: u64, | |
| 164 | ||
| 165 | mode: u32, | |
| 166 | uid: std.os.linux.uid_t, | |
| 167 | gid: std.os.linux.gid_t, | |
| 168 | __pad0: u32, | |
| 169 | rdev: dev_t, | |
| 170 | size: off_t, | |
| 171 | blksize: i64, | |
| 172 | blocks: i64, | |
| 173 | ||
| 174 | atim: std.os.linux.timespec, | |
| 175 | mtim: std.os.linux.timespec, | |
| 176 | ctim: std.os.linux.timespec, | |
| 177 | __unused: [3]i64, | |
| 178 | ||
| 179 | pub fn atime(self: @This()) std.os.linux.timespec { | |
| 180 | return self.atim; | |
| 181 | } | |
| 182 | ||
| 183 | pub fn mtime(self: @This()) std.os.linux.timespec { | |
| 184 | return self.mtim; | |
| 185 | } | |
| 186 | ||
| 187 | pub fn ctime(self: @This()) std.os.linux.timespec { | |
| 188 | return self.ctim; | |
| 189 | } | |
| 190 | }; |
lib/std/posix.zig+25-13| ... | ... | @@ -119,7 +119,18 @@ pub const STDIN_FILENO = system.STDIN_FILENO; |
| 119 | 119 | pub const STDOUT_FILENO = system.STDOUT_FILENO; |
| 120 | 120 | pub const SYS = system.SYS; |
| 121 | 121 | pub const Sigaction = system.Sigaction; |
| 122 | pub const Stat = system.Stat; | |
| 122 | pub const Stat = switch (native_os) { | |
| 123 | // Has no concept of `stat`. | |
| 124 | .windows => void, | |
| 125 | // The `stat` bits/wrappers are removed due to having to maintain the | |
| 126 | // different varying `struct stat`s per target and libc, leading to runtime | |
| 127 | // errors. | |
| 128 | // | |
| 129 | // Users targeting linux should add a comptime check and use `statx`, | |
| 130 | // similar to how `std.fs.File.stat` does. | |
| 131 | .linux => void, | |
| 132 | else => system.Stat, | |
| 133 | }; | |
| 123 | 134 | pub const T = system.T; |
| 124 | 135 | pub const TCP = system.TCP; |
| 125 | 136 | pub const VDSO = system.VDSO; |
| ... | ... | @@ -480,15 +491,21 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr |
| 480 | 491 | } |
| 481 | 492 | defer close(pathfd); |
| 482 | 493 | |
| 483 | const stat = fstatatZ(pathfd, "", AT.EMPTY_PATH) catch |err| switch (err) { | |
| 494 | const path_mode = if (linux.wrapped.statx( | |
| 495 | pathfd, | |
| 496 | "", | |
| 497 | AT.EMPTY_PATH, | |
| 498 | .{ .TYPE = true }, | |
| 499 | )) |stx| blk: { | |
| 500 | assert(stx.mask.TYPE); | |
| 501 | break :blk stx.mode; | |
| 502 | } else |err| switch (err) { | |
| 484 | 503 | error.NameTooLong => unreachable, |
| 485 | 504 | error.FileNotFound => unreachable, |
| 486 | error.Streaming => unreachable, | |
| 487 | error.BadPathName => return error.Unexpected, | |
| 488 | error.Canceled => return error.Canceled, | |
| 489 | 505 | else => |e| return e, |
| 490 | 506 | }; |
| 491 | if ((stat.mode & S.IFMT) == S.IFLNK) | |
| 507 | // Even though we only wanted TYPE, the kernel can still fill in the additional bits. | |
| 508 | if ((path_mode & S.IFMT) == S.IFLNK) | |
| 492 | 509 | return error.OperationNotSupported; |
| 493 | 510 | |
| 494 | 511 | var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined; |
| ... | ... | @@ -3843,13 +3860,9 @@ pub fn fstat(fd: fd_t) FStatError!Stat { |
| 3843 | 3860 | if (native_os == .wasi and !builtin.link_libc) { |
| 3844 | 3861 | return Stat.fromFilestat(try std.os.fstat_wasi(fd)); |
| 3845 | 3862 | } |
| 3846 | if (native_os == .windows) { | |
| 3847 | @compileError("fstat is not yet implemented on Windows"); | |
| 3848 | } | |
| 3849 | 3863 | |
| 3850 | const fstat_sym = if (lfs64_abi) system.fstat64 else system.fstat; | |
| 3851 | 3864 | var stat = mem.zeroes(Stat); |
| 3852 | switch (errno(fstat_sym(fd, &stat))) { | |
| 3865 | switch (errno(system.fstat(fd, &stat))) { | |
| 3853 | 3866 | .SUCCESS => return stat, |
| 3854 | 3867 | .INVAL => unreachable, |
| 3855 | 3868 | .BADF => unreachable, // Always a race condition. |
| ... | ... | @@ -3889,9 +3902,8 @@ pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!S |
| 3889 | 3902 | @compileError("use std.Io instead"); |
| 3890 | 3903 | } |
| 3891 | 3904 | |
| 3892 | const fstatat_sym = if (lfs64_abi) system.fstatat64 else system.fstatat; | |
| 3893 | 3905 | var stat = mem.zeroes(Stat); |
| 3894 | switch (errno(fstatat_sym(dirfd, pathname, &stat, flags))) { | |
| 3906 | switch (errno(system.fstatat(dirfd, pathname, &stat, flags))) { | |
| 3895 | 3907 | .SUCCESS => return stat, |
| 3896 | 3908 | .INVAL => unreachable, |
| 3897 | 3909 | .BADF => unreachable, // Always a race condition. |
lib/std/posix/test.zig+78-21| ... | ... | @@ -16,6 +16,7 @@ const AtomicRmwOp = std.builtin.AtomicRmwOp; |
| 16 | 16 | const AtomicOrder = std.builtin.AtomicOrder; |
| 17 | 17 | const native_os = builtin.target.os.tag; |
| 18 | 18 | const tmpDir = std.testing.tmpDir; |
| 19 | const AT = posix.AT; | |
| 19 | 20 | |
| 20 | 21 | // NOTE: several additional tests are in test/standalone/posix/. Any tests that mutate |
| 21 | 22 | // process-wide POSIX state (cwd, signals, etc) cannot be Zig unit tests and should be over there. |
| ... | ... | @@ -123,10 +124,24 @@ fn testReadlink(target_path: []const u8, symlink_path: []const u8) !void { |
| 123 | 124 | try expect(mem.eql(u8, target_path, given)); |
| 124 | 125 | } |
| 125 | 126 | |
| 126 | test "linkat with different directories" { | |
| 127 | if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`. | |
| 128 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; // `nstat.nlink` assertion is failing with LLVM 20+ for unclear reasons. | |
| 127 | fn getLinkInfo(fd: posix.fd_t) !struct { posix.ino_t, posix.nlink_t } { | |
| 128 | if (native_os == .linux) { | |
| 129 | const stx = try linux.wrapped.statx( | |
| 130 | fd, | |
| 131 | "", | |
| 132 | posix.AT.EMPTY_PATH, | |
| 133 | .{ .INO = true, .NLINK = true }, | |
| 134 | ); | |
| 135 | std.debug.assert(stx.mask.INO); | |
| 136 | std.debug.assert(stx.mask.NLINK); | |
| 137 | return .{ stx.ino, stx.nlink }; | |
| 138 | } | |
| 129 | 139 | |
| 140 | const st = try posix.fstat(fd); | |
| 141 | return .{ st.ino, st.nlink }; | |
| 142 | } | |
| 143 | ||
| 144 | test "linkat with different directories" { | |
| 130 | 145 | switch (native_os) { |
| 131 | 146 | .wasi, .linux, .illumos => {}, |
| 132 | 147 | else => return error.SkipZigTest, |
| ... | ... | @@ -153,19 +168,49 @@ test "linkat with different directories" { |
| 153 | 168 | defer nfd.close(); |
| 154 | 169 | |
| 155 | 170 | { |
| 156 | const estat = try posix.fstat(efd.handle); | |
| 157 | const nstat = try posix.fstat(nfd.handle); | |
| 158 | try testing.expectEqual(estat.ino, nstat.ino); | |
| 159 | try testing.expectEqual(@as(@TypeOf(nstat.nlink), 2), nstat.nlink); | |
| 171 | const eino, _ = try getLinkInfo(efd.handle); | |
| 172 | const nino, const nlink = try getLinkInfo(nfd.handle); | |
| 173 | try testing.expectEqual(eino, nino); | |
| 174 | try testing.expectEqual(@as(posix.nlink_t, 2), nlink); | |
| 160 | 175 | } |
| 161 | 176 | |
| 162 | 177 | // Test 2: remove link |
| 163 | 178 | try posix.unlinkat(subdir.fd, link_name, 0); |
| 179 | _, const elink = try getLinkInfo(efd.handle); | |
| 180 | try testing.expectEqual(@as(posix.nlink_t, 1), elink); | |
| 181 | } | |
| 164 | 182 | |
| 165 | { | |
| 166 | const estat = try posix.fstat(efd.handle); | |
| 167 | try testing.expectEqual(@as(@TypeOf(estat.nlink), 1), estat.nlink); | |
| 168 | } | |
| 183 | test "fstatat" { | |
| 184 | if (posix.Stat == void) return error.SkipZigTest; | |
| 185 | if (native_os == .wasi and !builtin.link_libc) return error.SkipZigTest; | |
| 186 | ||
| 187 | var tmp = tmpDir(.{}); | |
| 188 | defer tmp.cleanup(); | |
| 189 | ||
| 190 | // create dummy file | |
| 191 | const contents = "nonsense"; | |
| 192 | try tmp.dir.writeFile(.{ .sub_path = "file.txt", .data = contents }); | |
| 193 | ||
| 194 | // fetch file's info on the opened fd directly | |
| 195 | const file = try tmp.dir.openFile("file.txt", .{}); | |
| 196 | const stat = try posix.fstat(file.handle); | |
| 197 | defer file.close(); | |
| 198 | ||
| 199 | // now repeat but using `fstatat` instead | |
| 200 | const statat = try posix.fstatat(tmp.dir.fd, "file.txt", posix.AT.SYMLINK_NOFOLLOW); | |
| 201 | ||
| 202 | try expectEqual(stat.dev, statat.dev); | |
| 203 | try expectEqual(stat.ino, statat.ino); | |
| 204 | try expectEqual(stat.nlink, statat.nlink); | |
| 205 | try expectEqual(stat.mode, statat.mode); | |
| 206 | try expectEqual(stat.uid, statat.uid); | |
| 207 | try expectEqual(stat.gid, statat.gid); | |
| 208 | try expectEqual(stat.rdev, statat.rdev); | |
| 209 | try expectEqual(stat.size, statat.size); | |
| 210 | try expectEqual(stat.blksize, statat.blksize); | |
| 211 | // The stat.blocks/statat.blocks count is managed by the filesystem and may | |
| 212 | // change if the file is stored in a journal or "inline". | |
| 213 | // try expectEqual(stat.blocks, statat.blocks); | |
| 169 | 214 | } |
| 170 | 215 | |
| 171 | 216 | test "readlinkat" { |
| ... | ... | @@ -906,14 +951,31 @@ test "pwrite with empty buffer" { |
| 906 | 951 | try expectEqual(rc, 0); |
| 907 | 952 | } |
| 908 | 953 | |
| 954 | fn getFileMode(dir: posix.fd_t, path: []const u8) !posix.mode_t { | |
| 955 | const path_z = try posix.toPosixPath(path); | |
| 956 | const mode: posix.mode_t = if (native_os == .linux) blk: { | |
| 957 | const stx = try linux.wrapped.statx( | |
| 958 | dir, | |
| 959 | &path_z, | |
| 960 | posix.AT.SYMLINK_NOFOLLOW, | |
| 961 | .{ .MODE = true }, | |
| 962 | ); | |
| 963 | std.debug.assert(stx.mask.MODE); | |
| 964 | break :blk stx.mode; | |
| 965 | } else blk: { | |
| 966 | const st = try posix.fstatatZ(dir, &path_z, posix.AT.SYMLINK_NOFOLLOW); | |
| 967 | break :blk st.mode; | |
| 968 | }; | |
| 969 | ||
| 970 | return mode & 0b111_111_111; | |
| 971 | } | |
| 972 | ||
| 909 | 973 | fn expectMode(dir: posix.fd_t, file: []const u8, mode: posix.mode_t) !void { |
| 910 | const st = try posix.fstatat(dir, file, posix.AT.SYMLINK_NOFOLLOW); | |
| 911 | try expectEqual(mode, st.mode & 0b111_111_111); | |
| 974 | const actual = try getFileMode(dir, file); | |
| 975 | try expectEqual(mode, actual & 0b111_111_111); | |
| 912 | 976 | } |
| 913 | 977 | |
| 914 | 978 | test "fchmodat smoke test" { |
| 915 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/23808 | |
| 916 | ||
| 917 | 979 | if (!std.fs.has_executable_bit) return error.SkipZigTest; |
| 918 | 980 | |
| 919 | 981 | var tmp = tmpDir(.{}); |
| ... | ... | @@ -928,13 +990,8 @@ test "fchmodat smoke test" { |
| 928 | 990 | ); |
| 929 | 991 | posix.close(fd); |
| 930 | 992 | |
| 931 | if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // No `fstatat()`. | |
| 932 | ||
| 933 | 993 | try posix.symlinkat("regfile", tmp.dir.fd, "symlink"); |
| 934 | const sym_mode = blk: { | |
| 935 | const st = try posix.fstatat(tmp.dir.fd, "symlink", posix.AT.SYMLINK_NOFOLLOW); | |
| 936 | break :blk st.mode & 0b111_111_111; | |
| 937 | }; | |
| 994 | const sym_mode = try getFileMode(tmp.dir.fd, "symlink"); | |
| 938 | 995 | |
| 939 | 996 | try posix.fchmodat(tmp.dir.fd, "regfile", 0o640, 0); |
| 940 | 997 | try expectMode(tmp.dir.fd, "regfile", 0o640); |
src/link/MappedFile.zig+14| ... | ... | @@ -54,6 +54,20 @@ pub fn init(file: std.Io.File, gpa: std.mem.Allocator) !MappedFile { |
| 54 | 54 | }, |
| 55 | 55 | }; |
| 56 | 56 | } |
| 57 | if (is_linux) { | |
| 58 | const statx = try linux.wrapped.statx( | |
| 59 | mf.file.handle, | |
| 60 | "", | |
| 61 | std.posix.AT.EMPTY_PATH, | |
| 62 | .{ .TYPE = true, .SIZE = true, .BLOCKS = true }, | |
| 63 | ); | |
| 64 | assert(statx.mask.TYPE); | |
| 65 | assert(statx.mask.SIZE); | |
| 66 | assert(statx.mask.BLOCKS); | |
| 67 | ||
| 68 | if (!std.posix.S.ISREG(statx.mode)) return error.PathAlreadyExists; | |
| 69 | break :stat .{ statx.size, @max(std.heap.pageSize(), statx.blksize) }; | |
| 70 | } | |
| 57 | 71 | const stat = try std.posix.fstat(mf.file.handle); |
| 58 | 72 | if (!std.posix.S.ISREG(stat.mode)) return error.PathAlreadyExists; |
| 59 | 73 | break :stat .{ @bitCast(stat.size), @max(std.heap.pageSize(), stat.blksize) }; |
test/standalone/glibc_compat/glibc_runtime_check.zig+6-3| ... | ... | @@ -23,16 +23,19 @@ const c_string = @cImport( |
| 23 | 23 | // Version of glibc this test is being built to run against |
| 24 | 24 | const glibc_ver = builtin.os.versionRange().gnuLibCVersion().?; |
| 25 | 25 | |
| 26 | extern "c" fn fstatat(dirfd: i32, path: [*:0]const u8, buf: [*]const u8, flag: u32) c_int; | |
| 27 | extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: [*]const u8) c_int; | |
| 28 | ||
| 26 | 29 | // PR #17034 - fstat moved between libc_nonshared and libc |
| 27 | 30 | fn checkStat() !void { |
| 28 | 31 | const cwdFd = std.fs.cwd().fd; |
| 29 | 32 | |
| 30 | var stat = std.mem.zeroes(std.c.Stat); | |
| 31 | var result = std.c.fstatat(cwdFd, "a_file_that_definitely_does_not_exist", &stat, 0); | |
| 33 | var buf: [256]u8 = @splat(0); | |
| 34 | var result = fstatat(cwdFd, "a_file_that_definitely_does_not_exist", &buf, 0); | |
| 32 | 35 | assert(result == -1); |
| 33 | 36 | assert(std.posix.errno(result) == .NOENT); |
| 34 | 37 | |
| 35 | result = std.c.stat("a_file_that_definitely_does_not_exist", &stat); | |
| 38 | result = stat("a_file_that_definitely_does_not_exist", &buf); | |
| 36 | 39 | assert(result == -1); |
| 37 | 40 | assert(std.posix.errno(result) == .NOENT); |
| 38 | 41 | } |
test/standalone/posix/relpaths.zig+23-15| ... | ... | @@ -48,20 +48,29 @@ fn test_symlink(a: std.mem.Allocator, tmp: std.testing.TmpDir) !void { |
| 48 | 48 | try std.testing.expectEqualStrings(target_name, given); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | fn getLinkInfo(fd: std.posix.fd_t) !struct { std.posix.ino_t, std.posix.nlink_t } { | |
| 52 | if (builtin.target.os.tag == .linux) { | |
| 53 | const stx = try std.os.linux.wrapped.statx( | |
| 54 | fd, | |
| 55 | "", | |
| 56 | std.posix.AT.EMPTY_PATH, | |
| 57 | .{ .INO = true, .NLINK = true }, | |
| 58 | ); | |
| 59 | std.debug.assert(stx.mask.INO); | |
| 60 | std.debug.assert(stx.mask.NLINK); | |
| 61 | return .{ stx.ino, stx.nlink }; | |
| 62 | } | |
| 63 | ||
| 64 | const st = try std.posix.fstat(fd); | |
| 65 | return .{ st.ino, st.nlink }; | |
| 66 | } | |
| 67 | ||
| 51 | 68 | fn test_link(tmp: std.testing.TmpDir) !void { |
| 52 | 69 | switch (builtin.target.os.tag) { |
| 53 | 70 | .linux, .illumos => {}, |
| 54 | 71 | else => return, |
| 55 | 72 | } |
| 56 | 73 | |
| 57 | if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and builtin.target.os.tag == .linux and !builtin.link_libc) { | |
| 58 | return; // No `fstat()`. | |
| 59 | } | |
| 60 | ||
| 61 | if (builtin.cpu.arch.isMIPS64()) { | |
| 62 | return; // `nstat.nlink` assertion is failing with LLVM 20+ for unclear reasons. | |
| 63 | } | |
| 64 | ||
| 65 | 74 | const target_name = "link-target"; |
| 66 | 75 | const link_name = "newlink"; |
| 67 | 76 | |
| ... | ... | @@ -78,17 +87,16 @@ fn test_link(tmp: std.testing.TmpDir) !void { |
| 78 | 87 | defer nfd.close(); |
| 79 | 88 | |
| 80 | 89 | { |
| 81 | const estat = try std.posix.fstat(efd.handle); | |
| 82 | const nstat = try std.posix.fstat(nfd.handle); | |
| 83 | try std.testing.expectEqual(estat.ino, nstat.ino); | |
| 84 | try std.testing.expectEqual(@as(@TypeOf(nstat.nlink), 2), nstat.nlink); | |
| 90 | const eino, _ = try getLinkInfo(efd.handle); | |
| 91 | const nino, const nlink = try getLinkInfo(nfd.handle); | |
| 92 | try std.testing.expectEqual(eino, nino); | |
| 93 | try std.testing.expectEqual(@as(std.posix.nlink_t, 2), nlink); | |
| 85 | 94 | } |
| 86 | 95 | |
| 87 | 96 | // Test 2: Remove the link and see the stats update |
| 88 | 97 | try std.posix.unlink(link_name); |
| 89 | ||
| 90 | 98 | { |
| 91 | const estat = try std.posix.fstat(efd.handle); | |
| 92 | try std.testing.expectEqual(@as(@TypeOf(estat.nlink), 1), estat.nlink); | |
| 99 | _, const elink = try getLinkInfo(efd.handle); | |
| 100 | try std.testing.expectEqual(@as(std.posix.nlink_t, 1), elink); | |
| 93 | 101 | } |
| 94 | 102 | } |