]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Introduce and use TemporaryFile class
authorJoel Rosdahl <joel@rosdahl.net>
Sat, 25 Jul 2020 13:56:29 +0000 (15:56 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 25 Jul 2020 14:04:39 +0000 (16:04 +0200)
In addition to improving code clarity, this fixes a bug where the
fallback code for “-fdiagnostics-color” tried to operate on a closed
file descriptor.

src/AtomicFile.cpp
src/CMakeLists.txt
src/InodeCache.cpp
src/MiniTrace.cpp
src/TemporaryFile.cpp [new file with mode: 0644]
src/TemporaryFile.hpp [new file with mode: 0644]
src/ccache.cpp
src/execute.cpp
src/execute.hpp
src/legacy_util.cpp

index ca998189169843ff581aff25a176613ae4191e93..795c45fb42f2c6099c45700f928130af27f5a458 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "AtomicFile.hpp"
 
+#include "TemporaryFile.hpp"
 #include "Util.hpp"
 #include "exceptions.hpp"
 
@@ -25,9 +26,9 @@
 
 AtomicFile::AtomicFile(const std::string& path, Mode mode) : m_path(path)
 {
-  auto fd_and_path = Util::create_temp_fd(path + ".tmp");
-  m_stream = fdopen(fd_and_path.first, mode == Mode::binary ? "w+b" : "w+");
-  m_tmp_path = std::move(fd_and_path.second);
+  TemporaryFile tmp_file(path + ".tmp");
+  m_stream = fdopen(tmp_file.fd.release(), mode == Mode::binary ? "w+b" : "w+");
+  m_tmp_path = std::move(tmp_file.path);
 }
 
 AtomicFile::~AtomicFile()
index 1d3d25ed67c51290a4dc0f213a614f4cab923e5d..2a24a208330f37fde359f77487f68e8607068e3a 100644 (file)
@@ -23,6 +23,7 @@ set(
   ResultRetriever.cpp
   SignalHandler.cpp
   Stat.cpp
+  TemporaryFile.cpp
   ThreadPool.cpp
   Util.cpp
   ZstdCompressor.cpp
index adac7cac6701368df11944a4545d85802ea0a182..a8a9c9d663ce8393409ce3fa0b1a6d295bddeb8a 100644 (file)
@@ -23,6 +23,7 @@
 #include "Finalizer.hpp"
 #include "Hash.hpp"
 #include "Stat.hpp"
+#include "TemporaryFile.hpp"
 #include "Util.hpp"
 #include "ccache.hpp"
 #include "logging.hpp"
@@ -255,21 +256,19 @@ InodeCache::create_new_file(const std::string& filename)
 
   // Create the new file to a temporary name to prevent other processes from
   // mapping it before it is fully initialized.
-  auto temp_fd_and_path = Util::create_temp_fd(filename);
-  const auto& temp_path = temp_fd_and_path.second;
+  TemporaryFile tmp_file(filename);
 
-  Fd temp_fd(temp_fd_and_path.first);
-  Finalizer temp_file_remover([=] { unlink(temp_path.c_str()); });
+  Finalizer temp_file_remover([&] { unlink(tmp_file.path.c_str()); });
 
   bool is_nfs;
-  if (Util::is_nfs_fd(*temp_fd, &is_nfs) == 0 && is_nfs) {
+  if (Util::is_nfs_fd(*tmp_file.fd, &is_nfs) == 0 && is_nfs) {
     cc_log(
       "Inode cache not supported because the cache file would be located on"
       " nfs: %s",
       filename.c_str());
     return false;
   }
-  int err = Util::fallocate(*temp_fd, sizeof(SharedRegion));
+  int err = Util::fallocate(*tmp_file.fd, sizeof(SharedRegion));
   if (err) {
     cc_log("Failed to allocate file space for inode cache: %s", strerror(err));
     return false;
@@ -279,7 +278,7 @@ InodeCache::create_new_file(const std::string& filename)
                                          sizeof(SharedRegion),
                                          PROT_READ | PROT_WRITE,
                                          MAP_SHARED,
-                                         *temp_fd,
+                                         *tmp_file.fd,
                                          0));
   if (sr == reinterpret_cast<void*>(-1)) {
     cc_log("Failed to mmap new inode cache: %s", strerror(errno));
@@ -299,14 +298,14 @@ InodeCache::create_new_file(const std::string& filename)
   }
 
   munmap(sr, sizeof(SharedRegion));
-  temp_fd.close();
+  tmp_file.fd.close();
 
   // link() will fail silently if a file with the same name already exists.
   // This will be the case if two processes try to create a new file
   // simultaneously. Thus close the current file handle and reopen a new one,
   // which will make us use the first created file even if we didn't win the
   // race.
-  if (link(temp_path.c_str(), filename.c_str()) != 0) {
+  if (link(tmp_file.path.c_str(), filename.c_str()) != 0) {
     cc_log("Failed to link new inode cache: %s", strerror(errno));
     return false;
   }
index 90caad30667cb1d268cb5b1e63306b5c3e25ddc5..f82b27e100aa3770120ffded63e0b63a013409cc 100644 (file)
@@ -22,6 +22,7 @@
 
 #  include "ArgsInfo.hpp"
 #  include "MiniTrace.hpp"
+#  include "TemporaryFile.hpp"
 #  include "Util.hpp"
 #  include "legacy_util.hpp"
 
@@ -49,10 +50,8 @@ get_system_tmp_dir()
 MiniTrace::MiniTrace(const ArgsInfo& args_info)
   : m_args_info(args_info), m_trace_id(reinterpret_cast<void*>(getpid()))
 {
-  auto fd_and_path =
-    Util::create_temp_fd(get_system_tmp_dir() + "/ccache-trace");
-  m_tmp_trace_file = fd_and_path.second;
-  close(fd_and_path.first);
+  TemporaryFile tmp_file(get_system_tmp_dir() + "/ccache-trace");
+  m_tmp_trace_file = tmp_file.path;
 
   mtr_init(m_tmp_trace_file.c_str());
   MTR_INSTANT_C("", "", "time", fmt::format("{:f}", time_seconds()).c_str());
diff --git a/src/TemporaryFile.cpp b/src/TemporaryFile.cpp
new file mode 100644 (file)
index 0000000..f91f3b9
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright (C) 2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "TemporaryFile.hpp"
+
+#include "Util.hpp"
+#include "legacy_util.hpp"
+
+using nonstd::string_view;
+
+namespace {
+
+#ifndef _WIN32
+mode_t
+get_umask()
+{
+  static bool mask_retrieved = false;
+  static mode_t mask;
+  if (!mask_retrieved) {
+    mask = umask(0);
+    umask(mask);
+    mask_retrieved = true;
+  }
+  return mask;
+}
+#endif
+
+#ifndef HAVE_MKSTEMP
+// Cheap and nasty mkstemp replacement.
+int
+mkstemp(char* name_template)
+{
+#  ifdef __GNUC__
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#  endif
+  mktemp(name_template);
+#  ifdef __GNUC__
+#    pragma GCC diagnostic pop
+#  endif
+  return open(name_template, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
+}
+#endif
+
+} // namespace
+
+TemporaryFile::TemporaryFile(string_view path_prefix)
+{
+  if (!initialize(path_prefix) && errno == ENOENT) {
+    auto dir = Util::dir_name(path);
+    if (!Util::create_dir(dir)) {
+      fatal("Failed to create directory %s: %s",
+            std::string(dir).c_str(),
+            strerror(errno));
+    }
+    initialize(path_prefix);
+  }
+  if (!fd) {
+    fatal("Failed to create temporary file for %s: %s",
+          path.c_str(),
+          strerror(errno));
+  }
+
+  set_cloexec_flag(*fd);
+#ifndef _WIN32
+  fchmod(*fd, 0666 & ~get_umask());
+#endif
+}
+
+bool
+TemporaryFile::initialize(string_view path_prefix)
+{
+  path = std::string(path_prefix);
+  path += ".XXXXXX";
+  fd = Fd(mkstemp(const_cast<char*>(path.data()))); // cast needed before C++17
+  return bool(fd);
+}
diff --git a/src/TemporaryFile.hpp b/src/TemporaryFile.hpp
new file mode 100644 (file)
index 0000000..dc64f8b
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#pragma once
+
+#include "Fd.hpp"
+#include "NonCopyable.hpp"
+
+#include "third_party/nonstd/string_view.hpp"
+
+// This class represents a unique temporary file created by mkstemp. The file is
+// not deleted by the destructor.
+class TemporaryFile : NonCopyable
+{
+public:
+  // `path_prefix` is the base path. The resulting filename will be this path
+  //  plus a unique suffix. If `path_prefix` refers to a nonexistent directory
+  //  the directory will be created if possible.`
+  TemporaryFile(nonstd::string_view path_prefix);
+
+  TemporaryFile(TemporaryFile&& other) = default;
+
+  TemporaryFile& operator=(TemporaryFile&& other) = default;
+
+  // The resulting open file descriptor in read/write mode. Unset on error.
+  Fd fd;
+
+  // The actual filename. Empty on error.
+  std::string path;
+
+private:
+  bool initialize(nonstd::string_view path_prefix);
+};
index 9c5d56ef8d4a4234c3f086798d7badb4d1ac442f..70d0eaa51df817ddc5997ecabb69e1ac3ea2c671 100644 (file)
@@ -34,6 +34,7 @@
 #include "ResultRetriever.hpp"
 #include "SignalHandler.hpp"
 #include "StdMakeUnique.hpp"
+#include "TemporaryFile.hpp"
 #include "Util.hpp"
 #include "argprocessing.hpp"
 #include "cleanup.hpp"
@@ -622,8 +623,7 @@ use_relative_paths_in_depfile(const Context& ctx)
     return;
   }
 
-  std::string tmp_file = fmt::format("{}.tmp{}", output_dep, tmp_string());
-
+  std::string tmp_file = output_dep + ".tmp";
   try {
     Util::write_file(tmp_file, adjusted_file_content);
   } catch (const Error& e) {
@@ -696,38 +696,48 @@ result_name_from_depfile(Context& ctx, Hash& hash)
 // Execute the compiler/preprocessor, with logic to retry without requesting
 // colored diagnostics messages if that fails.
 static int
-execute(Context& ctx,
-        Args& args,
-        const std::string& stdout_path,
-        int stdout_fd,
-        const std::string& stderr_path,
-        int stderr_fd)
+do_execute(Context& ctx,
+           Args& args,
+           TemporaryFile&& tmp_stdout,
+           TemporaryFile&& tmp_stderr)
 {
   if (ctx.diagnostics_color_failed
       && ctx.guessed_compiler == GuessedCompiler::gcc) {
     args.erase_with_prefix("-fdiagnostics-color");
   }
-  int status =
-    execute(args.to_argv().data(), stdout_fd, stderr_fd, &ctx.compiler_pid);
+  int status = execute(args.to_argv().data(),
+                       std::move(tmp_stdout.fd),
+                       std::move(tmp_stderr.fd),
+                       &ctx.compiler_pid);
   if (status != 0 && !ctx.diagnostics_color_failed
       && ctx.guessed_compiler == GuessedCompiler::gcc) {
-    auto errors = Util::read_file(stderr_path);
+    auto errors = Util::read_file(tmp_stderr.path);
     if (errors.find("unrecognized command line option") != std::string::npos
         && errors.find("-fdiagnostics-color") != std::string::npos) {
-      // Old versions of GCC did not support colored diagnostics.
+      // Old versions of GCC do not support colored diagnostics.
       cc_log("-fdiagnostics-color is unsupported; trying again without it");
-      if (ftruncate(stdout_fd, 0) < 0 || lseek(stdout_fd, 0, SEEK_SET) < 0) {
-        cc_log(
-          "Failed to truncate %s: %s", stdout_path.c_str(), strerror(errno));
+
+      tmp_stdout.fd = Fd(open(
+        tmp_stdout.path.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600));
+      if (!tmp_stdout.fd) {
+        cc_log("Failed to truncate %s: %s",
+               tmp_stdout.path.c_str(),
+               strerror(errno));
         failed(STATS_ERROR);
       }
-      if (ftruncate(stderr_fd, 0) < 0 || lseek(stderr_fd, 0, SEEK_SET) < 0) {
-        cc_log(
-          "Failed to truncate %s: %s", stderr_path.c_str(), strerror(errno));
+
+      tmp_stderr.fd = Fd(open(
+        tmp_stderr.path.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600));
+      if (!tmp_stderr.fd) {
+        cc_log("Failed to truncate %s: %s",
+               tmp_stderr.path.c_str(),
+               strerror(errno));
         failed(STATS_ERROR);
       }
+
       ctx.diagnostics_color_failed = true;
-      return execute(ctx, args, stdout_path, stdout_fd, stderr_path, stderr_fd);
+      return do_execute(
+        ctx, args, std::move(tmp_stdout), std::move(tmp_stderr));
     }
   }
   return status;
@@ -856,22 +866,20 @@ to_cache(Context& ctx,
   cc_log("Running real compiler");
   MTR_BEGIN("execute", "compiler");
 
-  const auto tmp_stdout_fd_and_path = Util::create_temp_fd(
+  TemporaryFile tmp_stdout(
     fmt::format("{}/tmp.stdout", ctx.config.temporary_dir()));
-  int tmp_stdout_fd = tmp_stdout_fd_and_path.first;
-  const std::string& tmp_stdout = tmp_stdout_fd_and_path.second;
-  ctx.register_pending_tmp_file(tmp_stdout);
+  ctx.register_pending_tmp_file(tmp_stdout.path);
+  std::string tmp_stdout_path = tmp_stdout.path;
 
-  const auto tmp_stderr_fd_and_path = Util::create_temp_fd(
+  TemporaryFile tmp_stderr(
     fmt::format("{}/tmp.stderr", ctx.config.temporary_dir()));
-  int tmp_stderr_fd = tmp_stderr_fd_and_path.first;
-  const std::string& tmp_stderr = tmp_stderr_fd_and_path.second;
-  ctx.register_pending_tmp_file(tmp_stderr);
+  ctx.register_pending_tmp_file(tmp_stderr.path);
+  std::string tmp_stderr_path = tmp_stderr.path;
 
   int status;
   if (!ctx.config.depend_mode()) {
     status =
-      execute(ctx, args, tmp_stdout, tmp_stdout_fd, tmp_stderr, tmp_stderr_fd);
+      do_execute(ctx, args, std::move(tmp_stdout), std::move(tmp_stderr));
     args.pop_back(3);
   } else {
     // Use the original arguments (including dependency options) in depend
@@ -882,16 +890,12 @@ to_cache(Context& ctx,
     add_prefix(ctx, depend_mode_args, ctx.config.prefix_command());
 
     ctx.time_of_compilation = time(nullptr);
-    status = execute(ctx,
-                     depend_mode_args,
-                     tmp_stdout,
-                     tmp_stdout_fd,
-                     tmp_stderr,
-                     tmp_stderr_fd);
+    status = do_execute(
+      ctx, depend_mode_args, std::move(tmp_stdout), std::move(tmp_stderr));
   }
   MTR_END("execute", "compiler");
 
-  auto st = Stat::stat(tmp_stdout, Stat::OnError::log);
+  auto st = Stat::stat(tmp_stdout_path, Stat::OnError::log);
   if (!st) {
     // The stdout file was removed - cleanup in progress? Better bail out.
     failed(STATS_MISSING);
@@ -908,15 +912,15 @@ to_cache(Context& ctx,
   // compiler into tmp_stderr.
   if (!ctx.cpp_stderr.empty()) {
     std::string combined_stderr =
-      Util::read_file(ctx.cpp_stderr) + Util::read_file(tmp_stderr);
-    Util::write_file(tmp_stderr, combined_stderr);
+      Util::read_file(ctx.cpp_stderr) + Util::read_file(tmp_stderr_path);
+    Util::write_file(tmp_stderr_path, combined_stderr);
   }
 
   if (status != 0) {
     cc_log("Compiler gave exit status %d", status);
 
     // We can output stderr immediately instead of rerunning the compiler.
-    Util::send_to_stderr(Util::read_file(tmp_stderr),
+    Util::send_to_stderr(Util::read_file(tmp_stderr_path),
                          ctx.args_info.strip_diagnostics_colors);
 
     failed(STATS_STATUS, status);
@@ -948,7 +952,7 @@ to_cache(Context& ctx,
     failed(STATS_EMPTYOUTPUT);
   }
 
-  st = Stat::stat(tmp_stderr, Stat::OnError::log);
+  st = Stat::stat(tmp_stderr_path, Stat::OnError::log);
   if (!st) {
     failed(STATS_ERROR);
   }
@@ -957,7 +961,7 @@ to_cache(Context& ctx,
   Result::Writer result_writer(ctx, ctx.result_path());
 
   if (st.size() > 0) {
-    result_writer.write(Result::FileType::stderr_output, tmp_stderr);
+    result_writer.write(Result::FileType::stderr_output, tmp_stderr_path);
   }
   result_writer.write(Result::FileType::object, ctx.args_info.output_obj);
   if (ctx.args_info.generating_dependencies) {
@@ -1008,7 +1012,7 @@ to_cache(Context& ctx,
   }
 
   // Everything OK.
-  Util::send_to_stderr(Util::read_file(tmp_stderr),
+  Util::send_to_stderr(Util::read_file(tmp_stderr_path),
                        ctx.args_info.strip_diagnostics_colors);
 }
 
@@ -1030,20 +1034,14 @@ get_result_name_from_cpp(Context& ctx, Args& args, Hash& hash)
   } else {
     // Run cpp on the input file to obtain the .i.
 
-    // Limit the basename to 10 characters in order to cope with filesystem with
-    // small maximum filename length limits.
-    string_view input_base =
-      Util::get_truncated_base_name(ctx.args_info.input_file, 10);
-    auto stdout_fd_and_path = Util::create_temp_fd(
-      fmt::format("{}/{}.stdout", ctx.config.temporary_dir(), input_base));
-    int stdout_fd = stdout_fd_and_path.first;
-    stdout_path = stdout_fd_and_path.second;
+    TemporaryFile tmp_stdout(
+      fmt::format("{}/tmp.cpp_stdout", ctx.config.temporary_dir()));
+    stdout_path = tmp_stdout.path;
     ctx.register_pending_tmp_file(stdout_path);
 
-    auto stderr_fd_and_path = Util::create_temp_fd(
+    TemporaryFile tmp_stderr(
       fmt::format("{}/tmp.cpp_stderr", ctx.config.temporary_dir()));
-    int stderr_fd = stderr_fd_and_path.first;
-    stderr_path = stderr_fd_and_path.second;
+    stderr_path = tmp_stderr.path;
     ctx.register_pending_tmp_file(stderr_path);
 
     size_t args_added = 2;
@@ -1056,7 +1054,8 @@ get_result_name_from_cpp(Context& ctx, Args& args, Hash& hash)
     add_prefix(ctx, args, ctx.config.prefix_command_cpp());
     cc_log("Running preprocessor");
     MTR_BEGIN("execute", "preprocessor");
-    status = execute(ctx, args, stdout_path, stdout_fd, stderr_path, stderr_fd);
+    status =
+      do_execute(ctx, args, std::move(tmp_stdout), std::move(tmp_stderr));
     MTR_END("execute", "preprocessor");
     args.pop_back(args_added);
   }
index bbf9ceb77f14f284d116d21446728dc0aa08fff4..6f317d8df07463958997ae2f85c793ff10884fec 100644 (file)
@@ -24,6 +24,7 @@
 #include "Fd.hpp"
 #include "SignalHandler.hpp"
 #include "Stat.hpp"
+#include "TemporaryFile.hpp"
 #include "Util.hpp"
 #include "ccache.hpp"
 #include "logging.hpp"
@@ -36,9 +37,9 @@ using nonstd::string_view;
 
 #ifdef _WIN32
 int
-execute(const char* const* argv, int fd_out, int fd_err, pid_t* /*pid*/)
+execute(const char* const* argv, Fd&& fd_out, Fd&& fd_err, pid_t* /*pid*/)
 {
-  return win32execute(argv[0], argv, 1, fd_out, fd_err);
+  return win32execute(argv[0], argv, 1, fd_out.release(), fd_err.release());
 }
 
 // Re-create a win32 command line string based on **argv.
@@ -195,13 +196,11 @@ win32execute(const char* path,
   add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, path);
   BOOL ret = FALSE;
   if (length > 8192) {
-    auto fd_and_path = Util::create_temp_fd(path);
-    Fd fd(fd_and_path.first);
-    const char* tmp_file = fd_and_path.second.c_str();
-    if (!write_fd(*fd, args, length)) {
+    TemporaryFile tmp_file(path);
+    if (!write_fd(*tmp_file.fd, args, length)) {
       cc_log("Error writing @file; this command will probably fail: %s", args);
     }
-    std::string atfile = fmt::format("\"@{}\"", tmp_file);
+    std::string atfile = fmt::format("\"@{}\"", tmp_file.path);
     ret = CreateProcess(nullptr,
                         const_cast<char*>(atfile.c_str()),
                         nullptr,
@@ -212,7 +211,7 @@ win32execute(const char* path,
                         nullptr,
                         &si,
                         &pi);
-    Util::unlink_tmp(tmp_file);
+    Util::unlink_tmp(tmp_file.path);
   }
   if (!ret) {
     ret = CreateProcess(full_path_win_ext,
@@ -257,7 +256,7 @@ win32execute(const char* path,
 // Execute a compiler backend, capturing all output to the given paths the full
 // path to the compiler to run is in argv[0].
 int
-execute(const char* const* argv, int fd_out, int fd_err, pid_t* pid)
+execute(const char* const* argv, Fd&& fd_out, Fd&& fd_err, pid_t* pid)
 {
   cc_log_argv("Executing ", argv);
 
@@ -272,15 +271,15 @@ execute(const char* const* argv, int fd_out, int fd_err, pid_t* pid)
 
   if (*pid == 0) {
     // Child.
-    dup2(fd_out, STDOUT_FILENO);
-    close(fd_out);
-    dup2(fd_err, STDERR_FILENO);
-    close(fd_err);
+    dup2(*fd_out, STDOUT_FILENO);
+    fd_out.close();
+    dup2(*fd_err, STDERR_FILENO);
+    fd_err.close();
     x_exit(execv(argv[0], const_cast<char* const*>(argv)));
   }
 
-  close(fd_out);
-  close(fd_err);
+  fd_out.close();
+  fd_err.close();
 
   int status;
   if (waitpid(*pid, &status, 0) != *pid) {
index a8f7fc17d9b67bfc67cc707f7fe35c192e21d20e..e66f73a285ba2464b5c8f541a0fc8f832d767b6a 100644 (file)
 
 #include "system.hpp"
 
+#include "Fd.hpp"
+
 #include <string>
 
 class Context;
 
-int execute(const char* const* argv, int fd_out, int fd_err, pid_t* pid);
+int execute(const char* const* argv, Fd&& fd_out, Fd&& fd_err, pid_t* pid);
 std::string
 find_executable(const Context& ctx, const char* name, const char* exclude_name);
 std::string find_executable_in_path(const char* name,
index 51434f85ba5da80a2707d20cdc9c6b39984426b4..126eb74bc471143fb3e18549f044fcf0ce3964c3 100644 (file)
@@ -20,6 +20,7 @@
 #include "legacy_util.hpp"
 
 #include "Fd.hpp"
+#include "TemporaryFile.hpp"
 #include "Util.hpp"
 #include "exceptions.hpp"
 #include "logging.hpp"
@@ -159,8 +160,9 @@ clone_file(const char* src, const char* dest, bool via_tmp_file)
   Fd dest_fd;
   char* tmp_file = nullptr;
   if (via_tmp_file) {
-    tmp_file = x_strdup(dest);
-    dest_fd = Fd(create_tmp_fd(&tmp_file));
+    TemporaryFile temp_file(dest);
+    dest_fd = std::move(temp_file.fd);
+    tmp_file = x_strdup(temp_file.path.c_str());
   } else {
     dest_fd = Fd(open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666));
     if (!dest_fd) {
@@ -220,8 +222,9 @@ copy_file(const char* src, const char* dest, bool via_tmp_file)
   Fd dest_fd;
   char* tmp_file = nullptr;
   if (via_tmp_file) {
-    tmp_file = x_strdup(dest);
-    dest_fd = Fd(create_tmp_fd(&tmp_file));
+    TemporaryFile temp_file(dest);
+    dest_fd = std::move(temp_file.fd);
+    tmp_file = x_strdup(temp_file.path.c_str());
   } else {
     dest_fd = Fd(open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666));
     if (!dest_fd) {