blob: 01538a35f372d45322a14ac359b45b92b56fcace [file] [log] [blame] [edit]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "spaced/disk_usage_proxy.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/files/scoped_file.h>
#include <base/functional/callback.h>
#include <base/functional/callback_helpers.h>
#include <base/logging.h>
#include <spaced/proto_bindings/spaced.pb.h>
namespace spaced {
namespace {
void LogOnSignalConnected(const std::string& interface_name,
const std::string& signal_name,
bool success) {
if (!success) {
LOG(ERROR) << "Failed to connect to signal " << signal_name
<< " of interface " << interface_name;
}
}
} // namespace
DiskUsageProxy::DiskUsageProxy(
std::unique_ptr<org::chromium::SpacedProxyInterface> spaced_proxy)
: spaced_proxy_(std::move(spaced_proxy)) {}
std::unique_ptr<DiskUsageProxy> DiskUsageProxy::Generate() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::Bus> bus = new dbus::Bus(options);
if (!bus->Connect()) {
LOG(ERROR) << "D-Bus system bus is not ready";
return nullptr;
}
return std::make_unique<DiskUsageProxy>(
std::make_unique<org::chromium::SpacedProxy>(bus));
}
int64_t DiskUsageProxy::GetFreeDiskSpace(const base::FilePath& path) {
int64_t free_disk_space;
brillo::ErrorPtr error;
// Return -1 if call fails.
if (!spaced_proxy_->GetFreeDiskSpace(path.value(), &free_disk_space,
&error)) {
LOG(ERROR) << "Failed to call GetFreeDiskSpace, error: "
<< error->GetMessage();
return -1;
}
return free_disk_space;
}
void DiskUsageProxy::GetFreeDiskSpaceAsync(
const base::FilePath& path, base::OnceCallback<void(int64_t)> callback) {
auto splitted_callbacks = base::SplitOnceCallback(std::move(callback));
spaced_proxy_->GetFreeDiskSpaceAsync(
path.value(), std::move(splitted_callbacks.first),
base::BindOnce(
[](base::OnceCallback<void(int64_t)> callback, brillo::Error* error) {
LOG(ERROR) << "Failed to GetFreeDiskSpaceAsync: "
<< error->GetMessage();
std::move(callback).Run(-1);
},
std::move(splitted_callbacks.second)));
}
int64_t DiskUsageProxy::GetTotalDiskSpace(const base::FilePath& path) {
int64_t total_disk_space;
brillo::ErrorPtr error;
// Return -1 if call fails.
if (!spaced_proxy_->GetTotalDiskSpace(path.value(), &total_disk_space,
&error)) {
LOG(ERROR) << "Failed to call GetTotalDiskSpace, error: "
<< error->GetMessage();
return -1;
}
return total_disk_space;
}
int64_t DiskUsageProxy::GetRootDeviceSize() {
int64_t root_device_size;
brillo::ErrorPtr error;
// Return -1 if call fails.
if (!spaced_proxy_->GetRootDeviceSize(&root_device_size, &error)) {
LOG(ERROR) << "Failed to call GetRootDeviceSize, error: "
<< error->GetMessage();
return -1;
}
return root_device_size;
}
bool DiskUsageProxy::IsQuotaSupported(const base::FilePath& path) {
bool is_supported = false;
brillo::ErrorPtr error;
// Return false if call fails.
if (!spaced_proxy_->IsQuotaSupported(path.value(), &is_supported, &error)) {
LOG(ERROR) << "Failed to call IsQuotaSupported, error: "
<< error->GetMessage();
return false;
}
return is_supported;
}
int64_t DiskUsageProxy::GetQuotaCurrentSpaceForUid(const base::FilePath& path,
uint32_t uid) {
int64_t current_space = 0;
brillo::ErrorPtr error;
// Return -1 if call fails.
if (!spaced_proxy_->GetQuotaCurrentSpaceForUid(path.value(), uid,
&current_space, &error)) {
LOG(ERROR) << "Failed to call GetQuotaCurrentSpaceForUid, error: "
<< error->GetMessage();
return -1;
}
return current_space;
}
int64_t DiskUsageProxy::GetQuotaCurrentSpaceForGid(const base::FilePath& path,
uint32_t gid) {
int64_t current_space = 0;
brillo::ErrorPtr error;
// Return -1 if call fails.
if (!spaced_proxy_->GetQuotaCurrentSpaceForGid(path.value(), gid,
&current_space, &error)) {
LOG(ERROR) << "Failed to call GetQuotaCurrentSpaceForGid, error: "
<< error->GetMessage();
return -1;
}
return current_space;
}
int64_t DiskUsageProxy::GetQuotaCurrentSpaceForProjectId(
const base::FilePath& path, uint32_t project_id) {
int64_t current_space = 0;
brillo::ErrorPtr error;
// Return -1 if call fails.
if (!spaced_proxy_->GetQuotaCurrentSpaceForGid(path.value(), project_id,
&current_space, &error)) {
LOG(ERROR) << "Failed to call GetQuotaCurrentSpaceForProjectId, error: "
<< error->GetMessage();
return -1;
}
return current_space;
}
GetQuotaCurrentSpacesForIdsReply DiskUsageProxy::GetQuotaCurrentSpacesForIds(
const base::FilePath& path,
const std::vector<uint32_t>& uids,
const std::vector<uint32_t>& gids,
const std::vector<uint32_t>& project_ids) {
GetQuotaCurrentSpacesForIdsRequest request;
request.set_path(path.value());
request.mutable_uids()->Add(uids.begin(), uids.end());
request.mutable_gids()->Add(gids.begin(), gids.end());
request.mutable_project_ids()->Add(project_ids.begin(), project_ids.end());
GetQuotaCurrentSpacesForIdsReply reply;
brillo::ErrorPtr error;
if (!spaced_proxy_->GetQuotaCurrentSpacesForIds(request, &reply, &error)) {
LOG(ERROR) << "Failed to call GetQuotaCurrentSpacesForIds, error: "
<< error->GetMessage();
}
return reply;
}
bool DiskUsageProxy::SetProjectId(const base::ScopedFD& fd,
uint32_t project_id,
int* out_error) {
SetProjectIdReply result;
brillo::ErrorPtr error;
// Return false if call fails.
if (!spaced_proxy_->SetProjectId(fd, project_id, &result, &error)) {
*out_error = result.error();
LOG(ERROR) << "Failed to call SetProjectId, error: " << error->GetMessage();
return false;
}
return result.success();
}
bool DiskUsageProxy::SetProjectInheritanceFlag(const base::ScopedFD& fd,
bool enable,
int* out_error) {
SetProjectInheritanceFlagReply result;
brillo::ErrorPtr error;
// Return false if call fails.
if (!spaced_proxy_->SetProjectInheritanceFlag(fd, enable, &result, &error)) {
*out_error = result.error();
LOG(ERROR) << "Failed to call SetProjectInheritanceFlag, error: "
<< error->GetMessage();
return false;
}
return result.success();
}
void DiskUsageProxy::OnStatefulDiskSpaceUpdate(
const StatefulDiskSpaceUpdate& update) {
for (SpacedObserverInterface& observer : observer_list_) {
observer.OnStatefulDiskSpaceUpdate(update);
}
}
void DiskUsageProxy::AddObserver(SpacedObserverInterface* observer) {
CHECK(observer) << "Invalid observer";
observer_list_.AddObserver(observer);
}
void DiskUsageProxy::RemoveObserver(SpacedObserverInterface* observer) {
CHECK(observer) << "Invalid observer";
observer_list_.RemoveObserver(observer);
}
void DiskUsageProxy::StartMonitoring() {
spaced_proxy_->RegisterStatefulDiskSpaceUpdateSignalHandler(
base::BindRepeating(&DiskUsageProxy::OnStatefulDiskSpaceUpdate,
base::Unretained(this)),
base::BindOnce(LogOnSignalConnected));
}
} // namespace spaced