-// Copyright (C) 2019-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2019-2023 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
#include <core/exceptions.hpp>
#include <fmtmacros.hpp>
+#include <util/file.hpp>
AtomicFile::AtomicFile(const std::string& path, Mode mode) : m_path(path)
{
AtomicFile::commit()
{
ASSERT(m_stream);
- int result = fclose(m_stream);
+ int retcode = fclose(m_stream);
m_stream = nullptr;
- if (result == EOF) {
+ if (retcode == EOF) {
Util::unlink_tmp(m_tmp_path);
throw core::Error(
FMT("failed to write data to {}: {}", m_path, strerror(errno)));
}
- Util::rename(m_tmp_path, m_path);
+ const auto result = util::rename(m_tmp_path, m_path);
+ if (!result) {
+ throw core::Error(
+ FMT("failed to rename {} to {}: {}", m_tmp_path, m_path, result.error()));
+ }
}
return path.substr(0, path.length() - get_extension(path).length());
}
-void
-rename(const std::string& oldpath, const std::string& newpath)
-{
-#ifndef _WIN32
- if (::rename(oldpath.c_str(), newpath.c_str()) != 0) {
- throw core::Error(
- FMT("failed to rename {} to {}: {}", oldpath, newpath, strerror(errno)));
- }
-#else
- // Windows' rename() won't overwrite an existing file, so need to use
- // MoveFileEx instead.
- if (!MoveFileExA(
- oldpath.c_str(), newpath.c_str(), MOVEFILE_REPLACE_EXISTING)) {
- DWORD error = GetLastError();
- throw core::Error(FMT("failed to rename {} to {}: {}",
- oldpath,
- newpath,
- Win32Util::error_message(error)));
- }
-#endif
-}
-
void
send_to_fd(const Context& ctx, std::string_view text, int fd)
{
FMT("{}.ccache{}unlink", path, TemporaryFile::tmp_file_infix);
bool success = true;
- try {
- Util::rename(path, tmp_name);
- } catch (core::Error&) {
+ const auto result = util::rename(path, tmp_name);
+ if (!result) {
success = false;
saved_errno = errno;
}
// extension as determined by `get_extension()`.
std::string_view remove_extension(std::string_view path);
-// Rename `oldpath` to `newpath` (deleting `newpath`). Throws `core::Error` on
-// error.
-void rename(const std::string& oldpath, const std::string& newpath);
-
// Send `text` to file descriptor `fd`, optionally stripping ANSI color
// sequences if `ctx.args_info.strip_diagnostics_colors` is true and rewriting
// paths to absolute if `ctx.config.absolute_paths_in_stderr` is true. Throws
src_fd.close();
if (via_tmp_file) {
- Util::rename(tmp_file, dest);
+ const auto result = util::rename(tmp_file, dest);
+ if (!result) {
+ throw core::Error(
+ FMT("failed to rename {} to {}: {}", tmp_file, dest, result.error()));
+ }
}
# elif defined(__APPLE__)
(void)via_tmp_file;
wanted_level, util::format_digest(key) + suffix_from_type(type));
if (cache_file_path != wanted_path) {
Util::ensure_dir_exists(Util::dir_name(wanted_path));
+
+ // Note: Two ccache processes may move the file at the same time, so failure
+ // to rename is OK.
LOG("Moving {} to {}", cache_file_path, wanted_path);
- try {
- Util::rename(cache_file_path, wanted_path);
- } catch (const core::Error&) {
- // Two ccache processes may move the file at the same time, so failure
- // to rename is OK.
- }
+ util::rename(cache_file_path, wanted_path);
for (const auto& raw_file : m_added_raw_files) {
- try {
- Util::rename(
- raw_file,
- FMT("{}/{}", Util::dir_name(wanted_path), Util::base_name(raw_file)));
- } catch (const core::Error&) {
- // Two ccache processes may move the file at the same time, so failure
- // to rename is OK.
- }
+ util::rename(
+ raw_file,
+ FMT("{}/{}", Util::dir_name(wanted_path), Util::base_name(raw_file)));
}
}
}
#include <Logging.hpp>
#include <Stat.hpp>
#include <TemporaryFile.hpp>
-#include <Util.hpp>
#include <Win32Util.hpp>
#include <fmtmacros.hpp>
#include <util/Bytes.hpp>
#include <util/expected.hpp>
+#include <util/file.hpp>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
src_fd.close();
if (via_tmp_file == ViaTmpFile::yes) {
- Util::rename(tmp_file, dest);
+ const auto result = util::rename(tmp_file, dest);
+ if (!result) {
+ return nonstd::make_unexpected(
+ FMT("Failed to rename {} to {}: {}", tmp_file, dest, result.error()));
+ }
}
return {};
template nonstd::expected<std::vector<uint8_t>, std::string>
read_file_part(const std::string& path, size_t pos, size_t count);
+nonstd::expected<void, std::string>
+rename(const std::string& oldpath, const std::string& newpath)
+{
+#ifndef _WIN32
+ if (::rename(oldpath.c_str(), newpath.c_str()) != 0) {
+ return nonstd::make_unexpected(strerror(errno));
+ }
+#else
+ // Windows' rename() won't overwrite an existing file, so need to use
+ // MoveFileEx instead.
+ if (!MoveFileExA(
+ oldpath.c_str(), newpath.c_str(), MOVEFILE_REPLACE_EXISTING)) {
+ DWORD error = GetLastError();
+ return nonstd::make_unexpected(Win32Util::error_message(error));
+ }
+#endif
+ return {};
+}
+
void
set_timestamps(const std::string& path,
std::optional<util::TimePoint> mtime,
nonstd::expected<T, std::string>
read_file_part(const std::string& path, size_t pos, size_t count);
+// Rename `oldpath` to `newpath` (deleting `newpath`).
+//
+// Note: Mingw-w64's std::filesystem::rename is buggy and doesn't properly
+// overwrite an existing file, at least in version 9.1.0, hence this utility
+// function.
+nonstd::expected<void, std::string> rename(const std::string& oldpath,
+ const std::string& newpath);
+
// Set atime/mtime of `path`. If `mtime` is std::nullopt, set to the current
// time. If `atime` is std::nullopt, set to what `mtime` specifies.
void set_timestamps(const std::string& path,