blob: 3b9afa189690a340b15cf8e6b6d400803e2e73b5 [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
Ben Chanf51ff002011-04-25 12:41:57 -07009#include <base/logging.h>
Ben Chan6d0b2722011-11-18 08:24:14 -080010#include <chromeos/dbus/service_constants.h>
Ryan Cairnsea6505f2011-04-10 19:54:53 -070011
Ben Chan5ccd9fe2013-11-13 18:28:27 -080012#include "cros-disks/archive_manager.h"
13#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"
Ben Chan8dcede82011-07-25 20:56:13 -070019#include "cros-disks/platform.h"
François Degros8b4e31e2019-07-29 11:39:19 +100020#include "cros-disks/quote.h"
Klemen Kozjekb0658852017-08-15 13:03:48 +090021#include "cros-disks/rename_manager.h"
Szymon Sidor2733b512011-06-30 18:00:51 -070022
Ben Chan460439f2011-09-13 09:16:28 -070023namespace cros_disks {
Ryan Cairnsea6505f2011-04-10 19:54:53 -070024
Ben Chan445852f2017-10-02 23:00:16 -070025CrosDisksServer::CrosDisksServer(scoped_refptr<dbus::Bus> bus,
Ben Chan8dcede82011-07-25 20:56:13 -070026 Platform* platform,
Sergei Datsenko16821892019-04-05 11:26:38 +110027 DiskMonitor* disk_monitor,
Klemen Kozjekb0658852017-08-15 13:03:48 +090028 FormatManager* format_manager,
29 RenameManager* rename_manager)
Ben Chan445852f2017-10-02 23:00:16 -070030 : org::chromium::CrosDisksAdaptor(this),
31 dbus_object_(nullptr, bus, dbus::ObjectPath(kCrosDisksServicePath)),
Ben Chan8dcede82011-07-25 20:56:13 -070032 platform_(platform),
Sergei Datsenko16821892019-04-05 11:26:38 +110033 disk_monitor_(disk_monitor),
Klemen Kozjekb0658852017-08-15 13:03:48 +090034 format_manager_(format_manager),
35 rename_manager_(rename_manager) {
Ben Chan8dcede82011-07-25 20:56:13 -070036 CHECK(platform_) << "Invalid platform object";
Sergei Datsenko16821892019-04-05 11:26:38 +110037 CHECK(disk_monitor_) << "Invalid disk monitor object";
Ben Chanb092d752011-07-13 11:44:38 -070038 CHECK(format_manager_) << "Invalid format manager object";
Klemen Kozjekb0658852017-08-15 13:03:48 +090039 CHECK(rename_manager_) << "Invalid rename manager object";
Szymon Sidor2733b512011-06-30 18:00:51 -070040
Ben Chanc1e766c2011-11-21 12:56:59 -080041 format_manager_->set_observer(this);
Klemen Kozjekb0658852017-08-15 13:03:48 +090042 rename_manager_->set_observer(this);
Ben Chanf51ff002011-04-25 12:41:57 -070043}
Ryan Cairnsea6505f2011-04-10 19:54:53 -070044
Ben Chan445852f2017-10-02 23:00:16 -070045void CrosDisksServer::RegisterAsync(
46 const brillo::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
47 RegisterWithDBusObject(&dbus_object_);
48 dbus_object_.RegisterAsync(cb);
49}
50
Ben Chanf47fc352013-05-03 11:28:57 -070051void CrosDisksServer::RegisterMountManager(MountManager* mount_manager) {
52 CHECK(mount_manager) << "Invalid mount manager object";
53 mount_managers_.push_back(mount_manager);
54}
55
Ben Chan213c6d92019-04-10 16:21:52 -070056void CrosDisksServer::Format(const std::string& path,
57 const std::string& filesystem_type,
58 const std::vector<std::string>& options) {
Ben Chanc833a522012-09-27 23:47:00 -070059 FormatErrorType error_type = FORMAT_ERROR_NONE;
60 Disk disk;
Sergei Datsenko16821892019-04-05 11:26:38 +110061 if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(path), &disk)) {
Ben Chanc833a522012-09-27 23:47:00 -070062 error_type = FORMAT_ERROR_INVALID_DEVICE_PATH;
Ben Chanff92fa32017-10-17 16:17:15 -070063 } else if (disk.is_on_boot_device) {
Ben Chanc833a522012-09-27 23:47:00 -070064 error_type = FORMAT_ERROR_DEVICE_NOT_ALLOWED;
65 } else {
Ben Chanff92fa32017-10-17 16:17:15 -070066 error_type = format_manager_->StartFormatting(path, disk.device_file,
Austin Tankiange1a317c2019-06-12 18:02:20 +100067 filesystem_type, options);
Ben Chanc833a522012-09-27 23:47:00 -070068 }
69
Ben Chanc1e766c2011-11-21 12:56:59 -080070 if (error_type != FORMAT_ERROR_NONE) {
François Degros8b4e31e2019-07-29 11:39:19 +100071 LOG(ERROR) << "Could not format device " << quote(path) << " as filesystem "
72 << quote(filesystem_type) << ": " << error_type;
Ben Chan445852f2017-10-02 23:00:16 -070073 SendFormatCompletedSignal(error_type, path);
Szymon Sidor2733b512011-06-30 18:00:51 -070074 }
Szymon Sidor2733b512011-06-30 18:00:51 -070075}
76
Ben Chan213c6d92019-04-10 16:21:52 -070077void CrosDisksServer::Rename(const std::string& path,
78 const std::string& volume_name) {
Klemen Kozjekb0658852017-08-15 13:03:48 +090079 RenameErrorType error_type = RENAME_ERROR_NONE;
80 Disk disk;
Sergei Datsenko16821892019-04-05 11:26:38 +110081 if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(path), &disk)) {
Klemen Kozjekb0658852017-08-15 13:03:48 +090082 error_type = RENAME_ERROR_INVALID_DEVICE_PATH;
Ben Chanff92fa32017-10-17 16:17:15 -070083 } else if (disk.is_on_boot_device || disk.is_read_only) {
Klemen Kozjekb0658852017-08-15 13:03:48 +090084 error_type = RENAME_ERROR_DEVICE_NOT_ALLOWED;
85 } else {
Ben Chande0e3f62017-09-26 06:28:39 -070086 error_type = rename_manager_->StartRenaming(
Ben Chanff92fa32017-10-17 16:17:15 -070087 path, disk.device_file, volume_name, disk.filesystem_type);
Klemen Kozjekb0658852017-08-15 13:03:48 +090088 }
89
90 if (error_type != RENAME_ERROR_NONE) {
François Degros8b4e31e2019-07-29 11:39:19 +100091 LOG(ERROR) << "Could not rename device " << quote(path) << " as "
92 << quote(volume_name) << ": " << error_type;
Ben Chan445852f2017-10-02 23:00:16 -070093 SendRenameCompletedSignal(error_type, path);
Klemen Kozjekb0658852017-08-15 13:03:48 +090094 }
95}
96
Ben Chan213c6d92019-04-10 16:21:52 -070097MountManager* CrosDisksServer::FindMounter(
98 const std::string& source_path) const {
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +090099 for (const auto& manager : mount_managers_) {
100 if (manager->CanMount(source_path)) {
101 return manager;
102 }
103 }
104 return nullptr;
105}
106
Ben Chan213c6d92019-04-10 16:21:52 -0700107void CrosDisksServer::Mount(const std::string& source,
108 const std::string& filesystem_type,
109 const std::vector<std::string>& options) {
François Degros853c7d92020-02-17 10:32:21 +1100110 if (base::StringPiece(filesystem_type).starts_with(".rar"))
111 ArchiveManager::SetActive(filesystem_type != ".rar2fs");
112
Ben Chanfcb2fc02011-11-21 09:44:07 -0800113 MountErrorType error_type = MOUNT_ERROR_INVALID_PATH;
Ben Chan6d0b2722011-11-18 08:24:14 -0800114 MountSourceType source_type = MOUNT_SOURCE_INVALID;
Ben Chan213c6d92019-04-10 16:21:52 -0700115 std::string mount_path;
Ben Chan8dcede82011-07-25 20:56:13 -0700116
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000117 MountManager* mounter = FindMounter(source);
118 if (mounter) {
119 source_type = mounter->GetMountSourceType();
120 error_type = mounter->Mount(source, filesystem_type, options, &mount_path);
Ben Chan8dcede82011-07-25 20:56:13 -0700121 }
122
Ben Chanfcb2fc02011-11-21 09:44:07 -0800123 if (error_type != MOUNT_ERROR_NONE) {
François Degros8b4e31e2019-07-29 11:39:19 +1000124 LOG(ERROR) << "Failed to mount " << quote(source) << ": " << error_type;
Ben Chand3fdc722011-07-21 18:15:22 -0700125 }
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000126 SendMountCompletedSignal(error_type, source, source_type, mount_path);
Ben Chand3fdc722011-07-21 18:15:22 -0700127}
128
Ben Chan213c6d92019-04-10 16:21:52 -0700129uint32_t CrosDisksServer::Unmount(const std::string& path,
130 const std::vector<std::string>& options) {
François Degros3fe77c52020-02-20 14:44:54 +1100131 if (path.empty()) {
132 LOG(ERROR) << "Cannot unmount an empty path";
133 return MOUNT_ERROR_INVALID_ARGUMENT;
134 }
135
136 LOG_IF(WARNING, !options.empty())
137 << "Ignoring non-empty unmount options " << quote(options);
Anand K Mistry5a6d5fa2019-11-05 17:21:48 +1100138
Ben Chanfcb2fc02011-11-21 09:44:07 -0800139 MountErrorType error_type = MOUNT_ERROR_INVALID_PATH;
Ben Chan63ec9c42014-04-21 19:13:23 -0700140 for (const auto& manager : mount_managers_) {
François Degros3fe77c52020-02-20 14:44:54 +1100141 error_type = manager->Unmount(path);
142 if (error_type != MOUNT_ERROR_PATH_NOT_MOUNTED)
Ben Chan8dcede82011-07-25 20:56:13 -0700143 break;
Ben Chan8dcede82011-07-25 20:56:13 -0700144 }
145
François Degros3fe77c52020-02-20 14:44:54 +1100146 LOG_IF(ERROR, error_type != MOUNT_ERROR_NONE)
147 << "Cannot unmount " << quote(path) << ": " << error_type;
148
Anand K Mistry36d2b302018-08-15 14:57:05 +1000149 return error_type;
Ben Chand3fdc722011-07-21 18:15:22 -0700150}
151
Ben Chan445852f2017-10-02 23:00:16 -0700152void CrosDisksServer::UnmountAll() {
Ben Chan63ec9c42014-04-21 19:13:23 -0700153 for (const auto& manager : mount_managers_) {
Ben Chan8f513762011-11-14 12:44:42 -0800154 manager->UnmountAll();
155 }
156}
157
Ben Chan213c6d92019-04-10 16:21:52 -0700158std::vector<std::string> CrosDisksServer::EnumerateDevices() {
159 std::vector<Disk> disks = disk_monitor_->EnumerateDisks();
160 std::vector<std::string> devices;
Ben Chanf51ff002011-04-25 12:41:57 -0700161 devices.reserve(disks.size());
Ben Chan63ec9c42014-04-21 19:13:23 -0700162 for (const auto& disk : disks) {
Anand K Mistryd268ae32018-08-13 14:15:10 +1000163 devices.push_back(disk.native_path);
Ben Chan490319f2011-05-06 14:00:42 -0700164 }
Ben Chanf51ff002011-04-25 12:41:57 -0700165 return devices;
166}
167
Ben Chan213c6d92019-04-10 16:21:52 -0700168std::vector<CrosDisksServer::DBusMountEntry>
Ben Chan445852f2017-10-02 23:00:16 -0700169CrosDisksServer::EnumerateMountEntries() {
Ben Chan213c6d92019-04-10 16:21:52 -0700170 std::vector<DBusMountEntry> dbus_mount_entries;
Ben Chan8fb742b2014-04-28 23:46:57 -0700171 for (const auto& manager : mount_managers_) {
Ben Chan7dfb8102017-10-17 15:47:37 -0700172 for (const auto& mount_entry : manager->GetMountEntries()) {
Ben Chan0214e302017-10-17 15:39:16 -0700173 dbus_mount_entries.push_back(
Ben Chan445852f2017-10-02 23:00:16 -0700174 std::make_tuple(static_cast<uint32_t>(mount_entry.error_type),
175 mount_entry.source_path,
176 static_cast<uint32_t>(mount_entry.source_type),
177 mount_entry.mount_path));
Ben Chan8fb742b2014-04-28 23:46:57 -0700178 }
179 }
180 return dbus_mount_entries;
181}
182
Ben Chan445852f2017-10-02 23:00:16 -0700183bool CrosDisksServer::GetDeviceProperties(
184 brillo::ErrorPtr* error,
Ben Chan213c6d92019-04-10 16:21:52 -0700185 const std::string& device_path,
Ben Chan445852f2017-10-02 23:00:16 -0700186 brillo::VariantDictionary* properties) {
Ben Chanf51ff002011-04-25 12:41:57 -0700187 Disk disk;
Sergei Datsenko16821892019-04-05 11:26:38 +1100188 if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(device_path), &disk)) {
Ben Chan213c6d92019-04-10 16:21:52 -0700189 std::string message =
190 "Could not get the properties of device " + device_path;
Ben Chanf51ff002011-04-25 12:41:57 -0700191 LOG(ERROR) << message;
Ben Chan445852f2017-10-02 23:00:16 -0700192 brillo::Error::AddTo(error, FROM_HERE, brillo::errors::dbus::kDomain,
193 kCrosDisksServiceError, message);
194 return false;
Ben Chanf51ff002011-04-25 12:41:57 -0700195 }
Ben Chanff92fa32017-10-17 16:17:15 -0700196
Ben Chan445852f2017-10-02 23:00:16 -0700197 brillo::VariantDictionary temp_properties;
Ben Chan72640ea2018-07-26 18:09:53 -0700198 temp_properties[kIsAutoMountable] = disk.is_auto_mountable;
Ben Chan445852f2017-10-02 23:00:16 -0700199 temp_properties[kDeviceIsDrive] = disk.is_drive;
200 temp_properties[kDevicePresentationHide] = disk.is_hidden;
201 temp_properties[kDeviceIsMounted] = disk.IsMounted();
202 temp_properties[kDeviceIsMediaAvailable] = disk.is_media_available;
203 temp_properties[kDeviceIsOnBootDevice] = disk.is_on_boot_device;
204 temp_properties[kDeviceIsOnRemovableDevice] = disk.is_on_removable_device;
205 temp_properties[kDeviceIsVirtual] = disk.is_virtual;
Austin Tankiang36f5bb52019-03-25 16:49:30 +1100206 temp_properties[kStorageDevicePath] = disk.storage_device_path;
Ben Chan445852f2017-10-02 23:00:16 -0700207 temp_properties[kDeviceFile] = disk.device_file;
208 temp_properties[kIdUuid] = disk.uuid;
209 temp_properties[kIdLabel] = disk.label;
210 temp_properties[kVendorId] = disk.vendor_id;
211 temp_properties[kVendorName] = disk.vendor_name;
212 temp_properties[kProductId] = disk.product_id;
213 temp_properties[kProductName] = disk.product_name;
214 temp_properties[kDriveModel] = disk.drive_model;
Ben Chan445852f2017-10-02 23:00:16 -0700215 temp_properties[kDeviceMediaType] = static_cast<uint32_t>(disk.media_type);
216 temp_properties[kDeviceSize] = disk.device_capacity;
217 temp_properties[kDeviceIsReadOnly] = disk.is_read_only;
218 temp_properties[kFileSystemType] = disk.filesystem_type;
219 temp_properties[kDeviceMountPaths] = disk.mount_paths;
220 *properties = std::move(temp_properties);
221 return true;
Ben Chanf51ff002011-04-25 12:41:57 -0700222}
223
Ben Chan213c6d92019-04-10 16:21:52 -0700224void CrosDisksServer::OnFormatCompleted(const std::string& device_path,
Ben Chanc1e766c2011-11-21 12:56:59 -0800225 FormatErrorType error_type) {
Ben Chan445852f2017-10-02 23:00:16 -0700226 SendFormatCompletedSignal(error_type, device_path);
Ben Chanc1e766c2011-11-21 12:56:59 -0800227}
228
Ben Chan213c6d92019-04-10 16:21:52 -0700229void CrosDisksServer::OnRenameCompleted(const std::string& device_path,
Klemen Kozjekb0658852017-08-15 13:03:48 +0900230 RenameErrorType error_type) {
Ben Chan445852f2017-10-02 23:00:16 -0700231 SendRenameCompletedSignal(error_type, device_path);
Klemen Kozjekb0658852017-08-15 13:03:48 +0900232}
233
Ben Chan5988f292012-09-18 08:32:42 -0700234void CrosDisksServer::OnScreenIsLocked() {
235 // no-op
236}
237
238void CrosDisksServer::OnScreenIsUnlocked() {
239 // no-op
240}
241
Ben Chanb3bf8d12013-04-23 13:57:55 -0700242void CrosDisksServer::OnSessionStarted() {
Ben Chan63ec9c42014-04-21 19:13:23 -0700243 for (const auto& manager : mount_managers_) {
Ben Chanb3bf8d12013-04-23 13:57:55 -0700244 manager->StartSession();
Ben Chan8dcede82011-07-25 20:56:13 -0700245 }
Ben Chan6e726922011-06-28 15:54:32 -0700246}
247
Ben Chanb3bf8d12013-04-23 13:57:55 -0700248void CrosDisksServer::OnSessionStopped() {
Ben Chan63ec9c42014-04-21 19:13:23 -0700249 for (const auto& manager : mount_managers_) {
Ben Chanb3bf8d12013-04-23 13:57:55 -0700250 manager->StopSession();
Ben Chan8dcede82011-07-25 20:56:13 -0700251 }
Ben Chan6e726922011-06-28 15:54:32 -0700252}
253
254void CrosDisksServer::DispatchDeviceEvent(const DeviceEvent& event) {
255 switch (event.event_type) {
256 case DeviceEvent::kDeviceAdded:
Ben Chan445852f2017-10-02 23:00:16 -0700257 SendDeviceAddedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700258 break;
259 case DeviceEvent::kDeviceScanned:
Ben Chan445852f2017-10-02 23:00:16 -0700260 SendDeviceScannedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700261 break;
262 case DeviceEvent::kDeviceRemoved:
Ben Chan445852f2017-10-02 23:00:16 -0700263 SendDeviceRemovedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700264 break;
265 case DeviceEvent::kDiskAdded:
Ben Chan445852f2017-10-02 23:00:16 -0700266 SendDiskAddedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700267 break;
Ben Chan6e726922011-06-28 15:54:32 -0700268 case DeviceEvent::kDiskChanged:
Ben Chan445852f2017-10-02 23:00:16 -0700269 SendDiskChangedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700270 break;
271 case DeviceEvent::kDiskRemoved:
Ben Chan445852f2017-10-02 23:00:16 -0700272 SendDiskRemovedSignal(event.device_path);
Ben Chan6e726922011-06-28 15:54:32 -0700273 break;
274 default:
275 break;
276 }
277}
278
Ben Chanbdc39742011-05-11 17:51:26 -0700279} // namespace cros_disks