From 90a392ed8a30bc30697a3bec3115f4d2dff3a580 Mon Sep 17 00:00:00 2001 From: Niklas Korz Date: Sun, 22 Mar 2026 20:19:21 +0100 Subject: [PATCH] fix: resolve relative paths for atomic write target (#1564) Fixes #1383 This solves an edge case where the target path of an atomic write is a relative path without a directory part. In this case, the temporary file was written to the system's tempdir before, which may then fail the atomic rename as the tempdir often is on a different device such as tmpfs. --- packager/file/file.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packager/file/file.cc b/packager/file/file.cc index 51bb2c27ba..6f3a9cf4d7 100644 --- a/packager/file/file.cc +++ b/packager/file/file.cc @@ -74,7 +74,19 @@ bool DeleteLocalFile(const char* file_name) { bool WriteLocalFileAtomically(const char* file_name, const std::string& contents) { - const auto file_path = std::filesystem::u8path(file_name); + std::error_code ec; + // To atomically move the temporary file to the target location after write, + // they must be on the same device. For relative paths without a directory + // part, the parent path is empty, which fails TempFilePath's empty directory + // path check, thus falling back to /tmp that is on a potentially different + // device. We prevent this by resolving the absolute file path. + const auto file_path = + std::filesystem::absolute(std::filesystem::u8path(file_name), ec); + if (ec) { + LOG(ERROR) << "Failed to resolve file path '" << file_name + << "', error: " << ec; + return false; + } const auto dir_path = file_path.parent_path(); std::string temp_file_name; @@ -83,7 +95,6 @@ bool WriteLocalFileAtomically(const char* file_name, if (!File::WriteStringToFile(temp_file_name.c_str(), contents)) return false; - std::error_code ec; auto temp_file_path = std::filesystem::u8path(temp_file_name); std::filesystem::rename(temp_file_path, file_name, ec); if (ec) {