Browse Source

Merge branch 'upstream-KWSys' into file-copy-error-path

# By KWSys Upstream
* upstream-KWSys:
  KWSys 2022-11-15 (6c92b9b0)
Brad King 3 years ago
parent
commit
91dd7898ee
2 changed files with 66 additions and 38 deletions
  1. 32 28
      Source/kwsys/SystemTools.cxx
  2. 34 10
      Source/kwsys/SystemTools.hxx.in

+ 32 - 28
Source/kwsys/SystemTools.cxx

@@ -2290,8 +2290,8 @@ static std::string FileInDir(const std::string& source, const std::string& dir)
   return new_destination + '/' + SystemTools::GetFilenameName(source);
 }
 
-Status SystemTools::CopyFileIfDifferent(std::string const& source,
-                                        std::string const& destination)
+SystemTools::CopyStatus SystemTools::CopyFileIfDifferent(
+  std::string const& source, std::string const& destination)
 {
   // special check for a destination that is a directory
   // FilesDiffer does not handle file to directory compare
@@ -2308,7 +2308,7 @@ Status SystemTools::CopyFileIfDifferent(std::string const& source,
     }
   }
   // at this point the files must be the same so return true
-  return Status::Success();
+  return CopyStatus{ Status::Success(), CopyStatus::NoPath };
 }
 
 #define KWSYS_ST_BUFFER 4096
@@ -2434,13 +2434,13 @@ bool SystemTools::TextFilesDiffer(const std::string& path1,
   return false;
 }
 
