Skip to content

Platform specific error.IsDir behavior in fs.Dir.openFile #5732

@squeek502

Description

@squeek502

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, open on Linux only returns EISDIR when "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:

  1. Do a stat in fs.Dir.openFile on POSIX systems and return error.IsDir if the path is a directory.
  2. 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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    standard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions