| author | |
| committer | |
| log | c065e12dbefcde1a48926405bd4f401eadecaca2 |
| tree | 6b09232db1a05c86350f864d991963b38df10309 |
| parent | 31f1cc9a0d80e87efb1f414352ff9d6abf2067ca |
It turns out that nothing in the test suite was exercising
preadv/pwritev and so the previous commits silently broke them.
Adding tests revealed readvAll and preadvAll were also broken and not
covered by any test.3 files changed, 90 insertions(+), 5 deletions(-)
lib/std/fs/file.zig+3-3| ... | @@ -482,7 +482,7 @@ pub const File = struct { | ... | @@ -482,7 +482,7 @@ pub const File = struct { |
| 482 | /// order to handle partial reads from the underlying OS layer. | 482 | /// order to handle partial reads from the underlying OS layer. |
| 483 | /// See https://github.com/ziglang/zig/issues/7699 | 483 | /// See https://github.com/ziglang/zig/issues/7699 |
| 484 | pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize { | 484 | pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize { |
| 485 | if (iovecs.len == 0) return; | 485 | if (iovecs.len == 0) return 0; |
| 486 | 486 | ||
| 487 | var i: usize = 0; | 487 | var i: usize = 0; |
| 488 | var off: usize = 0; | 488 | var off: usize = 0; |
| ... | @@ -524,8 +524,8 @@ pub const File = struct { | ... | @@ -524,8 +524,8 @@ pub const File = struct { |
| 524 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in | 524 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in |
| 525 | /// order to handle partial reads from the underlying OS layer. | 525 | /// order to handle partial reads from the underlying OS layer. |
| 526 | /// See https://github.com/ziglang/zig/issues/7699 | 526 | /// See https://github.com/ziglang/zig/issues/7699 |
| 527 | pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void { | 527 | pub fn preadvAll(self: File, iovecs: []os.iovec, offset: u64) PReadError!usize { |
| 528 | if (iovecs.len == 0) return; | 528 | if (iovecs.len == 0) return 0; |
| 529 | 529 | ||
| 530 | var i: usize = 0; | 530 | var i: usize = 0; |
| 531 | var off: usize = 0; | 531 | var off: usize = 0; |
lib/std/fs/test.zig+83| ... | @@ -520,6 +520,89 @@ test "makePath, put some files in it, deleteTree" { | ... | @@ -520,6 +520,89 @@ test "makePath, put some files in it, deleteTree" { |
| 520 | } | 520 | } |
| 521 | } | 521 | } |
| 522 | 522 | ||
| 523 | test "writev, readv" { | ||
| 524 | var tmp = tmpDir(.{}); | ||
| 525 | defer tmp.cleanup(); | ||
| 526 | |||
| 527 | const line1 = "line1\n"; | ||
| 528 | const line2 = "line2\n"; | ||
| 529 | |||
| 530 | var buf1: [line1.len]u8 = undefined; | ||
| 531 | var buf2: [line2.len]u8 = undefined; | ||
| 532 | var write_vecs = [_]std.os.iovec_const{ | ||
| 533 | .{ | ||
| 534 | .iov_base = line1, | ||
| 535 | .iov_len = line1.len, | ||
| 536 | }, | ||
| 537 | .{ | ||
| 538 | .iov_base = line2, | ||
| 539 | .iov_len = line2.len, | ||
| 540 | }, | ||
| 541 | }; | ||
| 542 | var read_vecs = [_]std.os.iovec{ | ||
| 543 | .{ | ||
| 544 | .iov_base = &buf2, | ||
| 545 | .iov_len = buf2.len, | ||
| 546 | }, | ||
| 547 | .{ | ||
| 548 | .iov_base = &buf1, | ||
| 549 | .iov_len = buf1.len, | ||
| 550 | }, | ||
| 551 | }; | ||
| 552 | |||
| 553 | var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); | ||
| 554 | defer src_file.close(); | ||
| 555 | |||
| 556 | try src_file.writevAll(&write_vecs); | ||
| 557 | try testing.expectEqual(@as(u64, line1.len + line2.len), try src_file.getEndPos()); | ||
| 558 | try src_file.seekTo(0); | ||
| 559 | const read = try src_file.readvAll(&read_vecs); | ||
| 560 | try testing.expectEqual(@as(usize, line1.len + line2.len), read); | ||
| 561 | try testing.expectEqualStrings(&buf1, "line2\n"); | ||
| 562 | try testing.expectEqualStrings(&buf2, "line1\n"); | ||
| 563 | } | ||
| 564 | |||
| 565 | test "pwritev, preadv" { | ||
| 566 | var tmp = tmpDir(.{}); | ||
| 567 | defer tmp.cleanup(); | ||
| 568 | |||
| 569 | const line1 = "line1\n"; | ||
| 570 | const line2 = "line2\n"; | ||
| 571 | |||
| 572 | var buf1: [line1.len]u8 = undefined; | ||
| 573 | var buf2: [line2.len]u8 = undefined; | ||
| 574 | var write_vecs = [_]std.os.iovec_const{ | ||
| 575 | .{ | ||
| 576 | .iov_base = line1, | ||
| 577 | .iov_len = line1.len, | ||
| 578 | }, | ||
| 579 | .{ | ||
| 580 | .iov_base = line2, | ||
| 581 | .iov_len = line2.len, | ||
| 582 | }, | ||
| 583 | }; | ||
| 584 | var read_vecs = [_]std.os.iovec{ | ||
| 585 | .{ | ||
| 586 | .iov_base = &buf2, | ||
| 587 | .iov_len = buf2.len, | ||
| 588 | }, | ||
| 589 | .{ | ||
| 590 | .iov_base = &buf1, | ||
| 591 | .iov_len = buf1.len, | ||
| 592 | }, | ||
| 593 | }; | ||
| 594 | |||
| 595 | var src_file = try tmp.dir.createFile("test.txt", .{ .read = true }); | ||
| 596 | defer src_file.close(); | ||
| 597 | |||
| 598 | try src_file.pwritevAll(&write_vecs, 16); | ||
| 599 | try testing.expectEqual(@as(u64, 16 + line1.len + line2.len), try src_file.getEndPos()); | ||
| 600 | const read = try src_file.preadvAll(&read_vecs, 16); | ||
| 601 | try testing.expectEqual(@as(usize, line1.len + line2.len), read); | ||
| 602 | try testing.expectEqualStrings(&buf1, "line2\n"); | ||
| 603 | try testing.expectEqualStrings(&buf2, "line1\n"); | ||
| 604 | } | ||
| 605 | |||
| 523 | test "access file" { | 606 | test "access file" { |
| 524 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | 607 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 525 | 608 |
lib/std/os.zig+4-2| ... | @@ -646,8 +646,9 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { | ... | @@ -646,8 +646,9 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { |
| 646 | else | 646 | else |
| 647 | system.preadv; | 647 | system.preadv; |
| 648 | 648 | ||
| 649 | const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned | ||
| 649 | while (true) { | 650 | while (true) { |
| 650 | const rc = preadv_sym(fd, iov.ptr, iov_count, offset); | 651 | const rc = preadv_sym(fd, iov.ptr, iov_count, ioffset); |
| 651 | switch (errno(rc)) { | 652 | switch (errno(rc)) { |
| 652 | 0 => return @bitCast(usize, rc), | 653 | 0 => return @bitCast(usize, rc), |
| 653 | EINTR => continue, | 654 | EINTR => continue, |
| ... | @@ -998,8 +999,9 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz | ... | @@ -998,8 +999,9 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz |
| 998 | system.pwritev; | 999 | system.pwritev; |
| 999 | 1000 | ||
| 1000 | const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31); | 1001 | const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31); |
| 1002 | const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned | ||
| 1001 | while (true) { | 1003 | while (true) { |
| 1002 | const rc = pwritev_sym(fd, iov.ptr, iov_count, offset); | 1004 | const rc = pwritev_sym(fd, iov.ptr, iov_count, ioffset); |
| 1003 | switch (errno(rc)) { | 1005 | switch (errno(rc)) { |
| 1004 | 0 => return @intCast(usize, rc), | 1006 | 0 => return @intCast(usize, rc), |
| 1005 | EINTR => continue, | 1007 | EINTR => continue, |