authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-01-08 16:51:20-08:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-01-11 02:08:18-08:00
logb4831403c929d429c7710d5004ec32fd0dfbd0a4
tree565fdd5440bacc37db9467df4fa1981cafabd0f5
parentd08098861f47fb0974066fce8cc3af7d5709d12f

fileRead functions: handle INVALID_FUNCTION on Windows and map it to error.IsDir

INVALID_FUNCTION may be possible in other scenarios as well, but it is verifiably returned when the handle refers to a directory.

2 files changed, 16 insertions(+), 1 deletions(-)

lib/std/Io/Threaded.zig+6
......@@ -7987,6 +7987,9 @@ fn fileReadStreamingWindows(userdata: ?*anyopaque, file: File, data: []const []u
79877987 .LOCK_VIOLATION => return syscall.fail(error.LockViolation),
79887988 .ACCESS_DENIED => return syscall.fail(error.AccessDenied),
79897989 .INVALID_HANDLE => return syscall.fail(error.NotOpenForReading),
7990 // TODO: Determine if INVALID_FUNCTION is possible in more scenarios than just passing
7991 // a handle to a directory.
7992 .INVALID_FUNCTION => return syscall.fail(error.IsDir),
79907993 else => |err| {
79917994 syscall.finish();
79927995 return windows.unexpectedError(err);
......@@ -8144,6 +8147,9 @@ fn fileReadPositionalWindows(userdata: ?*anyopaque, file: File, data: []const []
81448147 .LOCK_VIOLATION => return syscall.fail(error.LockViolation),
81458148 .ACCESS_DENIED => return syscall.fail(error.AccessDenied),
81468149 .INVALID_HANDLE => return syscall.fail(error.NotOpenForReading),
8150 // TODO: Determine if INVALID_FUNCTION is possible in more scenarios than just passing
8151 // a handle to a directory.
8152 .INVALID_FUNCTION => return syscall.fail(error.IsDir),
81478153 else => |err| {
81488154 syscall.finish();
81498155 return windows.unexpectedError(err);
lib/std/fs/test.zig+10-1
......@@ -847,7 +847,16 @@ test "file operations on directories" {
847847
848848 {
849849 const handle = try ctx.dir.openFile(io, test_dir_name, .{ .allow_directory = true, .mode = .read_only });
850 handle.close(io);
850 defer handle.close(io);
851
852 // Reading from the handle should fail
853 const expected_err = switch (native_os) {
854 .wasi => error.NotOpenForReading,
855 else => error.IsDir,
856 };
857 var buf: [1]u8 = undefined;
858 try expectError(expected_err, handle.readStreaming(io, &.{&buf}));
859 try expectError(expected_err, handle.readPositional(io, &.{&buf}, 0));
851860 }
852861 try expectError(error.IsDir, ctx.dir.openFile(io, test_dir_name, .{ .allow_directory = false, .mode = .read_only }));
853862