| // Copyright 2020 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/developer/forensics/utils/previous_boot_file.h" | |
| #include <lib/syslog/cpp/macros.h> | |
| #include "src/lib/files/directory.h" | |
| #include "src/lib/files/file.h" | |
| #include "src/lib/files/path.h" | |
| #include "src/lib/fxl/strings/join_strings.h" | |
| #include "src/lib/fxl/strings/split_string.h" | |
| namespace forensics { | |
| PreviousBootFile PreviousBootFile::FromData(const bool is_first_instance, const std::string& file) { | |
| return PreviousBootFile(is_first_instance, files::JoinPath("/tmp", file), | |
| files::JoinPath("/data", file)); | |
| } | |
| PreviousBootFile PreviousBootFile::FromCache(const bool is_first_instance, | |
| const std::string& file) { | |
| return PreviousBootFile(is_first_instance, files::JoinPath("/tmp", file), | |
| files::JoinPath("/cache", file)); | |
| } | |
| PreviousBootFile::PreviousBootFile(const bool is_first_instance, const std::string& to, | |
| const std::string& from) | |
| : current_boot_path_(from), previous_boot_path_(to) { | |
| if (!is_first_instance) { | |
| return; | |
| } | |
| // Bail if the file doesn't exist. | |
| if (!files::IsFile(current_boot_path_)) { | |
| return; | |
| } | |
| // Bail if the file can't be read. | |
| std::string content; | |
| if (!files::ReadFileToString(current_boot_path_, &content)) { | |
| FX_LOGS(ERROR) << "Failed to read file " << current_boot_path_; | |
| return; | |
| } | |
| // Create the directory in /tmp the file is in. | |
| auto split_previous_boot_path = | |
| fxl::SplitStringCopy(previous_boot_path_, "/", fxl::WhiteSpaceHandling::kKeepWhitespace, | |
| fxl::SplitResult::kSplitWantNonEmpty); | |
| // Drop the file name from the path. | |
| if (!split_previous_boot_path.empty()) { | |
| split_previous_boot_path.pop_back(); | |
| } | |
| // Create the directory. | |
| if (!split_previous_boot_path.empty()) { | |
| files::CreateDirectory(fxl::JoinStrings(split_previous_boot_path, "/")); | |
| } | |
| // Copy the file content – we cannot move as the two files are under different namespaces. | |
| if (!files::WriteFile(previous_boot_path_, content.c_str(), content.size())) { | |
| FX_LOGS(ERROR) << "Failed to write file " << previous_boot_path_; | |
| return; | |
| } | |
| // Delete the original file. | |
| if (!files::DeletePath(current_boot_path_, /*recursive=*/true)) { | |
| FX_LOGS(ERROR) << "Failed to delete " << current_boot_path_; | |
| } | |
| } | |
| } // namespace forensics |