diff --git a/lib/std/Io.zig b/lib/std/Io.zig index edd66242ff..42c55c8848 100644 --- a/lib/std/Io.zig +++ b/lib/std/Io.zig @@ -705,8 +705,8 @@ pub const VTable = struct { fileSetLength: *const fn (?*anyopaque, File, u64) File.SetLengthError!void, fileSetOwner: *const fn (?*anyopaque, File, ?File.Uid, ?File.Gid) File.SetOwnerError!void, fileSetPermissions: *const fn (?*anyopaque, File, File.Permissions) File.SetPermissionsError!void, - fileSetTimestamps: *const fn (?*anyopaque, File, last_accessed: Timestamp, last_modified: Timestamp, File.SetTimestampsOptions) File.SetTimestampsError!void, - fileSetTimestampsNow: *const fn (?*anyopaque, File, File.SetTimestampsOptions) File.SetTimestampsError!void, + fileSetTimestamps: *const fn (?*anyopaque, File, last_accessed: Timestamp, last_modified: Timestamp) File.SetTimestampsError!void, + fileSetTimestampsNow: *const fn (?*anyopaque, File) File.SetTimestampsError!void, fileLock: *const fn (?*anyopaque, File, File.Lock) File.LockError!void, fileTryLock: *const fn (?*anyopaque, File, File.Lock) File.LockError!bool, fileUnlock: *const fn (?*anyopaque, File) void, @@ -726,7 +726,7 @@ pub const VTable = struct { /// Returns 0 on end of stream. netRead: *const fn (?*anyopaque, src: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize, netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, - netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.WriteFileError!usize, + netWriteFile: *const fn (?*anyopaque, net.Socket.Handle, header: []const u8, *Io.File.Reader, Io.Limit) net.Stream.Writer.WriteFileError!usize, netClose: *const fn (?*anyopaque, handle: net.Socket.Handle) void, netInterfaceNameResolve: *const fn (?*anyopaque, *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface, netInterfaceName: *const fn (?*anyopaque, net.Interface) net.Interface.NameError!net.Interface.Name, diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig index 46235d73f2..a0349498c5 100644 --- a/lib/std/Io/File.zig +++ b/lib/std/Io/File.zig @@ -274,7 +274,7 @@ pub fn sync(file: File, io: Io) SyncError!void { /// Test whether the file refers to a terminal. /// /// See also: -/// * `getOrEnableAnsiEscapeSupport` +/// * `enableAnsiEscapeCodes` /// * `supportsAnsiEscapeCodes`. pub fn isTty(file: File, io: Io) bool { return io.vtable.fileIsTty(io.userdata, file); @@ -282,7 +282,7 @@ pub fn isTty(file: File, io: Io) bool { pub const EnableAnsiEscapeCodesError = error{} || Io.Cancelable || Io.UnexpectedError; -pub fn enableAnsiEscapeCodes(file: File, io: Io) EnableAnsiEscapeCodesError { +pub fn enableAnsiEscapeCodes(file: File, io: Io) EnableAnsiEscapeCodesError!void { return io.vtable.fileEnableAnsiEscapeCodes(io.userdata, file); } diff --git a/lib/std/Io/File/Writer.zig b/lib/std/Io/File/Writer.zig index bb141f9ef6..e511e62e19 100644 --- a/lib/std/Io/File/Writer.zig +++ b/lib/std/Io/File/Writer.zig @@ -7,7 +7,7 @@ const assert = std.debug.assert; io: Io, file: File, -err: ?File.WriteError = null, +err: ?Error = null, mode: Mode = .positional, /// Tracks the true seek position in the file. To obtain the logical /// position, add the buffer size to this value. @@ -18,6 +18,29 @@ interface: Io.Writer, pub const Mode = File.Reader.Mode; +pub const Error = error{ + DiskQuota, + FileTooBig, + InputOutput, + NoSpaceLeft, + DeviceBusy, + InvalidArgument, + /// File descriptor does not hold the required rights to write to it. + AccessDenied, + PermissionDenied, + BrokenPipe, + SystemResources, + NotOpenForWriting, + /// The process cannot access the file because another process has locked + /// a portion of the file. Windows-only. + LockViolation, + /// Non-blocking has been enabled and this operation would block. + WouldBlock, + /// This error occurs when a device gets disconnected before or mid-flush + /// while it's being written to - errno(6): No such device or address. + NoDevice, +} || Io.Cancelable || Io.UnexpectedError; + pub const WriteFileError = error{ /// `out_fd` is an unconnected socket, or out_fd closed its read end. BrokenPipe, diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index d05516eae3..c31e86c992 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -6400,6 +6400,22 @@ fn fileWriteFileStreaming( return error.Unimplemented; } +fn netWriteFile( + userdata: ?*anyopaque, + socket_handle: net.Socket.Handle, + header: []const u8, + file_reader: *Io.File.Reader, + limit: Io.Limit, +) net.Stream.WriteFileError!usize { + const t: *Threaded = @ptrCast(@alignCast(userdata)); + _ = t; + _ = socket_handle; + _ = header; + _ = file_reader; + _ = limit; + return error.Unimplemented; // TODO +} + fn fileWriteFilePositional( userdata: ?*anyopaque, file: Io.File, diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index 65d2dfd5e4..2a56f3a4ab 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -1256,6 +1256,7 @@ pub const Stream = struct { interface: Io.Writer, stream: Stream, err: ?Error = null, + write_file_err: ?WriteFileError = null, pub const Error = error{ /// Another TCP Fast Open is already in progress. @@ -1285,12 +1286,17 @@ pub const Stream = struct { SocketNotBound, } || Io.UnexpectedError || Io.Cancelable; + pub const WriteFileError = error{} || Io.Cancelable || Io.UnexpectedError; + pub fn init(stream: Stream, io: Io, buffer: []u8) Writer { return .{ .io = io, .stream = stream, .interface = .{ - .vtable = &.{ .drain = drain }, + .vtable = &.{ + .drain = drain, + .sendFile = sendFile, + }, .buffer = buffer, }, }; @@ -1307,6 +1313,13 @@ pub const Stream = struct { }; return io_w.consume(n); } + + fn sendFile(io_w: *Io.Writer, file_reader: *Io.File.Reader, limit: Io.Limit) Io.Writer.FileError!usize { + _ = io_w; + _ = file_reader; + _ = limit; + return error.Unimplemented; // TODO + } }; pub fn reader(stream: Stream, io: Io, buffer: []u8) Reader { diff --git a/lib/std/Io/tty.zig b/lib/std/Io/tty.zig index 4f5ec8fd2d..d241a9cad8 100644 --- a/lib/std/Io/tty.zig +++ b/lib/std/Io/tty.zig @@ -55,7 +55,9 @@ pub const Config = union(enum) { if (force_color == false) return .no_color; - if (file.getOrEnableAnsiEscapeSupport()) return .escape_codes; + if (file.enableAnsiEscapeCodes()) |_| { + return .escape_codes; + } else |_| {} if (native_os == .windows and file.isTty()) { var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig index a7274be8c7..5e24627112 100644 --- a/lib/std/Progress.zig +++ b/lib/std/Progress.zig @@ -474,9 +474,9 @@ pub fn start(options: Options) Node { } const stderr: std.fs.File = .stderr(); global_progress.terminal = stderr; - if (stderr.getOrEnableAnsiEscapeSupport()) { + if (stderr.enableAnsiEscapeCodes()) |_| { global_progress.terminal_mode = .ansi_escape_codes; - } else if (is_windows and stderr.isTty()) { + } else |_| if (is_windows and stderr.isTty()) { global_progress.terminal_mode = TerminalMode{ .windows_api = .{ .code_page = windows.kernel32.GetConsoleOutputCP(), } }; diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 4641c52cb3..45080ee09f 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -796,226 +796,6 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { } } -/// Number of bytes read is returned. Upon reading end-of-file, zero is returned. -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// This operation is non-atomic on the following systems: -/// * Windows -/// On these systems, the read races with concurrent writes to the same file descriptor. -/// -/// This function assumes that all vectors, including zero-length vectors, have -/// a pointer within the address space of the application. -pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { - if (native_os == .windows) { - if (iov.len == 0) return 0; - const first = iov[0]; - return read(fd, first.base[0..first.len]); - } - if (native_os == .wasi and !builtin.link_libc) { - var nread: usize = undefined; - switch (wasi.fd_read(fd, iov.ptr, iov.len, &nread)) { - .SUCCESS => return nread, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, // currently not support in WASI - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - while (true) { - const rc = system.readv(fd, iov.ptr, @min(iov.len, IOV_MAX)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => unreachable, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - else => |err| return unexpectedErrno(err), - } - } -} - -pub const PReadError = std.Io.File.ReadPositionalError; - -/// Number of bytes read is returned. Upon reading end-of-file, zero is returned. -/// -/// Retries when interrupted by a signal. -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// Linux has a limit on how many bytes may be transferred in one `pread` call, which is `0x7ffff000` -/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as -/// well as stuffing the errno codes into the last `4096` values. This is noted on the `read` man page. -/// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL. -/// The corresponding POSIX limit is `maxInt(isize)`. -pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { - if (buf.len == 0) return 0; - if (native_os == .windows) { - return windows.ReadFile(fd, buf, offset); - } - if (native_os == .wasi and !builtin.link_libc) { - const iovs = [1]iovec{iovec{ - .base = buf.ptr, - .len = buf.len, - }}; - - var nread: usize = undefined; - switch (wasi.fd_pread(fd, &iovs, iovs.len, offset, &nread)) { - .SUCCESS => return nread, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForReading, // Can be a race condition. - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - // Prevent EINVAL. - const max_count = switch (native_os) { - .linux => 0x7ffff000, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => maxInt(i32), - else => maxInt(isize), - }; - - const pread_sym = if (lfs64_abi) system.pread64 else system.pread; - while (true) { - const rc = pread_sym(fd, buf.ptr, @min(buf.len, max_count), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => unreachable, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForReading, // Can be a race condition. - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } -} - -/// Number of bytes read is returned. Upon reading end-of-file, zero is returned. -/// -/// Retries when interrupted by a signal. -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// This operation is non-atomic on the following systems: -/// * Darwin -/// * Windows -/// On these systems, the read races with concurrent writes to the same file descriptor. -pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { - const have_pread_but_not_preadv = switch (native_os) { - .windows, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .haiku => true, - else => false, - }; - if (have_pread_but_not_preadv) { - // We could loop here; but proper usage of `preadv` must handle partial reads anyway. - // So we simply read into the first vector only. - if (iov.len == 0) return 0; - const first = iov[0]; - return pread(fd, first.base[0..first.len], offset); - } - if (native_os == .wasi and !builtin.link_libc) { - var nread: usize = undefined; - switch (wasi.fd_pread(fd, iov.ptr, iov.len, offset, &nread)) { - .SUCCESS => return nread, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - const preadv_sym = if (lfs64_abi) system.preadv64 else system.preadv; - while (true) { - const rc = preadv_sym(fd, iov.ptr, @min(iov.len, IOV_MAX), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @bitCast(rc), - .INTR => continue, - .INVAL => unreachable, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForReading, // can be a race condition - .IO => return error.InputOutput, - .ISDIR => return error.IsDir, - .NOBUFS => return error.SystemResources, - .NOMEM => return error.SystemResources, - .NOTCONN => return error.SocketUnconnected, - .CONNRESET => return error.ConnectionResetByPeer, - .TIMEDOUT => return error.Timeout, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - else => |err| return unexpectedErrno(err), - } - } -} - pub const WriteError = error{ DiskQuota, FileTooBig, @@ -1140,183 +920,6 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { } } -pub const PWriteError = WriteError || error{Unseekable}; - -/// Write to a file descriptor, with a position offset. -/// Retries when interrupted by a signal. -/// Returns the number of bytes written. If nonzero bytes were supplied, this will be nonzero. -/// -/// Note that a successful write() may transfer fewer bytes than supplied. Such partial writes can -/// occur for various reasons; for example, because there was insufficient space on the disk -/// device to write all of the requested bytes, or because a blocked write() to a socket, pipe, or -/// similar was interrupted by a signal handler after it had transferred some, but before it had -/// transferred all of the requested bytes. In the event of a partial write, the caller can make -/// another write() call to transfer the remaining bytes. The subsequent call will either -/// transfer further bytes or may result in an error (e.g., if the disk is now full). -/// -/// For POSIX systems, if `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are -/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. -/// -/// Linux has a limit on how many bytes may be transferred in one `pwrite` call, which is `0x7ffff000` -/// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as -/// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page. -/// The limit on Darwin is `0x7fffffff`, trying to write more than that returns EINVAL. -/// The corresponding POSIX limit is `maxInt(isize)`. -pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { - if (bytes.len == 0) return 0; - if (native_os == .windows) { - return windows.WriteFile(fd, bytes, offset); - } - if (native_os == .wasi and !builtin.link_libc) { - const ciovs = [1]iovec_const{iovec_const{ - .base = bytes.ptr, - .len = bytes.len, - }}; - - var nwritten: usize = undefined; - switch (wasi.fd_pwrite(fd, &ciovs, ciovs.len, offset, &nwritten)) { - .SUCCESS => return nwritten, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForWriting, // can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - // Prevent EINVAL. - const max_count = switch (native_os) { - .linux => 0x7ffff000, - .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => maxInt(i32), - else => maxInt(isize), - }; - - const pwrite_sym = if (lfs64_abi) system.pwrite64 else system.pwrite; - while (true) { - const rc = pwrite_sym(fd, bytes.ptr, @min(bytes.len, max_count), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => return error.InvalidArgument, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForWriting, // Can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .BUSY => return error.DeviceBusy, - else => |err| return unexpectedErrno(err), - } - } -} - -/// Write multiple buffers to a file descriptor, with a position offset. -/// Retries when interrupted by a signal. -/// Returns the number of bytes written. If nonzero bytes were supplied, this will be nonzero. -/// -/// Note that a successful write() may transfer fewer than count bytes. Such partial writes can -/// occur for various reasons; for example, because there was insufficient space on the disk -/// device to write all of the requested bytes, or because a blocked write() to a socket, pipe, or -/// similar was interrupted by a signal handler after it had transferred some, but before it had -/// transferred all of the requested bytes. In the event of a partial write, the caller can make -/// another write() call to transfer the remaining bytes. The subsequent call will either -/// transfer further bytes or may result in an error (e.g., if the disk is now full). -/// -/// If `fd` is opened in non blocking mode, the function will -/// return error.WouldBlock when EAGAIN is received. -/// -/// The following systems do not have this syscall, and will return partial writes if more than one -/// vector is provided: -/// * Darwin -/// * Windows -/// -/// If `iov.len` is larger than `IOV_MAX`, a partial write will occur. -pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usize { - const have_pwrite_but_not_pwritev = switch (native_os) { - .windows, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos, .haiku => true, - else => false, - }; - - if (have_pwrite_but_not_pwritev) { - // We could loop here; but proper usage of `pwritev` must handle partial writes anyway. - // So we simply write the first vector only. - if (iov.len == 0) return 0; - const first = iov[0]; - return pwrite(fd, first.base[0..first.len], offset); - } - if (native_os == .wasi and !builtin.link_libc) { - var nwritten: usize = undefined; - switch (wasi.fd_pwrite(fd, iov.ptr, iov.len, offset, &nwritten)) { - .SUCCESS => return nwritten, - .INTR => unreachable, - .INVAL => unreachable, - .FAULT => unreachable, - .AGAIN => unreachable, - .BADF => return error.NotOpenForWriting, // Can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .NOTCAPABLE => return error.AccessDenied, - else => |err| return unexpectedErrno(err), - } - } - - const pwritev_sym = if (lfs64_abi) system.pwritev64 else system.pwritev; - while (true) { - const rc = pwritev_sym(fd, iov.ptr, @min(iov.len, IOV_MAX), @bitCast(offset)); - switch (errno(rc)) { - .SUCCESS => return @intCast(rc), - .INTR => continue, - .INVAL => return error.InvalidArgument, - .FAULT => unreachable, - .SRCH => return error.ProcessNotFound, - .AGAIN => return error.WouldBlock, - .BADF => return error.NotOpenForWriting, // Can be a race condition. - .DESTADDRREQ => unreachable, // `connect` was never called. - .DQUOT => return error.DiskQuota, - .FBIG => return error.FileTooBig, - .IO => return error.InputOutput, - .NOSPC => return error.NoSpaceLeft, - .PERM => return error.PermissionDenied, - .PIPE => return error.BrokenPipe, - .NXIO => return error.Unseekable, - .SPIPE => return error.Unseekable, - .OVERFLOW => return error.Unseekable, - .BUSY => return error.DeviceBusy, - else => |err| return unexpectedErrno(err), - } - } -} - pub const OpenError = std.Io.File.OpenError || error{WouldBlock}; /// Open and possibly create a file. Keeps trying if it gets interrupted.