summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/cmSystemTools.cxx43
-rw-r--r--Source/cmSystemTools.h8
2 files changed, 48 insertions, 3 deletions
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 0807590770..eb0271222a 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -149,6 +149,27 @@ static int cm_archive_read_open_file(struct archive* a, const char* file,
# define environ (*_NSGetEnviron())
#endif
+namespace {
+void ReportError(std::string* err)
+{
+ if (!err) {
+ return;
+ }
+#ifdef _WIN32
+ LPSTR message = NULL;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&message, 0, NULL);
+ *err = std::string(message, size);
+ LocalFree(message);
+#else
+ *err = strerror(errno);
+#endif
+}
+}
+
bool cmSystemTools::s_RunCommandHideConsole = false;
bool cmSystemTools::s_DisableRunCommandOutput = false;
bool cmSystemTools::s_ErrorOccured = false;
@@ -967,6 +988,13 @@ bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname)
bool cmSystemTools::RenameFile(const std::string& oldname,
const std::string& newname)
{
+ return cmSystemTools::RenameFile(oldname, newname, nullptr) ==
+ RenameResult::Success;
+}
+
+cmSystemTools::RenameResult cmSystemTools::RenameFile(
+ std::string const& oldname, std::string const& newname, std::string* err)
+{
#ifdef _WIN32
# ifndef INVALID_FILE_ATTRIBUTES
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
@@ -1004,7 +1032,8 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
// 3) Windows Explorer has an associated directory already opened.
if (move_last_error != ERROR_ACCESS_DENIED &&
move_last_error != ERROR_SHARING_VIOLATION) {
- return false;
+ ReportError(err);
+ return RenameResult::Failure;
}
DWORD const attrs = GetFileAttributesW(newname_wstr.c_str());
@@ -1028,10 +1057,18 @@ bool cmSystemTools::RenameFile(const std::string& oldname,
save_restore_file_attributes.SetPath(newname_wstr);
}
SetLastError(move_last_error);
- return retry.Count > 0;
+ if (retry.Count > 0) {
+ return RenameResult::Success;
+ }
+ ReportError(err);
+ return RenameResult::Failure;
#else
/* On UNIX we have an OS-provided call to do this atomically. */
- return rename(oldname.c_str(), newname.c_str()) == 0;
+ if (rename(oldname.c_str(), newname.c_str()) == 0) {
+ return RenameResult::Success;
+ }
+ ReportError(err);
+ return RenameResult::Failure;
#endif
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 5bbbb0c7b6..bb9013508e 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -128,10 +128,18 @@ public:
static bool SimpleGlob(const std::string& glob,
std::vector<std::string>& files, int type = 0);
+ enum class RenameResult
+ {
+ Success,
+ Failure,
+ };
+
/** Rename a file or directory within a single disk volume (atomic
if possible). */
static bool RenameFile(const std::string& oldname,
const std::string& newname);
+ static RenameResult RenameFile(std::string const& oldname,
+ std::string const& newname, std::string* err);
//! Rename a file if contents are different, delete the source otherwise
static void MoveFileIfDifferent(const std::string& source,