-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
From #5717:
I didn't include a read-only test because I was unsure about how to handle the differing errors per-platform, as mentioned here:
On Linux, when opening a file with read-only permissions, there is no way to determine whether the file descriptor is a directory handle without an additional syscall.
That is,
openon Linux only returnsEISDIRwhen "pathname refers to a directory and the access requested involved writing".
The following code will give error.IsDir on Windows, but will succeed on Linux/FreeBSD/Mac/etc:
const std = @import("std");
const fs = std.fs;
pub fn main() !void {
try fs.cwd().makePath("dir");
const file = try fs.cwd().openFile("dir", .{});
file.close();
}(note that doing something like file.readAll afterwards on Linux/etc will fail with error.IsDir)
There are two ways that this can be addressed that I can imagine:
- Do a
statinfs.Dir.openFileon POSIX systems and returnerror.IsDirif the path is a directory. - Document this and make users deal with the platform-specific behavior
Neither seems quite ideal.
For an example of what option 2 would look like from the user's perspective, this is what zig fmt does:
Lines 752 to 759 in 626b5ec
| const source_file = try dir.openFile(sub_path, .{}); | |
| var file_closed = false; | |
| errdefer if (!file_closed) source_file.close(); | |
| const stat = try source_file.stat(); | |
| if (stat.kind == .Directory) | |
| return error.IsDir; |
That is, on Windows, the try dir.openFile(sub_path, .{}); returns error.IsDir, while on other platforms, stat is used afterwards to return error.IsDir manually. Note, though, that in this case, the stat info is used again later, so moving the stat in the openFile call would lose the possibility for that optimization.