[PATCH 17/18] mingw: emulate `stat()` a little more faithfully
- From
Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Dec 17, 2025, 14:08 UTC
- Message-ID
- <2e73ab42217496739adc5881d900552bce006c05.1765980535.git.gitgitgadget@gmail.com>
- In-Reply-To
- <pull.2018.git.1765980535.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
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> --- compat/mingw.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
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);
-- gitgitgadget