-Status SystemTools::CopyFileContentBlockwise(std::string const& source,
-                                             std::string const& destination)
+SystemTools::CopyStatus SystemTools::CopyFileContentBlockwise(
+  std::string const& source, std::string const& destination)
 {
   // Open files
   kwsys::ifstream fin(source.c_str(), std::ios::in | std::ios::binary);
   if (!fin) {
-    return Status::POSIX_errno();
+    return CopyStatus{ Status::POSIX_errno(), CopyStatus::SourcePath };
   }
 
   // try and remove the destination file so that read only destination files
@@ -2452,7 +2452,7 @@ Status SystemTools::CopyFileContentBlockwise(std::string const& source,
   kwsys::ofstream fout(destination.c_str(),
                        std::ios::out | std::ios::trunc | std::ios::binary);
   if (!fout) {
-    return Status::POSIX_errno();
+    return CopyStatus{ Status::POSIX_errno(), CopyStatus::DestPath };
   }
 
   // This copy loop is very sensitive on certain platforms with
@@ -2481,10 +2481,10 @@ Status SystemTools::CopyFileContentBlockwise(std::string const& source,
   fout.close();
 
   if (!fout) {
-    return Status::POSIX_errno();
+    return CopyStatus{ Status::POSIX_errno(), CopyStatus::DestPath };
   }
 
-  return Status::Success();
+  return CopyStatus{ Status::Success(), CopyStatus::NoPath };
 }
 
 /**
@@ -2499,13 +2499,13 @@ Status SystemTools::CopyFileContentBlockwise(std::string const& source,
  * - The underlying filesystem does not support file cloning
  * - An unspecified error occurred
  */
-Status SystemTools::CloneFileContent(std::string const& source,
-                                     std::string const& destination)
+SystemTools::CopyStatus SystemTools::CloneFileContent(
+  std::string const& source, std::string const& destination)
 {
 #if defined(__linux) && defined(FICLONE)
   int in = open(source.c_str(), O_RDONLY);
   if (in < 0) {
-    return Status::POSIX_errno();
+    return CopyStatus{ Status::POSIX_errno(), CopyStatus::SourcePath };
   }
 
   SystemTools::RemoveFile(destination);
@@ -2513,14 +2513,14 @@ Status SystemTools::CloneFileContent(std::string const& source,
   int out =
     open(destination.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
   if (out < 0) {
-    Status status = Status::POSIX_errno();
+    CopyStatus status{ Status::POSIX_errno(), CopyStatus::DestPath };
     close(in);
     return status;
   }
 
-  Status status = Status::Success();
+  CopyStatus status{ Status::Success(), CopyStatus::NoPath };
   if (ioctl(out, FICLONE, in) < 0) {
-    status = Status::POSIX_errno();
+    status = CopyStatus{ Status::POSIX_errno(), CopyStatus::NoPath };
   }
   close(in);
   close(out);
@@ -2532,40 +2532,41 @@ Status SystemTools::CloneFileContent(std::string const& source,
   // be updated by `copy_file_if_different` and `copy_file`.
   if (copyfile(source.c_str(), destination.c_str(), nullptr,
                COPYFILE_METADATA | COPYFILE_CLONE) < 0) {
-    return Status::POSIX_errno();
+    return CopyStatus{ Status::POSIX_errno(), CopyStatus::NoPath };
   }
 #  if KWSYS_CXX_HAS_UTIMENSAT
   // utimensat is only available on newer Unixes and macOS 10.13+
   if (utimensat(AT_FDCWD, destination.c_str(), nullptr, 0) < 0) {
-    return Status::POSIX_errno();
+    return CopyStatus{ Status::POSIX_errno(), CopyStatus::DestPath };
   }
 #  else
   // fall back to utimes
   if (utimes(destination.c_str(), nullptr) < 0) {
-    return Status::POSIX_errno();
+    return CopyStatus{ Status::POSIX_errno(), CopyStatus::DestPath };
   }
 #  endif
-  return Status::Success();
+  return CopyStatus{ Status::Success(), CopyStatus::NoPath };
 #else
   (void)source;
   (void)destination;
-  return Status::POSIX(ENOSYS);
+  return CopyStatus{ Status::POSIX(ENOSYS), CopyStatus::NoPath };
 #endif
 }
 
 /**
  * Copy a file named by "source" to the file named by "destination".
  */
-Status SystemTools::CopyFileAlways(std::string const& source,
-                                   std::string const& destination)
+SystemTools::CopyStatus SystemTools::CopyFileAlways(
+  std::string const& source, std::string const& destination)
 {
-  Status status;
+  CopyStatus status;
   mode_t perm = 0;
   Status perms = SystemTools::GetPermissions(source, perm);
   std::string real_destination = destination;
 
   if (SystemTools::FileIsDirectory(source)) {
-    status = SystemTools::MakeDirectory(destination);
+    status = CopyStatus{ SystemTools::MakeDirectory(destination),
+                         CopyStatus::DestPath };
     if (!status.IsSuccess()) {
       return status;
     }
@@ -2590,7 +2591,8 @@ Status SystemTools::CopyFileAlways(std::string const& source,
 
     // Create destination directory
     if (!destination_dir.empty()) {
-      status = SystemTools::MakeDirectory(destination_dir);
+      status = CopyStatus{ SystemTools::MakeDirectory(destination_dir),
+                           CopyStatus::DestPath };
       if (!status.IsSuccess()) {
         return status;
       }
@@ -2606,13 +2608,15 @@ Status SystemTools::CopyFileAlways(std::string const& source,
     }
   }
   if (perms) {
-    status = SystemTools::SetPermissions(real_destination, perm);
+    status = CopyStatus{ SystemTools::SetPermissions(real_destination, perm),
+                         CopyStatus::DestPath };
   }
   return status;
 }
 
-Status SystemTools::CopyAFile(std::string const& source,
-                              std::string const& destination, bool always)
+SystemTools::CopyStatus SystemTools::CopyAFile(std::string const& source,
+                                               std::string const& destination,
+                                               bool always)
 {
   if (always) {
     return SystemTools::CopyFileAlways(source, destination);

+ 34 - 10
Source/kwsys/SystemTools.hxx.in

@@ -565,12 +565,35 @@ public:
   static Status MakeDirectory(std::string const& path,
                               const mode_t* mode = nullptr);
 
+  /**
+   * Represent the result of a file copy operation.
+   * This is the result 'Status' and, if the operation failed,
+   * an indication of whether the error occurred on the source
+   * or destination path.
+   */
+  struct CopyStatus : public Status
+  {
+    enum WhichPath
+    {
+      NoPath,
+      SourcePath,
+      DestPath,
+    };
+    CopyStatus() = default;
+    CopyStatus(Status s, WhichPath p)
+      : Status(s)
+      , Path(p)
+    {
+    }
+    WhichPath Path = NoPath;
+  };
+
   /**
    * Copy the source file to the destination file only
    * if the two files differ.
    */
-  static Status CopyFileIfDifferent(std::string const& source,
-                                    std::string const& destination);
+  static CopyStatus CopyFileIfDifferent(std::string const& source,
+                                        std::string const& destination);
 
   /**
    * Compare the contents of two files.  Return true if different
@@ -588,13 +611,13 @@ public:
   /**
    * Blockwise copy source to destination file
    */
-  static Status CopyFileContentBlockwise(std::string const& source,
-                                         std::string const& destination);
+  static CopyStatus CopyFileContentBlockwise(std::string const& source,
+                                             std::string const& destination);
   /**
    * Clone the source file to the destination file
    */
-  static Status CloneFileContent(std::string const& source,
-                                 std::string const& destination);
+  static CopyStatus CloneFileContent(std::string const& source,
+                                     std::string const& destination);
 
   /**
    * Return true if the two files are the same file
@@ -604,16 +627,17 @@ public:
   /**
    * Copy a file.
    */
-  static Status CopyFileAlways(std::string const& source,
-                               std::string const& destination);
+  static CopyStatus CopyFileAlways(std::string const& source,
+                                   std::string const& destination);
 
   /**
    * Copy a file.  If the "always" argument is true the file is always
    * copied.  If it is false, the file is copied only if it is new or
    * has changed.
    */
-  static Status CopyAFile(std::string const& source,
-                          std::string const& destination, bool always = true);
+  static CopyStatus CopyAFile(std::string const& source,
+                              std::string const& destination,
+                              bool always = true);
 
   /**
    * Copy content directory to another directory with all files and