diff options
author | 2024-04-19 13:10:58 +0100 | |
---|---|---|
committer | 2024-04-30 10:43:18 +0000 | |
commit | 256d751dd830fc6bf28f8b1aa99346e3b951e4c1 (patch) | |
tree | becbb4e551d7913e8fd06ddadd8a29a85e8c97bc /artd/file_utils.cc | |
parent | bd45d4629ef5a62baab677ef4e7708a89ff6ec12 (diff) |
Refactor NewFile::CommitAllOrAbandon.
This refactoring creates a more generic function to back
NewFile::CommitAllOrAbandon, which can be used for moving any files.
The generic function will be used for moving Pre-reboot Dexopt staged
files.
Bug: 311377497
Test: m test-art-host-gtest-art_artd_tests
Change-Id: If17392557229d857743011942d0a666e925a0448
Diffstat (limited to 'artd/file_utils.cc')
-rw-r--r-- | artd/file_utils.cc | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/artd/file_utils.cc b/artd/file_utils.cc index f3558534ba..1415efbdb3 100644 --- a/artd/file_utils.cc +++ b/artd/file_utils.cc @@ -26,6 +26,7 @@ #include <string> #include <string_view> #include <system_error> +#include <unordered_set> #include <utility> #include "aidl/com/android/server/art/FsPermission.h" @@ -46,7 +47,7 @@ using ::aidl::com::android::server::art::FsPermission; using ::android::base::make_scope_guard; using ::android::base::Result; -void UnlinkIfExists(const std::string& path) { +void UnlinkIfExists(std::string_view path) { std::error_code ec; std::filesystem::remove(path, ec); if (ec) { @@ -85,7 +86,6 @@ Result<void> NewFile::CommitOrAbandon() { "Failed to move new file '{}' to path '{}': {}", temp_path_, final_path_, ec.message()); } cleanup.Disable(); - committed_ = true; return {}; } @@ -122,15 +122,35 @@ void NewFile::Unlink() { Result<void> NewFile::CommitAllOrAbandon(const std::vector<NewFile*>& files_to_commit, const std::vector<std::string_view>& files_to_remove) { + std::vector<std::pair<std::string_view, std::string_view>> files_to_move; + + auto cleanup = make_scope_guard([&]() { + for (NewFile* file : files_to_commit) { + file->Unlink(); + } + }); + for (NewFile* file : files_to_commit) { + OR_RETURN(file->Keep()); + files_to_move.emplace_back(file->TempPath(), file->FinalPath()); + } + cleanup.Disable(); + + return MoveAllOrAbandon(files_to_move, files_to_remove); +} + +Result<void> MoveAllOrAbandon( + const std::vector<std::pair<std::string_view, std::string_view>>& files_to_move, + const std::vector<std::string_view>& files_to_remove) { std::vector<std::pair<std::string_view, std::string>> moved_files; + std::unordered_set<std::string_view> committed_files; auto cleanup = make_scope_guard([&]() { - // Clean up new files. - for (NewFile* new_file : files_to_commit) { - if (new_file->committed_) { - UnlinkIfExists(new_file->FinalPath()); + // Clean up `files_to_move`. + for (const auto& [src_path, dst_path] : files_to_move) { + if (committed_files.find(dst_path) != committed_files.end()) { + UnlinkIfExists(dst_path); } else { - new_file->Cleanup(); + UnlinkIfExists(src_path); } } @@ -151,9 +171,9 @@ Result<void> NewFile::CommitAllOrAbandon(const std::vector<NewFile*>& files_to_c // Move old files to temporary locations. std::vector<std::string_view> all_files_to_remove; - all_files_to_remove.reserve(files_to_commit.size() + files_to_remove.size()); - for (NewFile* file : files_to_commit) { - all_files_to_remove.push_back(file->FinalPath()); + all_files_to_remove.reserve(files_to_move.size() + files_to_remove.size()); + for (const auto& [src_path, dst_path] : files_to_move) { + all_files_to_remove.push_back(dst_path); } all_files_to_remove.insert( all_files_to_remove.end(), files_to_remove.begin(), files_to_remove.end()); @@ -168,7 +188,7 @@ Result<void> NewFile::CommitAllOrAbandon(const std::vector<NewFile*>& files_to_c return ErrnoErrorf("Old file '{}' is a directory", original_path); } if (std::filesystem::exists(status)) { - std::string temp_path = BuildTempPath(original_path, "XXXXXX"); + std::string temp_path = NewFile::BuildTempPath(original_path, "XXXXXX"); int fd = mkstemps(temp_path.data(), /*suffixlen=*/4); if (fd < 0) { return ErrnoErrorf("Failed to create temporary path for old file '{}'", original_path); @@ -188,9 +208,14 @@ Result<void> NewFile::CommitAllOrAbandon(const std::vector<NewFile*>& files_to_c } } - // Commit new files. - for (NewFile* file : files_to_commit) { - OR_RETURN(file->CommitOrAbandon()); + // Move `files_to_move`. + for (const auto& [src_path, dst_path] : files_to_move) { + std::error_code ec; + std::filesystem::rename(src_path, dst_path, ec); + if (ec) { + return Errorf("Failed to move file from '{}' to '{}': {}", src_path, dst_path, ec.message()); + } + committed_files.insert(dst_path); } cleanup.Disable(); |