aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-12-05 17:41:27 -0800
committerAndrew Kelley <andrew@ziglang.org>2025-12-23 22:15:07 -0800
commit72b76077ab4e5042b13ea311063f2c7e867e00ba (patch)
treebda79bf0b7899c4ebdc514ff1c1a2cfd03f81563 /lib
parentba999d608c304c37667175b35e4a64f87d90351c (diff)
downloadzig-72b76077ab4e5042b13ea311063f2c7e867e00ba.tar.gz
zig-72b76077ab4e5042b13ea311063f2c7e867e00ba.zip
std: fix some surface level compilation errors
And boldly remove preadv, pwritev, readv, writev, pread, pwrite from std.posix.
Diffstat (limited to 'lib')
-rw-r--r--lib/std/Io.zig6
-rw-r--r--lib/std/Io/File.zig4
-rw-r--r--lib/std/Io/File/Writer.zig25
-rw-r--r--lib/std/Io/Threaded.zig16
-rw-r--r--lib/std/Io/net.zig15
-rw-r--r--lib/std/Io/tty.zig4
-rw-r--r--lib/std/Progress.zig4
-rw-r--r--lib/std/posix.zig397
8 files changed, 64 insertions, 407 deletions
diff --git a/lib/std/Io.zig b/lib/std/Io.zig
index acca9f700c..0727e3efd3 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 9a743847ad..bc6c1c4688 100644
--- a/lib/std/Io/Threaded.zig
+++ b/lib/std/Io/Threaded.zig
@@ -6581,6 +6581,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 3e2bb0969d..08e0bd71f0 100644
--- a/lib/std/Io/tty.zig
+++ b/lib/std/Io/tty.zig
@@ -50,7 +50,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 d1ab503661..467d4754ff 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 a35f3e52dc..392987ec50 100644
--- a/lib/std/posix.zig
+++ b/lib/std/posix.zig
@@ -813,226 +813,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,
@@ -1157,183 +937,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.