Skip to content

Commit 20280fc

Browse files
kbleesdscho
authored andcommittedFeb 6, 2025
Win32: let mingw_lstat() error early upon problems with reparse points
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>
1 parent 9c44fef commit 20280fc

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed
 

Diff for: ‎compat/mingw.c

+9-5
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,7 @@ static int has_valid_directory_prefix(wchar_t *wfilename)
946946
int mingw_lstat(const char *file_name, struct stat *buf)
947947
{
948948
WIN32_FILE_ATTRIBUTE_DATA fdata;
949+
WIN32_FIND_DATAW findbuf = { 0 };
949950
wchar_t wfilename[MAX_LONG_PATH];
950951
int wlen = xutftowcs_long_path(wfilename, file_name);
951952
if (wlen < 0)
@@ -960,6 +961,13 @@ int mingw_lstat(const char *file_name, struct stat *buf)
960961
}
961962

962963
if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
964+
/* for reparse points, use FindFirstFile to get the reparse tag */
965+
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
966+
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
967+
if (handle == INVALID_HANDLE_VALUE)
968+
goto error;
969+
FindClose(handle);
970+
}
963971
buf->st_ino = 0;
964972
buf->st_gid = 0;
965973
buf->st_uid = 0;
@@ -972,20 +980,16 @@ int mingw_lstat(const char *file_name, struct stat *buf)
972980
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
973981
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
974982
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
975-
WIN32_FIND_DATAW findbuf;
976-
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
977-
if (handle != INVALID_HANDLE_VALUE) {
978983
if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
979984
(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
980985
buf->st_mode = S_IFLNK | S_IREAD;
981986
if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
982987
buf->st_mode |= S_IWRITE;
983988
}
984-
FindClose(handle);
985-
}
986989
}
987990
return 0;
988991
}
992+
error:
989993
switch (GetLastError()) {
990994
case ERROR_ACCESS_DENIED:
991995
case ERROR_SHARING_VIOLATION:

0 commit comments

Comments
 (0)