Răsfoiți Sursa

cmSystemTools: Implement GetRealPath on Windows

Override the KWSys GetRealPath on Windows and use uv_fs_realpath first
to resolve symbolic links.

Fixes: #17206
Manuel Núñez 8 ani în urmă
părinte
comite
640709e7db
2 a modificat fișierele cu 39 adăugiri și 0 ștergeri
  1. 35 0
      Source/cmSystemTools.cxx
  2. 4 0
      Source/cmSystemTools.h

+ 35 - 0
Source/cmSystemTools.cxx

@@ -50,6 +50,8 @@
 #include <windows.h>
 // include wincrypt.h after windows.h
 #include <wincrypt.h>
+
+#include "cm_uv.h"
 #else
 #include <sys/time.h>
 #include <unistd.h>
@@ -943,6 +945,39 @@ cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry()
   }
   return retry;
 }
+
+std::string cmSystemTools::GetRealPath(const std::string& path,
+                                       std::string* errorMessage)
+{
+  // uv_fs_realpath uses Windows Vista API so fallback to kwsys if not found
+  std::string resolved_path;
+  uv_fs_t req;
+  int err = uv_fs_realpath(NULL, &req, path.c_str(), NULL);
+  if (!err) {
+    resolved_path = std::string((char*)req.ptr);
+    cmSystemTools::ConvertToUnixSlashes(resolved_path);
+    // Normalize to upper-case drive letter as GetActualCaseForPath does.
+    if (resolved_path.size() > 1 && resolved_path[1] == ':') {
+      resolved_path[0] = toupper(resolved_path[0]);
+    }
+  } else if (err == UV_ENOSYS) {
+    resolved_path = cmsys::SystemTools::GetRealPath(path, errorMessage);
+  } else if (errorMessage) {
+    LPSTR message = NULL;
+    DWORD size = FormatMessageA(
+      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+        FORMAT_MESSAGE_IGNORE_INSERTS,
+      NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message, 0,
+      NULL);
+    *errorMessage = std::string(message, size);
+    LocalFree(message);
+
+    resolved_path = "";
+  } else {
+    resolved_path = path;
+  }
+  return resolved_path;
+}
 #endif
 
 bool cmSystemTools::RenameFile(const char* oldname, const char* newname)

+ 4 - 0
Source/cmSystemTools.h

@@ -497,6 +497,10 @@ public:
     unsigned int Delay;
   };
   static WindowsFileRetry GetWindowsFileRetry();
+
+  /** Get the real path for a given path, removing all symlinks. */
+  static std::string GetRealPath(const std::string& path,
+                                 std::string* errorMessage = 0);
 #endif
 private:
   static bool s_ForceUnixPaths;