Skip to content

Commit 5e7d3d1

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
mingw: emulate stat() a little more faithfully
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()` for 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 #2531. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 848c09c commit 5e7d3d1

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

compat/mingw.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,19 @@ int mingw_stat(const char *file_name, struct stat *buf)
11971197
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
11981198
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
11991199
if (hnd == INVALID_HANDLE_VALUE) {
1200-
errno = err_win_to_posix(GetLastError());
1200+
DWORD err = GetLastError();
1201+
1202+
if (err == ERROR_ACCESS_DENIED &&
1203+
!mingw_lstat(file_name, buf) &&
1204+
!S_ISLNK(buf->st_mode))
1205+
/*
1206+
* POSIX semantics state to still try to fill
1207+
* information, even if permission is denied to create
1208+
* a file handle.
1209+
*/
1210+
return 0;
1211+
1212+
errno = err_win_to_posix(err);
12011213
return -1;
12021214
}
12031215
result = get_file_info_by_handle(hnd, buf);

0 commit comments

Comments
 (0)