| // Copyright 2020 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 "vm_tools/common/naming.h" |
| #include "vm_tools/pstore_dump/persistent_ram_buffer.h" |
| |
| #include <string> |
| |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <brillo/flag_helper.h> |
| #include <brillo/cryptohome.h> |
| #include <brillo/dbus/async_event_sequencer.h> |
| #include <chromeos/dbus/service_constants.h> |
| #include <dbus/bus.h> |
| #include <dbus/message.h> |
| #include <dbus/object_proxy.h> |
| |
| namespace { |
| |
| bool GetPrimaryUsername(std::string* out_username) { |
| DCHECK(out_username); |
| |
| dbus::Bus::Options options; |
| options.bus_type = dbus::Bus::SYSTEM; |
| scoped_refptr<dbus::Bus> bus = new dbus::Bus(options); |
| CHECK(bus->Connect()) << "Failed to connect to system D-Bus"; |
| |
| dbus::ObjectProxy* session_manager_proxy = bus->GetObjectProxy( |
| login_manager::kSessionManagerServiceName, |
| dbus::ObjectPath(login_manager::kSessionManagerServicePath)); |
| dbus::MethodCall method_call( |
| login_manager::kSessionManagerInterface, |
| login_manager::kSessionManagerRetrievePrimarySession); |
| std::unique_ptr<dbus::Response> response = |
| session_manager_proxy->CallMethodAndBlock( |
| &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); |
| if (!response.get()) { |
| LOG(ERROR) << "Cannot retrieve username for primary session."; |
| bus->ShutdownAndBlock(); |
| return false; |
| } |
| |
| dbus::MessageReader response_reader(response.get()); |
| if (!response_reader.PopString(out_username)) { |
| LOG(ERROR) << "Primary session username bad format."; |
| bus->ShutdownAndBlock(); |
| return false; |
| } |
| bus->ShutdownAndBlock(); |
| return true; |
| } |
| |
| bool FindARCVMPstorePath(base::FilePath* out_path) { |
| DCHECK(out_path); |
| |
| std::string primary_username; |
| if (!GetPrimaryUsername(&primary_username)) { |
| LOG(ERROR) << "Failed to get primary username"; |
| return false; |
| } |
| |
| base::FilePath root_path = |
| brillo::cryptohome::home::GetRootPath(primary_username); |
| if (root_path.empty()) { |
| LOG(ERROR) << "Failed to get the cryptohome root path of user of ARCVM"; |
| return false; |
| } |
| base::FilePath pstore_path = root_path.Append("crosvm").Append( |
| vm_tools::GetEncodedName("arcvm") + ".pstore"); |
| if (!base::PathExists(pstore_path)) { |
| LOG(ERROR) << "The .pstore file doesn't exist: " << pstore_path; |
| return false; |
| } |
| *out_path = pstore_path; |
| return true; |
| } |
| |
| } // namespace |
| |
| int main(int argc, char** argv) { |
| DEFINE_string(file, "", "path to a .pstore file (default: ARCVM's .pstore)"); |
| brillo::FlagHelper::Init( |
| argc, argv, |
| "A helper to read .pstore files generated by the ARCVM's guest kernel."); |
| |
| base::FilePath path; |
| if (!FLAGS_file.empty()) { |
| path = base::FilePath(FLAGS_file); |
| } else if (!FindARCVMPstorePath(&path)) { |
| LOG(ERROR) |
| << "Failed to detect the .pstore file. Please use --file option."; |
| exit(EXIT_FAILURE); |
| } |
| |
| if (!vm_tools::pstore_dump::HandlePstore(path)) { |
| exit(EXIT_FAILURE); |
| } |
| exit(EXIT_SUCCESS); |
| } |