| author | |
| committer | |
| log | 89412fda775aecdedf4047355f2c45b48334a285 |
| tree | 1aa3818600ec8bdead689f0a60bf507b4c259370 |
| parent | 69b54b0cd12fb90f8ff101bc66e433a81d4b8409 |
7 files changed, 202 insertions(+), 156 deletions(-)
lib/std/Io/File.zig+11-83| ... | @@ -47,90 +47,14 @@ pub const Stat = struct { | ... | @@ -47,90 +47,14 @@ pub const Stat = struct { |
| 47 | kind: Kind, | 47 | kind: Kind, |
| 48 | 48 | ||
| 49 | /// Last access time in nanoseconds, relative to UTC 1970-01-01. | 49 | /// Last access time in nanoseconds, relative to UTC 1970-01-01. |
| 50 | /// TODO change this to Io.Timestamp except don't waste storage on clock | ||
| 50 | atime: i128, | 51 | atime: i128, |
| 51 | /// Last modification time in nanoseconds, relative to UTC 1970-01-01. | 52 | /// Last modification time in nanoseconds, relative to UTC 1970-01-01. |
| 53 | /// TODO change this to Io.Timestamp except don't waste storage on clock | ||
| 52 | mtime: i128, | 54 | mtime: i128, |
| 53 | /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01. | 55 | /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01. |
| 56 | /// TODO change this to Io.Timestamp except don't waste storage on clock | ||
| 54 | ctime: i128, | 57 | ctime: i128, |
| 55 | |||
| 56 | pub fn fromPosix(st: std.posix.Stat) Stat { | ||
| 57 | const atime = st.atime(); | ||
| 58 | const mtime = st.mtime(); | ||
| 59 | const ctime = st.ctime(); | ||
| 60 | return .{ | ||
| 61 | .inode = st.ino, | ||
| 62 | .size = @bitCast(st.size), | ||
| 63 | .mode = st.mode, | ||
| 64 | .kind = k: { | ||
| 65 | const m = st.mode & std.posix.S.IFMT; | ||
| 66 | switch (m) { | ||
| 67 | std.posix.S.IFBLK => break :k .block_device, | ||
| 68 | std.posix.S.IFCHR => break :k .character_device, | ||
| 69 | std.posix.S.IFDIR => break :k .directory, | ||
| 70 | std.posix.S.IFIFO => break :k .named_pipe, | ||
| 71 | std.posix.S.IFLNK => break :k .sym_link, | ||
| 72 | std.posix.S.IFREG => break :k .file, | ||
| 73 | std.posix.S.IFSOCK => break :k .unix_domain_socket, | ||
| 74 | else => {}, | ||
| 75 | } | ||
| 76 | if (builtin.os.tag == .illumos) switch (m) { | ||
| 77 | std.posix.S.IFDOOR => break :k .door, | ||
| 78 | std.posix.S.IFPORT => break :k .event_port, | ||
| 79 | else => {}, | ||
| 80 | }; | ||
| 81 | |||
| 82 | break :k .unknown; | ||
| 83 | }, | ||
| 84 | .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec, | ||
| 85 | .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec, | ||
| 86 | .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec, | ||
| 87 | }; | ||
| 88 | } | ||
| 89 | |||
| 90 | pub fn fromLinux(stx: std.os.linux.Statx) Stat { | ||
| 91 | const atime = stx.atime; | ||
| 92 | const mtime = stx.mtime; | ||
| 93 | const ctime = stx.ctime; | ||
| 94 | |||
| 95 | return .{ | ||
| 96 | .inode = stx.ino, | ||
| 97 | .size = stx.size, | ||
| 98 | .mode = stx.mode, | ||
| 99 | .kind = switch (stx.mode & std.os.linux.S.IFMT) { | ||
| 100 | std.os.linux.S.IFDIR => .directory, | ||
| 101 | std.os.linux.S.IFCHR => .character_device, | ||
| 102 | std.os.linux.S.IFBLK => .block_device, | ||
| 103 | std.os.linux.S.IFREG => .file, | ||
| 104 | std.os.linux.S.IFIFO => .named_pipe, | ||
| 105 | std.os.linux.S.IFLNK => .sym_link, | ||
| 106 | std.os.linux.S.IFSOCK => .unix_domain_socket, | ||
| 107 | else => .unknown, | ||
| 108 | }, | ||
| 109 | .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec, | ||
| 110 | .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec, | ||
| 111 | .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec, | ||
| 112 | }; | ||
| 113 | } | ||
| 114 | |||
| 115 | pub fn fromWasi(st: std.os.wasi.filestat_t) Stat { | ||
| 116 | return .{ | ||
| 117 | .inode = st.ino, | ||
| 118 | .size = @bitCast(st.size), | ||
| 119 | .mode = 0, | ||
| 120 | .kind = switch (st.filetype) { | ||
| 121 | .BLOCK_DEVICE => .block_device, | ||
| 122 | .CHARACTER_DEVICE => .character_device, | ||
| 123 | .DIRECTORY => .directory, | ||
| 124 | .SYMBOLIC_LINK => .sym_link, | ||
| 125 | .REGULAR_FILE => .file, | ||
| 126 | .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, | ||
| 127 | else => .unknown, | ||
| 128 | }, | ||
| 129 | .atime = st.atim, | ||
| 130 | .mtime = st.mtim, | ||
| 131 | .ctime = st.ctim, | ||
| 132 | }; | ||
| 133 | } | ||
| 134 | }; | 58 | }; |
| 135 | 59 | ||
| 136 | pub fn stdout() File { | 60 | pub fn stdout() File { |
| ... | @@ -145,13 +69,17 @@ pub fn stdin() File { | ... | @@ -145,13 +69,17 @@ pub fn stdin() File { |
| 145 | return .{ .handle = if (is_windows) std.os.windows.peb().ProcessParameters.hStdInput else std.posix.STDIN_FILENO }; | 69 | return .{ .handle = if (is_windows) std.os.windows.peb().ProcessParameters.hStdInput else std.posix.STDIN_FILENO }; |
| 146 | } | 70 | } |
| 147 | 71 | ||
| 148 | pub const StatError = std.posix.FStatError || Io.Cancelable; | 72 | pub const StatError = error{ |
| 73 | SystemResources, | ||
| 74 | /// In WASI, this error may occur when the file descriptor does | ||
| 75 | /// not hold the required rights to get its filestat information. | ||
| 76 | AccessDenied, | ||
| 77 | PermissionDenied, | ||
| 78 | } || Io.Cancelable || Io.UnexpectedError; | ||
| 149 | 79 | ||
| 150 | /// Returns `Stat` containing basic information about the `File`. | 80 | /// Returns `Stat` containing basic information about the `File`. |
| 151 | pub fn stat(file: File, io: Io) StatError!Stat { | 81 | pub fn stat(file: File, io: Io) StatError!Stat { |
| 152 | _ = file; | 82 | return io.vtable.fileStat(io.userdata, file); |
| 153 | _ = io; | ||
| 154 | @panic("TODO"); | ||
| 155 | } | 83 | } |
| 156 | 84 | ||
| 157 | pub const OpenFlags = std.fs.File.OpenFlags; | 85 | pub const OpenFlags = std.fs.File.OpenFlags; |
lib/std/Io/Threaded.zig+152-3| ... | @@ -163,7 +163,12 @@ pub fn io(pool: *Pool) Io { | ... | @@ -163,7 +163,12 @@ pub fn io(pool: *Pool) Io { |
| 163 | .dirMake = dirMake, | 163 | .dirMake = dirMake, |
| 164 | .dirStat = dirStat, | 164 | .dirStat = dirStat, |
| 165 | .dirStatPath = dirStatPath, | 165 | .dirStatPath = dirStatPath, |
| 166 | .fileStat = fileStat, | 166 | .fileStat = switch (builtin.os.tag) { |
| 167 | .linux => fileStatLinux, | ||
| 168 | .windows => fileStatWindows, | ||
| 169 | .wasi => fileStatWasi, | ||
| 170 | else => fileStatPosix, | ||
| 171 | }, | ||
| 167 | .createFile = createFile, | 172 | .createFile = createFile, |
| 168 | .fileOpen = fileOpen, | 173 | .fileOpen = fileOpen, |
| 169 | .fileClose = fileClose, | 174 | .fileClose = fileClose, |
| ... | @@ -781,14 +786,80 @@ fn dirStatPath(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8) Io.Dir. | ... | @@ -781,14 +786,80 @@ fn dirStatPath(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8) Io.Dir. |
| 781 | @panic("TODO"); | 786 | @panic("TODO"); |
| 782 | } | 787 | } |
| 783 | 788 | ||
| 784 | fn fileStat(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { | 789 | fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { |
| 785 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | 790 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 786 | try pool.checkCancel(); | 791 | const fstat_sym = if (posix.lfs64_abi) posix.system.fstat64 else posix.system.fstat; |
| 792 | while (true) { | ||
| 793 | try pool.checkCancel(); | ||
| 794 | var stat = std.mem.zeroes(posix.Stat); | ||
| 795 | switch (posix.errno(fstat_sym(file.handle, &stat))) { | ||
| 796 | .SUCCESS => return statFromPosix(&stat), | ||
| 797 | .INTR => continue, | ||
| 798 | .INVAL => |err| return errnoBug(err), | ||
| 799 | .BADF => |err| return errnoBug(err), | ||
| 800 | .NOMEM => return error.SystemResources, | ||
| 801 | .ACCES => return error.AccessDenied, | ||
| 802 | else => |err| return posix.unexpectedErrno(err), | ||
| 803 | } | ||
| 804 | } | ||
| 805 | } | ||
| 806 | |||
| 807 | fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { | ||
| 808 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | ||
| 809 | const linux = std.os.linux; | ||
| 810 | while (true) { | ||
| 811 | try pool.checkCancel(); | ||
| 812 | var statx = std.mem.zeroes(linux.Statx); | ||
| 813 | const rc = linux.statx( | ||
| 814 | file.handle, | ||
| 815 | "", | ||
| 816 | linux.AT.EMPTY_PATH, | ||
| 817 | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, | ||
| 818 | &statx, | ||
| 819 | ); | ||
| 820 | switch (linux.E.init(rc)) { | ||
| 821 | .SUCCESS => return statFromLinux(&statx), | ||
| 822 | .INTR => continue, | ||
| 823 | .ACCES => |err| return errnoBug(err), | ||
| 824 | .BADF => |err| return errnoBug(err), | ||
| 825 | .FAULT => |err| return errnoBug(err), | ||
| 826 | .INVAL => |err| return errnoBug(err), | ||
| 827 | .LOOP => |err| return errnoBug(err), | ||
| 828 | .NAMETOOLONG => |err| return errnoBug(err), | ||
| 829 | .NOENT => |err| return errnoBug(err), | ||
| 830 | .NOMEM => return error.SystemResources, | ||
| 831 | .NOTDIR => |err| return errnoBug(err), | ||
| 832 | else => |err| return posix.unexpectedErrno(err), | ||
| 833 | } | ||
| 834 | } | ||
| 835 | } | ||
| 787 | 836 | ||
| 837 | fn fileStatWindows(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { | ||
| 838 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | ||
| 839 | try pool.checkCancel(); | ||
| 788 | _ = file; | 840 | _ = file; |
| 789 | @panic("TODO"); | 841 | @panic("TODO"); |
| 790 | } | 842 | } |
| 791 | 843 | ||
| 844 | fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.Stat { | ||
| 845 | if (builtin.link_libc) return fileStatPosix(userdata, file); | ||
| 846 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | ||
| 847 | while (true) { | ||
| 848 | try pool.checkCancel(); | ||
| 849 | var stat: std.os.wasi.filestat_t = undefined; | ||
| 850 | switch (std.os.wasi.fd_filestat_get(file.handle, &stat)) { | ||
| 851 | .SUCCESS => return statFromWasi(&stat), | ||
| 852 | .INTR => continue, | ||
| 853 | .INVAL => |err| return errnoBug(err), | ||
| 854 | .BADF => |err| return errnoBug(err), | ||
| 855 | .NOMEM => return error.SystemResources, | ||
| 856 | .ACCES => return error.AccessDenied, | ||
| 857 | .NOTCAPABLE => return error.AccessDenied, | ||
| 858 | else => |err| return posix.unexpectedErrno(err), | ||
| 859 | } | ||
| 860 | } | ||
| 861 | } | ||
| 862 | |||
| 792 | fn createFile( | 863 | fn createFile( |
| 793 | userdata: ?*anyopaque, | 864 | userdata: ?*anyopaque, |
| 794 | dir: Io.Dir, | 865 | dir: Io.Dir, |
| ... | @@ -2114,3 +2185,81 @@ fn clockToWasi(clock: Io.Timestamp.Clock) std.os.wasi.clockid_t { | ... | @@ -2114,3 +2185,81 @@ fn clockToWasi(clock: Io.Timestamp.Clock) std.os.wasi.clockid_t { |
| 2114 | .cpu_thread => .THREAD_CPUTIME_ID, | 2185 | .cpu_thread => .THREAD_CPUTIME_ID, |
| 2115 | }; | 2186 | }; |
| 2116 | } | 2187 | } |
| 2188 | |||
| 2189 | fn statFromLinux(stx: *const std.os.linux.Statx) Io.File.Stat { | ||
| 2190 | const atime = stx.atime; | ||
| 2191 | const mtime = stx.mtime; | ||
| 2192 | const ctime = stx.ctime; | ||
| 2193 | return .{ | ||
| 2194 | .inode = stx.ino, | ||
| 2195 | .size = stx.size, | ||
| 2196 | .mode = stx.mode, | ||
| 2197 | .kind = switch (stx.mode & std.os.linux.S.IFMT) { | ||
| 2198 | std.os.linux.S.IFDIR => .directory, | ||
| 2199 | std.os.linux.S.IFCHR => .character_device, | ||
| 2200 | std.os.linux.S.IFBLK => .block_device, | ||
| 2201 | std.os.linux.S.IFREG => .file, | ||
| 2202 | std.os.linux.S.IFIFO => .named_pipe, | ||
| 2203 | std.os.linux.S.IFLNK => .sym_link, | ||
| 2204 | std.os.linux.S.IFSOCK => .unix_domain_socket, | ||
| 2205 | else => .unknown, | ||
| 2206 | }, | ||
| 2207 | .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec, | ||
| 2208 | .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec, | ||
| 2209 | .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec, | ||
| 2210 | }; | ||
| 2211 | } | ||
| 2212 | |||
| 2213 | fn statFromPosix(st: *const std.posix.Stat) Io.File.Stat { | ||
| 2214 | const atime = st.atime(); | ||
| 2215 | const mtime = st.mtime(); | ||
| 2216 | const ctime = st.ctime(); | ||
| 2217 | return .{ | ||
| 2218 | .inode = st.ino, | ||
| 2219 | .size = @bitCast(st.size), | ||
| 2220 | .mode = st.mode, | ||
| 2221 | .kind = k: { | ||
| 2222 | const m = st.mode & std.posix.S.IFMT; | ||
| 2223 | switch (m) { | ||
| 2224 | std.posix.S.IFBLK => break :k .block_device, | ||
| 2225 | std.posix.S.IFCHR => break :k .character_device, | ||
| 2226 | std.posix.S.IFDIR => break :k .directory, | ||
| 2227 | std.posix.S.IFIFO => break :k .named_pipe, | ||
| 2228 | std.posix.S.IFLNK => break :k .sym_link, | ||
| 2229 | std.posix.S.IFREG => break :k .file, | ||
| 2230 | std.posix.S.IFSOCK => break :k .unix_domain_socket, | ||
| 2231 | else => {}, | ||
| 2232 | } | ||
| 2233 | if (builtin.os.tag == .illumos) switch (m) { | ||
| 2234 | std.posix.S.IFDOOR => break :k .door, | ||
| 2235 | std.posix.S.IFPORT => break :k .event_port, | ||
| 2236 | else => {}, | ||
| 2237 | }; | ||
| 2238 | |||
| 2239 | break :k .unknown; | ||
| 2240 | }, | ||
| 2241 | .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec, | ||
| 2242 | .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec, | ||
| 2243 | .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec, | ||
| 2244 | }; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | fn statFromWasi(st: *const std.os.wasi.filestat_t) Io.File.Stat { | ||
| 2248 | return .{ | ||
| 2249 | .inode = st.ino, | ||
| 2250 | .size = @bitCast(st.size), | ||
| 2251 | .mode = 0, | ||
| 2252 | .kind = switch (st.filetype) { | ||
| 2253 | .BLOCK_DEVICE => .block_device, | ||
| 2254 | .CHARACTER_DEVICE => .character_device, | ||
| 2255 | .DIRECTORY => .directory, | ||
| 2256 | .SYMBOLIC_LINK => .sym_link, | ||
| 2257 | .REGULAR_FILE => .file, | ||
| 2258 | .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, | ||
| 2259 | else => .unknown, | ||
| 2260 | }, | ||
| 2261 | .atime = st.atim, | ||
| 2262 | .mtime = st.mtim, | ||
| 2263 | .ctime = st.ctim, | ||
| 2264 | }; | ||
| 2265 | } |
lib/std/debug.zig+3-1| ... | @@ -82,6 +82,7 @@ pub const SelfInfoError = error{ | ... | @@ -82,6 +82,7 @@ pub const SelfInfoError = error{ |
| 82 | /// The required debug info could not be read from disk due to some IO error. | 82 | /// The required debug info could not be read from disk due to some IO error. |
| 83 | ReadFailed, | 83 | ReadFailed, |
| 84 | OutOfMemory, | 84 | OutOfMemory, |
| 85 | Canceled, | ||
| 85 | Unexpected, | 86 | Unexpected, |
| 86 | }; | 87 | }; |
| 87 | 88 | ||
| ... | @@ -691,6 +692,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri | ... | @@ -691,6 +692,7 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, writer: *Wri |
| 691 | error.UnsupportedDebugInfo => "unwind info unsupported", | 692 | error.UnsupportedDebugInfo => "unwind info unsupported", |
| 692 | error.ReadFailed => "filesystem error", | 693 | error.ReadFailed => "filesystem error", |
| 693 | error.OutOfMemory => "out of memory", | 694 | error.OutOfMemory => "out of memory", |
| 695 | error.Canceled => "operation canceled", | ||
| 694 | error.Unexpected => "unexpected error", | 696 | error.Unexpected => "unexpected error", |
| 695 | }; | 697 | }; |
| 696 | if (it.stratOk(options.allow_unsafe_unwind)) { | 698 | if (it.stratOk(options.allow_unsafe_unwind)) { |
| ... | @@ -1079,7 +1081,7 @@ fn printSourceAtAddress(gpa: Allocator, debug_info: *SelfInfo, writer: *Writer, | ... | @@ -1079,7 +1081,7 @@ fn printSourceAtAddress(gpa: Allocator, debug_info: *SelfInfo, writer: *Writer, |
| 1079 | error.UnsupportedDebugInfo, | 1081 | error.UnsupportedDebugInfo, |
| 1080 | error.InvalidDebugInfo, | 1082 | error.InvalidDebugInfo, |
| 1081 | => .unknown, | 1083 | => .unknown, |
| 1082 | error.ReadFailed, error.Unexpected => s: { | 1084 | error.ReadFailed, error.Unexpected, error.Canceled => s: { |
| 1083 | tty_config.setColor(writer, .dim) catch {}; | 1085 | tty_config.setColor(writer, .dim) catch {}; |
| 1084 | try writer.print("Failed to read debug info from filesystem, trace may be incomplete\n\n", .{}); | 1086 | try writer.print("Failed to read debug info from filesystem, trace may be incomplete\n\n", .{}); |
| 1085 | tty_config.setColor(writer, .reset) catch {}; | 1087 | tty_config.setColor(writer, .reset) catch {}; |
lib/std/debug/ElfFile.zig+2-1| ... | @@ -108,6 +108,7 @@ pub const LoadError = error{ | ... | @@ -108,6 +108,7 @@ pub const LoadError = error{ |
| 108 | LockedMemoryLimitExceeded, | 108 | LockedMemoryLimitExceeded, |
| 109 | ProcessFdQuotaExceeded, | 109 | ProcessFdQuotaExceeded, |
| 110 | SystemFdQuotaExceeded, | 110 | SystemFdQuotaExceeded, |
| 111 | Canceled, | ||
| 111 | Unexpected, | 112 | Unexpected, |
| 112 | }; | 113 | }; |
| 113 | 114 | ||
| ... | @@ -408,7 +409,7 @@ fn loadInner( | ... | @@ -408,7 +409,7 @@ fn loadInner( |
| 408 | arena: Allocator, | 409 | arena: Allocator, |
| 409 | elf_file: std.fs.File, | 410 | elf_file: std.fs.File, |
| 410 | opt_crc: ?u32, | 411 | opt_crc: ?u32, |
| 411 | ) (LoadError || error{CrcMismatch})!LoadInnerResult { | 412 | ) (LoadError || error{ CrcMismatch, Canceled })!LoadInnerResult { |
| 412 | const mapped_mem: []align(std.heap.page_size_min) const u8 = mapped: { | 413 | const mapped_mem: []align(std.heap.page_size_min) const u8 = mapped: { |
| 413 | const file_len = std.math.cast( | 414 | const file_len = std.math.cast( |
| 414 | usize, | 415 | usize, |
lib/std/debug/SelfInfo/Elf.zig+1| ... | @@ -336,6 +336,7 @@ const Module = struct { | ... | @@ -336,6 +336,7 @@ const Module = struct { |
| 336 | var elf_file = load_result catch |err| switch (err) { | 336 | var elf_file = load_result catch |err| switch (err) { |
| 337 | error.OutOfMemory, | 337 | error.OutOfMemory, |
| 338 | error.Unexpected, | 338 | error.Unexpected, |
| 339 | error.Canceled, | ||
| 339 | => |e| return e, | 340 | => |e| return e, |
| 340 | 341 | ||
| 341 | error.Overflow, | 342 | error.Overflow, |
lib/std/fs/File.zig+32-60| ... | @@ -1,10 +1,12 @@ | ... | @@ -1,10 +1,12 @@ |
| 1 | const File = @This(); | ||
| 2 | |||
| 1 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 2 | const Os = std.builtin.Os; | ||
| 3 | const native_os = builtin.os.tag; | 4 | const native_os = builtin.os.tag; |
| 4 | const is_windows = native_os == .windows; | 5 | const is_windows = native_os == .windows; |
| 5 | 6 | ||
| 6 | const File = @This(); | ||
| 7 | const std = @import("../std.zig"); | 7 | const std = @import("../std.zig"); |
| 8 | const Io = std.Io; | ||
| 9 | const Os = std.builtin.Os; | ||
| 8 | const Allocator = std.mem.Allocator; | 10 | const Allocator = std.mem.Allocator; |
| 9 | const posix = std.posix; | 11 | const posix = std.posix; |
| 10 | const math = std.math; | 12 | const math = std.math; |
| ... | @@ -17,12 +19,12 @@ const Alignment = std.mem.Alignment; | ... | @@ -17,12 +19,12 @@ const Alignment = std.mem.Alignment; |
| 17 | /// The OS-specific file descriptor or file handle. | 19 | /// The OS-specific file descriptor or file handle. |
| 18 | handle: Handle, | 20 | handle: Handle, |
| 19 | 21 | ||
| 20 | pub const Handle = std.Io.File.Handle; | 22 | pub const Handle = Io.File.Handle; |
| 21 | pub const Mode = std.Io.File.Mode; | 23 | pub const Mode = Io.File.Mode; |
| 22 | pub const INode = std.Io.File.INode; | 24 | pub const INode = Io.File.INode; |
| 23 | pub const Uid = posix.uid_t; | 25 | pub const Uid = posix.uid_t; |
| 24 | pub const Gid = posix.gid_t; | 26 | pub const Gid = posix.gid_t; |
| 25 | pub const Kind = std.Io.File.Kind; | 27 | pub const Kind = Io.File.Kind; |
| 26 | 28 | ||
| 27 | /// This is the default mode given to POSIX operating systems for creating | 29 | /// This is the default mode given to POSIX operating systems for creating |
| 28 | /// files. `0o666` is "-rw-rw-rw-" which is counter-intuitive at first, | 30 | /// files. `0o666` is "-rw-rw-rw-" which is counter-intuitive at first, |
| ... | @@ -386,7 +388,7 @@ pub fn mode(self: File) ModeError!Mode { | ... | @@ -386,7 +388,7 @@ pub fn mode(self: File) ModeError!Mode { |
| 386 | return (try self.stat()).mode; | 388 | return (try self.stat()).mode; |
| 387 | } | 389 | } |
| 388 | 390 | ||
| 389 | pub const Stat = std.Io.File.Stat; | 391 | pub const Stat = Io.File.Stat; |
| 390 | 392 | ||
| 391 | pub const StatError = posix.FStatError; | 393 | pub const StatError = posix.FStatError; |
| 392 | 394 | ||
| ... | @@ -436,39 +438,9 @@ pub fn stat(self: File) StatError!Stat { | ... | @@ -436,39 +438,9 @@ pub fn stat(self: File) StatError!Stat { |
| 436 | }; | 438 | }; |
| 437 | } | 439 | } |
| 438 | 440 | ||
| 439 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 441 | var threaded: Io.Threaded = .init_single_threaded; |
| 440 | const st = try std.os.fstat_wasi(self.handle); | 442 | const io = threaded.io(); |
| 441 | return Stat.fromWasi(st); | 443 | return Io.File.stat(.{ .handle = self.handle }, io); |
| 442 | } | ||
| 443 | |||
| 444 | if (builtin.os.tag == .linux) { | ||
| 445 | var stx = std.mem.zeroes(linux.Statx); | ||
| 446 | |||
| 447 | const rc = linux.statx( | ||
| 448 | self.handle, | ||
| 449 | "", | ||
| 450 | linux.AT.EMPTY_PATH, | ||
| 451 | linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME, | ||
| 452 | &stx, | ||
| 453 | ); | ||
| 454 | |||
| 455 | return switch (linux.E.init(rc)) { | ||
| 456 | .SUCCESS => Stat.fromLinux(stx), | ||
| 457 | .ACCES => unreachable, | ||
| 458 | .BADF => unreachable, | ||
| 459 | .FAULT => unreachable, | ||
| 460 | .INVAL => unreachable, | ||
| 461 | .LOOP => unreachable, | ||
| 462 | .NAMETOOLONG => unreachable, | ||
| 463 | .NOENT => unreachable, | ||
| 464 | .NOMEM => error.SystemResources, | ||
| 465 | .NOTDIR => unreachable, | ||
| 466 | else => |err| posix.unexpectedErrno(err), | ||
| 467 | }; | ||
| 468 | } | ||
| 469 | |||
| 470 | const st = try posix.fstat(self.handle); | ||
| 471 | return Stat.fromPosix(st); | ||
| 472 | } | 444 | } |
| 473 | 445 | ||
| 474 | pub const ChmodError = posix.FChmodError; | 446 | pub const ChmodError = posix.FChmodError; |
| ... | @@ -785,8 +757,8 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError | ... | @@ -785,8 +757,8 @@ pub fn pwritev(self: File, iovecs: []posix.iovec_const, offset: u64) PWriteError |
| 785 | return posix.pwritev(self.handle, iovecs, offset); | 757 | return posix.pwritev(self.handle, iovecs, offset); |
| 786 | } | 758 | } |
| 787 | 759 | ||
| 788 | /// Deprecated in favor of `std.Io.File.Reader`. | 760 | /// Deprecated in favor of `Io.File.Reader`. |
| 789 | pub const Reader = std.Io.File.Reader; | 761 | pub const Reader = Io.File.Reader; |
| 790 | 762 | ||
| 791 | pub const Writer = struct { | 763 | pub const Writer = struct { |
| 792 | file: File, | 764 | file: File, |
| ... | @@ -799,7 +771,7 @@ pub const Writer = struct { | ... | @@ -799,7 +771,7 @@ pub const Writer = struct { |
| 799 | copy_file_range_err: ?CopyFileRangeError = null, | 771 | copy_file_range_err: ?CopyFileRangeError = null, |
| 800 | fcopyfile_err: ?FcopyfileError = null, | 772 | fcopyfile_err: ?FcopyfileError = null, |
| 801 | seek_err: ?Writer.SeekError = null, | 773 | seek_err: ?Writer.SeekError = null, |
| 802 | interface: std.Io.Writer, | 774 | interface: Io.Writer, |
| 803 | 775 | ||
| 804 | pub const Mode = Reader.Mode; | 776 | pub const Mode = Reader.Mode; |
| 805 | 777 | ||
| ... | @@ -845,13 +817,13 @@ pub const Writer = struct { | ... | @@ -845,13 +817,13 @@ pub const Writer = struct { |
| 845 | }; | 817 | }; |
| 846 | } | 818 | } |
| 847 | 819 | ||
| 848 | pub fn initInterface(buffer: []u8) std.Io.Writer { | 820 | pub fn initInterface(buffer: []u8) Io.Writer { |
| 849 | return .{ | 821 | return .{ |
| 850 | .vtable = &.{ | 822 | .vtable = &.{ |
| 851 | .drain = drain, | 823 | .drain = drain, |
| 852 | .sendFile = switch (builtin.zig_backend) { | 824 | .sendFile = switch (builtin.zig_backend) { |
| 853 | else => sendFile, | 825 | else => sendFile, |
| 854 | .stage2_aarch64 => std.Io.Writer.unimplementedSendFile, | 826 | .stage2_aarch64 => Io.Writer.unimplementedSendFile, |
| 855 | }, | 827 | }, |
| 856 | }, | 828 | }, |
| 857 | .buffer = buffer, | 829 | .buffer = buffer, |
| ... | @@ -859,7 +831,7 @@ pub const Writer = struct { | ... | @@ -859,7 +831,7 @@ pub const Writer = struct { |
| 859 | } | 831 | } |
| 860 | 832 | ||
| 861 | /// TODO when this logic moves from fs.File to Io.File the io parameter should be deleted | 833 | /// TODO when this logic moves from fs.File to Io.File the io parameter should be deleted |
| 862 | pub fn moveToReader(w: *Writer, io: std.Io) Reader { | 834 | pub fn moveToReader(w: *Writer, io: Io) Reader { |
| 863 | defer w.* = undefined; | 835 | defer w.* = undefined; |
| 864 | return .{ | 836 | return .{ |
| 865 | .io = io, | 837 | .io = io, |
| ... | @@ -871,7 +843,7 @@ pub const Writer = struct { | ... | @@ -871,7 +843,7 @@ pub const Writer = struct { |
| 871 | }; | 843 | }; |
| 872 | } | 844 | } |
| 873 | 845 | ||
| 874 | pub fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize { | 846 | pub fn drain(io_w: *Io.Writer, data: []const []const u8, splat: usize) Io.Writer.Error!usize { |
| 875 | const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); | 847 | const w: *Writer = @alignCast(@fieldParentPtr("interface", io_w)); |
| 876 | const handle = w.file.handle; | 848 | const handle = w.file.handle; |
| 877 | const buffered = io_w.buffered(); | 849 | const buffered = io_w.buffered(); |
| ... | @@ -1021,10 +993,10 @@ pub const Writer = struct { | ... | @@ -1021,10 +993,10 @@ pub const Writer = struct { |
| 1021 | } | 993 | } |
| 1022 | 994 | ||
| 1023 | pub fn sendFile( | 995 | pub fn sendFile( |
| 1024 | io_w: *std.Io.Writer, | 996 | io_w: *Io.Writer, |
| 1025 | file_reader: *std.Io.File.Reader, | 997 | file_reader: *Io.File.Reader, |
| 1026 | limit: std.Io.Limit, | 998 | limit: Io.Limit, |
| 1027 | ) std.Io.Writer.FileError!usize { | 999 | ) Io.Writer.FileError!usize { |
| 1028 | const reader_buffered = file_reader.interface.buffered(); | 1000 | const reader_buffered = file_reader.interface.buffered(); |
| 1029 | if (reader_buffered.len >= @intFromEnum(limit)) | 1001 | if (reader_buffered.len >= @intFromEnum(limit)) |
| 1030 | return sendFileBuffered(io_w, file_reader, limit.slice(reader_buffered)); | 1002 | return sendFileBuffered(io_w, file_reader, limit.slice(reader_buffered)); |
| ... | @@ -1288,16 +1260,16 @@ pub const Writer = struct { | ... | @@ -1288,16 +1260,16 @@ pub const Writer = struct { |
| 1288 | } | 1260 | } |
| 1289 | 1261 | ||
| 1290 | fn sendFileBuffered( | 1262 | fn sendFileBuffered( |
| 1291 | io_w: *std.Io.Writer, | 1263 | io_w: *Io.Writer, |
| 1292 | file_reader: *std.Io.File.Reader, | 1264 | file_reader: *Io.File.Reader, |
| 1293 | reader_buffered: []const u8, | 1265 | reader_buffered: []const u8, |
| 1294 | ) std.Io.Writer.FileError!usize { | 1266 | ) Io.Writer.FileError!usize { |
| 1295 | const n = try drain(io_w, &.{reader_buffered}, 1); | 1267 | const n = try drain(io_w, &.{reader_buffered}, 1); |
| 1296 | file_reader.seekBy(@intCast(n)) catch return error.ReadFailed; | 1268 | file_reader.seekBy(@intCast(n)) catch return error.ReadFailed; |
| 1297 | return n; | 1269 | return n; |
| 1298 | } | 1270 | } |
| 1299 | 1271 | ||
| 1300 | pub fn seekTo(w: *Writer, offset: u64) (Writer.SeekError || std.Io.Writer.Error)!void { | 1272 | pub fn seekTo(w: *Writer, offset: u64) (Writer.SeekError || Io.Writer.Error)!void { |
| 1301 | try w.interface.flush(); | 1273 | try w.interface.flush(); |
| 1302 | try seekToUnbuffered(w, offset); | 1274 | try seekToUnbuffered(w, offset); |
| 1303 | } | 1275 | } |
| ... | @@ -1321,7 +1293,7 @@ pub const Writer = struct { | ... | @@ -1321,7 +1293,7 @@ pub const Writer = struct { |
| 1321 | } | 1293 | } |
| 1322 | } | 1294 | } |
| 1323 | 1295 | ||
| 1324 | pub const EndError = SetEndPosError || std.Io.Writer.Error; | 1296 | pub const EndError = SetEndPosError || Io.Writer.Error; |
| 1325 | 1297 | ||
| 1326 | /// Flushes any buffered data and sets the end position of the file. | 1298 | /// Flushes any buffered data and sets the end position of the file. |
| 1327 | /// | 1299 | /// |
| ... | @@ -1352,14 +1324,14 @@ pub const Writer = struct { | ... | @@ -1352,14 +1324,14 @@ pub const Writer = struct { |
| 1352 | /// | 1324 | /// |
| 1353 | /// Positional is more threadsafe, since the global seek position is not | 1325 | /// Positional is more threadsafe, since the global seek position is not |
| 1354 | /// affected. | 1326 | /// affected. |
| 1355 | pub fn reader(file: File, io: std.Io, buffer: []u8) Reader { | 1327 | pub fn reader(file: File, io: Io, buffer: []u8) Reader { |
| 1356 | return .init(.{ .handle = file.handle }, io, buffer); | 1328 | return .init(.{ .handle = file.handle }, io, buffer); |
| 1357 | } | 1329 | } |
| 1358 | 1330 | ||
| 1359 | /// Positional is more threadsafe, since the global seek position is not | 1331 | /// Positional is more threadsafe, since the global seek position is not |
| 1360 | /// affected, but when such syscalls are not available, preemptively | 1332 | /// affected, but when such syscalls are not available, preemptively |
| 1361 | /// initializing in streaming mode skips a failed syscall. | 1333 | /// initializing in streaming mode skips a failed syscall. |
| 1362 | pub fn readerStreaming(file: File, io: std.Io, buffer: []u8) Reader { | 1334 | pub fn readerStreaming(file: File, io: Io, buffer: []u8) Reader { |
| 1363 | return .initStreaming(.{ .handle = file.handle }, io, buffer); | 1335 | return .initStreaming(.{ .handle = file.handle }, io, buffer); |
| 1364 | } | 1336 | } |
| 1365 | 1337 | ||
| ... | @@ -1541,10 +1513,10 @@ pub fn downgradeLock(file: File) LockError!void { | ... | @@ -1541,10 +1513,10 @@ pub fn downgradeLock(file: File) LockError!void { |
| 1541 | } | 1513 | } |
| 1542 | } | 1514 | } |
| 1543 | 1515 | ||
| 1544 | pub fn adaptToNewApi(file: File) std.Io.File { | 1516 | pub fn adaptToNewApi(file: File) Io.File { |
| 1545 | return .{ .handle = file.handle }; | 1517 | return .{ .handle = file.handle }; |
| 1546 | } | 1518 | } |
| 1547 | 1519 | ||
| 1548 | pub fn adaptFromNewApi(file: std.Io.File) File { | 1520 | pub fn adaptFromNewApi(file: Io.File) File { |
| 1549 | return .{ .handle = file.handle }; | 1521 | return .{ .handle = file.handle }; |
| 1550 | } | 1522 | } |
lib/std/posix.zig+1-8| ... | @@ -4458,14 +4458,7 @@ pub fn wait4(pid: pid_t, flags: u32, ru: ?*rusage) WaitPidResult { | ... | @@ -4458,14 +4458,7 @@ pub fn wait4(pid: pid_t, flags: u32, ru: ?*rusage) WaitPidResult { |
| 4458 | } | 4458 | } |
| 4459 | } | 4459 | } |
| 4460 | 4460 | ||
| 4461 | pub const FStatError = error{ | 4461 | pub const FStatError = std.Io.File.StatError; |
| 4462 | SystemResources, | ||
| 4463 | |||
| 4464 | /// In WASI, this error may occur when the file descriptor does | ||
| 4465 | /// not hold the required rights to get its filestat information. | ||
| 4466 | AccessDenied, | ||
| 4467 | PermissionDenied, | ||
| 4468 | } || UnexpectedError; | ||
| 4469 | 4462 | ||
| 4470 | /// Return information about a file descriptor. | 4463 | /// Return information about a file descriptor. |
| 4471 | pub fn fstat(fd: fd_t) FStatError!Stat { | 4464 | pub fn fstat(fd: fd_t) FStatError!Stat { |