]> git.ipfire.org Git - thirdparty/git.git/commitdiff
mingw: emulate `stat()` a little more faithfully
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Wed, 17 Dec 2025 14:08:54 +0000 (14:08 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Dec 2025 23:22:20 +0000 (08:22 +0900)
When creating directories via `safe_create_leading_directories()`, we
might encounter an already-existing directory which is not
readable by the current user. To handle that situation, Git's code calls
`stat()` to determine whether we're looking at a directory.

In such a case, `CreateFile()` will fail, though, no matter what, and
consequently `mingw_stat()` will fail, too. But POSIX semantics seem to
still allow `stat()` to go forward.

So let's call `mingw_lstat()` to the rescue if we fail to get a file
handle due to denied permission in `mingw_stat()`, and fill the stat
info that way.

We need to be careful to not allow this to go forward in case that we're
looking at a symbolic link: to resolve the link, we would still have to
create a file handle, and we just found out that we cannot. Therefore,
`stat()` still needs to fail with `EACCES` in that case.

This fixes https://github.com/git-for-windows/git/issues/2531.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/mingw.c

index 3e2110a87ae35dc4148c3fe102b1d24ac44feb0b..628a3941d24647f919e39ba44e635a367a37d353 100644 (file)
@@ -1273,7 +1273,19 @@ int mingw_stat(const char *file_name, struct stat *buf)
                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
                        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
        if (hnd == INVALID_HANDLE_VALUE) {
-               errno = err_win_to_posix(GetLastError());
+               DWORD err = GetLastError();
+
+               if (err == ERROR_ACCESS_DENIED &&
+                   !mingw_lstat(file_name, buf) &&
+                   !S_ISLNK(buf->st_mode))
+                       /*
+                        * POSIX semantics state to still try to fill
+                        * information, even if permission is denied to create
+                        * a file handle.
+                        */
+                       return 0;
+
+               errno = err_win_to_posix(err);
                return -1;
        }
        result = get_file_info_by_handle(hnd, buf);