From 823e1df54c34c7133c1e602c8d6ea3091e6d9682 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 4 Nov 2024 11:47:51 -0500 Subject: [PATCH 1/2] cmSystemTools: Implement GetRealPath on Windows Use `cm::PathResolver`'s `RealPath` variant to normalize paths, look up their on-disk case, and resolve symlinks, but without resolving `subst` drives on Windows. Fixes: #17206 --- Source/cmFileCommand.cxx | 4 +--- Source/cmSystemTools.cxx | 26 ++++++++++++++++++++++++-- Source/cmSystemTools.h | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 82847c438b..e6fe94b1ce 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1409,8 +1409,7 @@ bool HandleRealPathCommand(std::vector const& args, auto basePath = cmCMakePath{ *arguments.BaseDirectory }; path = basePath.Append(path); } - result = cmSystemTools::GetActualCaseForPath( - cmSystemTools::GetRealPath(path.String())); + result = cmSystemTools::GetRealPath(path.String()); }; std::string realPath; @@ -1420,7 +1419,6 @@ bool HandleRealPathCommand(std::vector const& args, std::string oldPolicyPath = cmSystemTools::CollapseFullPath(input, *arguments.BaseDirectory); oldPolicyPath = cmSystemTools::GetRealPath(oldPolicyPath); - oldPolicyPath = cmSystemTools::GetActualCaseForPath(oldPolicyPath); if (warnAbout152) { computeNewPath(input, realPath); if (oldPolicyPath != realPath) { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index ee8d95b049..9fa828408d 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1138,6 +1138,29 @@ std::string cmSystemTools::GetRealPathResolvingWindowsSubst( #endif } +std::string cmSystemTools::GetRealPath(const std::string& path, + std::string* errorMessage) +{ +#ifdef _WIN32 + std::string resolved_path; + using namespace cm::PathResolver; + // IWYU pragma: no_forward_declare cm::PathResolver::Policies::RealPath + static const Resolver resolver(RealOS); + cmsys::Status status = resolver.Resolve(path, resolved_path); + if (!status) { + if (errorMessage) { + *errorMessage = status.GetString(); + resolved_path.clear(); + } else { + resolved_path = path; + } + } + return resolved_path; +#else + return cmsys::SystemTools::GetRealPath(path, errorMessage); +#endif +} + void cmSystemTools::InitializeLibUV() { #if defined(_WIN32) @@ -2703,8 +2726,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0) wchar_t modulepath[_MAX_PATH]; ::GetModuleFileNameW(nullptr, modulepath, sizeof(modulepath)); std::string path = cmsys::Encoding::ToNarrow(modulepath); - std::string realPath = - cmSystemTools::GetRealPathResolvingWindowsSubst(path, nullptr); + std::string realPath = cmSystemTools::GetRealPath(path, nullptr); if (realPath.empty()) { realPath = path; } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 4d825845f8..a17dca83a7 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -610,6 +610,8 @@ public: resolve subst drives too. */ static std::string GetRealPathResolvingWindowsSubst( const std::string& path, std::string* errorMessage = nullptr); + static std::string GetRealPath(const std::string& path, + std::string* errorMessage = nullptr); /** Perform one-time initialization of libuv. */ static void InitializeLibUV(); From 16af27fd42a4242a12ea5a4321d82a17b0582026 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 4 Nov 2024 12:02:04 -0500 Subject: [PATCH 2/2] cmSystemTools: Drop GetRealPathResolvingWindowsSubst It was created by commit 83630d4918 (cmSystemTools: Revert GetRealPath implementation on Windows, 2018-05-29, v3.11.3~3^2) to preserve support on Windows for one call site. Now that `GetRealPath` works again on Windows, we can use that instead. Issue: #18033 --- Source/cmSystemTools.cxx | 37 ------------------------------------- Source/cmSystemTools.h | 6 +----- Source/cmTimestamp.cxx | 3 +-- 3 files changed, 2 insertions(+), 44 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9fa828408d..f322e6459a 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1101,43 +1101,6 @@ std::string cmSystemTools::GetComspec() #endif -std::string cmSystemTools::GetRealPathResolvingWindowsSubst( - const std::string& path, std::string* errorMessage) -{ -#ifdef _WIN32 - // 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(nullptr, &req, path.c_str(), nullptr); - 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 = nullptr; - DWORD size = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message, - 0, nullptr); - *errorMessage = std::string(message, size); - LocalFree(message); - - resolved_path = ""; - } else { - resolved_path = path; - } - return resolved_path; -#else - return cmsys::SystemTools::GetRealPath(path, errorMessage); -#endif -} - std::string cmSystemTools::GetRealPath(const std::string& path, std::string* errorMessage) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index a17dca83a7..4f62aee639 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -605,11 +605,7 @@ public: static std::string GetComspec(); #endif - /** Get the real path for a given path, removing all symlinks. - This variant of GetRealPath also works on Windows but will - resolve subst drives too. */ - static std::string GetRealPathResolvingWindowsSubst( - const std::string& path, std::string* errorMessage = nullptr); + /** Get the real path for a given path, removing all symlinks. */ static std::string GetRealPath(const std::string& path, std::string* errorMessage = nullptr); diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx index 4d8bc027d8..cb6eb6fbd0 100644 --- a/Source/cmTimestamp.cxx +++ b/Source/cmTimestamp.cxx @@ -62,8 +62,7 @@ std::string cmTimestamp::FileModificationTime(const char* path, const std::string& formatString, bool utcFlag) const { - std::string real_path = - cmSystemTools::GetRealPathResolvingWindowsSubst(path); + std::string real_path = cmSystemTools::GetRealPath(path); if (!cmsys::SystemTools::FileExists(real_path)) { return std::string();