blob: f0f862e2f644620b96296f952fa025c7785fe17d [file] [log] [blame]
// Copyright 2021 The Chromium OS 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 "oobe_config/pstore_storage.h"
#include <sstream>
#include <string>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/optional.h>
#include <base/strings/strcat.h>
#include <base/strings/string_number_conversions.h>
#include "oobe_config/rollback_constants.h"
namespace oobe_config {
namespace {
const char kRollbackDataKey[] = "rollback_data";
const char kRamoopsFilePattern[] = "pmsg-ramoops-*";
base::FilePath PrefixAbsolutePath(const base::FilePath& prefix,
const base::FilePath& file_path) {
if (prefix.empty())
return file_path;
DCHECK(!file_path.empty());
DCHECK_EQ('/', file_path.value()[0]);
return prefix.Append(file_path.value().substr(1));
}
base::FileEnumerator EnumerateRamoops(const base::FilePath& root_path) {
return base::FileEnumerator(
PrefixAbsolutePath(root_path, base::FilePath(kPstorePath)),
/*recursive=*/false, base::FileEnumerator::FILES, kRamoopsFilePattern);
}
bool ExtractRollbackData(const base::FilePath& file,
std::string* rollback_data) {
std::string file_content;
base::ReadFileToString(file, &file_content);
std::stringstream file_stream(file_content);
std::string key;
while (file_stream && key != kRollbackDataKey) {
file_stream >> key;
}
if (file_stream && key == kRollbackDataKey) {
std::string hex_rollback_data;
file_stream >> hex_rollback_data;
*rollback_data = hex_rollback_data;
return true; // Data may be completely empty - that is valid as well.
}
return false;
}
base::Optional<std::string> HexToBinary(const std::string& hex) {
std::string binary;
bool success = base::HexStringToString(hex, &binary);
if (!success) {
LOG(ERROR) << "Could not decode rollback data.";
return base::nullopt;
}
return binary;
}
} // namespace
bool StageForPstore(const std::string& data, const base::FilePath& root_path) {
std::string hex_data_with_header = base::StrCat(
{kRollbackDataKey, " ", base::HexEncode(data.data(), data.size())});
int bytes_written = base::WriteFile(
PrefixAbsolutePath(root_path, base::FilePath(kRollbackDataForPmsgFile)),
hex_data_with_header.c_str(), hex_data_with_header.size());
if (bytes_written != hex_data_with_header.size()) {
LOG(ERROR) << "Could not write " << kRollbackDataForPmsgFile;
return false;
}
return true;
}
base::Optional<std::string> LoadFromPstore(const base::FilePath& root_path) {
base::FileEnumerator pmsg_ramoops_enumerator = EnumerateRamoops(root_path);
for (base::FilePath ramoops_file = pmsg_ramoops_enumerator.Next();
!ramoops_file.empty(); ramoops_file = pmsg_ramoops_enumerator.Next()) {
LOG(INFO) << "Looking at file " << ramoops_file.value();
std::string rollback_data;
if (ExtractRollbackData(ramoops_file, &rollback_data)) {
return HexToBinary(rollback_data);
}
LOG(INFO) << "No rollback data found in that file.";
}
LOG(ERROR) << "No rollback data found.";
return base::nullopt;
}
} // namespace oobe_config