From: Joel Rosdahl Date: Thu, 26 May 2022 08:25:11 +0000 (+0200) Subject: fix: Fall back to copying temporary preprocessed output file X-Git-Tag: v4.7~219 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cbedccc9fa30f8958dc3e7fbdf900a952f63d5ad;p=thirdparty%2Fccache.git fix: Fall back to copying temporary preprocessed output file [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 --- diff --git a/src/Result.cpp b/src/Result.cpp index bc7c313d6..b272f33c3 100644 --- a/src/Result.cpp +++ b/src/Result.cpp @@ -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()); diff --git a/src/ResultRetriever.cpp b/src/ResultRetriever.cpp index c1c584ebc..430ff9667 100644 --- a/src/ResultRetriever.cpp +++ b/src/ResultRetriever.cpp @@ -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). diff --git a/src/Util.cpp b/src/Util.cpp index b94ee1a81..bb1f145b7 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -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 is_absolute_path_with_prefix(std::string_view path) { diff --git a/src/Util.hpp b/src/Util.hpp index bf5548440..4358fca5a 100644 --- a/src/Util.hpp +++ b/src/Util.hpp @@ -32,6 +32,7 @@ #include #include +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: diff --git a/src/ccache.cpp b/src/ccache.cpp index 2a57d2c94..bdc872902 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -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(