| 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 | 482 | /// order to handle partial reads from the underlying OS layer. |
| 483 | 483 | /// See https://github.com/ziglang/zig/issues/7699 |
| 484 | 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 | 487 | var i: usize = 0; |
| 488 | 488 | var off: usize = 0; |
| ... | ... | @@ -524,8 +524,8 @@ pub const File = struct { |
| 524 | 524 | /// The `iovecs` parameter is mutable because this function needs to mutate the fields in |
| 525 | 525 | /// order to handle partial reads from the underlying OS layer. |
| 526 | 526 | /// See https://github.com/ziglang/zig/issues/7699 |
| 527 | pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void { | |
| 528 | if (iovecs.len == 0) return; | |
| 527 | pub fn preadvAll(self: File, iovecs: []os.iovec, offset: u64) PReadError!usize { | |
| 528 | if (iovecs.len == 0) return 0; | |
| 529 | 529 | |
| 530 | 530 | var i: usize = 0; |
| 531 | 531 | var off: usize = 0; |
lib/std/fs/test.zig+83| ... | ... | @@ -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 | 606 | test "access file" { |
| 524 | 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 | 646 | else |
| 647 | 647 | system.preadv; |
| 648 | 648 | |
| 649 | const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned | |
| 649 | 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 | 652 | switch (errno(rc)) { |
| 652 | 653 | 0 => return @bitCast(usize, rc), |
| 653 | 654 | EINTR => continue, |
| ... | ... | @@ -998,8 +999,9 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz |
| 998 | 999 | system.pwritev; |
| 999 | 1000 | |
| 1000 | 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 | 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 | 1005 | switch (errno(rc)) { |
| 1004 | 1006 | 0 => return @intCast(usize, rc), |
| 1005 | 1007 | EINTR => continue, |