Skip to content

Commit

Permalink
Win32: let mingw_lstat() error early upon problems with reparse points
Browse files Browse the repository at this point in the history
When obtaining lstat information for reparse points, we need to call
FindFirstFile() in addition to GetFileInformationEx() to obtain the type
of the reparse point (symlink, mount point etc.). However, currently there
is no error handling whatsoever if FindFirstFile() fails.

Call FindFirstFile() before modifying the stat *buf output parameter and
error out if the call fails.

Note: The FindFirstFile() return value includes all the data that we get
from GetFileAttributesEx(), so we could replace GetFileAttributesEx() with
FindFirstFile(). We don't do that because GetFileAttributesEx() is about
twice as fast for single files. I.e. we only pay the extra cost of calling
FindFirstFile() in the rare case that we encounter a reparse point.

Note: The indentation of the remaining reparse point code will be fixed in
the next patch.

Signed-off-by: Karsten Blees <blees@dcon.de>
  • Loading branch information
kblees authored and dscho committed Sep 18, 2024
1 parent bfb6c70 commit f027e0c
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,7 @@ static int has_valid_directory_prefix(wchar_t *wfilename)
int mingw_lstat(const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
WIN32_FIND_DATAW findbuf = { 0 };
wchar_t wfilename[MAX_LONG_PATH];
int wlen = xutftowcs_long_path(wfilename, file_name);
if (wlen < 0)
Expand All @@ -880,6 +881,13 @@ int mingw_lstat(const char *file_name, struct stat *buf)
}

if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
/* for reparse points, use FindFirstFile to get the reparse tag */
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
if (handle == INVALID_HANDLE_VALUE)
goto error;
FindClose(handle);
}
buf->st_ino = 0;
buf->st_gid = 0;
buf->st_uid = 0;
Expand All @@ -892,20 +900,16 @@ int mingw_lstat(const char *file_name, struct stat *buf)
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
WIN32_FIND_DATAW findbuf;
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
if (handle != INVALID_HANDLE_VALUE) {
if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
buf->st_mode = S_IFLNK | S_IREAD;
if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
buf->st_mode |= S_IWRITE;
}
FindClose(handle);
}
}
return 0;
}
error:
switch (GetLastError()) {
case ERROR_ACCESS_DENIED:
case ERROR_SHARING_VIOLATION:
Expand Down

0 comments on commit f027e0c

Please sign in to comment.