diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 5b230064199c4d90df6c9e5ce7ecf155dcd46313..04384b3d68e4e8c26f610731479f4ec435c7cc44 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -5053,7 +5053,7 @@ pub fn dirOpenFileWtf16( .VALID_FLAGS, .OPEN, .{ - .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .IO = .SYNCHRONOUS_NONALERT, .NON_DIRECTORY_FILE = !allow_directory, .OPEN_REPARSE_POINT = !flags.follow_symlinks, }, @@ -8136,7 +8136,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink .{ .DIRECTORY_FILE = false, .NON_DIRECTORY_FILE = false, - .IO = .ASYNCHRONOUS, + .IO = .SYNCHRONOUS_NONALERT, .OPEN_REPARSE_POINT = true, }, null, @@ -8202,7 +8202,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined; switch ((try deviceIoControl(&.{ - .file = .{ .handle = result_handle, .flags = .{ .nonblocking = true } }, + .file = .{ .handle = result_handle, .flags = .{ .nonblocking = false } }, .code = .GET_REPARSE_POINT, .out = &reparse_buf, })).u.Status) { @@ -18995,7 +18995,7 @@ fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!windows .{ .DIRECTORY_FILE = options.filter == .dir_only, .NON_DIRECTORY_FILE = options.filter == .non_directory_only, - .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .IO = .SYNCHRONOUS_NONALERT, .OPEN_REPARSE_POINT = !options.follow_symlinks, }, null, diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index bf16a7c216b4f9087195c7a98160e6b765687960..fc613ccdaa313d46dab643f849149293f422a9a5 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -758,6 +758,43 @@ test "readFileAlloc" { ); } +test "file operations with follow_symlinks=false" { + const io = testing.io; + + var tmp_dir = tmpDir(.{}); + defer tmp_dir.cleanup(); + + const contents = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; + try tmp_dir.dir.writeFile(io, .{ + .sub_path = "test_file", + .data = contents, + }); + + // Without lock + { + var file = try tmp_dir.dir.openFile(io, "test_file", .{ .follow_symlinks = false }); + defer file.close(io); + + var file_reader = file.reader(io, &.{}); + const actual_contents = try file_reader.interface.allocRemaining(testing.allocator, .unlimited); + defer testing.allocator.free(actual_contents); + + try std.testing.expectEqualSlices(u8, contents, actual_contents); + } + + // With lock + { + var file = try tmp_dir.dir.openFile(io, "test_file", .{ .follow_symlinks = false, .lock = .exclusive }); + defer file.close(io); + + var file_reader = file.reader(io, &.{}); + const actual_contents = try file_reader.interface.allocRemaining(testing.allocator, .unlimited); + defer testing.allocator.free(actual_contents); + + try std.testing.expectEqualSlices(u8, contents, actual_contents); + } +} + test "Dir.statFile" { try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void {