aboutsummaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
authorJohannes Schindelin <johannes.schindelin@gmx.de>2026-01-09 20:05:14 +0000
committerJunio C Hamano <gitster@pobox.com>2026-01-09 18:32:55 -0800
commit2cba5746c03f85fedd45a08b4f91921c5960bb36 (patch)
tree884e6c76a3e3ae6b87b797b823f6537ef732f96c /compat
parent6206f7aeb0c584c91d226e32d446d6d062fa9674 (diff)
downloadgit-2cba5746c03f85fedd45a08b4f91921c5960bb36.tar.xz
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()` 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>
Diffstat (limited to 'compat')
-rw-r--r--compat/mingw.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 3e2110a87a..628a3941d2 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -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);