Skip to content

Commit

Permalink
mingw: emulate stat() a little more faithfully
Browse files Browse the repository at this point in the history
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 <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Sep 22, 2022
1 parent 348c78a commit 5d11986
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion compat/mingw.c
Expand Up @@ -1086,7 +1086,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);
Expand Down

0 comments on commit 5d11986

Please sign in to comment.