diff --git a/lib/std/os.zig b/lib/std/os.zig index 5735539366e84f3856fd86758ae3de3ae83fdc1f..e85a6fe42fd1a35dbe955591024a9831733c91e6 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -787,7 +787,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { /// 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. /// -/// If `iov.len` is larger than will fit in a `u31`, a partial write will occur. +/// If `iov.len` is larger than `IOV_MAX`, a partial write will occur. pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { if (std.Target.current.os.tag == .windows) { // TODO improve this to use WriteFileScatter @@ -816,7 +816,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { } } - const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31); + const iov_count = if (iov.len > IOV_MAX) IOV_MAX else @intCast(u31, iov.len); while (true) { const rc = system.writev(fd, iov.ptr, iov_count); switch (errno(rc)) { @@ -954,7 +954,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { /// * Darwin /// * Windows /// -/// If `iov.len` is larger than will fit in a `u31`, a partial write will occur. +/// 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 (std.Target.current.os.tag) { .windows, .macos, .ios, .watchos, .tvos, .haiku => true, @@ -997,7 +997,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz else system.pwritev; - const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31); + const iov_count = if (iov.len > IOV_MAX) IOV_MAX else @intCast(u31, iov.len); const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned while (true) { const rc = pwritev_sym(fd, iov.ptr, iov_count, ioffset); diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index 91705c0d2e44561d81e9049b1639ec41ca4def7f..f39b5948d7d3d76b27ecee2eebd1d16717744c03 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -235,6 +235,7 @@ pub const host_t = mach_port_t; pub const CALENDAR_CLOCK = 1; pub const PATH_MAX = 1024; +pub const IOV_MAX = 16; pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig index 573721749cd5f167ca81efe612b207afad704366..dfa54972f37cc3676572ed6b043de0e771ffded6 100644 --- a/lib/std/os/bits/dragonfly.zig +++ b/lib/std/os/bits/dragonfly.zig @@ -168,6 +168,7 @@ pub const SA_NOCLDWAIT = 0x0020; pub const SA_SIGINFO = 0x0040; pub const PATH_MAX = 1024; +pub const IOV_MAX = KERN_IOV_MAX; pub const ino_t = c_ulong; diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index 1805941993943c6dbef53fe710ede0f55dcdf472..b08c31c8e3b12f7bed1bd0af9a88b6f806a23d74 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -238,8 +238,10 @@ pub const CTL_DEBUG = 5; pub const KERN_PROC = 14; // struct: process entries pub const KERN_PROC_PATHNAME = 12; // path to executable +pub const KERN_IOV_MAX = 35; pub const PATH_MAX = 1024; +pub const IOV_MAX = KERN_IOV_MAX; pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig index f3ece9349334ea529a953b9785e41c66e01151ab..af04d0536bf16665ded4d0bb75950e063e2de390 100644 --- a/lib/std/os/bits/netbsd.zig +++ b/lib/std/os/bits/netbsd.zig @@ -405,8 +405,10 @@ pub const CTL_DEBUG = 5; pub const KERN_PROC_ARGS = 48; // struct: process argv/env pub const KERN_PROC_PATHNAME = 5; // path to executable +pub const KERN_IOV_MAX = 38; pub const PATH_MAX = 1024; +pub const IOV_MAX = KERN_IOV_MAX; pub const STDIN_FILENO = 0; pub const STDOUT_FILENO = 1; diff --git a/lib/std/os/bits/wasi.zig b/lib/std/os/bits/wasi.zig index 5102d9b439a5b67be9670a97f7f3685f7b3d797c..ece97eacce60576ce379dd4cd3f4fe5b3ad1f3f7 100644 --- a/lib/std/os/bits/wasi.zig +++ b/lib/std/os/bits/wasi.zig @@ -76,6 +76,8 @@ pub const kernel_stat = struct { } }; +pub const IOV_MAX = 1024; + pub const AT_REMOVEDIR: u32 = 0x4; pub const AT_FDCWD: fd_t = -2; diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig index 6184c9770699d6ad2fbeec833486716ce65601f6..fb23f4459aeec22c99324be225792e7a4352d10c 100644 --- a/lib/std/os/test.zig +++ b/lib/std/os/test.zig @@ -786,3 +786,17 @@ test "dup & dup2" { var buf: [7]u8 = undefined; try testing.expectEqualStrings("dupdup2", buf[0..try file.readAll(&buf)]); } + +test "writev longer than IOV_MAX" { + if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; + + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + var file = try tmp.dir.createFile("pwritev", .{}); + defer file.close(); + + const iovecs = [_]os.iovec_const{.{ .iov_base = "a", .iov_len = 1 }} ** (os.IOV_MAX + 1); + const amt = try file.writev(&iovecs); + try testing.expectEqual(@as(usize, os.IOV_MAX), amt); +}