]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
fix: Fall back to copying temporary preprocessed output file
authorJoel Rosdahl <joel@rosdahl.net>
Thu, 26 May 2022 08:25:11 +0000 (10:25 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 26 May 2022 08:49:06 +0000 (10:49 +0200)
[1] added a suitable file extension to the temporary file used for
capturing the preprocessed output by creating a hard link. This fails
when the temporary directory is on a file system that doesn't support
hard links.

Fix this by falling back to copying when hard-linking fails.

Closes #1079.

[1]: 4da9f2b474b7ee39cd54ab4261f90936f3c944ec

src/Result.cpp
src/ResultRetriever.cpp
src/Util.cpp
src/Util.hpp
src/ccache.cpp

index bc7c313d6c21c5e8d85b5211da315faa0b0f5caa..b272f33c310dc188f9c992f9b9a275433b7528bc 100644 (file)
@@ -417,7 +417,7 @@ Result::Writer::write_raw_file_entry(const std::string& path,
   const auto raw_file = get_raw_file_path(m_result_path, entry_number);
   const auto old_stat = Stat::stat(raw_file);
   try {
-    Util::clone_hard_link_or_copy_file(m_ctx, path, raw_file, true);
+    Util::clone_hard_link_or_copy_file(m_ctx.config, path, raw_file, true);
   } catch (core::Error& e) {
     throw core::Error(
       "Failed to store {} as raw file {}: {}", path, raw_file, e.what());
index c1c584ebc815071cde11099407245b528127426c..430ff966711e80712243b4e12410f73d4fd096e0 100644 (file)
@@ -117,7 +117,8 @@ ResultRetriever::on_entry_start(uint8_t entry_number,
   } else if (dest_path == "/dev/null") {
     LOG_RAW("Not writing to /dev/null");
   } else if (raw_file) {
-    Util::clone_hard_link_or_copy_file(m_ctx, *raw_file, dest_path, false);
+    Util::clone_hard_link_or_copy_file(
+      m_ctx.config, *raw_file, dest_path, false);
 
     // Update modification timestamp to save the file from LRU cleanup (and, if
     // hard-linked, to make the object file newer than the source file).
index b94ee1a81b71bb252db9244be64d6629480981bb..bb1f145b78579006f64770944d4614a858f75649 100644 (file)
@@ -293,13 +293,14 @@ clone_file(const std::string& src, const std::string& dest, bool via_tmp_file)
 }
 #endif // FILE_CLONING_SUPPORTED
 
-void
-clone_hard_link_or_copy_file(const Context& ctx,
-                             const std::string& source,
+static void
+clone_hard_link_or_copy_file(const std::string& source,
                              const std::string& dest,
+                             bool try_clone,
+                             bool try_hard_link,
                              bool via_tmp_file)
 {
-  if (ctx.config.file_clone()) {
+  if (try_clone) {
 #ifdef FILE_CLONING_SUPPORTED
     LOG("Cloning {} to {}", source, dest);
     try {
@@ -312,7 +313,7 @@ clone_hard_link_or_copy_file(const Context& ctx,
     LOG("Not cloning {} to {} since it's unsupported", source, dest);
 #endif
   }
-  if (ctx.config.hard_link()) {
+  if (try_hard_link) {
     LOG("Hard linking {} to {}", source, dest);
     try {
       Util::hard_link(source, dest);
@@ -332,6 +333,16 @@ clone_hard_link_or_copy_file(const Context& ctx,
   copy_file(source, dest, via_tmp_file);
 }
 
+void
+clone_hard_link_or_copy_file(const Config& config,
+                             const std::string& source,
+                             const std::string& dest,
+                             bool via_tmp_file)
+{
+  clone_hard_link_or_copy_file(
+    source, dest, config.file_clone(), config.hard_link(), via_tmp_file);
+}
+
 size_t
 common_dir_prefix_length(std::string_view dir, std::string_view path)
 {
@@ -783,6 +794,12 @@ hard_link(const std::string& oldpath, const std::string& newpath)
 #endif
 }
 
+void
+hard_link_or_copy(const std::string& oldpath, const std::string& newpath)
+{
+  return clone_hard_link_or_copy_file(oldpath, newpath, false, true, false);
+}
+
 std::optional<size_t>
 is_absolute_path_with_prefix(std::string_view path)
 {
index bf55484409f83ffc573812fcf39da7119f649f9a..4358fca5a6337295fddf98c000e291f596593226 100644 (file)
@@ -32,6 +32,7 @@
 #include <utility>
 #include <vector>
 
+class Config;
 class Context;
 
 namespace Util {
@@ -97,7 +98,7 @@ void clone_file(const std::string& src,
 // Clone, hard link or copy a file from `source` to `dest` depending on settings
 // in `ctx`. If cloning or hard linking cannot and should not be done the file
 // will be copied instead. Throws `core::Error` on error.
-void clone_hard_link_or_copy_file(const Context& ctx,
+void clone_hard_link_or_copy_file(const Config& config,
                                   const std::string& source,
                                   const std::string& dest,
                                   bool via_tmp_file = false);
@@ -192,6 +193,10 @@ mode_t get_umask();
 // Hard-link `oldpath` to `newpath`. Throws `core::Error` on error.
 void hard_link(const std::string& oldpath, const std::string& newpath);
 
+// Hard-link `oldpath` to `newpath`, or fall back to copying if hard-linking
+// doesn't work. Throws `core::Error` on error.
+void hard_link_or_copy(const std::string& oldpath, const std::string& newpath);
+
 // Write bytes in big endian order from an integer value.
 //
 // Parameters:
index 2a57d2c944fdcfb4dc1d38a533c88c5caf13410e..bdc87290250fe78b48894f8243fe40d618bcda4f 100644 (file)
@@ -1125,7 +1125,7 @@ get_result_key_from_cpp(Context& ctx, Args& args, Hash& hash)
     // stdout_path needs the proper cpp_extension for the compiler to do its
     // thing correctly.
     stdout_path = FMT("{}.{}", tmp_stdout.path, ctx.config.cpp_extension());
-    Util::hard_link(tmp_stdout.path, stdout_path);
+    Util::hard_link_or_copy(tmp_stdout.path, stdout_path);
     ctx.register_pending_tmp_file(stdout_path);
 
     TemporaryFile tmp_stderr(