]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Extract temporary file creation code into a function
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 23 Sep 2019 20:36:37 +0000 (22:36 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 5 Oct 2019 21:16:31 +0000 (23:16 +0200)
Also, use cstdio instead of iostream since that will be needed in
upcoming commits to get hold on the underlying file descriptor.

src/AtomicFile.cpp
src/AtomicFile.hpp
src/util.cpp
src/util.hpp

index 994b8c1bec80b3a48ab33ecbb1130847f6103dff..c73d39a3b91435d88ee495319ae5c1fdcfcbbc74 100644 (file)
 #include "Error.hpp"
 #include "ccache.hpp"
 
+#include <cassert>
 #include <cerrno>
 #include <fmt/core.h>
 #include <unistd.h>
 
 AtomicFile::AtomicFile(const std::string& path, Mode mode) : m_path(path)
 {
-  char* tmp_path = x_strdup(path.c_str());
-  int fd = create_tmp_fd(&tmp_path);
-  m_tmp_path = tmp_path;
-  m_stream.open(tmp_path,
-                mode == Mode::Binary ? std::ios::out | std::ios::binary
-                                     : std::ios::out);
-  free(tmp_path);
-  ::close(fd);
-
-  if (!m_stream) {
-    throw Error(fmt::format("failed to create {}: {}", path, strerror(errno)));
-  }
+  auto fd_and_path = util::create_temp_fd(path);
+  m_stream = fdopen(fd_and_path.first, mode == Mode::Binary ? "w+b" : "w+");
+  m_tmp_path = std::move(fd_and_path.second);
 }
 
 AtomicFile::~AtomicFile()
 {
-  if (m_stream.is_open()) {
+  if (m_stream) {
     // close() was not called so remove the lingering temporary file.
-    m_stream.close();
+    fclose(m_stream);
     tmp_unlink(m_tmp_path.c_str());
   }
 }
@@ -53,8 +45,7 @@ AtomicFile::~AtomicFile()
 void
 AtomicFile::write(const std::string& data)
 {
-  m_stream.write(data.data(), data.size());
-  if (!m_stream) {
+  if (fwrite(data.data(), data.size(), 1, m_stream) != 1) {
     throw Error(
       fmt::format("failed to write data to {}: {}", m_path, strerror(errno)));
   }
@@ -63,8 +54,7 @@ AtomicFile::write(const std::string& data)
 void
 AtomicFile::write(const std::vector<uint8_t>& data)
 {
-  m_stream.write(reinterpret_cast<const char*>(data.data()), data.size());
-  if (!m_stream) {
+  if (fwrite(data.data(), data.size(), 1, m_stream) != 1) {
     throw Error(
       fmt::format("failed to write data to {}: {}", m_path, strerror(errno)));
   }
@@ -73,7 +63,9 @@ AtomicFile::write(const std::vector<uint8_t>& data)
 void
 AtomicFile::close()
 {
-  m_stream.close();
+  assert(m_stream);
+  fclose(m_stream);
+  m_stream = nullptr;
   if (x_rename(m_tmp_path.c_str(), m_path.c_str()) != 0) {
     throw Error(fmt::format("failed to rename {} to {}", m_tmp_path, m_path));
   }
index 68c09a3d1737275f7d3325395974b576ceb33fca..ed2e6c8d1c385a41c5dfb26738a25a77f843934c 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "system.hpp"
 
-#include <fstream>
+#include <cstdio>
 #include <string>
 #include <vector>
 
@@ -45,5 +45,5 @@ public:
 private:
   const std::string m_path;
   std::string m_tmp_path;
-  std::ofstream m_stream;
+  FILE* m_stream;
 };
index f74fb1509da39f15d614b7b8d3281e68675e3f02..d066a90e70c946dce9dcc816b5580cdcd9196cba 100644 (file)
@@ -1799,6 +1799,16 @@ create_dir(const std::string& dir)
   }
 }
 
+std::pair<int, std::string>
+create_temp_fd(const std::string& path_prefix)
+{
+  char* tmp_path = x_strdup(path_prefix.c_str());
+  int fd = create_tmp_fd(&tmp_path);
+  std::string actual_path = tmp_path;
+  free(tmp_path);
+  return {fd, actual_path};
+}
+
 std::string
 dir_name(const std::string& path)
 {
index decff6ce91e90d8630c06acb6c41dc89b93b97f3..caf24e5a1635c7719b634a9eda35855e2f27a43b 100644 (file)
@@ -25,6 +25,7 @@
 #include <functional>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 namespace util {
@@ -43,6 +44,16 @@ std::string base_name(const std::string& path);
 // Returns true if the directory exists or could be created, otherwise false.
 bool create_dir(const std::string& dir);
 
+// Create a unique temporary file.
+//
+// Parameters:
+// - path_prefix: Base path. The resulting filename will be this path plus a
+//   unique suffix.
+//
+// Returns the open file descriptor (in read/write mode) and the actual
+// filename.
+std::pair<int, std::string> create_temp_fd(const std::string& path_prefix);
+
 // Get directory name of path.
 std::string dir_name(const std::string& path);