| ... | ... | @@ -342,7 +342,7 @@ pub fn seekTo(self: File, offset: u64) SeekError!void { |
| 342 | 342 | return posix.lseek_SET(self.handle, offset); |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | | pub const GetSeekPosError = posix.SeekError || posix.FStatError; |
| 345 | pub const GetSeekPosError = posix.SeekError || StatError; |
| 346 | 346 | |
| 347 | 347 | /// TODO: integrate with async I/O |
| 348 | 348 | pub fn getPos(self: File) GetSeekPosError!u64 { |
| ... | ... | @@ -357,7 +357,7 @@ pub fn getEndPos(self: File) GetSeekPosError!u64 { |
| 357 | 357 | return (try self.stat()).size; |
| 358 | 358 | } |
| 359 | 359 | |
| 360 | | pub const ModeError = posix.FStatError; |
| 360 | pub const ModeError = StatError; |
| 361 | 361 | |
| 362 | 362 | /// TODO: integrate with async I/O |
| 363 | 363 | pub fn mode(self: File) ModeError!Mode { |
| ... | ... | @@ -392,7 +392,7 @@ pub const Stat = struct { |
| 392 | 392 | /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01. |
| 393 | 393 | ctime: i128, |
| 394 | 394 | |
| 395 | | pub fn fromSystem(st: posix.Stat) Stat { |
| 395 | pub fn fromPosix(st: posix.Stat) Stat { |
| 396 | 396 | const atime = st.atime(); |
| 397 | 397 | const mtime = st.mtime(); |
| 398 | 398 | const ctime = st.ctime(); |
| ... | ... | @@ -426,6 +426,31 @@ pub const Stat = struct { |
| 426 | 426 | }; |
| 427 | 427 | } |
| 428 | 428 | |
| 429 | pub fn fromLinux(stx: linux.Statx) Stat { |
| 430 | const atime = stx.atime; |
| 431 | const mtime = stx.mtime; |
| 432 | const ctime = stx.ctime; |
| 433 | |
| 434 | return .{ |
| 435 | .inode = stx.ino, |
| 436 | .size = stx.size, |
| 437 | .mode = stx.mode, |
| 438 | .kind = switch (stx.mode & linux.S.IFMT) { |
| 439 | linux.S.IFDIR => .directory, |
| 440 | linux.S.IFCHR => .character_device, |
| 441 | linux.S.IFBLK => .block_device, |
| 442 | linux.S.IFREG => .file, |
| 443 | linux.S.IFIFO => .named_pipe, |
| 444 | linux.S.IFLNK => .sym_link, |
| 445 | linux.S.IFSOCK => .unix_domain_socket, |
| 446 | else => .unknown, |
| 447 | }, |
| 448 | .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec, |
| 449 | .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec, |
| 450 | .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec, |
| 451 | }; |
| 452 | } |
| 453 | |
| 429 | 454 | pub fn fromWasi(st: std.os.wasi.filestat_t) Stat { |
| 430 | 455 | return .{ |
| 431 | 456 | .inode = st.ino, |
| ... | ... | @@ -502,8 +527,34 @@ pub fn stat(self: File) StatError!Stat { |
| 502 | 527 | return Stat.fromWasi(st); |
| 503 | 528 | } |
| 504 | 529 | |
| 530 | if (builtin.os.tag == .linux) { |
| 531 | var stx = std.mem.zeroes(linux.Statx); |
| 532 | |
| 533 | const rc = linux.statx( |
| 534 | self.handle, |
| 535 | "", |
| 536 | linux.AT.EMPTY_PATH, |
| 537 | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, |
| 538 | &stx, |
| 539 | ); |
| 540 | |
| 541 | return switch (linux.E.init(rc)) { |
| 542 | .SUCCESS => Stat.fromLinux(stx), |
| 543 | .ACCES => unreachable, |
| 544 | .BADF => unreachable, |
| 545 | .FAULT => unreachable, |
| 546 | .INVAL => unreachable, |
| 547 | .LOOP => unreachable, |
| 548 | .NAMETOOLONG => unreachable, |
| 549 | .NOENT => unreachable, |
| 550 | .NOMEM => error.SystemResources, |
| 551 | .NOTDIR => unreachable, |
| 552 | else => |err| posix.unexpectedErrno(err), |
| 553 | }; |
| 554 | } |
| 555 | |
| 505 | 556 | const st = try posix.fstat(self.handle); |
| 506 | | return Stat.fromSystem(st); |
| 557 | return Stat.fromPosix(st); |
| 507 | 558 | } |
| 508 | 559 | |
| 509 | 560 | pub const ChmodError = posix.FChmodError; |
| ... | ... | @@ -1009,16 +1060,29 @@ pub fn metadata(self: File) MetadataError!Metadata { |
| 1009 | 1060 | }; |
| 1010 | 1061 | }, |
| 1011 | 1062 | .linux => blk: { |
| 1012 | | const l = std.os.linux; |
| 1013 | | var stx = std.mem.zeroes(l.Statx); |
| 1014 | | const rcx = l.statx(self.handle, "\x00", l.AT.EMPTY_PATH, l.STATX_TYPE | |
| 1015 | | l.STATX_MODE | l.STATX_ATIME | l.STATX_MTIME | l.STATX_BTIME, &stx); |
| 1016 | | |
| 1017 | | switch (posix.errno(rcx)) { |
| 1063 | var stx = std.mem.zeroes(linux.Statx); |
| 1064 | |
| 1065 | // We are gathering information for Metadata, which is meant to contain all the |
| 1066 | // native OS information about the file, so use all known flags. |
| 1067 | const rc = linux.statx( |
| 1068 | self.handle, |
| 1069 | "", |
| 1070 | linux.AT.EMPTY_PATH, |
| 1071 | linux.STATX_BASIC_STATS | linux.STATX_BTIME, |
| 1072 | &stx, |
| 1073 | ); |
| 1074 | |
| 1075 | switch (posix.errno(rc)) { |
| 1018 | 1076 | .SUCCESS => {}, |
| 1077 | .ACCES => unreachable, |
| 1019 | 1078 | .BADF => unreachable, |
| 1020 | 1079 | .FAULT => unreachable, |
| 1080 | .INVAL => unreachable, |
| 1081 | .LOOP => unreachable, |
| 1082 | .NAMETOOLONG => unreachable, |
| 1083 | .NOENT => unreachable, |
| 1021 | 1084 | .NOMEM => return error.SystemResources, |
| 1085 | .NOTDIR => unreachable, |
| 1022 | 1086 | else => |err| return posix.unexpectedErrno(err), |
| 1023 | 1087 | } |
| 1024 | 1088 | |
| ... | ... | @@ -1712,6 +1776,7 @@ const posix = std.posix; |
| 1712 | 1776 | const io = std.io; |
| 1713 | 1777 | const math = std.math; |
| 1714 | 1778 | const assert = std.debug.assert; |
| 1779 | const linux = std.os.linux; |
| 1715 | 1780 | const windows = std.os.windows; |
| 1716 | 1781 | const Os = std.builtin.Os; |
| 1717 | 1782 | const maxInt = std.math.maxInt; |