| // 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 |