blob: 221582e60dfb9a08c484da64aad89095bcec5046 [file] [log] [blame]
// Copyright 2018 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 <sysexits.h>
#include <iostream>
#include <string>
#include <vector>
#include <base/logging.h>
#include <base/strings/string_split.h>
#include <brillo/flag_helper.h>
#include <chromeos/constants/imageloader.h>
#include <dbus/bus.h>
#include <libimageloader/manifest.h>
#include "dlcservice/dbus-proxies.h"
#include "dlcservice/proto_bindings/dlcservice.pb.h"
#include "dlcservice/utils.h"
using org::chromium::DlcServiceInterfaceProxy;
class DlcServiceUtil {
public:
DlcServiceUtil() {}
~DlcServiceUtil() {}
// Initialize the dlcservice proxy. Returns true on success, false otherwise.
// Sets the given error pointer on failure.
bool Init(int* error_ptr) {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::Bus> bus{new dbus::Bus{options}};
if (!bus->Connect()) {
LOG(ERROR) << "Failed to connect to DBus.";
*error_ptr = EX_UNAVAILABLE;
return false;
}
dlc_service_proxy_ = std::make_unique<DlcServiceInterfaceProxy>(bus);
return true;
}
// Install a list of DLC modules. Returns true if all modules install
// successfully, false otherwise.
bool Install(const std::vector<std::string>& dlc_ids,
const std::string& omaha_url,
int* error_ptr) {
brillo::ErrorPtr error;
std::string mount_point;
for (auto& dlc_id : dlc_ids) {
LOG(INFO) << "Attempting to install DLC module '" << dlc_id << "'.";
if (!dlc_service_proxy_->Install(dlc_id, omaha_url, &mount_point,
&error)) {
LOG(ERROR) << "Failed to install '" << dlc_id << "', "
<< error->GetMessage();
*error_ptr = EX_SOFTWARE;
return false;
}
LOG(INFO) << "'" << dlc_id << "' successfully installed and mounted at '"
<< mount_point << "'.";
}
return true;
}
// Uninstall a list of DLC modules. Returns true of all uninstall operations
// complete successfully, false otherwise. Sets the given error pointer on
// failure.
bool Uninstall(const std::vector<std::string>& dlc_ids, int* error_ptr) {
brillo::ErrorPtr error;
for (auto& dlc_id : dlc_ids) {
LOG(INFO) << "Attempting to uninstall DLC module '" << dlc_id << "'.";
if (!dlc_service_proxy_->Uninstall(dlc_id, &error)) {
LOG(ERROR) << "Failed to uninstall '" << dlc_id << "', "
<< error->GetMessage();
*error_ptr = EX_SOFTWARE;
return false;
}
LOG(INFO) << "'" << dlc_id << "' successfully uninstalled.";
}
return true;
}
// Retrieves a list of all installed DLC modules. Returns true if the list is
// retrieved successfully, false otherwise. Sets the given error pointer on
// failure.
bool GetInstalled(dlcservice::DlcModuleList* dlc_module_list,
int* error_ptr) {
std::string dlc_module_list_string;
brillo::ErrorPtr error;
if (!dlc_service_proxy_->GetInstalled(&dlc_module_list_string, &error)) {
LOG(ERROR) << "Failed to get the list of installed DLC modules, "
<< error->GetMessage();
*error_ptr = EX_SOFTWARE;
return false;
}
if (!dlc_module_list->ParseFromString(dlc_module_list_string)) {
LOG(ERROR) << "Failed to parse DlcModuleList protobuf.";
*error_ptr = EX_SOFTWARE;
return false;
}
return true;
}
// Prints the information contained in the manifest of a DLC.
static bool PrintDlcDetails(const std::string& dlc_id) {
imageloader::Manifest manifest;
if (!dlcservice::utils::GetDlcManifest(
base::FilePath(imageloader::kDlcManifestRootpath), dlc_id,
&manifest)) {
LOG(ERROR) << "Failed to get DLC module manifest.";
return false;
}
std::cout << "\tname: " << manifest.name() << std::endl;
std::cout << "\tid: " << manifest.id() << std::endl;
std::cout << "\tversion: " << manifest.version() << std::endl;
std::cout << "\tmanifest version: " << manifest.manifest_version()
<< std::endl;
std::cout << "\tpreallocated size: " << manifest.preallocated_size()
<< std::endl;
std::cout << "\tsize: " << manifest.size() << std::endl;
std::cout << "\timage type: " << manifest.image_type() << std::endl;
std::cout << "\tremovable: " << (manifest.is_removable() ? "true" : "false")
<< std::endl;
std::cout << "\tfs-type: ";
switch (manifest.fs_type()) {
case imageloader::FileSystem::kExt4:
std::cout << "ext4" << std::endl;
break;
case imageloader::FileSystem::kSquashFS:
std::cout << "squashfs" << std::endl;
break;
}
return true;
}
private:
std::unique_ptr<DlcServiceInterfaceProxy> dlc_service_proxy_;
DISALLOW_COPY_AND_ASSIGN(DlcServiceUtil);
};
int main(int argc, const char** argv) {
DEFINE_bool(install, false, "Install a given list of DLC modules.");
DEFINE_bool(uninstall, false, "Uninstall a given list of DLC modules.");
DEFINE_bool(list, false, "List all installed DLC modules.");
DEFINE_bool(oneline, false, "Print short module DLC module information.");
DEFINE_string(dlc_ids, "", "Colon separated list of DLC module ids.");
DEFINE_string(omaha_url, "",
"Overrides the default Omaha URL in the update_engine.");
brillo::FlagHelper::Init(argc, argv, "dlcservice_util");
// Enforce mutually exclusive flags. Additional exclusive flags can be added
// to this list.
auto exclusive_flags = {FLAGS_install, FLAGS_uninstall, FLAGS_list};
if (std::count(exclusive_flags.begin(), exclusive_flags.end(), true) != 1) {
LOG(ERROR) << "Exactly one of --install, --uninstall, --list must be set.";
return EX_SOFTWARE;
}
int error;
DlcServiceUtil client;
if (!client.Init(&error)) {
LOG(ERROR) << "Failed to initialize client.";
return error;
}
if (FLAGS_install) {
std::vector<std::string> dlc_id_list = SplitString(
FLAGS_dlc_ids, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (dlc_id_list.empty()) {
LOG(ERROR) << "Please specify a list of DLC modules to install.";
return EX_SOFTWARE;
}
if (!client.Install(dlc_id_list, FLAGS_omaha_url, &error)) {
LOG(ERROR) << "Failed to install DLC modules.";
return error;
}
} else if (FLAGS_uninstall) {
std::vector<std::string> dlc_id_list = SplitString(
FLAGS_dlc_ids, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (dlc_id_list.empty()) {
LOG(ERROR) << "Please specify a list of DLC modules to uninstall.";
return EX_SOFTWARE;
}
if (!client.Uninstall(dlc_id_list, &error)) {
LOG(ERROR) << "Failed to uninstall DLC modules.";
return error;
}
} else if (FLAGS_list) {
dlcservice::DlcModuleList dlc_module_list;
if (!client.GetInstalled(&dlc_module_list, &error)) {
LOG(ERROR) << "Failed to get DLC module list.";
return error;
}
std::cout << "Installed DLC modules:\n";
for (const auto& dlc_module_info : dlc_module_list.dlc_module_infos()) {
std::cout << dlc_module_info.dlc_id() << std::endl;
if (!FLAGS_oneline) {
if (!DlcServiceUtil::PrintDlcDetails(dlc_module_info.dlc_id()))
LOG(ERROR) << "Failed to print details of DLC '"
<< dlc_module_info.dlc_id() << "'.";
}
}
}
return EX_OK;
}