]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add compat version of GetFinalPathNameByHandle 73/head
authorAnders Björklund <anders@itension.se>
Fri, 4 Mar 2016 14:22:59 +0000 (15:22 +0100)
committerAnders Björklund <anders@itension.se>
Fri, 4 Mar 2016 14:38:06 +0000 (15:38 +0100)
configure.ac
util.c

index af56dca60cee5c771729b1b641fe655f35c30080..988ac315ff4f46c2e3cd60a3572fc1f2081cd0df 100644 (file)
@@ -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 73fb4d5a07d4abfef3285d8cf5b1ccf0fe8da310..b0d4491a8d049ac29215e8f078426687cb0ae848 100644 (file)
--- a/util.c
+++ b/util.c
@@ -31,6 +31,8 @@
 #ifdef _WIN32
 #include <windows.h>
 #include <sys/locking.h>
+#include <psapi.h>
+#include <tchar.h>
 #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 {