diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-03-16 04:11:41 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-16 04:11:41 -0400 |
| commit | bd242ce1ce9ef6ffb1af4432d892bf582dcdba8a (patch) | |
| tree | 34caaa3f320e8830a5f1f1c93a4b5d70c0d192a8 /lib/std/fs | |
| parent | a2c6ecd6dc0bdbe2396be9b055852324f16d34c9 (diff) | |
| parent | 7177b3994626114e57bf8df36ca84fd942bac282 (diff) | |
| download | zig-bd242ce1ce9ef6ffb1af4432d892bf582dcdba8a.tar.gz zig-bd242ce1ce9ef6ffb1af4432d892bf582dcdba8a.zip | |
Merge pull request #14647 from ziglang/build-parallel
zig build: run steps in parallel
Diffstat (limited to 'lib/std/fs')
| -rw-r--r-- | lib/std/fs/file.zig | 38 | ||||
| -rw-r--r-- | lib/std/fs/test.zig | 30 |
2 files changed, 55 insertions, 13 deletions
diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index bf93a61239..8235b8aecf 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -1048,12 +1048,27 @@ pub const File = struct { /// Returns the number of bytes read. If the number read is smaller than the total bytes /// from all the buffers, it means the file reached the end. Reaching the end of a file /// is not an error condition. - /// 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 + /// + /// The `iovecs` parameter is mutable because: + /// * This function needs to mutate the fields in order to handle partial + /// reads from the underlying OS layer. + /// * The OS layer expects pointer addresses to be inside the application's address space + /// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer + /// addresses when the length is zero. So this function modifies the iov_base fields + /// when the length is zero. + /// + /// Related open issue: https://github.com/ziglang/zig/issues/7699 pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize { if (iovecs.len == 0) return 0; + // We use the address of this local variable for all zero-length + // vectors so that the OS does not complain that we are giving it + // addresses outside the application's address space. + var garbage: [1]u8 = undefined; + for (iovecs) |*v| { + if (v.iov_len == 0) v.iov_base = &garbage; + } + var i: usize = 0; var off: usize = 0; while (true) { @@ -1181,13 +1196,26 @@ pub const File = struct { } } - /// The `iovecs` parameter is mutable because this function needs to mutate the fields in - /// order to handle partial writes from the underlying OS layer. + /// The `iovecs` parameter is mutable because: + /// * This function needs to mutate the fields in order to handle partial + /// writes from the underlying OS layer. + /// * The OS layer expects pointer addresses to be inside the application's address space + /// even if the length is zero. Meanwhile, in Zig, slices may have undefined pointer + /// addresses when the length is zero. So this function modifies the iov_base fields + /// when the length is zero. /// See https://github.com/ziglang/zig/issues/7699 /// See equivalent function: `std.net.Stream.writevAll`. pub fn writevAll(self: File, iovecs: []os.iovec_const) WriteError!void { if (iovecs.len == 0) return; + // We use the address of this local variable for all zero-length + // vectors so that the OS does not complain that we are giving it + // addresses outside the application's address space. + var garbage: [1]u8 = undefined; + for (iovecs) |*v| { + if (v.iov_len == 0) v.iov_base = &garbage; + } + var i: usize = 0; while (true) { var amt = try self.writev(iovecs[i..]); diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 16458d7dc4..1fbd7dbd63 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -1124,17 +1124,31 @@ test "open file with exclusive lock twice, make sure second lock waits" { test "open file with exclusive nonblocking lock twice (absolute paths)" { if (builtin.os.tag == .wasi) return error.SkipZigTest; - const allocator = testing.allocator; + var random_bytes: [12]u8 = undefined; + std.crypto.random.bytes(&random_bytes); - const cwd = try std.process.getCwdAlloc(allocator); - defer allocator.free(cwd); - const file_paths: [2][]const u8 = .{ cwd, "zig-test-absolute-paths.txt" }; - const filename = try fs.path.resolve(allocator, &file_paths); - defer allocator.free(filename); + var random_b64: [fs.base64_encoder.calcSize(random_bytes.len)]u8 = undefined; + _ = fs.base64_encoder.encode(&random_b64, &random_bytes); - const file1 = try fs.createFileAbsolute(filename, .{ .lock = .Exclusive, .lock_nonblocking = true }); + const sub_path = random_b64 ++ "-zig-test-absolute-paths.txt"; - const file2 = fs.createFileAbsolute(filename, .{ .lock = .Exclusive, .lock_nonblocking = true }); + const gpa = testing.allocator; + + const cwd = try std.process.getCwdAlloc(gpa); + defer gpa.free(cwd); + + const filename = try fs.path.resolve(gpa, &[_][]const u8{ cwd, sub_path }); + defer gpa.free(filename); + + const file1 = try fs.createFileAbsolute(filename, .{ + .lock = .Exclusive, + .lock_nonblocking = true, + }); + + const file2 = fs.createFileAbsolute(filename, .{ + .lock = .Exclusive, + .lock_nonblocking = true, + }); file1.close(); try testing.expectError(error.WouldBlock, file2); |
