blob: cc186835193f825a396490870186f62ee2c068ad [file] [log] [blame]
[email protected]2321d282012-01-31 23:06:591// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]4ae73292011-11-15 05:20:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4cbead42012-08-26 12:02:395#include "chromeos/disks/disk_mount_manager.h"
[email protected]a66a23cb2012-06-19 23:15:336
avi6e1a22d2015-12-21 03:43:207#include <stddef.h>
8#include <stdint.h>
9
Klemen Kozjek46f1c6192017-08-25 19:20:5410#include <map>
[email protected]4ae73292011-11-15 05:20:1811#include <set>
Klemen Kozjek46f1c6192017-08-25 19:20:5412#include <string>
[email protected]4ae73292011-11-15 05:20:1813
[email protected]4ae73292011-11-15 05:20:1814#include "base/bind.h"
avi6e1a22d2015-12-21 03:43:2015#include "base/macros.h"
avi8194ad62016-09-20 16:58:3616#include "base/memory/ptr_util.h"
[email protected]c6944272012-01-06 22:12:2817#include "base/memory/weak_ptr.h"
[email protected]3fc40c142011-12-01 13:09:0418#include "base/observer_list.h"
[email protected]afa339d72013-06-11 06:32:5119#include "base/strings/string_util.h"
[email protected]64e199252012-04-06 01:54:3620#include "chromeos/dbus/dbus_thread_manager.h"
hirono9f5eae542015-06-22 04:28:4121#include "chromeos/disks/suspend_unmount_manager.h"
[email protected]4ae73292011-11-15 05:20:1822
23namespace chromeos {
24namespace disks {
25
26namespace {
27
Aga Wronska0856cf842017-12-01 20:51:5128constexpr char kDefaultFormattedDeviceName[] = "UNTITLED";
29constexpr char kDefaultFormatVFAT[] = "vfat";
30constexpr char kDeviceNotFound[] = "Device could not be found";
31constexpr char kStatefulPartition[] = "/mnt/stateful_partition";
[email protected]4ae73292011-11-15 05:20:1832DiskMountManager* g_disk_mount_manager = NULL;
33
34// The DiskMountManager implementation.
35class DiskMountManagerImpl : public DiskMountManager {
36 public:
[email protected]a2e4ee22014-07-11 05:16:3537 DiskMountManagerImpl() :
38 already_refreshed_(false),
39 weak_ptr_factory_(this) {
[email protected]4ae73292011-11-15 05:20:1840 DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get();
[email protected]4ae73292011-11-15 05:20:1841 cros_disks_client_ = dbus_thread_manager->GetCrosDisksClient();
hirono9f5eae542015-06-22 04:28:4142 PowerManagerClient* power_manager_client =
43 dbus_thread_manager->GetPowerManagerClient();
44 suspend_unmount_manager_.reset(
45 new SuspendUnmountManager(this, power_manager_client));
[email protected]a0278d52014-05-06 03:36:1546 cros_disks_client_->SetMountEventHandler(
[email protected]4ae73292011-11-15 05:20:1847 base::Bind(&DiskMountManagerImpl::OnMountEvent,
[email protected]a0278d52014-05-06 03:36:1548 weak_ptr_factory_.GetWeakPtr()));
49 cros_disks_client_->SetMountCompletedHandler(
[email protected]4ae73292011-11-15 05:20:1850 base::Bind(&DiskMountManagerImpl::OnMountCompleted,
51 weak_ptr_factory_.GetWeakPtr()));
[email protected]a0278d52014-05-06 03:36:1552 cros_disks_client_->SetFormatCompletedHandler(
53 base::Bind(&DiskMountManagerImpl::OnFormatCompleted,
54 weak_ptr_factory_.GetWeakPtr()));
Klemen Kozjekbf5610f2017-08-25 20:20:0955 cros_disks_client_->SetRenameCompletedHandler(
56 base::Bind(&DiskMountManagerImpl::OnRenameCompleted,
57 weak_ptr_factory_.GetWeakPtr()));
[email protected]4ae73292011-11-15 05:20:1858 }
59
Chris Watkins2c529d62017-11-29 02:14:4160 ~DiskMountManagerImpl() override = default;
[email protected]4ae73292011-11-15 05:20:1861
62 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:4963 void AddObserver(Observer* observer) override {
[email protected]4ae73292011-11-15 05:20:1864 observers_.AddObserver(observer);
65 }
66
67 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:4968 void RemoveObserver(Observer* observer) override {
[email protected]4ae73292011-11-15 05:20:1869 observers_.RemoveObserver(observer);
70 }
71
72 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:4973 void MountPath(const std::string& source_path,
74 const std::string& source_format,
75 const std::string& mount_label,
yamaguchicc8186b2016-08-08 06:38:5476 MountType type,
77 MountAccessMode access_mode) override {
[email protected]4ae73292011-11-15 05:20:1878 // Hidden and non-existent devices should not be mounted.
79 if (type == MOUNT_TYPE_DEVICE) {
80 DiskMap::const_iterator it = disks_.find(source_path);
81 if (it == disks_.end() || it->second->is_hidden()) {
[email protected]d7760592014-05-16 07:57:5282 OnMountCompleted(MountEntry(MOUNT_ERROR_INTERNAL, source_path, type,
83 ""));
[email protected]4ae73292011-11-15 05:20:1884 return;
85 }
86 }
[email protected]4ae73292011-11-15 05:20:1887 cros_disks_client_->Mount(
yamaguchicc8186b2016-08-08 06:38:5488 source_path, source_format, mount_label, access_mode,
yamaguchifa8efc72016-10-21 15:05:5189 REMOUNT_OPTION_MOUNT_NEW_DEVICE,
[email protected]4ae73292011-11-15 05:20:1890 // When succeeds, OnMountCompleted will be called by
91 // "MountCompleted" signal instead.
[email protected]c6944272012-01-06 22:12:2892 base::Bind(&base::DoNothing),
[email protected]4ae73292011-11-15 05:20:1893 base::Bind(&DiskMountManagerImpl::OnMountCompleted,
94 weak_ptr_factory_.GetWeakPtr(),
[email protected]d7760592014-05-16 07:57:5295 MountEntry(MOUNT_ERROR_INTERNAL, source_path, type, "")));
yamaguchi6594bf7e12016-08-24 22:16:1196
97 // Record the access mode option passed to CrosDisks.
98 // This is needed because CrosDisks service methods doesn't return the info
99 // via DBus.
100 access_modes_.insert(std::make_pair(source_path, access_mode));
[email protected]4ae73292011-11-15 05:20:18101 }
102
103 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49104 void UnmountPath(const std::string& mount_path,
105 UnmountOptions options,
106 const UnmountPathCallback& callback) override {
[email protected]3af8e1b2012-09-15 20:46:05107 UnmountChildMounts(mount_path);
[email protected]10795ae2012-10-10 07:33:49108 cros_disks_client_->Unmount(mount_path, options,
[email protected]4ae73292011-11-15 05:20:18109 base::Bind(&DiskMountManagerImpl::OnUnmountPath,
[email protected]10795ae2012-10-10 07:33:49110 weak_ptr_factory_.GetWeakPtr(),
[email protected]8f919ee2013-03-14 19:53:29111 callback,
[email protected]ffdcc7a9c2013-07-02 06:59:39112 true,
113 mount_path),
[email protected]10795ae2012-10-10 07:33:49114 base::Bind(&DiskMountManagerImpl::OnUnmountPath,
115 weak_ptr_factory_.GetWeakPtr(),
[email protected]8f919ee2013-03-14 19:53:29116 callback,
[email protected]ffdcc7a9c2013-07-02 06:59:39117 false,
118 mount_path));
[email protected]4ae73292011-11-15 05:20:18119 }
120
yamaguchide59ed62016-11-08 10:07:10121 void RemountAllRemovableDrives(MountAccessMode mode) override {
122 // TODO(yamaguchi): Retry for tentative remount failures. crbug.com/661455
123 for (const auto& device_path_and_disk : disks_) {
124 const Disk& disk = *device_path_and_disk.second;
125 if (disk.is_read_only_hardware()) {
126 // Read-only devices can be mounted in RO mode only. No need to remount.
127 continue;
128 }
129 if (!disk.is_mounted()) {
130 continue;
131 }
132 RemountRemovableDrive(disk, mode);
133 }
134 }
135
[email protected]4ae73292011-11-15 05:20:18136 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49137 void FormatMountedDevice(const std::string& mount_path) override {
[email protected]e3c1fc92012-11-15 00:56:46138 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path);
139 if (mount_point == mount_points_.end()) {
140 LOG(ERROR) << "Mount point with path \"" << mount_path << "\" not found.";
[email protected]f026c0f2014-05-06 21:52:35141 OnFormatCompleted(FORMAT_ERROR_UNKNOWN, mount_path);
[email protected]4ae73292011-11-15 05:20:18142 return;
143 }
[email protected]e3c1fc92012-11-15 00:56:46144
145 std::string device_path = mount_point->second.source_path;
146 DiskMap::const_iterator disk = disks_.find(device_path);
147 if (disk == disks_.end()) {
148 LOG(ERROR) << "Device with path \"" << device_path << "\" not found.";
[email protected]f026c0f2014-05-06 21:52:35149 OnFormatCompleted(FORMAT_ERROR_UNKNOWN, device_path);
[email protected]e3c1fc92012-11-15 00:56:46150 return;
151 }
yamaguchibffc32eb2016-08-17 06:35:39152 if (disk->second->is_read_only()) {
153 LOG(ERROR) << "Mount point with path \"" << mount_path
154 << "\" is read-only.";
155 OnFormatCompleted(FORMAT_ERROR_DEVICE_NOT_ALLOWED, mount_path);
156 return;
157 }
[email protected]e3c1fc92012-11-15 00:56:46158
[email protected]8f919ee2013-03-14 19:53:29159 UnmountPath(disk->second->mount_path(),
160 UNMOUNT_OPTIONS_NONE,
161 base::Bind(&DiskMountManagerImpl::OnUnmountPathForFormat,
162 weak_ptr_factory_.GetWeakPtr(),
163 device_path));
[email protected]4ae73292011-11-15 05:20:18164 }
165
Klemen Kozjekbf5610f2017-08-25 20:20:09166 void RenameMountedDevice(const std::string& mount_path,
167 const std::string& volume_name) override {
168 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path);
169 if (mount_point == mount_points_.end()) {
170 LOG(ERROR) << "Mount point with path '" << mount_path << "' not found.";
171 OnRenameCompleted(RENAME_ERROR_UNKNOWN, mount_path);
172 return;
173 }
174
175 std::string device_path = mount_point->second.source_path;
176 DiskMap::const_iterator iter = disks_.find(device_path);
177 if (iter == disks_.end()) {
178 LOG(ERROR) << "Device with path '" << device_path << "' not found.";
179 OnRenameCompleted(RENAME_ERROR_UNKNOWN, device_path);
180 return;
181 }
182 if (iter->second->is_read_only()) {
183 LOG(ERROR) << "Mount point with path '" << mount_path
184 << "' is read-only.";
185 OnRenameCompleted(RENAME_ERROR_DEVICE_NOT_ALLOWED, mount_path);
186 return;
187 }
188
189 UnmountPath(
190 iter->second->mount_path(), UNMOUNT_OPTIONS_NONE,
191 base::Bind(&DiskMountManagerImpl::OnUnmountPathForRename,
192 weak_ptr_factory_.GetWeakPtr(), device_path, volume_name));
193 }
194
[email protected]4ae73292011-11-15 05:20:18195 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49196 void UnmountDeviceRecursively(
[email protected]4ae73292011-11-15 05:20:18197 const std::string& device_path,
mostynb4f4cf142014-10-06 13:57:52198 const UnmountDeviceRecursivelyCallbackType& callback) override {
[email protected]4ae73292011-11-15 05:20:18199 std::vector<std::string> devices_to_unmount;
200
201 // Get list of all devices to unmount.
202 int device_path_len = device_path.length();
203 for (DiskMap::iterator it = disks_.begin(); it != disks_.end(); ++it) {
204 if (!it->second->mount_path().empty() &&
205 strncmp(device_path.c_str(), it->second->device_path().c_str(),
206 device_path_len) == 0) {
207 devices_to_unmount.push_back(it->second->mount_path());
208 }
209 }
[email protected]e008d4fa2013-02-21 06:38:01210
[email protected]4ae73292011-11-15 05:20:18211 // We should detect at least original device.
212 if (devices_to_unmount.empty()) {
213 if (disks_.find(device_path) == disks_.end()) {
[email protected]e008d4fa2013-02-21 06:38:01214 LOG(WARNING) << "Unmount recursive request failed for device "
215 << device_path << ", with error: " << kDeviceNotFound;
216 callback.Run(false);
[email protected]4ae73292011-11-15 05:20:18217 return;
218 }
[email protected]e008d4fa2013-02-21 06:38:01219
220 // Nothing to unmount.
221 callback.Run(true);
222 return;
[email protected]4ae73292011-11-15 05:20:18223 }
[email protected]e008d4fa2013-02-21 06:38:01224
225 // We will send the same callback data object to all Unmount calls and use
[email protected]a2e4ee22014-07-11 05:16:35226 // it to synchronize callbacks.
[email protected]e008d4fa2013-02-21 06:38:01227 // Note: this implementation has a potential memory leak issue. For
228 // example if this instance is destructed before all the callbacks for
229 // Unmount are invoked, the memory pointed by |cb_data| will be leaked.
230 // It is because the UnmountDeviceRecursivelyCallbackData keeps how
231 // many times OnUnmountDeviceRecursively callback is called and when
232 // all the callbacks are called, |cb_data| will be deleted in the method.
233 // However destructing the instance before all callback invocations will
234 // cancel all pending callbacks, so that the |cb_data| would never be
235 // deleted.
236 // Fortunately, in the real scenario, the instance will be destructed
237 // only for ShutDown. So, probably the memory would rarely be leaked.
238 // TODO(hidehiko): Fix the issue.
239 UnmountDeviceRecursivelyCallbackData* cb_data =
240 new UnmountDeviceRecursivelyCallbackData(
241 callback, devices_to_unmount.size());
242 for (size_t i = 0; i < devices_to_unmount.size(); ++i) {
243 cros_disks_client_->Unmount(
244 devices_to_unmount[i],
245 UNMOUNT_OPTIONS_NONE,
246 base::Bind(&DiskMountManagerImpl::OnUnmountDeviceRecursively,
[email protected]ffdcc7a9c2013-07-02 06:59:39247 weak_ptr_factory_.GetWeakPtr(),
248 cb_data,
249 true,
250 devices_to_unmount[i]),
[email protected]e008d4fa2013-02-21 06:38:01251 base::Bind(&DiskMountManagerImpl::OnUnmountDeviceRecursively,
[email protected]ffdcc7a9c2013-07-02 06:59:39252 weak_ptr_factory_.GetWeakPtr(),
253 cb_data,
254 false,
255 devices_to_unmount[i]));
[email protected]4ae73292011-11-15 05:20:18256 }
257 }
258
259 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49260 void EnsureMountInfoRefreshed(
hironoa4b675d2015-07-29 01:13:37261 const EnsureMountInfoRefreshedCallback& callback,
262 bool force) override {
263 if (!force && already_refreshed_) {
[email protected]a2e4ee22014-07-11 05:16:35264 callback.Run(true);
265 return;
266 }
267
268 refresh_callbacks_.push_back(callback);
269 if (refresh_callbacks_.size() == 1) {
270 // If there's no in-flight refreshing task, start it.
Aga Wronskaddc1a752017-12-01 19:44:02271 cros_disks_client_->EnumerateDevices(
[email protected]a2e4ee22014-07-11 05:16:35272 base::Bind(&DiskMountManagerImpl::RefreshAfterEnumerateDevices,
273 weak_ptr_factory_.GetWeakPtr()),
274 base::Bind(&DiskMountManagerImpl::RefreshCompleted,
275 weak_ptr_factory_.GetWeakPtr(), false));
276 }
[email protected]4ae73292011-11-15 05:20:18277 }
278
279 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49280 const DiskMap& disks() const override { return disks_; }
[email protected]4ae73292011-11-15 05:20:18281
[email protected]bcfa0072012-08-07 01:08:57282 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49283 const Disk* FindDiskBySourcePath(
284 const std::string& source_path) const override {
[email protected]bcfa0072012-08-07 01:08:57285 DiskMap::const_iterator disk_it = disks_.find(source_path);
avi8194ad62016-09-20 16:58:36286 return disk_it == disks_.end() ? NULL : disk_it->second.get();
[email protected]bcfa0072012-08-07 01:08:57287 }
[email protected]4ae73292011-11-15 05:20:18288
289 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49290 const MountPointMap& mount_points() const override { return mount_points_; }
[email protected]4ae73292011-11-15 05:20:18291
[email protected]e3c1fc92012-11-15 00:56:46292 // DiskMountManager override.
avi8194ad62016-09-20 16:58:36293 bool AddDiskForTest(std::unique_ptr<Disk> disk) override {
[email protected]e3c1fc92012-11-15 00:56:46294 if (disks_.find(disk->device_path()) != disks_.end()) {
295 LOG(ERROR) << "Attempt to add a duplicate disk";
296 return false;
297 }
298
avi8194ad62016-09-20 16:58:36299 disks_.insert(std::make_pair(disk->device_path(), std::move(disk)));
[email protected]e3c1fc92012-11-15 00:56:46300 return true;
301 }
302
303 // DiskMountManager override.
304 // Corresponding disk should be added to the manager before this is called.
dchengae98daa2015-01-21 20:30:49305 bool AddMountPointForTest(const MountPointInfo& mount_point) override {
[email protected]e3c1fc92012-11-15 00:56:46306 if (mount_points_.find(mount_point.mount_path) != mount_points_.end()) {
307 LOG(ERROR) << "Attempt to add a duplicate mount point";
308 return false;
309 }
310 if (mount_point.mount_type == chromeos::MOUNT_TYPE_DEVICE &&
311 disks_.find(mount_point.source_path) == disks_.end()) {
312 LOG(ERROR) << "Device mount points must have a disk entry.";
313 return false;
314 }
315
316 mount_points_.insert(std::make_pair(mount_point.mount_path, mount_point));
317 return true;
318 }
319
[email protected]4ae73292011-11-15 05:20:18320 private:
Klemen Kozjek46f1c6192017-08-25 19:20:54321 // A struct to represent information about a format changes.
322 struct FormatChange {
323 // new file system type
324 std::string file_system_type;
325 // New volume name
326 std::string volume_name;
327 };
328
329 // Stores new volume name and file system type for a device on which
330 // formatting is invoked on, so that OnFormatCompleted can set it back to
331 // |disks_|. The key is a device_path and the value is a FormatChange.
332 std::map<std::string, FormatChange> pending_format_changes_;
333
Klemen Kozjekbf5610f2017-08-25 20:20:09334 // Stores new volume name for a device on which renaming is invoked on, so
335 // that OnRenameCompleted can set it back to |disks_|. The key is a
336 // device_path and the value is new volume_name.
337 std::map<std::string, std::string> pending_rename_changes_;
338
[email protected]e008d4fa2013-02-21 06:38:01339 struct UnmountDeviceRecursivelyCallbackData {
340 UnmountDeviceRecursivelyCallbackData(
341 const UnmountDeviceRecursivelyCallbackType& in_callback,
342 int in_num_pending_callbacks)
343 : callback(in_callback),
344 num_pending_callbacks(in_num_pending_callbacks) {
[email protected]4ae73292011-11-15 05:20:18345 }
[email protected]e008d4fa2013-02-21 06:38:01346
347 const UnmountDeviceRecursivelyCallbackType callback;
348 size_t num_pending_callbacks;
[email protected]4ae73292011-11-15 05:20:18349 };
350
yamaguchide59ed62016-11-08 10:07:10351 void RemountRemovableDrive(const Disk& disk,
352 MountAccessMode access_mode) {
353 const std::string& mount_path = disk.mount_path();
354 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path);
355 if (mount_point == mount_points_.end()) {
356 // Not in mount_points_. This happens when the mount_points ans disks_ are
357 // inconsistent.
358 LOG(ERROR) << "Mount point with path \"" << mount_path << "\" not found.";
359 OnMountCompleted(
360 MountEntry(MOUNT_ERROR_PATH_NOT_MOUNTED, disk.device_path(),
361 MOUNT_TYPE_DEVICE, mount_path));
362 return;
363 }
364 const std::string& source_path = mount_point->second.source_path;
365
366 // Update the access mode option passed to CrosDisks.
367 // This is needed because CrosDisks service methods doesn't return the info
368 // via DBus, and must be updated before issuing Mount command as it'll be
369 // read by the handler of MountCompleted signal.
370 access_modes_[source_path] = access_mode;
371
372 cros_disks_client_->Mount(
373 mount_point->second.source_path, std::string(), std::string(),
374 access_mode, REMOUNT_OPTION_REMOUNT_EXISTING_DEVICE,
375 // When succeeds, OnMountCompleted will be called by
376 // "MountCompleted" signal instead.
377 base::Bind(&base::DoNothing),
378 base::Bind(&DiskMountManagerImpl::OnMountCompleted,
379 weak_ptr_factory_.GetWeakPtr(),
380 MountEntry(MOUNT_ERROR_INTERNAL, source_path,
381 mount_point->second.mount_type, "")));
382 }
383
[email protected]3af8e1b2012-09-15 20:46:05384 // Unmounts all mount points whose source path is transitively parented by
385 // |mount_path|.
386 void UnmountChildMounts(const std::string& mount_path_in) {
387 std::string mount_path = mount_path_in;
388 // Let's make sure mount path has trailing slash.
pkasting9022cb42016-02-05 00:08:56389 if (mount_path.back() != '/')
[email protected]3af8e1b2012-09-15 20:46:05390 mount_path += '/';
391
392 for (MountPointMap::iterator it = mount_points_.begin();
393 it != mount_points_.end();
394 ++it) {
brettw95509312015-07-16 23:57:33395 if (base::StartsWith(it->second.source_path, mount_path,
396 base::CompareCase::SENSITIVE)) {
[email protected]8f919ee2013-03-14 19:53:29397 // TODO(tbarzic): Handle the case where this fails.
398 UnmountPath(it->second.mount_path,
399 UNMOUNT_OPTIONS_NONE,
400 UnmountPathCallback());
[email protected]3af8e1b2012-09-15 20:46:05401 }
402 }
403 }
404
[email protected]e008d4fa2013-02-21 06:38:01405 // Callback for UnmountDeviceRecursively.
406 void OnUnmountDeviceRecursively(
407 UnmountDeviceRecursivelyCallbackData* cb_data,
408 bool success,
409 const std::string& mount_path) {
[email protected]4ae73292011-11-15 05:20:18410 if (success) {
411 // Do standard processing for Unmount event.
[email protected]8f919ee2013-03-14 19:53:29412 OnUnmountPath(UnmountPathCallback(), true, mount_path);
[email protected]a0278d52014-05-06 03:36:15413 VLOG(1) << mount_path << " unmounted.";
[email protected]4ae73292011-11-15 05:20:18414 }
415 // This is safe as long as all callbacks are called on the same thread as
[email protected]e008d4fa2013-02-21 06:38:01416 // UnmountDeviceRecursively.
417 cb_data->num_pending_callbacks--;
[email protected]4ae73292011-11-15 05:20:18418
[email protected]e008d4fa2013-02-21 06:38:01419 if (cb_data->num_pending_callbacks == 0) {
420 // This code has a problem that the |success| status used here is for the
421 // last "unmount" callback, but not whether all unmounting is succeeded.
422 // TODO(hidehiko): Fix the issue.
423 cb_data->callback.Run(success);
[email protected]4ae73292011-11-15 05:20:18424 delete cb_data;
425 }
426 }
427
428 // Callback to handle MountCompleted signal and Mount method call failure.
[email protected]d7760592014-05-16 07:57:52429 void OnMountCompleted(const MountEntry& entry) {
[email protected]4ae73292011-11-15 05:20:18430 MountCondition mount_condition = MOUNT_CONDITION_NONE;
[email protected]d7760592014-05-16 07:57:52431 if (entry.mount_type() == MOUNT_TYPE_DEVICE) {
432 if (entry.error_code() == MOUNT_ERROR_UNKNOWN_FILESYSTEM) {
[email protected]4ae73292011-11-15 05:20:18433 mount_condition = MOUNT_CONDITION_UNKNOWN_FILESYSTEM;
[email protected]a66a23cb2012-06-19 23:15:33434 }
[email protected]d7760592014-05-16 07:57:52435 if (entry.error_code() == MOUNT_ERROR_UNSUPPORTED_FILESYSTEM) {
[email protected]4ae73292011-11-15 05:20:18436 mount_condition = MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM;
[email protected]a66a23cb2012-06-19 23:15:33437 }
[email protected]4ae73292011-11-15 05:20:18438 }
[email protected]d7760592014-05-16 07:57:52439 const MountPointInfo mount_info(entry.source_path(),
440 entry.mount_path(),
441 entry.mount_type(),
[email protected]4ae73292011-11-15 05:20:18442 mount_condition);
443
[email protected]4ae73292011-11-15 05:20:18444 // If the device is corrupted but it's still possible to format it, it will
445 // be fake mounted.
[email protected]d7760592014-05-16 07:57:52446 if ((entry.error_code() == MOUNT_ERROR_NONE ||
447 mount_info.mount_condition) &&
[email protected]4ae73292011-11-15 05:20:18448 mount_points_.find(mount_info.mount_path) == mount_points_.end()) {
449 mount_points_.insert(MountPointMap::value_type(mount_info.mount_path,
450 mount_info));
451 }
yamaguchi6594bf7e12016-08-24 22:16:11452
[email protected]d7760592014-05-16 07:57:52453 if ((entry.error_code() == MOUNT_ERROR_NONE ||
454 mount_info.mount_condition) &&
[email protected]4ae73292011-11-15 05:20:18455 mount_info.mount_type == MOUNT_TYPE_DEVICE &&
456 !mount_info.source_path.empty() &&
457 !mount_info.mount_path.empty()) {
458 DiskMap::iterator iter = disks_.find(mount_info.source_path);
yamaguchi6594bf7e12016-08-24 22:16:11459 if (iter != disks_.end()) { // disk might have been removed by now?
avi8194ad62016-09-20 16:58:36460 Disk* disk = iter->second.get();
yamaguchi6594bf7e12016-08-24 22:16:11461 DCHECK(disk);
yamaguchide59ed62016-11-08 10:07:10462 // Currently the MountCompleted signal doesn't tell whether the device
463 // is mounted in read-only mode or not. Instead use the mount option
464 // recorded by DiskMountManagerImpl::MountPath().
yamaguchi6594bf7e12016-08-24 22:16:11465 // |source_path| should be same as |disk->device_path| because
466 // |VolumeManager::OnDiskEvent()| passes the latter to cros-disks as a
467 // source path when mounting a device.
468 AccessModeMap::iterator it = access_modes_.find(entry.source_path());
yamaguchide59ed62016-11-08 10:07:10469
470 // Store whether the disk was mounted in read-only mode due to a policy.
471 disk->set_write_disabled_by_policy(
472 it != access_modes_.end() && !disk->is_read_only_hardware()
473 && it->second == MOUNT_ACCESS_MODE_READ_ONLY);
Klemen Kozjekbf5610f2017-08-25 20:20:09474 disk->SetMountPath(mount_info.mount_path);
[email protected]4ae73292011-11-15 05:20:18475 }
[email protected]4ae73292011-11-15 05:20:18476 }
yamaguchi6594bf7e12016-08-24 22:16:11477 // Observers may read the values of disks_. So notify them after tweaking
478 // values of disks_.
479 NotifyMountStatusUpdate(MOUNTING, entry.error_code(), mount_info);
[email protected]4ae73292011-11-15 05:20:18480 }
481
482 // Callback for UnmountPath.
[email protected]8f919ee2013-03-14 19:53:29483 void OnUnmountPath(const UnmountPathCallback& callback,
484 bool success,
485 const std::string& mount_path) {
[email protected]4ae73292011-11-15 05:20:18486 MountPointMap::iterator mount_points_it = mount_points_.find(mount_path);
[email protected]8f919ee2013-03-14 19:53:29487 if (mount_points_it == mount_points_.end()) {
488 // The path was unmounted, but not as a result of this unmount request,
489 // so return error.
490 if (!callback.is_null())
491 callback.Run(MOUNT_ERROR_INTERNAL);
[email protected]4ae73292011-11-15 05:20:18492 return;
[email protected]8f919ee2013-03-14 19:53:29493 }
[email protected]e3c1fc92012-11-15 00:56:46494
495 NotifyMountStatusUpdate(
[email protected]10795ae2012-10-10 07:33:49496 UNMOUNTING,
497 success ? MOUNT_ERROR_NONE : MOUNT_ERROR_INTERNAL,
[email protected]a66a23cb2012-06-19 23:15:33498 MountPointInfo(mount_points_it->second.source_path,
499 mount_points_it->second.mount_path,
500 mount_points_it->second.mount_type,
501 mount_points_it->second.mount_condition));
[email protected]10795ae2012-10-10 07:33:49502
[email protected]4ae73292011-11-15 05:20:18503 std::string path(mount_points_it->second.source_path);
[email protected]10795ae2012-10-10 07:33:49504 if (success)
505 mount_points_.erase(mount_points_it);
506
[email protected]e3c1fc92012-11-15 00:56:46507 DiskMap::iterator disk_iter = disks_.find(path);
508 if (disk_iter != disks_.end()) {
509 DCHECK(disk_iter->second);
510 if (success)
511 disk_iter->second->clear_mount_path();
[email protected]4ae73292011-11-15 05:20:18512 }
[email protected]10795ae2012-10-10 07:33:49513
[email protected]8f919ee2013-03-14 19:53:29514 if (!callback.is_null())
515 callback.Run(success ? MOUNT_ERROR_NONE : MOUNT_ERROR_INTERNAL);
516 }
517
518 void OnUnmountPathForFormat(const std::string& device_path,
519 MountError error_code) {
520 if (error_code == MOUNT_ERROR_NONE &&
521 disks_.find(device_path) != disks_.end()) {
522 FormatUnmountedDevice(device_path);
523 } else {
[email protected]f026c0f2014-05-06 21:52:35524 OnFormatCompleted(FORMAT_ERROR_UNKNOWN, device_path);
[email protected]4ae73292011-11-15 05:20:18525 }
526 }
527
[email protected]e3c1fc92012-11-15 00:56:46528 // Starts device formatting.
529 void FormatUnmountedDevice(const std::string& device_path) {
530 DiskMap::const_iterator disk = disks_.find(device_path);
531 DCHECK(disk != disks_.end() && disk->second->mount_path().empty());
532
Klemen Kozjek46f1c6192017-08-25 19:20:54533 pending_format_changes_[device_path] = {kDefaultFormatVFAT,
534 kDefaultFormattedDeviceName};
535
[email protected]f026c0f2014-05-06 21:52:35536 cros_disks_client_->Format(
Klemen Kozjek46f1c6192017-08-25 19:20:54537 device_path, kDefaultFormatVFAT,
[email protected]f026c0f2014-05-06 21:52:35538 base::Bind(&DiskMountManagerImpl::OnFormatStarted,
Klemen Kozjek46f1c6192017-08-25 19:20:54539 weak_ptr_factory_.GetWeakPtr(), device_path),
[email protected]f026c0f2014-05-06 21:52:35540 base::Bind(&DiskMountManagerImpl::OnFormatCompleted,
Klemen Kozjek46f1c6192017-08-25 19:20:54541 weak_ptr_factory_.GetWeakPtr(), FORMAT_ERROR_UNKNOWN,
[email protected]f026c0f2014-05-06 21:52:35542 device_path));
[email protected]e3c1fc92012-11-15 00:56:46543 }
544
[email protected]f026c0f2014-05-06 21:52:35545 // Callback for Format.
546 void OnFormatStarted(const std::string& device_path) {
547 NotifyFormatStatusUpdate(FORMAT_STARTED, FORMAT_ERROR_NONE, device_path);
[email protected]4ae73292011-11-15 05:20:18548 }
549
[email protected]a0278d52014-05-06 03:36:15550 // Callback to handle FormatCompleted signal and Format method call failure.
551 void OnFormatCompleted(FormatError error_code,
[email protected]f026c0f2014-05-06 21:52:35552 const std::string& device_path) {
Klemen Kozjek46f1c6192017-08-25 19:20:54553 auto iter = disks_.find(device_path);
Klemen Kozjekbf5610f2017-08-25 20:20:09554
Klemen Kozjek46f1c6192017-08-25 19:20:54555 // disk might have been removed by now?
556 if (iter != disks_.end()) {
557 Disk* disk = iter->second.get();
558 DCHECK(disk);
559
560 auto pending_change = pending_format_changes_.find(device_path);
Klemen Kozjekbf5610f2017-08-25 20:20:09561 if (pending_change != pending_format_changes_.end() &&
562 error_code == FORMAT_ERROR_NONE) {
563 disk->set_device_label(pending_change->second.volume_name);
564 disk->set_file_system_type(pending_change->second.file_system_type);
Klemen Kozjek46f1c6192017-08-25 19:20:54565 }
566 }
567
Klemen Kozjekbf5610f2017-08-25 20:20:09568 pending_format_changes_.erase(device_path);
569
[email protected]f026c0f2014-05-06 21:52:35570 NotifyFormatStatusUpdate(FORMAT_COMPLETED, error_code, device_path);
[email protected]a0278d52014-05-06 03:36:15571 }
572
Klemen Kozjekbf5610f2017-08-25 20:20:09573 void OnUnmountPathForRename(const std::string& device_path,
574 const std::string& volume_name,
575 MountError error_code) {
576 if (error_code != MOUNT_ERROR_NONE ||
577 disks_.find(device_path) == disks_.end()) {
578 OnRenameCompleted(RENAME_ERROR_UNKNOWN, device_path);
579 return;
580 }
581
582 RenameUnmountedDevice(device_path, volume_name);
583 }
584
585 // Start device renaming
586 void RenameUnmountedDevice(const std::string& device_path,
587 const std::string& volume_name) {
588 DiskMap::const_iterator disk = disks_.find(device_path);
589 DCHECK(disk != disks_.end() && disk->second->mount_path().empty());
590
591 pending_rename_changes_[device_path] = volume_name;
592 cros_disks_client_->Rename(
593 device_path, volume_name,
594 base::Bind(&DiskMountManagerImpl::OnRenameStarted,
595 weak_ptr_factory_.GetWeakPtr(), device_path),
596 base::Bind(&DiskMountManagerImpl::OnRenameCompleted,
597 weak_ptr_factory_.GetWeakPtr(), RENAME_ERROR_UNKNOWN,
598 device_path));
599 }
600
601 // Callback for Rename.
602 void OnRenameStarted(const std::string& device_path) {
603 NotifyRenameStatusUpdate(RENAME_STARTED, RENAME_ERROR_NONE, device_path);
604 }
605
606 // Callback to handle RenameCompleted signal and Rename method call failure.
607 void OnRenameCompleted(RenameError error_code,
608 const std::string& device_path) {
609 auto iter = disks_.find(device_path);
610
611 // disk might have been removed by now?
612 if (iter != disks_.end()) {
613 Disk* disk = iter->second.get();
614 DCHECK(disk);
615
616 auto pending_change = pending_rename_changes_.find(device_path);
617 if (pending_change != pending_rename_changes_.end() &&
618 error_code == RENAME_ERROR_NONE)
619 disk->set_device_label(pending_change->second);
620 }
621
622 pending_rename_changes_.erase(device_path);
623
624 NotifyRenameStatusUpdate(RENAME_COMPLETED, error_code, device_path);
625 }
626
[email protected]a2e4ee22014-07-11 05:16:35627 // Callback for GetDeviceProperties.
[email protected]4ae73292011-11-15 05:20:18628 void OnGetDeviceProperties(const DiskInfo& disk_info) {
Aga Wronskaddc1a752017-12-01 19:44:02629 if (disk_info.is_virtual())
[email protected]4ae73292011-11-15 05:20:18630 return;
631
632 LOG(WARNING) << "Found disk " << disk_info.device_path();
633 // Delete previous disk info for this path:
634 bool is_new = true;
Klemen Kozjekbf5610f2017-08-25 20:20:09635 std::string base_mount_path = std::string();
[email protected]4ae73292011-11-15 05:20:18636 DiskMap::iterator iter = disks_.find(disk_info.device_path());
637 if (iter != disks_.end()) {
Klemen Kozjekbf5610f2017-08-25 20:20:09638 base_mount_path = iter->second->base_mount_path();
[email protected]4ae73292011-11-15 05:20:18639 disks_.erase(iter);
640 is_new = false;
641 }
yamaguchieaaad982016-10-24 09:46:17642
643 // If the device was mounted by the instance, apply recorded parameter.
644 // Otherwise, default to false.
645 // Lookup by |device_path| which we pass to cros-disks when mounting a
646 // device in |VolumeManager::OnDiskEvent()|.
647 auto access_mode = access_modes_.find(disk_info.device_path());
648 bool write_disabled_by_policy = access_mode != access_modes_.end()
649 && access_mode->second == chromeos::MOUNT_ACCESS_MODE_READ_ONLY;
Aga Wronskaddc1a752017-12-01 19:44:02650 // TODO(agawronska): Add constructor for Disk from DiskInfo. Introduce Disk
651 // builder class for tests.
Klemen Kozjek46f1c6192017-08-25 19:20:54652 Disk* disk = new Disk(
653 disk_info.device_path(), disk_info.mount_path(),
654 write_disabled_by_policy, disk_info.system_path(),
655 disk_info.file_path(), disk_info.label(), disk_info.drive_label(),
656 disk_info.vendor_id(), disk_info.vendor_name(), disk_info.product_id(),
657 disk_info.product_name(), disk_info.uuid(),
658 FindSystemPathPrefix(disk_info.system_path()), disk_info.device_type(),
659 disk_info.total_size_in_bytes(), disk_info.is_drive(),
660 disk_info.is_read_only(), disk_info.has_media(),
661 disk_info.on_boot_device(), disk_info.on_removable_device(),
Klemen Kozjekbf5610f2017-08-25 20:20:09662 disk_info.is_hidden(), disk_info.file_system_type(), base_mount_path);
avi8194ad62016-09-20 16:58:36663 disks_.insert(
664 std::make_pair(disk_info.device_path(), base::WrapUnique(disk)));
Aga Wronskaddc1a752017-12-01 19:44:02665 NotifyDiskStatusUpdate(is_new ? DISK_ADDED : DISK_CHANGED, *disk);
[email protected]4ae73292011-11-15 05:20:18666 }
667
[email protected]a2e4ee22014-07-11 05:16:35668 // Part of EnsureMountInfoRefreshed(). Called after the list of devices are
669 // enumerated.
670 void RefreshAfterEnumerateDevices(const std::vector<std::string>& devices) {
671 std::set<std::string> current_device_set(devices.begin(), devices.end());
[email protected]4ae73292011-11-15 05:20:18672 for (DiskMap::iterator iter = disks_.begin(); iter != disks_.end(); ) {
673 if (current_device_set.find(iter->first) == current_device_set.end()) {
[email protected]4ae73292011-11-15 05:20:18674 disks_.erase(iter++);
675 } else {
676 ++iter;
677 }
678 }
[email protected]a2e4ee22014-07-11 05:16:35679 RefreshDeviceAtIndex(devices, 0);
680 }
681
682 // Part of EnsureMountInfoRefreshed(). Called for each device to refresh info.
683 void RefreshDeviceAtIndex(const std::vector<std::string>& devices,
684 size_t index) {
685 if (index == devices.size()) {
686 // All devices info retrieved. Proceed to enumerate mount point info.
687 cros_disks_client_->EnumerateMountEntries(
688 base::Bind(&DiskMountManagerImpl::RefreshAfterEnumerateMountEntries,
689 weak_ptr_factory_.GetWeakPtr()),
690 base::Bind(&DiskMountManagerImpl::RefreshCompleted,
691 weak_ptr_factory_.GetWeakPtr(), false));
692 return;
693 }
694
695 cros_disks_client_->GetDeviceProperties(
696 devices[index],
697 base::Bind(&DiskMountManagerImpl::RefreshAfterGetDeviceProperties,
698 weak_ptr_factory_.GetWeakPtr(), devices, index + 1),
hirono8067bf02015-08-10 03:12:25699 base::Bind(&DiskMountManagerImpl::RefreshDeviceAtIndex,
700 weak_ptr_factory_.GetWeakPtr(), devices, index + 1));
[email protected]a2e4ee22014-07-11 05:16:35701 }
702
703 // Part of EnsureMountInfoRefreshed().
704 void RefreshAfterGetDeviceProperties(const std::vector<std::string>& devices,
705 size_t next_index,
706 const DiskInfo& disk_info) {
707 OnGetDeviceProperties(disk_info);
708 RefreshDeviceAtIndex(devices, next_index);
709 }
710
711 // Part of EnsureMountInfoRefreshed(). Called after mount entries are listed.
712 void RefreshAfterEnumerateMountEntries(
713 const std::vector<MountEntry>& entries) {
714 for (size_t i = 0; i < entries.size(); ++i)
715 OnMountCompleted(entries[i]);
716 RefreshCompleted(true);
717 }
718
719 // Part of EnsureMountInfoRefreshed(). Called when the refreshing is done.
720 void RefreshCompleted(bool success) {
721 already_refreshed_ = true;
722 for (size_t i = 0; i < refresh_callbacks_.size(); ++i)
723 refresh_callbacks_[i].Run(success);
724 refresh_callbacks_.clear();
[email protected]4ae73292011-11-15 05:20:18725 }
726
727 // Callback to handle mount event signals.
[email protected]e24f8762011-12-20 00:10:04728 void OnMountEvent(MountEventType event, const std::string& device_path_arg) {
729 // Take a copy of the argument so we can modify it below.
730 std::string device_path = device_path_arg;
[email protected]4ae73292011-11-15 05:20:18731 switch (event) {
[email protected]e3c1fc92012-11-15 00:56:46732 case CROS_DISKS_DISK_ADDED: {
[email protected]4ae73292011-11-15 05:20:18733 cros_disks_client_->GetDeviceProperties(
734 device_path,
735 base::Bind(&DiskMountManagerImpl::OnGetDeviceProperties,
736 weak_ptr_factory_.GetWeakPtr()),
[email protected]c6944272012-01-06 22:12:28737 base::Bind(&base::DoNothing));
[email protected]e3c1fc92012-11-15 00:56:46738 break;
[email protected]4ae73292011-11-15 05:20:18739 }
[email protected]e3c1fc92012-11-15 00:56:46740 case CROS_DISKS_DISK_REMOVED: {
[email protected]4ae73292011-11-15 05:20:18741 // Search and remove disks that are no longer present.
742 DiskMountManager::DiskMap::iterator iter = disks_.find(device_path);
743 if (iter != disks_.end()) {
avi8194ad62016-09-20 16:58:36744 Disk* disk = iter->second.get();
Aga Wronskaddc1a752017-12-01 19:44:02745 NotifyDiskStatusUpdate(DISK_REMOVED, *disk);
[email protected]4ae73292011-11-15 05:20:18746 disks_.erase(iter);
747 }
[email protected]e3c1fc92012-11-15 00:56:46748 break;
[email protected]4ae73292011-11-15 05:20:18749 }
[email protected]e3c1fc92012-11-15 00:56:46750 case CROS_DISKS_DEVICE_ADDED: {
[email protected]4ae73292011-11-15 05:20:18751 system_path_prefixes_.insert(device_path);
[email protected]e3c1fc92012-11-15 00:56:46752 NotifyDeviceStatusUpdate(DEVICE_ADDED, device_path);
[email protected]4ae73292011-11-15 05:20:18753 break;
754 }
[email protected]e3c1fc92012-11-15 00:56:46755 case CROS_DISKS_DEVICE_REMOVED: {
[email protected]4ae73292011-11-15 05:20:18756 system_path_prefixes_.erase(device_path);
[email protected]e3c1fc92012-11-15 00:56:46757 NotifyDeviceStatusUpdate(DEVICE_REMOVED, device_path);
[email protected]4ae73292011-11-15 05:20:18758 break;
759 }
[email protected]e3c1fc92012-11-15 00:56:46760 case CROS_DISKS_DEVICE_SCANNED: {
761 NotifyDeviceStatusUpdate(DEVICE_SCANNED, device_path);
[email protected]4ae73292011-11-15 05:20:18762 break;
763 }
[email protected]4ae73292011-11-15 05:20:18764 default: {
765 LOG(ERROR) << "Unknown event: " << event;
[email protected]4ae73292011-11-15 05:20:18766 }
767 }
[email protected]4ae73292011-11-15 05:20:18768 }
769
770 // Notifies all observers about disk status update.
Aga Wronskaddc1a752017-12-01 19:44:02771 void NotifyDiskStatusUpdate(DiskEvent event, const Disk& disk) {
772 for (auto& observer : observers_) {
773 disk.IsAutoMountable() ? observer.OnAutoMountableDiskEvent(event, disk)
774 : observer.OnBootDeviceDiskEvent(event, disk);
775 }
[email protected]4ae73292011-11-15 05:20:18776 }
777
778 // Notifies all observers about device status update.
[email protected]e3c1fc92012-11-15 00:56:46779 void NotifyDeviceStatusUpdate(DeviceEvent event,
[email protected]4ae73292011-11-15 05:20:18780 const std::string& device_path) {
yusukes262cf7e22016-10-14 20:56:53781 for (auto& observer : observers_)
782 observer.OnDeviceEvent(event, device_path);
[email protected]4ae73292011-11-15 05:20:18783 }
784
785 // Notifies all observers about mount completion.
[email protected]e3c1fc92012-11-15 00:56:46786 void NotifyMountStatusUpdate(MountEvent event,
787 MountError error_code,
788 const MountPointInfo& mount_info) {
yusukes262cf7e22016-10-14 20:56:53789 for (auto& observer : observers_)
790 observer.OnMountEvent(event, error_code, mount_info);
[email protected]e3c1fc92012-11-15 00:56:46791 }
792
793 void NotifyFormatStatusUpdate(FormatEvent event,
794 FormatError error_code,
795 const std::string& device_path) {
yusukes262cf7e22016-10-14 20:56:53796 for (auto& observer : observers_)
797 observer.OnFormatEvent(event, error_code, device_path);
[email protected]4ae73292011-11-15 05:20:18798 }
799
Klemen Kozjekbf5610f2017-08-25 20:20:09800 void NotifyRenameStatusUpdate(RenameEvent event,
801 RenameError error_code,
802 const std::string& device_path) {
803 for (auto& observer : observers_)
804 observer.OnRenameEvent(event, error_code, device_path);
805 }
806
[email protected]4ae73292011-11-15 05:20:18807 // Finds system path prefix from |system_path|.
808 const std::string& FindSystemPathPrefix(const std::string& system_path) {
809 if (system_path.empty())
[email protected]8790210c2013-12-02 05:29:53810 return base::EmptyString();
[email protected]4ae73292011-11-15 05:20:18811 for (SystemPathPrefixSet::const_iterator it = system_path_prefixes_.begin();
812 it != system_path_prefixes_.end();
813 ++it) {
814 const std::string& prefix = *it;
brettw95509312015-07-16 23:57:33815 if (base::StartsWith(system_path, prefix, base::CompareCase::SENSITIVE))
[email protected]4ae73292011-11-15 05:20:18816 return prefix;
817 }
[email protected]8790210c2013-12-02 05:29:53818 return base::EmptyString();
[email protected]4ae73292011-11-15 05:20:18819 }
820
[email protected]4ae73292011-11-15 05:20:18821 // Mount event change observers.
brettw236d3172015-06-03 16:31:43822 base::ObserverList<Observer> observers_;
[email protected]4ae73292011-11-15 05:20:18823
824 CrosDisksClient* cros_disks_client_;
825
826 // The list of disks found.
827 DiskMountManager::DiskMap disks_;
828
829 DiskMountManager::MountPointMap mount_points_;
830
831 typedef std::set<std::string> SystemPathPrefixSet;
832 SystemPathPrefixSet system_path_prefixes_;
833
[email protected]a2e4ee22014-07-11 05:16:35834 bool already_refreshed_;
835 std::vector<EnsureMountInfoRefreshedCallback> refresh_callbacks_;
836
dcheng0a6e80c2016-04-08 18:37:38837 std::unique_ptr<SuspendUnmountManager> suspend_unmount_manager_;
hirono9f5eae542015-06-22 04:28:41838
yamaguchi6594bf7e12016-08-24 22:16:11839 // Whether the instance attempted to mount a device in read-only mode for
840 // each source path.
841 typedef std::map<std::string, chromeos::MountAccessMode> AccessModeMap;
842 AccessModeMap access_modes_;
843
[email protected]4ae73292011-11-15 05:20:18844 base::WeakPtrFactory<DiskMountManagerImpl> weak_ptr_factory_;
845
846 DISALLOW_COPY_AND_ASSIGN(DiskMountManagerImpl);
847};
848
[email protected]a66a23cb2012-06-19 23:15:33849} // namespace
[email protected]4ae73292011-11-15 05:20:18850
851DiskMountManager::Disk::Disk(const std::string& device_path,
852 const std::string& mount_path,
yamaguchieaaad982016-10-24 09:46:17853 bool write_disabled_by_policy,
[email protected]4ae73292011-11-15 05:20:18854 const std::string& system_path,
855 const std::string& file_path,
856 const std::string& device_label,
857 const std::string& drive_label,
[email protected]202e9fee2012-09-13 20:21:29858 const std::string& vendor_id,
859 const std::string& vendor_name,
860 const std::string& product_id,
861 const std::string& product_name,
[email protected]9c5620d32012-07-31 01:00:38862 const std::string& fs_uuid,
[email protected]4ae73292011-11-15 05:20:18863 const std::string& system_path_prefix,
864 DeviceType device_type,
avi6e1a22d2015-12-21 03:43:20865 uint64_t total_size_in_bytes,
[email protected]4ae73292011-11-15 05:20:18866 bool is_parent,
yamaguchieaaad982016-10-24 09:46:17867 bool is_read_only_hardware,
[email protected]4ae73292011-11-15 05:20:18868 bool has_media,
869 bool on_boot_device,
[email protected]79ed457b2014-07-22 04:07:26870 bool on_removable_device,
Klemen Kozjek46f1c6192017-08-25 19:20:54871 bool is_hidden,
Klemen Kozjekbf5610f2017-08-25 20:20:09872 const std::string& file_system_type,
873 const std::string& base_mount_path)
[email protected]4ae73292011-11-15 05:20:18874 : device_path_(device_path),
875 mount_path_(mount_path),
yamaguchieaaad982016-10-24 09:46:17876 write_disabled_by_policy_(write_disabled_by_policy),
[email protected]4ae73292011-11-15 05:20:18877 system_path_(system_path),
878 file_path_(file_path),
879 device_label_(device_label),
880 drive_label_(drive_label),
[email protected]202e9fee2012-09-13 20:21:29881 vendor_id_(vendor_id),
882 vendor_name_(vendor_name),
883 product_id_(product_id),
884 product_name_(product_name),
[email protected]9c5620d32012-07-31 01:00:38885 fs_uuid_(fs_uuid),
[email protected]4ae73292011-11-15 05:20:18886 system_path_prefix_(system_path_prefix),
887 device_type_(device_type),
888 total_size_in_bytes_(total_size_in_bytes),
889 is_parent_(is_parent),
yamaguchieaaad982016-10-24 09:46:17890 is_read_only_hardware_(is_read_only_hardware),
[email protected]4ae73292011-11-15 05:20:18891 has_media_(has_media),
892 on_boot_device_(on_boot_device),
[email protected]79ed457b2014-07-22 04:07:26893 on_removable_device_(on_removable_device),
Klemen Kozjek46f1c6192017-08-25 19:20:54894 is_hidden_(is_hidden),
Klemen Kozjekbf5610f2017-08-25 20:20:09895 file_system_type_(file_system_type),
896 base_mount_path_(base_mount_path) {}
[email protected]4ae73292011-11-15 05:20:18897
vmpstr2a0c10402016-04-08 21:28:07898DiskMountManager::Disk::Disk(const Disk& other) = default;
899
Chris Watkins2c529d62017-11-29 02:14:41900DiskMountManager::Disk::~Disk() = default;
[email protected]4ae73292011-11-15 05:20:18901
Klemen Kozjekbf5610f2017-08-25 20:20:09902void DiskMountManager::Disk::SetMountPath(const std::string& mount_path) {
903 mount_path_ = mount_path;
904
905 if (base_mount_path_.empty())
906 base_mount_path_ = mount_path;
907}
908
Aga Wronskaddc1a752017-12-01 19:44:02909bool DiskMountManager::Disk::IsAutoMountable() const {
910 // Disks are considered auto-mountable if they are:
911 // 1. Non-virtual
912 // 2. Not on boot device
913 // Only the second condition is checked here, because Disks are created from
914 // non-virtual mount devices only.
915 return !on_boot_device_;
916};
917
Aga Wronska0856cf842017-12-01 20:51:51918bool DiskMountManager::Disk::IsStatefulPartition() const {
919 return mount_path_ == kStatefulPartition;
920}
921
avi8194ad62016-09-20 16:58:36922bool DiskMountManager::AddDiskForTest(std::unique_ptr<Disk> disk) {
[email protected]e3c1fc92012-11-15 00:56:46923 return false;
924}
925
926bool DiskMountManager::AddMountPointForTest(const MountPointInfo& mount_point) {
927 return false;
928}
929
[email protected]4ae73292011-11-15 05:20:18930// static
[email protected]4ae73292011-11-15 05:20:18931std::string DiskMountManager::MountConditionToString(MountCondition condition) {
932 switch (condition) {
933 case MOUNT_CONDITION_NONE:
934 return "";
935 case MOUNT_CONDITION_UNKNOWN_FILESYSTEM:
936 return "unknown_filesystem";
937 case MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM:
938 return "unsupported_filesystem";
939 default:
940 NOTREACHED();
941 }
942 return "";
943}
944
945// static
[email protected]2321d282012-01-31 23:06:59946std::string DiskMountManager::DeviceTypeToString(DeviceType type) {
947 switch (type) {
948 case DEVICE_TYPE_USB:
949 return "usb";
950 case DEVICE_TYPE_SD:
951 return "sd";
952 case DEVICE_TYPE_OPTICAL_DISC:
953 return "optical";
954 case DEVICE_TYPE_MOBILE:
955 return "mobile";
956 default:
957 return "unknown";
958 }
959}
960
961// static
[email protected]4ae73292011-11-15 05:20:18962void DiskMountManager::Initialize() {
[email protected]b307bceb2011-11-17 07:49:55963 if (g_disk_mount_manager) {
964 LOG(WARNING) << "DiskMountManager was already initialized";
965 return;
966 }
[email protected]4ae73292011-11-15 05:20:18967 g_disk_mount_manager = new DiskMountManagerImpl();
[email protected]b307bceb2011-11-17 07:49:55968 VLOG(1) << "DiskMountManager initialized";
969}
970
971// static
972void DiskMountManager::InitializeForTesting(
973 DiskMountManager* disk_mount_manager) {
974 if (g_disk_mount_manager) {
975 LOG(WARNING) << "DiskMountManager was already initialized";
976 return;
977 }
978 g_disk_mount_manager = disk_mount_manager;
979 VLOG(1) << "DiskMountManager initialized";
[email protected]4ae73292011-11-15 05:20:18980}
981
982// static
983void DiskMountManager::Shutdown() {
[email protected]b307bceb2011-11-17 07:49:55984 if (!g_disk_mount_manager) {
985 LOG(WARNING) << "DiskMountManager::Shutdown() called with NULL manager";
986 return;
[email protected]4ae73292011-11-15 05:20:18987 }
[email protected]b307bceb2011-11-17 07:49:55988 delete g_disk_mount_manager;
989 g_disk_mount_manager = NULL;
990 VLOG(1) << "DiskMountManager Shutdown completed";
[email protected]4ae73292011-11-15 05:20:18991}
992
993// static
994DiskMountManager* DiskMountManager::GetInstance() {
995 return g_disk_mount_manager;
996}
997
998} // namespace disks
999} // namespace chromeos