blob: 802a8008bb50e6673756d1d840a590a9310359de [file] [log] [blame]
Ryan Cairnsea6505f2011-04-10 19:54:53 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Chan5ccd9fe2013-11-13 18:28:27 -08005#include "cros-disks/cros_disks_server.h"
Ben Chan6e726922011-06-28 15:54:32 -07006
Ben Chan445852f2017-10-02 23:00:16 -07007#include <utility>
8
Qijiang Fan713061e2021-03-08 15:45:12 +09009#include <base/check.h>
Ben Chanf51ff002011-04-25 12:41:57 -070010#include <base/logging.h>
Ben Chan6d0b2722011-11-18 08:24:14 -080011#include <chromeos/dbus/service_constants.h>
Ryan Cairnsea6505f2011-04-10 19:54:53 -070012
Ben Chan5ccd9fe2013-11-13 18:28:27 -080013#include "cros-disks/device_event.h"
Ben Chanbdc39742011-05-11 17:51:26 -070014#include "cros-disks/disk.h"
Ben Chan5ccd9fe2013-11-13 18:28:27 -080015#include "cros-disks/disk_manager.h"
Sergei Datsenko16821892019-04-05 11:26:38 +110016#include "cros-disks/disk_monitor.h"
François Degrosbf7bb592019-07-12 09:49:52 +100017#include "cros-disks/error_logger.h"
Ben Chan5ccd9fe2013-11-13 18:28:27 -080018#include "cros-disks/format_manager.h"
Omid Tourzan7943a9d2020-08-31 13:54:36 +100019#include "cros-disks/partition_manager.h"
Ben Chan8dcede82011-07-25 20:56:13 -070020#include "cros-disks/platform.h"
François Degros8b4e31e2019-07-29 11:39:19 +100021#include "cros-disks/quote.h"
Klemen Kozjekb0658852017-08-15 13:03:48 +090022#include "cros-disks/rename_manager.h"
Szymon Sidor2733b512011-06-30 18:00:51 -070023
Ben Chan460439f2011-09-13 09:16:28 -070024namespace cros_disks {
Ryan Cairnsea6505f2011-04-10 19:54:53 -070025
Ben Chan445852f2017-10-02 23:00:16 -070026CrosDisksServer::CrosDisksServer(scoped_refptr<dbus::Bus> bus,
Ben Chan8dcede82011-07-25 20:56:13 -070027 Platform* platform,
Sergei Datsenko16821892019-04-05 11:26:38 +110028 DiskMonitor* disk_monitor,
Klemen Kozjekb0658852017-08-15 13:03:48 +090029 FormatManager* format_manager,
Omid Tourzan7943a9d2020-08-31 13:54:36 +100030 PartitionManager* partition_manager,
Klemen Kozjekb0658852017-08-15 13:03:48 +090031 RenameManager* rename_manager)
Ben Chan445852f2017-10-02 23:00:16 -070032 : org::chromium::CrosDisksAdaptor(this),
33 dbus_object_(nullptr, bus, dbus::ObjectPath(kCrosDisksServicePath)),
Ben Chan8dcede82011-07-25 20:56:13 -070034 platform_(platform),
Sergei Datsenko16821892019-04-05 11:26:38 +110035 disk_monitor_(disk_monitor),
Klemen Kozjekb0658852017-08-15 13:03:48 +090036 format_manager_(format_manager),
Omid Tourzan7943a9d2020-08-31 13:54:36 +100037 partition_manager_(partition_manager),
Klemen Kozjekb0658852017-08-15 13:03:48 +090038 rename_manager_(rename_manager) {
Ben Chan8dcede82011-07-25 20:56:13 -070039 CHECK(platform_) << "Invalid platform object";
Sergei Datsenko16821892019-04-05 11:26:38 +110040 CHECK(disk_monitor_) << "Invalid disk monitor object";
Ben Chanb092d752011-07-13 11:44:38 -070041 CHECK(format_manager_) << "Invalid format manager object";
Omid Tourzan7943a9d2020-08-31 13:54:36 +100042 CHECK(partition_manager_) << "Invalid partition manager object";
Klemen Kozjekb0658852017-08-15 13:03:48 +090043 CHECK(rename_manager_) << "Invalid rename manager object";
Szymon Sidor2733b512011-06-30 18:00:51 -070044
Ben Chanc1e766c2011-11-21 12:56:59 -080045 format_manager_->set_observer(this);
Klemen Kozjekb0658852017-08-15 13:03:48 +090046 rename_manager_->set_observer(this);
Ben Chanf51ff002011-04-25 12:41:57 -070047}
Ryan Cairnsea6505f2011-04-10 19:54:53 -070048
Ben Chan445852f2017-10-02 23:00:16 -070049void CrosDisksServer::RegisterAsync(
50 const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
51 RegisterWithDBusObject(&dbus_object_);
52 dbus_object_.RegisterAsync(cb);
53}
54
Ben Chanf47fc352013-05-03 11:28:57 -070055void CrosDisksServer::RegisterMountManager(MountManager* mount_manager) {
56 CHECK(mount_manager) << "Invalid mount manager object";
57 mount_managers_.push_back(mount_manager);
58}
59
Ben Chan213c6d92019-04-10 16:21:52 -070060void CrosDisksServer::Format(const std::string& path,
61 const std::string& filesystem_type,
62 const std::vector<std::string>& options) {
Ben Chanc833a522012-09-27 23:47:00 -070063 FormatErrorType error_type = FORMAT_ERROR_NONE;
64 Disk disk;
Sergei Datsenko16821892019-04-05 11:26:38 +110065 if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(path), &disk)) {
Ben Chanc833a522012-09-27 23:47:00 -070066 error_type = FORMAT_ERROR_INVALID_DEVICE_PATH;
Ben Chanc833a522012-09-27 23:47:00 -070067 } else {
Ben Chanff92fa32017-10-17 16:17:15 -070068 error_type = format_manager_->StartFormatting(path, disk.device_file,
Austin Tankiange1a317c2019-06-12 18:02:20 +100069 filesystem_type, options);
Ben Chanc833a522012-09-27 23:47:00 -070070 }
71
Ben Chanc1e766c2011-11-21 12:56:59 -080072 if (error_type != FORMAT_ERROR_NONE) {
François Degros8b4e31e2019-07-29 11:39:19 +100073 LOG(ERROR) << "Could not format device " << quote(path) << " as filesystem "
74 << quote(filesystem_type) << ": " << error_type;
Ben Chan445852f2017-10-02 23:00:16 -070075 SendFormatCompletedSignal(error_type, path);
Szymon Sidor2733b512011-06-30 18:00:51 -070076 }
Szymon Sidor2733b512011-06-30 18:00:51 -070077}
78
Omid Tourzan7943a9d2020-08-31 13:54:36 +100079void CrosDisksServer::SinglePartitionFormat(
80 std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<uint32_t>> response,
81 const std::string& path) {
82 Disk disk;
83
84 if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(path), &disk)) {
85 LOG(ERROR) << "Invalid device path: " << quote(path)
86 << " error code: " << PARTITION_ERROR_INVALID_DEVICE_PATH;
87 response->Return(PARTITION_ERROR_INVALID_DEVICE_PATH);
88 } else if (disk.is_on_boot_device || !disk.is_drive || disk.is_read_only) {
89 LOG(ERROR) << "Device not allowed: " << quote(path)
90 << " error code: " << PARTITION_ERROR_DEVICE_NOT_ALLOWED;
91 response->Return(PARTITION_ERROR_DEVICE_NOT_ALLOWED);
92 } else {
93 partition_manager_->StartSinglePartitionFormat(
94 base::FilePath(disk.device_file),
95 base::BindOnce(&CrosDisksServer::OnPartitionCompleted,
96 base::Unretained(this), std::move(response)));
97 }
98}
99
Ben Chan213c6d92019-04-10 16:21:52 -0700100void CrosDisksServer::Rename(const std::string& path,
101 const std::string& volume_name) {
Klemen Kozjekb0658852017-08-15 13:03:48 +0900102 RenameErrorType error_type = RENAME_ERROR_NONE;
103 Disk disk;
Sergei Datsenko16821892019-04-05 11:26:38 +1100104 if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(path), &disk)) {
Klemen Kozjekb0658852017-08-15 13:03:48 +0900105 error_type = RENAME_ERROR_INVALID_DEVICE_PATH;
Klemen Kozjekb0658852017-08-15 13:03:48 +0900106 } else {
Ben Chande0e3f62017-09-26 06:28:39 -0700107 error_type = rename_manager_->StartRenaming(
Ben Chanff92fa32017-10-17 16:17:15 -0700108 path, disk.device_file, volume_name, disk.filesystem_type);
Klemen Kozjekb0658852017-08-15 13:03:48 +0900109 }
110
111 if (error_type != RENAME_ERROR_NONE) {
François Degros8b4e31e2019-07-29 11:39:19 +1000112 LOG(ERROR) << "Could not rename device " << quote(path) << " as "
113 << quote(volume_name) << ": " << error_type;
Ben Chan445852f2017-10-02 23:00:16 -0700114 SendRenameCompletedSignal(error_type, path);
Klemen Kozjekb0658852017-08-15 13:03:48 +0900115 }
116}
117
Ben Chan213c6d92019-04-10 16:21:52 -0700118MountManager* CrosDisksServer::FindMounter(
119 const std::string& source_path) const {
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900120 for (const auto& manager : mount_managers_) {
121 if (manager->CanMount(source_path)) {
122 return manager;
123 }
124 }
125 return nullptr;
126}
127
Ben Chan213c6d92019-04-10 16:21:52 -0700128void CrosDisksServer::Mount(const std::string& source,
129 const std::string& filesystem_type,
130 const std::vector<std::string>& options) {
Ben Chanfcb2fc02011-11-21 09:44:07 -0800131 MountErrorType error_type = MOUNT_ERROR_INVALID_PATH;
Ben Chan6d0b2722011-11-18 08:24:14 -0800132 MountSourceType source_type = MOUNT_SOURCE_INVALID;
Ben Chan213c6d92019-04-10 16:21:52 -0700133 std::string mount_path;
Ben Chan8dcede82011-07-25 20:56:13 -0700134
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000135 MountManager* mounter = FindMounter(source);
136 if (mounter) {
137 source_type = mounter->GetMountSourceType();
138 error_type = mounter->Mount(source, filesystem_type, options, &mount_path);
Ben Chan8dcede82011-07-25 20:56:13 -0700139 }
140
Ben Chanfcb2fc02011-11-21 09:44:07 -0800141 if (error_type != MOUNT_ERROR_NONE) {
François Degrosca450862021-01-14 14:40:02 +1100142 LOG(ERROR) << "Cannot mount " << redact(source) << " of type "
143 << quote(filesystem_type) << ": " << error_type;
Ben Chand3fdc722011-07-21 18:15:22 -0700144 }
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000145 SendMountCompletedSignal(error_type, source, source_type, mount_path);
Ben Chand3fdc722011-07-21 18:15:22 -0700146}
147
Ben Chan213c6d92019-04-10 16:21:52 -0700148uint32_t CrosDisksServer::Unmount(const std::string& path,
149 const std::vector<std::string>& options) {
François Degros3fe77c52020-02-20 14:44:54 +1100150 if (path.empty()) {
151 LOG(ERROR) << "Cannot unmount an empty path";
152 return MOUNT_ERROR_INVALID_ARGUMENT;
153 }
154
155 LOG_IF(WARNING, !options.empty())
156 << "Ignoring non-empty unmount options " << quote(options);
Anand K Mistry5a6d5fa2019-11-05 17:21:48 +1100157
Ben Chanfcb2fc02011-11-21 09:44:07 -0800158 MountErrorType error_type = MOUNT_ERROR_INVALID_PATH;
Ben Chan63ec9c42014-04-21 19:13:23 -0700159 for (const auto& manager : mount_managers_) {
François Degros3fe77c52020-02-20 14:44:54 +1100160 error_type = manager->Unmount(path);
161 if (error_type != MOUNT_ERROR_PATH_NOT_MOUNTED)
Ben Chan8dcede82011-07-25 20:56:13 -0700162 break;
Ben Chan8dcede82011-07-25 20:56:13 -0700163 }
164
François Degros3fe77c52020-02-20 14:44:54 +1100165 LOG_IF(ERROR, error_type != MOUNT_ERROR_NONE)
166 << "Cannot unmount " << quote(path) << ": " << error_type;
167
Anand K Mistry36d2b302018-08-15 14:57:05 +1000168 return error_type;
Ben Chand3fdc722011-07-21 18:15:22 -0700169}
170
Ben Chan445852f2017-10-02 23:00:16 -0700171void CrosDisksServer::UnmountAll() {
Ben Chan63ec9c42014-04-21 19:13:23 -0700172 for (const auto& manager : mount_managers_) {
Ben Chan8f513762011-11-14 12:44:42 -0800173 manager->UnmountAll();
174 }
175}
176
Ben Chan213c6d92019-04-10 16:21:52 -0700177std::vector<std::string> CrosDisksServer::EnumerateDevices() {
178 std::vector<Disk> disks = disk_monitor_->EnumerateDisks();
179 std::vector<std::string> devices;
Ben Chanf51ff002011-04-25 12:41:57 -0700180 devices.reserve(disks.size());
Ben Chan63ec9c42014-04-21 19:13:23 -0700181 for (const auto& disk : disks) {
Anand K Mistryd268ae32018-08-13 14:15:10 +1000182 devices.push_back(disk.native_path);
Ben Chan490319f2011-05-06 14:00:42 -0700183 }
Ben Chanf51ff002011-04-25 12:41:57 -0700184 return devices;
185}
186
Ben Chan213c6d92019-04-10 16:21:52 -0700187std::vector<CrosDisksServer::DBusMountEntry>
Ben Chan445852f2017-10-02 23:00:16 -0700188CrosDisksServer::EnumerateMountEntries() {
Ben Chan213c6d92019-04-10 16:21:52 -0700189 std::vector<DBusMountEntry> dbus_mount_entries;
Ben Chan8fb742b2014-04-28 23:46:57 -0700190 for (const auto& manager : mount_managers_) {
Ben Chan7dfb8102017-10-17 15:47:37 -0700191 for (const auto& mount_entry : manager->GetMountEntries()) {
Ben Chan0214e302017-10-17 15:39:16 -0700192 dbus_mount_entries.push_back(
Ben Chan445852f2017-10-02 23:00:16 -0700193 std::make_tuple(static_cast<uint32_t>(mount_entry.error_type),
194 mount_entry.source_path,
195 static_cast<uint32_t>(mount_entry.source_type),
196 mount_entry.mount_path));
Ben Chan8fb742b2014-04-28 23:46:57 -0700197 }
198 }
199 return dbus_mount_entries;
200}
201
Ben Chan445852f2017-10-02 23:00:16 -0700202bool CrosDisksServer::GetDeviceProperties(
203 brillo::ErrorPtr* error,
Ben Chan213c6d92019-04-10 16:21:52 -0700204 const std::string& device_path,
Ben Chan445852f2017-10-02 23:00:16 -0700205 brillo::VariantDictionary* properties) {
Ben Chanf51ff002011-04-25 12:41:57 -0700206 Disk disk;
Sergei Datsenko16821892019-04-05 11:26:38 +1100207 if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(device_path), &disk)) {
Ben Chan213c6d92019-04-10 16:21:52 -0700208 std::string message =
209 "Could not get the properties of device " + device_path;
Ben Chanf51ff002011-04-25 12:41:57 -0700210 LOG(ERROR) << message;
Ben Chan445852f2017-10-02 23:00:16 -0700211 brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
212 kCrosDisksServiceError, message);
213 return false;
Ben Chanf51ff002011-04-25 12:41:57 -0700214 }
Ben Chanff92fa32017-10-17 16:17:15 -0700215
Ben Chan445852f2017-10-02 23:00:16 -0700216 brillo::VariantDictionary temp_properties;
Ben Chan72640ea2018-07-26 18:09:53 -0700217 temp_properties[kIsAutoMountable] = disk.is_auto_mountable;
Ben Chan445852f2017-10-02 23:00:16 -0700218 temp_properties[kDeviceIsDrive] = disk.is_drive;
219 temp_properties[kDevicePresentationHide] = disk.is_hidden;
220 temp_properties[kDeviceIsMounted] = disk.IsMounted();
221 temp_properties[kDeviceIsMediaAvailable] = disk.is_media_available;
222 temp_properties[kDeviceIsOnBootDevice] = disk.is_on_boot_device;
223 temp_properties[kDeviceIsOnRemovableDevice] = disk.is_on_removable_device;
224 temp_properties[kDeviceIsVirtual] = disk.is_virtual;
Austin Tankiang36f5bb52019-03-25 16:49:30 +1100225 temp_properties[kStorageDevicePath] = disk.storage_device_path;
Ben Chan445852f2017-10-02 23:00:16 -0700226 temp_properties[kDeviceFile] = disk.device_file;
227 temp_properties[kIdUuid] = disk.uuid;
228 temp_properties[kIdLabel] = disk.label;
229 temp_properties[kVendorId] = disk.vendor_id;
230 temp_properties[kVendorName] = disk.vendor_name;
231 temp_properties[kProductId] = disk.product_id;
232 temp_properties[kProductName] = disk.product_name;
233 temp_properties[kDriveModel] = disk.drive_model;
Ben Chan445852f2017-10-02 23:00:16 -0700234 temp_properties[kDeviceMediaType] = static_cast<uint32_t>(disk.media_type);
Timothy Lohd8133442020-11-03 16:21:07 +1100235 temp_properties[kBusNumber] = disk.bus_number;
236 temp_properties[kDeviceNumber] = disk.device_number;
Ben Chan445852f2017-10-02 23:00:16 -0700237 temp_properties[kDeviceSize] = disk.device_capacity;
238 temp_properties[kDeviceIsReadOnly] = disk.is_read_only;
239 temp_properties[kFileSystemType] = disk.filesystem_type;
240 temp_properties[kDeviceMountPaths] = disk.mount_paths;
241 *properties = std::move(temp_properties);
242 return true;
Ben Chanf51ff002011-04-25 12:41:57 -0700243}
244
Sergei Datsenkoad8b5042020-09-21 22:39:04 +1000245void CrosDisksServer::AddDeviceToAllowlist(const std::string& device_path) {
246 disk_monitor_->AddDeviceToAllowlist(base::FilePath(device_path));
247}
248
249void CrosDisksServer::RemoveDeviceFromAllowlist(
250 const std::string& device_path) {
251 disk_monitor_->RemoveDeviceFromAllowlist(base::FilePath(device_path));
252}
253
Ben Chan213c6d92019-04-10 16:21:52 -0700254void CrosDisksServer::OnFormatCompleted(const std::string& device_path,
Ben Chanc1e766c2011-11-21 12:56:59 -0800255 FormatErrorType error_type) {
Ben Chan445852f2017-10-02 23:00:16 -0700256 SendFormatCompletedSignal(error_type, device_path);
Ben Chanc1e766c2011-11-21 12:56:59 -0800257}
258
Omid Tourzan7943a9d2020-08-31 13:54:36 +1000259void CrosDisksServer::OnPartitionCompleted(
260 std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<uint32_t>> response,
261 const base::FilePath& device_path,
262 PartitionErrorType error_type) {
263 LOG(ERROR) << "Partitioning for device " << quote(device_path)
264 << " completed, result code: " << std::to_string(error_type);
265 response->Return(error_type);
266}
267
Ben Chan213c6d92019-04-10 16:21:52 -0700268void CrosDisksServer::OnRenameCompleted(const std::string& device_path,
Klemen Kozjekb0658852017-08-15 13:03:48 +0900269 RenameErrorType error_type) {
Ben Chan445852f2017-10-02 23:00:16 -0700270 SendRenameCompletedSignal(error_type, device_path);
Klemen Kozjekb0658852017-08-15 13:03:48 +0900271}
272
Ben Chan5988f292012-09-18 08:32:42 -0700273void CrosDisksServer::OnScreenIsLocked() {
274 // no-op
275}
276
277void CrosDisksServer::OnScreenIsUnlocked() {
278 // no-op
279}
280
Ben Chanb3bf8d12013-04-23 13:57:55 -0700281void CrosDisksServer::OnSessionStarted() {
Ben Chan63ec9c42014-04-21 19:13:23 -0700282 for (const auto& manager : mount_managers_) {
Ben Chanb3bf8d12013-04-23 13:57:55 -0700283 manager->StartSession();
Ben Chan8dcede82011-07-25 20:56:13 -0700284 }
Ben Chan6e726922011-06-28 15:54:32 -0700285}
286
Ben Chanb3bf8d12013-04-23 13:57:55 -0700287void CrosDisksServer::OnSessionStopped() {
Ben Chan63ec9c42014-04-21 19:13:23 -0700288 for (const auto& manager : mount_managers_) {
Ben Chanb3bf8d12013-04-23 13:57:55 -0700289 manager->StopSession();
Ben Chan8dcede82011-07-25 20:56:13 -0700290 }
Ben Chan6e726922011-06-28 15:54:32 -0700291}
292
293void CrosDisksServer::DispatchDeviceEvent(const DeviceEvent& event) {
294 switch (event.event_type) {
295 case DeviceEvent::kDeviceAdded:
Ben Chan445852f2017-10-02 23:00:16 -0700296 SendDeviceAddedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700297 break;
298 case DeviceEvent::kDeviceScanned:
Ben Chan445852f2017-10-02 23:00:16 -0700299 SendDeviceScannedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700300 break;
301 case DeviceEvent::kDeviceRemoved:
Ben Chan445852f2017-10-02 23:00:16 -0700302 SendDeviceRemovedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700303 break;
304 case DeviceEvent::kDiskAdded:
Ben Chan445852f2017-10-02 23:00:16 -0700305 SendDiskAddedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700306 break;
Ben Chan6e726922011-06-28 15:54:32 -0700307 case DeviceEvent::kDiskChanged:
Ben Chan445852f2017-10-02 23:00:16 -0700308 SendDiskChangedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700309 break;
310 case DeviceEvent::kDiskRemoved:
Ben Chan445852f2017-10-02 23:00:16 -0700311 SendDiskRemovedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700312 break;
313 default:
314 break;
315 }
316}
317
Ben Chanbdc39742011-05-11 17:51:26 -0700318} // namespace cros_disks