ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.95k stars 2.55k forks source link

Dir.openDir fails to open symlinks (Windows) #6642

Open BarabasGitHub opened 4 years ago

BarabasGitHub commented 4 years ago

Edit: sorry, initial report was false. The problem is when opening "C:/symlink".

This fails with Test [1/1] test "open dir with symlink"... [default] (err): NotDir:

test "open dir with symlink" {
    _ = try @import("std").fs.cwd().openDir("C:/symlink/normal_dir", .{});
}
daurnimator commented 4 years ago

hmm is this failing by telling us we need to follow reparse points?

BarabasGitHub commented 4 years ago

I don't know to be honest. The docs of NtCreateFile say

If the CreateOptions parameter specifies the FILE_OPEN_REPARSE_POINT flag and NtCreateFile opens a file with a reparse point, normal reparse processing does not occur and NtCreateFile attempts to directly open the reparse point file. If the FILE_OPEN_REPARSE_POINT flag is not specified, normal reparse point processing occurs for the file. In either case, if the open operation was successful, NtCreateFile returns STATUS_SUCCESS; otherwise, an error code. The NtCreateFile function never returns STATUS_REPARSE.

And as far as I can tell FILE_OPEN_REPARSE_POINT is not set in the zig code.

Oh wait. My apparently I made a mistake. It works fine with "C:/symlink/normal_dir" but not with "C:/symlink".

BarabasGitHub commented 4 years ago

It works with "C:/symlink/dir". It doesn't work with "C:/symlink" even if passing .no_follow=true. It does work if I apply

--- a/lib/std/fs.zig
+++ b/lib/std/fs.zig
@@ -1248,7 +1248,7 @@ pub const Dir = struct {
             // implement this: https://git.midipix.org/ntapi/tree/src/fs/ntapi_tt_open_physical_parent_directory.c
             @panic("TODO opening '..' with a relative directory handle is not yet implemented on Windows");
         }
-        const open_reparse_point: w.DWORD = if (no_follow) w.FILE_OPEN_REPARSE_POINT else 0x0;
+        const open_reparse_point_or_dir: w.DWORD = if (no_follow) w.FILE_OPEN_REPARSE_POINT else w.FILE_DIRECTORY_FILE;
         var io: w.IO_STATUS_BLOCK = undefined;
         const rc = w.ntdll.NtCreateFile(
             &result.fd,
@@ -1259,7 +1259,7 @@ pub const Dir = struct {
             0,
             w.FILE_SHARE_READ | w.FILE_SHARE_WRITE,
             w.FILE_OPEN,
-            w.FILE_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point,
+            w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point_or_dir,
             null,
             0,
         );

And in powershell cd C:\symlink also doesn't work, but cd C:\symlink\dir does. So maybe it's not a problem that can be solved. (Though I do wonder why my zig fails to run while it did work before, see #6640 )