| author | |
| committer | |
| log | 72c4b80d31c3ccecbd8cf96e5afdf756e055dc6a |
| tree | 08db5921f6b3c08fb9f6590fac8c29f9941c4c25 |
| parent | 62e3d67605075f27134736917495e7a7a17869f6 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
Co-authored-by: Veikka Tuominen <git@vexu.eu>7 files changed, 26 insertions(+), 4 deletions(-)
lib/std/os.zig+4-4| ... | ... | @@ -787,7 +787,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { |
| 787 | 787 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are |
| 788 | 788 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. |
| 789 | 789 | /// |
| 790 | /// If `iov.len` is larger than will fit in a `u31`, a partial write will occur. | |
| 790 | /// If `iov.len` is larger than `IOV_MAX`, a partial write will occur. | |
| 791 | 791 | pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { |
| 792 | 792 | if (std.Target.current.os.tag == .windows) { |
| 793 | 793 | // TODO improve this to use WriteFileScatter |
| ... | ... | @@ -816,7 +816,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { |
| 816 | 816 | } |
| 817 | 817 | } |
| 818 | 818 | |
| 819 | const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31); | |
| 819 | const iov_count = if (iov.len > IOV_MAX) IOV_MAX else @intCast(u31, iov.len); | |
| 820 | 820 | while (true) { |
| 821 | 821 | const rc = system.writev(fd, iov.ptr, iov_count); |
| 822 | 822 | switch (errno(rc)) { |
| ... | ... | @@ -954,7 +954,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { |
| 954 | 954 | /// * Darwin |
| 955 | 955 | /// * Windows |
| 956 | 956 | /// |
| 957 | /// If `iov.len` is larger than will fit in a `u31`, a partial write will occur. | |
| 957 | /// If `iov.len` is larger than `IOV_MAX`, a partial write will occur. | |
| 958 | 958 | pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usize { |
| 959 | 959 | const have_pwrite_but_not_pwritev = switch (std.Target.current.os.tag) { |
| 960 | 960 | .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 |
| 997 | 997 | else |
| 998 | 998 | system.pwritev; |
| 999 | 999 | |
| 1000 | const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31); | |
| 1000 | const iov_count = if (iov.len > IOV_MAX) IOV_MAX else @intCast(u31, iov.len); | |
| 1001 | 1001 | const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned |
| 1002 | 1002 | while (true) { |
| 1003 | 1003 | const rc = pwritev_sym(fd, iov.ptr, iov_count, ioffset); |
lib/std/os/bits/darwin.zig+1| ... | ... | @@ -235,6 +235,7 @@ pub const host_t = mach_port_t; |
| 235 | 235 | pub const CALENDAR_CLOCK = 1; |
| 236 | 236 | |
| 237 | 237 | pub const PATH_MAX = 1024; |
| 238 | pub const IOV_MAX = 16; | |
| 238 | 239 | |
| 239 | 240 | pub const STDIN_FILENO = 0; |
| 240 | 241 | pub const STDOUT_FILENO = 1; |
lib/std/os/bits/dragonfly.zig+1| ... | ... | @@ -168,6 +168,7 @@ pub const SA_NOCLDWAIT = 0x0020; |
| 168 | 168 | pub const SA_SIGINFO = 0x0040; |
| 169 | 169 | |
| 170 | 170 | pub const PATH_MAX = 1024; |
| 171 | pub const IOV_MAX = KERN_IOV_MAX; | |
| 171 | 172 | |
| 172 | 173 | pub const ino_t = c_ulong; |
| 173 | 174 |
lib/std/os/bits/freebsd.zig+2| ... | ... | @@ -238,8 +238,10 @@ pub const CTL_DEBUG = 5; |
| 238 | 238 | |
| 239 | 239 | pub const KERN_PROC = 14; // struct: process entries |
| 240 | 240 | pub const KERN_PROC_PATHNAME = 12; // path to executable |
| 241 | pub const KERN_IOV_MAX = 35; | |
| 241 | 242 | |
| 242 | 243 | pub const PATH_MAX = 1024; |
| 244 | pub const IOV_MAX = KERN_IOV_MAX; | |
| 243 | 245 | |
| 244 | 246 | pub const STDIN_FILENO = 0; |
| 245 | 247 | pub const STDOUT_FILENO = 1; |
lib/std/os/bits/netbsd.zig+2| ... | ... | @@ -405,8 +405,10 @@ pub const CTL_DEBUG = 5; |
| 405 | 405 | |
| 406 | 406 | pub const KERN_PROC_ARGS = 48; // struct: process argv/env |
| 407 | 407 | pub const KERN_PROC_PATHNAME = 5; // path to executable |
| 408 | pub const KERN_IOV_MAX = 38; | |
| 408 | 409 | |
| 409 | 410 | pub const PATH_MAX = 1024; |
| 411 | pub const IOV_MAX = KERN_IOV_MAX; | |
| 410 | 412 | |
| 411 | 413 | pub const STDIN_FILENO = 0; |
| 412 | 414 | pub const STDOUT_FILENO = 1; |
lib/std/os/bits/wasi.zig+2| ... | ... | @@ -76,6 +76,8 @@ pub const kernel_stat = struct { |
| 76 | 76 | } |
| 77 | 77 | }; |
| 78 | 78 | |
| 79 | pub const IOV_MAX = 1024; | |
| 80 | ||
| 79 | 81 | pub const AT_REMOVEDIR: u32 = 0x4; |
| 80 | 82 | pub const AT_FDCWD: fd_t = -2; |
| 81 | 83 |
lib/std/os/test.zig+14| ... | ... | @@ -786,3 +786,17 @@ test "dup & dup2" { |
| 786 | 786 | var buf: [7]u8 = undefined; |
| 787 | 787 | try testing.expectEqualStrings("dupdup2", buf[0..try file.readAll(&buf)]); |
| 788 | 788 | } |
| 789 | ||
| 790 | test "writev longer than IOV_MAX" { | |
| 791 | if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; | |
| 792 | ||
| 793 | var tmp = tmpDir(.{}); | |
| 794 | defer tmp.cleanup(); | |
| 795 | ||
| 796 | var file = try tmp.dir.createFile("pwritev", .{}); | |
| 797 | defer file.close(); | |
| 798 | ||
| 799 | const iovecs = [_]os.iovec_const{.{ .iov_base = "a", .iov_len = 1 }} ** (os.IOV_MAX + 1); | |
| 800 | const amt = try file.writev(&iovecs); | |
| 801 | try testing.expectEqual(@as(usize, os.IOV_MAX), amt); | |
| 802 | } |