From d41582fc94e823cbfbb214e08e73ad214619a71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20N=C3=BA=C3=B1ez?= Date: Wed, 30 Aug 2017 11:08:31 +0200 Subject: Call GetRealPath through cmSystemTools instead of KWSys directly This will allow a wrapper to be added to extend functionality. --- Source/cmFilePathChecksum.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx index f9afeef..f84360e 100644 --- a/Source/cmFilePathChecksum.cxx +++ b/Source/cmFilePathChecksum.cxx @@ -34,10 +34,10 @@ void cmFilePathChecksum::setupParentDirs(std::string const& currentSrcDir, std::string const& projectSrcDir, std::string const& projectBinDir) { - this->parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir); - this->parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir); - this->parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir); - this->parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir); + this->parentDirs[0].first = cmSystemTools::GetRealPath(currentSrcDir); + this->parentDirs[1].first = cmSystemTools::GetRealPath(currentBinDir); + this->parentDirs[2].first = cmSystemTools::GetRealPath(projectSrcDir); + this->parentDirs[3].first = cmSystemTools::GetRealPath(projectBinDir); this->parentDirs[0].second = "CurrentSource"; this->parentDirs[1].second = "CurrentBinary"; @@ -50,7 +50,7 @@ std::string cmFilePathChecksum::get(std::string const& filePath) const std::string relPath; std::string relSeed; { - std::string const fileReal = cmsys::SystemTools::GetRealPath(filePath); + std::string const fileReal = cmSystemTools::GetRealPath(filePath); std::string parentDir; // Find closest project parent directory for (auto const& pDir : this->parentDirs) { -- cgit v0.12 From 640709e7db054e90d5e6609eeb16a01af34b5a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20N=C3=BA=C3=B1ez?= Date: Mon, 2 Oct 2017 11:42:07 +0200 Subject: cmSystemTools: Implement GetRealPath on Windows Override the KWSys GetRealPath on Windows and use uv_fs_realpath first to resolve symbolic links. Fixes: #17206 --- Source/cmSystemTools.cxx | 35 +++++++++++++++++++++++++++++++++++ Source/cmSystemTools.h | 4 ++++ 2 files changed, 39 insertions(+) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 63c1452..5d1f5f7 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -50,6 +50,8 @@ #include // include wincrypt.h after windows.h #include + +#include "cm_uv.h" #else #include #include @@ -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) diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index e7082e6..2646df9 100644 --- a/Source/cmSystemTools.h +++ b/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; -- cgit v0.12 From 393e0fbe630a698d9c8c972059e5de1da727f76a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20N=C3=BA=C3=B1ez?= Date: Mon, 2 Oct 2017 11:42:19 +0200 Subject: cmTimestamp: For symlinks switch to timestamp of resolved path ModifiedTime uses stat on UNIX which does resolve symlinks, however Windows implementation relies on GetFileAttributesExW which does not. Getting real file path before calling ModifiedTime will not change UNIX semantic and will fix Windows behavior. Fixes: #17206 --- Source/cmTimestamp.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 9fb79d9..e747adb 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -33,11 +33,13 @@ std::string cmTimestamp::FileModificationTime(const char* path, const std::string& formatString, bool utcFlag) { - if (!cmsys::SystemTools::FileExists(path)) { + std::string real_path = cmSystemTools::GetRealPath(path); + + if (!cmsys::SystemTools::FileExists(real_path)) { return std::string(); } - time_t mtime = cmsys::SystemTools::ModifiedTime(path); + time_t mtime = cmsys::SystemTools::ModifiedTime(real_path); return CreateTimestampFromTimeT(mtime, formatString, utcFlag); } -- cgit v0.12