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);
}
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
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;
+}
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;
// 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 {
{
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 {
// 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);
#include <Context.hpp>
#include <File.hpp>
#include <Logging.hpp>
+#include <TemporaryFile.hpp>
#include <Util.hpp>
#include <core/CacheEntry.hpp>
#include <core/exceptions.hpp>
// 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;
}