diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 3a8fd9e9a3..bc202c7b89 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -482,7 +482,7 @@ pub const File = struct { /// order to handle partial reads from the underlying OS layer. /// See https://github.com/ziglang/zig/issues/7699 pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize { - if (iovecs.len == 0) return; + if (iovecs.len == 0) return 0; var i: usize = 0; var off: usize = 0; @@ -524,8 +524,8 @@ pub const File = struct { /// The `iovecs` parameter is mutable because this function needs to mutate the fields in /// order to handle partial reads from the underlying OS layer. /// See https://github.com/ziglang/zig/issues/7699 - pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void { - if (iovecs.len == 0) return; + pub fn preadvAll(self: File, iovecs: []os.iovec, offset: u64) PReadError!usize { + if (iovecs.len == 0) return 0; var i: usize = 0; var off: usize = 0; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 3417e782c0..f586c50b6a 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -520,6 +520,89 @@ test "makePath, put some files in it, deleteTree" { } } +test "writev, readv" { + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + const line1 = "line1\n"; + const line2 = "line2\n"; + + var buf1: [line1.len]u8 = undefined; + var buf2: [line2.len]u8 = undefined; + var write_vecs = [_]std.os.iovec_const{ + .{ + .iov_base = line1, + .iov_len = line1.len, + }, + .{ + .iov_base = line2, + .iov_len = line2.len, + }, + }; + var read_vecs = [_]std.os.iovec{ + .{ + .iov_base = &buf2, + .iov_len = buf2.len, + }, + .{ + .iov_base = &buf1, + .iov_len = buf1.len, + }, + }; + + var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); + defer src_file.close(); + + try src_file.writevAll(&write_vecs); + try testing.expectEqual(@as(u64, line1.len + line2.len), try src_file.getEndPos()); + try src_file.seekTo(0); + const read = try src_file.readvAll(&read_vecs); + try testing.expectEqual(@as(usize, line1.len + line2.len), read); + try testing.expectEqualStrings(&buf1, "line2\n"); + try testing.expectEqualStrings(&buf2, "line1\n"); +} + +test "pwritev, preadv" { + var tmp = tmpDir(.{}); + defer tmp.cleanup(); + + const line1 = "line1\n"; + const line2 = "line2\n"; + + var buf1: [line1.len]u8 = undefined; + var buf2: [line2.len]u8 = undefined; + var write_vecs = [_]std.os.iovec_const{ + .{ + .iov_base = line1, + .iov_len = line1.len, + }, + .{ + .iov_base = line2, + .iov_len = line2.len, + }, + }; + var read_vecs = [_]std.os.iovec{ + .{ + .iov_base = &buf2, + .iov_len = buf2.len, + }, + .{ + .iov_base = &buf1, + .iov_len = buf1.len, + }, + }; + + var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); + defer src_file.close(); + + try src_file.pwritevAll(&write_vecs, 16); + try testing.expectEqual(@as(u64, 16 + line1.len + line2.len), try src_file.getEndPos()); + const read = try src_file.preadvAll(&read_vecs, 16); + try testing.expectEqual(@as(usize, line1.len + line2.len), read); + try testing.expectEqualStrings(&buf1, "line2\n"); + try testing.expectEqualStrings(&buf2, "line1\n"); +} + test "access file" { if (builtin.os.tag == .wasi) return error.SkipZigTest; diff --git a/lib/std/os.zig b/lib/std/os.zig index 358290a347..0ee20d7c8e 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -646,8 +646,9 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { else system.preadv; + const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned while (true) { - const rc = preadv_sym(fd, iov.ptr, iov_count, offset); + const rc = preadv_sym(fd, iov.ptr, iov_count, ioffset); switch (errno(rc)) { 0 => return @bitCast(usize, rc), EINTR => continue, @@ -998,8 +999,9 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz system.pwritev; const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31); + const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned while (true) { - const rc = pwritev_sym(fd, iov.ptr, iov_count, offset); + const rc = pwritev_sym(fd, iov.ptr, iov_count, ioffset); switch (errno(rc)) { 0 => return @intCast(usize, rc), EINTR => continue,