Skip to content

Commit c26b934

Browse files
kbleesGit for Windows Build Agent
authored andcommitted
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 <[email protected]>
1 parent 9833e1c commit c26b934

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

compat/mingw.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,7 @@ static int has_valid_directory_prefix(wchar_t *wfilename)
961961
int mingw_lstat(const char *file_name, struct stat *buf)
962962
{
963963
WIN32_FILE_ATTRIBUTE_DATA fdata;
964+
WIN32_FIND_DATAW findbuf = { 0 };
964965
wchar_t wfilename[MAX_LONG_PATH];
965966
int wlen = xutftowcs_long_path(wfilename, file_name);
966967
if (wlen < 0)
@@ -975,6 +976,13 @@ int mingw_lstat(const char *file_name, struct stat *buf)
975976
}
976977

977978
if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
979+
/* for reparse points, use FindFirstFile to get the reparse tag */
980+
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
981+
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
982+
if (handle == INVALID_HANDLE_VALUE)
983+
goto error;
984+
FindClose(handle);
985+
}
978986
buf->st_ino = 0;
979987
buf->st_gid = 0;
980988
buf->st_uid = 0;
@@ -987,20 +995,16 @@ int mingw_lstat(const char *file_name, struct stat *buf)
987995
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
988996
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
989997
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
990-
WIN32_FIND_DATAW findbuf;
991-
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
992-
if (handle != INVALID_HANDLE_VALUE) {
993998
if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
994999
(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
9951000
buf->st_mode = S_IFLNK | S_IREAD;
9961001
if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
9971002
buf->st_mode |= S_IWRITE;
9981003
}
999-
FindClose(handle);
1000-
}
10011004
}
10021005
return 0;
10031006
}
1007+
error:
10041008
switch (GetLastError()) {
10051009
case ERROR_ACCESS_DENIED:
10061010
case ERROR_SHARING_VIOLATION:

0 commit comments

Comments
 (0)