From: Joel Rosdahl Date: Mon, 23 Sep 2019 20:36:37 +0000 (+0200) Subject: Extract temporary file creation code into a function X-Git-Tag: v4.0~767 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dba7713cb17e3ed556133f83e3a219e503335883;p=thirdparty%2Fccache.git Extract temporary file creation code into a function Also, use cstdio instead of iostream since that will be needed in upcoming commits to get hold on the underlying file descriptor. --- diff --git a/src/AtomicFile.cpp b/src/AtomicFile.cpp index 994b8c1be..c73d39a3b 100644 --- a/src/AtomicFile.cpp +++ b/src/AtomicFile.cpp @@ -21,31 +21,23 @@ #include "Error.hpp" #include "ccache.hpp" +#include #include #include #include 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& data) { - m_stream.write(reinterpret_cast(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& 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)); } diff --git a/src/AtomicFile.hpp b/src/AtomicFile.hpp index 68c09a3d1..ed2e6c8d1 100644 --- a/src/AtomicFile.hpp +++ b/src/AtomicFile.hpp @@ -20,7 +20,7 @@ #include "system.hpp" -#include +#include #include #include @@ -45,5 +45,5 @@ public: private: const std::string m_path; std::string m_tmp_path; - std::ofstream m_stream; + FILE* m_stream; }; diff --git a/src/util.cpp b/src/util.cpp index f74fb1509..d066a90e7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1799,6 +1799,16 @@ create_dir(const std::string& dir) } } +std::pair +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) { diff --git a/src/util.hpp b/src/util.hpp index decff6ce9..caf24e5a1 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #include 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 create_temp_fd(const std::string& path_prefix); + // Get directory name of path. std::string dir_name(const std::string& path);