From: Anders Björklund Date: Fri, 4 Mar 2016 14:22:59 +0000 (+0100) Subject: Add compat version of GetFinalPathNameByHandle X-Git-Tag: v3.3~100 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a21da6fff6e7f796c42b1a6f784d42945395025b;p=thirdparty%2Fccache.git Add compat version of GetFinalPathNameByHandle --- diff --git a/configure.ac b/configure.ac index af56dca60..988ac315f 100644 --- a/configure.ac +++ b/configure.ac @@ -123,6 +123,7 @@ fi dnl Linking on Windows needs ws2_32 if test x${windows_os} = xyes; then LIBS="$LIBS -lws2_32" + AC_CHECK_FUNCS(GetFinalPathNameByHandleW,[],[LIBS="$LIBS -lpsapi"]) fi AC_C_BIGENDIAN diff --git a/util.c b/util.c index 73fb4d5a0..b0d4491a8 100644 --- a/util.c +++ b/util.c @@ -31,6 +31,8 @@ #ifdef _WIN32 #include #include +#include +#include #endif static FILE *logfile; @@ -1078,6 +1080,93 @@ parse_size_with_suffix(const char *str, uint64_t *size) } +#if defined(_WIN32) && !defined(HAVE_GETFINALPATHNAMEBYHANDLEW) +static BOOL GetFileNameFromHandle(HANDLE hFile, TCHAR *pszFilename, + WORD cchFilename) +{ + BOOL bSuccess = FALSE; + HANDLE hFileMap; + + // Get the file size. + DWORD dwFileSizeHi = 0; + DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi); + + if (dwFileSizeLo == 0 && dwFileSizeHi == 0) { + // Cannot map a file with a length of zero. + return FALSE; + } + + // Create a file mapping object. + hFileMap = CreateFileMapping(hFile, + NULL, + PAGE_READONLY, + 0, + 1, + NULL); + + if (hFileMap) { + // Create a file mapping to get the file name. + void *pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1); + + if (pMem) { + if (GetMappedFileName(GetCurrentProcess(), + pMem, + pszFilename, + cchFilename)) { + + // Translate path with device name to drive letters. + TCHAR szTemp[512]; + szTemp[0] = '\0'; + + if (GetLogicalDriveStrings(512-1, szTemp)) { + TCHAR szName[MAX_PATH]; + TCHAR szDrive[3] = TEXT(" :"); + BOOL bFound = FALSE; + TCHAR *p = szTemp; + + do + { + // Copy the drive letter to the template string + *szDrive = *p; + + // Look up each device name + if (QueryDosDevice(szDrive, szName, MAX_PATH)) { + size_t uNameLen = _tcslen(szName); + + if (uNameLen < MAX_PATH) { + bFound = _tcsnicmp(pszFilename, szName, uNameLen) == 0 + && *(pszFilename + uNameLen) == _T('\\'); + + if (bFound) { + // Reconstruct pszFilename using szTempFile + // Replace device path with DOS path + TCHAR szTempFile[MAX_PATH]; + _sntprintf(szTempFile, + MAX_PATH-1, + TEXT("%s%s"), + szDrive, + pszFilename+uNameLen); + _tcsncpy(pszFilename, szTempFile, + _tcslen(szTempFile)); + } + } + } + + // Go to the next NULL character. + while (*p++) ; + } while (!bFound && *p); // end of string + } + } + bSuccess = TRUE; + UnmapViewOfFile(pMem); + } + + CloseHandle(hFileMap); + } + return(bSuccess); +} +#endif + /* A sane realpath() function, trying to cope with stupid path limits and a * broken API. Caller frees. */ char * @@ -1100,7 +1189,11 @@ x_realpath(const char *path) path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE != path_handle) { +#ifdef HAVE_GETFINALPATHNAMEBYHANDLEW GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED); +#else + GetFileNameFromHandle(path_handle, ret, maxlen); +#endif CloseHandle(path_handle); p = ret + 4; /* strip \\?\ from the file name */ } else {