From: Joel Rosdahl Date: Mon, 12 Sep 2022 11:25:45 +0000 (+0200) Subject: fix: Make sure that temporary files always have .tmp. in the name X-Git-Tag: v4.7~56 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=60fe1672d9e36f4334d39d0c606dd07d401e1fa1;p=thirdparty%2Fccache.git fix: Make sure that temporary files always have .tmp. in the name PrimaryStorage::clean_dir relies on being able to classify temporary files from the filename. --- diff --git a/src/AtomicFile.cpp b/src/AtomicFile.cpp index ec5fead6e..c9d82c3e2 100644 --- a/src/AtomicFile.cpp +++ b/src/AtomicFile.cpp @@ -27,7 +27,7 @@ AtomicFile::AtomicFile(const std::string& path, Mode mode) : m_path(path) { - TemporaryFile tmp_file(path + ".tmp"); + TemporaryFile tmp_file(path); m_stream = fdopen(tmp_file.fd.release(), mode == Mode::binary ? "w+b" : "w+"); m_tmp_path = std::move(tmp_file.path); } diff --git a/src/TemporaryFile.cpp b/src/TemporaryFile.cpp index 0d7e80bfb..257481234 100644 --- a/src/TemporaryFile.cpp +++ b/src/TemporaryFile.cpp @@ -35,7 +35,7 @@ TemporaryFile::TemporaryFile(std::string_view path_prefix, std::string_view suffix) - : path(FMT("{}.XXXXXX{}", path_prefix, suffix)) + : path(FMT("{}{}XXXXXX{}", path_prefix, tmp_file_infix, suffix)) { Util::ensure_dir_exists(Util::dir_name(path)); #ifdef _WIN32 @@ -59,3 +59,9 @@ TemporaryFile::TemporaryFile(std::string_view path_prefix, fchmod(*fd, 0666 & ~Util::get_umask()); #endif } + +bool +TemporaryFile::is_tmp_file(std::string_view path) +{ + return Util::base_name(path).find(tmp_file_infix) != std::string::npos; +} diff --git a/src/TemporaryFile.hpp b/src/TemporaryFile.hpp index 29d8597e3..b773c0a4b 100644 --- a/src/TemporaryFile.hpp +++ b/src/TemporaryFile.hpp @@ -28,15 +28,19 @@ class TemporaryFile { public: + static constexpr char tmp_file_infix[] = ".tmp."; + // `path_prefix` is the base path. The resulting filename will be this path - // plus a unique string plus `suffix`. If `path_prefix` refers to a - // nonexistent directory the directory will be created if possible.` - TemporaryFile(std::string_view path_prefix, std::string_view suffix = {}); + // plus a unique string plus `suffix`. If `path_prefix` refers to a + // nonexistent directory the directory will be created if possible. + TemporaryFile(std::string_view path_prefix, std::string_view suffix = ".tmp"); TemporaryFile(TemporaryFile&& other) noexcept = default; TemporaryFile& operator=(TemporaryFile&& other) noexcept = default; + static bool is_tmp_file(std::string_view path); + // The resulting open file descriptor in read/write mode. Unset on error. Fd fd; diff --git a/src/Util.cpp b/src/Util.cpp index 179bbc7f6..8b0b6e0ec 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -1315,7 +1315,8 @@ unlink_safe(const std::string& path, UnlinkLog unlink_log) // If path is on an NFS share, unlink isn't atomic, so we rename to a temp // file. We don't care if the temp file is trashed, so it's always safe to // unlink it first. - std::string tmp_name = path + ".ccache.rm.tmp"; + const std::string tmp_name = + FMT("{}.ccache{}unlink", path, TemporaryFile::tmp_file_infix); bool success = true; try { diff --git a/src/ccache.cpp b/src/ccache.cpp index 0d1c4b027..4a10147e3 100644 --- a/src/ccache.cpp +++ b/src/ccache.cpp @@ -679,7 +679,7 @@ get_tmp_fd(Context& ctx, { if (capture_output) { TemporaryFile tmp_stdout( - FMT("{}/tmp.{}", ctx.config.temporary_dir(), description)); + FMT("{}/{}", ctx.config.temporary_dir(), description)); ctx.register_pending_tmp_file(tmp_stdout.path); return {std::move(tmp_stdout.fd), std::move(tmp_stdout.path)}; } else { @@ -1158,9 +1158,8 @@ get_result_key_from_cpp(Context& ctx, Args& args, Hash& hash) // preprocessed_path needs the proper cpp_extension for the compiler to do // its thing correctly. - TemporaryFile tmp_stdout( - FMT("{}/tmp.cpp_stdout", ctx.config.temporary_dir()), - FMT(".{}", ctx.config.cpp_extension())); + TemporaryFile tmp_stdout(FMT("{}/cpp_stdout", ctx.config.temporary_dir()), + FMT(".{}", ctx.config.cpp_extension())); preprocessed_path = tmp_stdout.path; tmp_stdout.fd.close(); // We're only using the path. ctx.register_pending_tmp_file(preprocessed_path); diff --git a/src/storage/primary/PrimaryStorage_cleanup.cpp b/src/storage/primary/PrimaryStorage_cleanup.cpp index d3a0b1b93..6165c724d 100644 --- a/src/storage/primary/PrimaryStorage_cleanup.cpp +++ b/src/storage/primary/PrimaryStorage_cleanup.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -124,7 +125,7 @@ PrimaryStorage::clean_dir(const std::string& subdir, // Delete any tmp files older than 1 hour right away. if (file.lstat().mtime() + 3600 < current_time - && Util::base_name(file.path()).find(".tmp.") != std::string::npos) { + && TemporaryFile::is_tmp_file(file.path())) { Util::unlink_tmp(file.path()); continue; }