Преглед изворни кода

cmSystemTools: Add RenameFile signature to capture the error message

Brad King пре 4 година
родитељ
комит
0c2dc34504
2 измењених фајлова са 48 додато и 3 уклоњено
  1. 40 3
      Source/cmSystemTools.cxx
  2. 8 0
      Source/cmSystemTools.h

+ 40 - 3
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;
@@ -966,6 +987,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
@@ -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
 }
 

+ 8 - 0
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,