blob: 6a9eab748706989a00e089f7258626f9c37c2ee2 [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>
Hidehiko Abe06ce6dc2017-12-08 19:32:0313#include <utility>
14#include <vector>
[email protected]4ae73292011-11-15 05:20:1815
[email protected]4ae73292011-11-15 05:20:1816#include "base/bind.h"
Peter Kasting383640f52018-02-13 06:22:4017#include "base/bind_helpers.h"
avi6e1a22d2015-12-21 03:43:2018#include "base/macros.h"
avi8194ad62016-09-20 16:58:3619#include "base/memory/ptr_util.h"
[email protected]c6944272012-01-06 22:12:2820#include "base/memory/weak_ptr.h"
[email protected]3fc40c142011-12-01 13:09:0421#include "base/observer_list.h"
[email protected]afa339d72013-06-11 06:32:5122#include "base/strings/string_util.h"
Hidehiko Abe06ce6dc2017-12-08 19:32:0323#include "chromeos/dbus/cros_disks_client.h"
[email protected]64e199252012-04-06 01:54:3624#include "chromeos/dbus/dbus_thread_manager.h"
hirono9f5eae542015-06-22 04:28:4125#include "chromeos/disks/suspend_unmount_manager.h"
[email protected]4ae73292011-11-15 05:20:1826
27namespace chromeos {
28namespace disks {
29
30namespace {
31
Aga Wronska0856cf842017-12-01 20:51:5132constexpr char kDefaultFormattedDeviceName[] = "UNTITLED";
33constexpr char kDefaultFormatVFAT[] = "vfat";
34constexpr char kDeviceNotFound[] = "Device could not be found";
35constexpr char kStatefulPartition[] = "/mnt/stateful_partition";
[email protected]4ae73292011-11-15 05:20:1836DiskMountManager* g_disk_mount_manager = NULL;
37
38// The DiskMountManager implementation.
Hidehiko Abe06ce6dc2017-12-08 19:32:0339class DiskMountManagerImpl : public DiskMountManager,
40 public CrosDisksClient::Observer {
[email protected]4ae73292011-11-15 05:20:1841 public:
[email protected]a2e4ee22014-07-11 05:16:3542 DiskMountManagerImpl() :
43 already_refreshed_(false),
44 weak_ptr_factory_(this) {
[email protected]4ae73292011-11-15 05:20:1845 DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get();
[email protected]4ae73292011-11-15 05:20:1846 cros_disks_client_ = dbus_thread_manager->GetCrosDisksClient();
hirono9f5eae542015-06-22 04:28:4147 PowerManagerClient* power_manager_client =
48 dbus_thread_manager->GetPowerManagerClient();
49 suspend_unmount_manager_.reset(
50 new SuspendUnmountManager(this, power_manager_client));
Hidehiko Abe06ce6dc2017-12-08 19:32:0351 cros_disks_client_->AddObserver(this);
[email protected]4ae73292011-11-15 05:20:1852 }
53
Hidehiko Abe06ce6dc2017-12-08 19:32:0354 ~DiskMountManagerImpl() override { cros_disks_client_->RemoveObserver(this); }
[email protected]4ae73292011-11-15 05:20:1855
56 // DiskMountManager override.
Hidehiko Abe06ce6dc2017-12-08 19:32:0357 void AddObserver(DiskMountManager::Observer* observer) override {
[email protected]4ae73292011-11-15 05:20:1858 observers_.AddObserver(observer);
59 }
60
61 // DiskMountManager override.
Hidehiko Abe06ce6dc2017-12-08 19:32:0362 void RemoveObserver(DiskMountManager::Observer* observer) override {
[email protected]4ae73292011-11-15 05:20:1863 observers_.RemoveObserver(observer);
64 }
65
66 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:4967 void MountPath(const std::string& source_path,
68 const std::string& source_format,
69 const std::string& mount_label,
yamaguchicc8186b2016-08-08 06:38:5470 MountType type,
71 MountAccessMode access_mode) override {
[email protected]4ae73292011-11-15 05:20:1872 // Hidden and non-existent devices should not be mounted.
73 if (type == MOUNT_TYPE_DEVICE) {
74 DiskMap::const_iterator it = disks_.find(source_path);
75 if (it == disks_.end() || it->second->is_hidden()) {
[email protected]d7760592014-05-16 07:57:5276 OnMountCompleted(MountEntry(MOUNT_ERROR_INTERNAL, source_path, type,
77 ""));
[email protected]4ae73292011-11-15 05:20:1878 return;
79 }
80 }
[email protected]4ae73292011-11-15 05:20:1881 cros_disks_client_->Mount(
yamaguchicc8186b2016-08-08 06:38:5482 source_path, source_format, mount_label, access_mode,
yamaguchifa8efc72016-10-21 15:05:5183 REMOUNT_OPTION_MOUNT_NEW_DEVICE,
Hidehiko Abec293cdcf2018-02-08 02:10:4584 base::BindOnce(&DiskMountManagerImpl::OnMount,
85 weak_ptr_factory_.GetWeakPtr(), source_path, type));
yamaguchi6594bf7e12016-08-24 22:16:1186
87 // Record the access mode option passed to CrosDisks.
88 // This is needed because CrosDisks service methods doesn't return the info
89 // via DBus.
90 access_modes_.insert(std::make_pair(source_path, access_mode));
[email protected]4ae73292011-11-15 05:20:1891 }
92
93 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:4994 void UnmountPath(const std::string& mount_path,
95 UnmountOptions options,
96 const UnmountPathCallback& callback) override {
[email protected]3af8e1b2012-09-15 20:46:0597 UnmountChildMounts(mount_path);
Hidehiko Abec293cdcf2018-02-08 02:10:4598 cros_disks_client_->Unmount(
99 mount_path, options,
100 base::BindOnce(&DiskMountManagerImpl::OnUnmountPath,
101 weak_ptr_factory_.GetWeakPtr(), callback, mount_path));
[email protected]4ae73292011-11-15 05:20:18102 }
103
yamaguchide59ed62016-11-08 10:07:10104 void RemountAllRemovableDrives(MountAccessMode mode) override {
105 // TODO(yamaguchi): Retry for tentative remount failures. crbug.com/661455
106 for (const auto& device_path_and_disk : disks_) {
107 const Disk& disk = *device_path_and_disk.second;
108 if (disk.is_read_only_hardware()) {
109 // Read-only devices can be mounted in RO mode only. No need to remount.
110 continue;
111 }
112 if (!disk.is_mounted()) {
113 continue;
114 }
115 RemountRemovableDrive(disk, mode);
116 }
117 }
118
[email protected]4ae73292011-11-15 05:20:18119 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49120 void FormatMountedDevice(const std::string& mount_path) override {
[email protected]e3c1fc92012-11-15 00:56:46121 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path);
122 if (mount_point == mount_points_.end()) {
123 LOG(ERROR) << "Mount point with path \"" << mount_path << "\" not found.";
[email protected]f026c0f2014-05-06 21:52:35124 OnFormatCompleted(FORMAT_ERROR_UNKNOWN, mount_path);
[email protected]4ae73292011-11-15 05:20:18125 return;
126 }
[email protected]e3c1fc92012-11-15 00:56:46127
128 std::string device_path = mount_point->second.source_path;
129 DiskMap::const_iterator disk = disks_.find(device_path);
130 if (disk == disks_.end()) {
131 LOG(ERROR) << "Device with path \"" << device_path << "\" not found.";
[email protected]f026c0f2014-05-06 21:52:35132 OnFormatCompleted(FORMAT_ERROR_UNKNOWN, device_path);
[email protected]e3c1fc92012-11-15 00:56:46133 return;
134 }
yamaguchibffc32eb2016-08-17 06:35:39135 if (disk->second->is_read_only()) {
136 LOG(ERROR) << "Mount point with path \"" << mount_path
137 << "\" is read-only.";
138 OnFormatCompleted(FORMAT_ERROR_DEVICE_NOT_ALLOWED, mount_path);
139 return;
140 }
[email protected]e3c1fc92012-11-15 00:56:46141
[email protected]8f919ee2013-03-14 19:53:29142 UnmountPath(disk->second->mount_path(),
143 UNMOUNT_OPTIONS_NONE,
144 base::Bind(&DiskMountManagerImpl::OnUnmountPathForFormat,
145 weak_ptr_factory_.GetWeakPtr(),
146 device_path));
[email protected]4ae73292011-11-15 05:20:18147 }
148
Klemen Kozjekbf5610f2017-08-25 20:20:09149 void RenameMountedDevice(const std::string& mount_path,
150 const std::string& volume_name) override {
151 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path);
152 if (mount_point == mount_points_.end()) {
153 LOG(ERROR) << "Mount point with path '" << mount_path << "' not found.";
154 OnRenameCompleted(RENAME_ERROR_UNKNOWN, mount_path);
155 return;
156 }
157
158 std::string device_path = mount_point->second.source_path;
159 DiskMap::const_iterator iter = disks_.find(device_path);
160 if (iter == disks_.end()) {
161 LOG(ERROR) << "Device with path '" << device_path << "' not found.";
162 OnRenameCompleted(RENAME_ERROR_UNKNOWN, device_path);
163 return;
164 }
165 if (iter->second->is_read_only()) {
166 LOG(ERROR) << "Mount point with path '" << mount_path
167 << "' is read-only.";
168 OnRenameCompleted(RENAME_ERROR_DEVICE_NOT_ALLOWED, mount_path);
169 return;
170 }
171
172 UnmountPath(
173 iter->second->mount_path(), UNMOUNT_OPTIONS_NONE,
174 base::Bind(&DiskMountManagerImpl::OnUnmountPathForRename,
175 weak_ptr_factory_.GetWeakPtr(), device_path, volume_name));
176 }
177
[email protected]4ae73292011-11-15 05:20:18178 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49179 void UnmountDeviceRecursively(
[email protected]4ae73292011-11-15 05:20:18180 const std::string& device_path,
mostynb4f4cf142014-10-06 13:57:52181 const UnmountDeviceRecursivelyCallbackType& callback) override {
[email protected]4ae73292011-11-15 05:20:18182 std::vector<std::string> devices_to_unmount;
183
184 // Get list of all devices to unmount.
185 int device_path_len = device_path.length();
186 for (DiskMap::iterator it = disks_.begin(); it != disks_.end(); ++it) {
187 if (!it->second->mount_path().empty() &&
188 strncmp(device_path.c_str(), it->second->device_path().c_str(),
189 device_path_len) == 0) {
190 devices_to_unmount.push_back(it->second->mount_path());
191 }
192 }
[email protected]e008d4fa2013-02-21 06:38:01193
[email protected]4ae73292011-11-15 05:20:18194 // We should detect at least original device.
195 if (devices_to_unmount.empty()) {
196 if (disks_.find(device_path) == disks_.end()) {
[email protected]e008d4fa2013-02-21 06:38:01197 LOG(WARNING) << "Unmount recursive request failed for device "
198 << device_path << ", with error: " << kDeviceNotFound;
199 callback.Run(false);
[email protected]4ae73292011-11-15 05:20:18200 return;
201 }
[email protected]e008d4fa2013-02-21 06:38:01202
203 // Nothing to unmount.
204 callback.Run(true);
205 return;
[email protected]4ae73292011-11-15 05:20:18206 }
[email protected]e008d4fa2013-02-21 06:38:01207
208 // We will send the same callback data object to all Unmount calls and use
[email protected]a2e4ee22014-07-11 05:16:35209 // it to synchronize callbacks.
[email protected]e008d4fa2013-02-21 06:38:01210 // Note: this implementation has a potential memory leak issue. For
211 // example if this instance is destructed before all the callbacks for
212 // Unmount are invoked, the memory pointed by |cb_data| will be leaked.
213 // It is because the UnmountDeviceRecursivelyCallbackData keeps how
214 // many times OnUnmountDeviceRecursively callback is called and when
215 // all the callbacks are called, |cb_data| will be deleted in the method.
216 // However destructing the instance before all callback invocations will
217 // cancel all pending callbacks, so that the |cb_data| would never be
218 // deleted.
219 // Fortunately, in the real scenario, the instance will be destructed
220 // only for ShutDown. So, probably the memory would rarely be leaked.
221 // TODO(hidehiko): Fix the issue.
222 UnmountDeviceRecursivelyCallbackData* cb_data =
223 new UnmountDeviceRecursivelyCallbackData(
224 callback, devices_to_unmount.size());
225 for (size_t i = 0; i < devices_to_unmount.size(); ++i) {
226 cros_disks_client_->Unmount(
Hidehiko Abec293cdcf2018-02-08 02:10:45227 devices_to_unmount[i], UNMOUNT_OPTIONS_NONE,
228 base::BindOnce(&DiskMountManagerImpl::OnUnmountDeviceRecursively,
229 weak_ptr_factory_.GetWeakPtr(), cb_data,
230 devices_to_unmount[i]));
[email protected]4ae73292011-11-15 05:20:18231 }
232 }
233
234 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49235 void EnsureMountInfoRefreshed(
hironoa4b675d2015-07-29 01:13:37236 const EnsureMountInfoRefreshedCallback& callback,
237 bool force) override {
238 if (!force && already_refreshed_) {
[email protected]a2e4ee22014-07-11 05:16:35239 callback.Run(true);
240 return;
241 }
242
243 refresh_callbacks_.push_back(callback);
244 if (refresh_callbacks_.size() == 1) {
245 // If there's no in-flight refreshing task, start it.
Aga Wronskaddc1a752017-12-01 19:44:02246 cros_disks_client_->EnumerateDevices(
[email protected]a2e4ee22014-07-11 05:16:35247 base::Bind(&DiskMountManagerImpl::RefreshAfterEnumerateDevices,
248 weak_ptr_factory_.GetWeakPtr()),
249 base::Bind(&DiskMountManagerImpl::RefreshCompleted,
250 weak_ptr_factory_.GetWeakPtr(), false));
251 }
[email protected]4ae73292011-11-15 05:20:18252 }
253
254 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49255 const DiskMap& disks() const override { return disks_; }
[email protected]4ae73292011-11-15 05:20:18256
[email protected]bcfa0072012-08-07 01:08:57257 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49258 const Disk* FindDiskBySourcePath(
259 const std::string& source_path) const override {
[email protected]bcfa0072012-08-07 01:08:57260 DiskMap::const_iterator disk_it = disks_.find(source_path);
avi8194ad62016-09-20 16:58:36261 return disk_it == disks_.end() ? NULL : disk_it->second.get();
[email protected]bcfa0072012-08-07 01:08:57262 }
[email protected]4ae73292011-11-15 05:20:18263
264 // DiskMountManager override.
dchengae98daa2015-01-21 20:30:49265 const MountPointMap& mount_points() const override { return mount_points_; }
[email protected]4ae73292011-11-15 05:20:18266
[email protected]e3c1fc92012-11-15 00:56:46267 // DiskMountManager override.
avi8194ad62016-09-20 16:58:36268 bool AddDiskForTest(std::unique_ptr<Disk> disk) override {
[email protected]e3c1fc92012-11-15 00:56:46269 if (disks_.find(disk->device_path()) != disks_.end()) {
270 LOG(ERROR) << "Attempt to add a duplicate disk";
271 return false;
272 }
273
avi8194ad62016-09-20 16:58:36274 disks_.insert(std::make_pair(disk->device_path(), std::move(disk)));
[email protected]e3c1fc92012-11-15 00:56:46275 return true;
276 }
277
278 // DiskMountManager override.
279 // Corresponding disk should be added to the manager before this is called.
dchengae98daa2015-01-21 20:30:49280 bool AddMountPointForTest(const MountPointInfo& mount_point) override {
[email protected]e3c1fc92012-11-15 00:56:46281 if (mount_points_.find(mount_point.mount_path) != mount_points_.end()) {
282 LOG(ERROR) << "Attempt to add a duplicate mount point";
283 return false;
284 }
285 if (mount_point.mount_type == chromeos::MOUNT_TYPE_DEVICE &&
286 disks_.find(mount_point.source_path) == disks_.end()) {
287 LOG(ERROR) << "Device mount points must have a disk entry.";
288 return false;
289 }
290
291 mount_points_.insert(std::make_pair(mount_point.mount_path, mount_point));
292 return true;
293 }
294
[email protected]4ae73292011-11-15 05:20:18295 private:
Klemen Kozjek46f1c6192017-08-25 19:20:54296 // A struct to represent information about a format changes.
297 struct FormatChange {
298 // new file system type
299 std::string file_system_type;
300 // New volume name
301 std::string volume_name;
302 };
303
304 // Stores new volume name and file system type for a device on which
305 // formatting is invoked on, so that OnFormatCompleted can set it back to
306 // |disks_|. The key is a device_path and the value is a FormatChange.
307 std::map<std::string, FormatChange> pending_format_changes_;
308
Klemen Kozjekbf5610f2017-08-25 20:20:09309 // Stores new volume name for a device on which renaming is invoked on, so
310 // that OnRenameCompleted can set it back to |disks_|. The key is a
311 // device_path and the value is new volume_name.
312 std::map<std::string, std::string> pending_rename_changes_;
313
[email protected]e008d4fa2013-02-21 06:38:01314 struct UnmountDeviceRecursivelyCallbackData {
315 UnmountDeviceRecursivelyCallbackData(
316 const UnmountDeviceRecursivelyCallbackType& in_callback,
317 int in_num_pending_callbacks)
318 : callback(in_callback),
319 num_pending_callbacks(in_num_pending_callbacks) {
[email protected]4ae73292011-11-15 05:20:18320 }
[email protected]e008d4fa2013-02-21 06:38:01321
322 const UnmountDeviceRecursivelyCallbackType callback;
323 size_t num_pending_callbacks;
[email protected]4ae73292011-11-15 05:20:18324 };
325
Hidehiko Abec293cdcf2018-02-08 02:10:45326 // Called on D-Bus CrosDisksClient::Mount() is done.
327 void OnMount(const std::string& source_path, MountType type, bool result) {
328 // When succeeds, OnMountCompleted will be called by "MountCompleted",
329 // signal instead. Do nothing now.
330 if (result)
331 return;
332
333 OnMountCompleted(
334 MountEntry(MOUNT_ERROR_INTERNAL, source_path, type, std::string()));
335 }
336
yamaguchide59ed62016-11-08 10:07:10337 void RemountRemovableDrive(const Disk& disk,
338 MountAccessMode access_mode) {
339 const std::string& mount_path = disk.mount_path();
340 MountPointMap::const_iterator mount_point = mount_points_.find(mount_path);
341 if (mount_point == mount_points_.end()) {
342 // Not in mount_points_. This happens when the mount_points ans disks_ are
343 // inconsistent.
344 LOG(ERROR) << "Mount point with path \"" << mount_path << "\" not found.";
345 OnMountCompleted(
346 MountEntry(MOUNT_ERROR_PATH_NOT_MOUNTED, disk.device_path(),
347 MOUNT_TYPE_DEVICE, mount_path));
348 return;
349 }
350 const std::string& source_path = mount_point->second.source_path;
351
352 // Update the access mode option passed to CrosDisks.
353 // This is needed because CrosDisks service methods doesn't return the info
354 // via DBus, and must be updated before issuing Mount command as it'll be
355 // read by the handler of MountCompleted signal.
356 access_modes_[source_path] = access_mode;
357
358 cros_disks_client_->Mount(
359 mount_point->second.source_path, std::string(), std::string(),
360 access_mode, REMOUNT_OPTION_REMOUNT_EXISTING_DEVICE,
Hidehiko Abec293cdcf2018-02-08 02:10:45361 base::BindOnce(&DiskMountManagerImpl::OnMount,
362 weak_ptr_factory_.GetWeakPtr(), source_path,
363 mount_point->second.mount_type));
yamaguchide59ed62016-11-08 10:07:10364 }
365
[email protected]3af8e1b2012-09-15 20:46:05366 // Unmounts all mount points whose source path is transitively parented by
367 // |mount_path|.
368 void UnmountChildMounts(const std::string& mount_path_in) {
369 std::string mount_path = mount_path_in;
370 // Let's make sure mount path has trailing slash.
pkasting9022cb42016-02-05 00:08:56371 if (mount_path.back() != '/')
[email protected]3af8e1b2012-09-15 20:46:05372 mount_path += '/';
373
374 for (MountPointMap::iterator it = mount_points_.begin();
375 it != mount_points_.end();
376 ++it) {
brettw95509312015-07-16 23:57:33377 if (base::StartsWith(it->second.source_path, mount_path,
378 base::CompareCase::SENSITIVE)) {
[email protected]8f919ee2013-03-14 19:53:29379 // TODO(tbarzic): Handle the case where this fails.
380 UnmountPath(it->second.mount_path,
381 UNMOUNT_OPTIONS_NONE,
382 UnmountPathCallback());
[email protected]3af8e1b2012-09-15 20:46:05383 }
384 }
385 }
386
[email protected]e008d4fa2013-02-21 06:38:01387 // Callback for UnmountDeviceRecursively.
Hidehiko Abec293cdcf2018-02-08 02:10:45388 void OnUnmountDeviceRecursively(UnmountDeviceRecursivelyCallbackData* cb_data,
389 const std::string& mount_path,
390 bool success) {
[email protected]4ae73292011-11-15 05:20:18391 if (success) {
392 // Do standard processing for Unmount event.
Hidehiko Abec293cdcf2018-02-08 02:10:45393 OnUnmountPath(UnmountPathCallback(), mount_path, true /* success */);
[email protected]a0278d52014-05-06 03:36:15394 VLOG(1) << mount_path << " unmounted.";
[email protected]4ae73292011-11-15 05:20:18395 }
396 // This is safe as long as all callbacks are called on the same thread as
[email protected]e008d4fa2013-02-21 06:38:01397 // UnmountDeviceRecursively.
398 cb_data->num_pending_callbacks--;
[email protected]4ae73292011-11-15 05:20:18399
[email protected]e008d4fa2013-02-21 06:38:01400 if (cb_data->num_pending_callbacks == 0) {
401 // This code has a problem that the |success| status used here is for the
402 // last "unmount" callback, but not whether all unmounting is succeeded.
403 // TODO(hidehiko): Fix the issue.
404 cb_data->callback.Run(success);
[email protected]4ae73292011-11-15 05:20:18405 delete cb_data;
406 }
407 }
408
Hidehiko Abe06ce6dc2017-12-08 19:32:03409 // CrosDisksClient::Observer override.
410 void OnMountCompleted(const MountEntry& entry) override {
[email protected]4ae73292011-11-15 05:20:18411 MountCondition mount_condition = MOUNT_CONDITION_NONE;
[email protected]d7760592014-05-16 07:57:52412 if (entry.mount_type() == MOUNT_TYPE_DEVICE) {
413 if (entry.error_code() == MOUNT_ERROR_UNKNOWN_FILESYSTEM) {
[email protected]4ae73292011-11-15 05:20:18414 mount_condition = MOUNT_CONDITION_UNKNOWN_FILESYSTEM;
[email protected]a66a23cb2012-06-19 23:15:33415 }
[email protected]d7760592014-05-16 07:57:52416 if (entry.error_code() == MOUNT_ERROR_UNSUPPORTED_FILESYSTEM) {
[email protected]4ae73292011-11-15 05:20:18417 mount_condition = MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM;
[email protected]a66a23cb2012-06-19 23:15:33418 }
[email protected]4ae73292011-11-15 05:20:18419 }
[email protected]d7760592014-05-16 07:57:52420 const MountPointInfo mount_info(entry.source_path(),
421 entry.mount_path(),
422 entry.mount_type(),
[email protected]4ae73292011-11-15 05:20:18423 mount_condition);
424
[email protected]4ae73292011-11-15 05:20:18425 // If the device is corrupted but it's still possible to format it, it will
426 // be fake mounted.
[email protected]d7760592014-05-16 07:57:52427 if ((entry.error_code() == MOUNT_ERROR_NONE ||
428 mount_info.mount_condition) &&
[email protected]4ae73292011-11-15 05:20:18429 mount_points_.find(mount_info.mount_path) == mount_points_.end()) {
430 mount_points_.insert(MountPointMap::value_type(mount_info.mount_path,
431 mount_info));
432 }
yamaguchi6594bf7e12016-08-24 22:16:11433
[email protected]d7760592014-05-16 07:57:52434 if ((entry.error_code() == MOUNT_ERROR_NONE ||
435 mount_info.mount_condition) &&
[email protected]4ae73292011-11-15 05:20:18436 mount_info.mount_type == MOUNT_TYPE_DEVICE &&
437 !mount_info.source_path.empty() &&
438 !mount_info.mount_path.empty()) {
439 DiskMap::iterator iter = disks_.find(mount_info.source_path);
yamaguchi6594bf7e12016-08-24 22:16:11440 if (iter != disks_.end()) { // disk might have been removed by now?
avi8194ad62016-09-20 16:58:36441 Disk* disk = iter->second.get();
yamaguchi6594bf7e12016-08-24 22:16:11442 DCHECK(disk);
yamaguchide59ed62016-11-08 10:07:10443 // Currently the MountCompleted signal doesn't tell whether the device
444 // is mounted in read-only mode or not. Instead use the mount option
445 // recorded by DiskMountManagerImpl::MountPath().
yamaguchi6594bf7e12016-08-24 22:16:11446 // |source_path| should be same as |disk->device_path| because
447 // |VolumeManager::OnDiskEvent()| passes the latter to cros-disks as a
448 // source path when mounting a device.
449 AccessModeMap::iterator it = access_modes_.find(entry.source_path());
yamaguchide59ed62016-11-08 10:07:10450
451 // Store whether the disk was mounted in read-only mode due to a policy.
452 disk->set_write_disabled_by_policy(
453 it != access_modes_.end() && !disk->is_read_only_hardware()
454 && it->second == MOUNT_ACCESS_MODE_READ_ONLY);
Klemen Kozjekbf5610f2017-08-25 20:20:09455 disk->SetMountPath(mount_info.mount_path);
[email protected]4ae73292011-11-15 05:20:18456 }
[email protected]4ae73292011-11-15 05:20:18457 }
yamaguchi6594bf7e12016-08-24 22:16:11458 // Observers may read the values of disks_. So notify them after tweaking
459 // values of disks_.
460 NotifyMountStatusUpdate(MOUNTING, entry.error_code(), mount_info);
[email protected]4ae73292011-11-15 05:20:18461 }
462
463 // Callback for UnmountPath.
[email protected]8f919ee2013-03-14 19:53:29464 void OnUnmountPath(const UnmountPathCallback& callback,
Hidehiko Abec293cdcf2018-02-08 02:10:45465 const std::string& mount_path,
466 bool success) {
[email protected]4ae73292011-11-15 05:20:18467 MountPointMap::iterator mount_points_it = mount_points_.find(mount_path);
[email protected]8f919ee2013-03-14 19:53:29468 if (mount_points_it == mount_points_.end()) {
469 // The path was unmounted, but not as a result of this unmount request,
470 // so return error.
471 if (!callback.is_null())
472 callback.Run(MOUNT_ERROR_INTERNAL);
[email protected]4ae73292011-11-15 05:20:18473 return;
[email protected]8f919ee2013-03-14 19:53:29474 }
[email protected]e3c1fc92012-11-15 00:56:46475
476 NotifyMountStatusUpdate(
[email protected]10795ae2012-10-10 07:33:49477 UNMOUNTING,
478 success ? MOUNT_ERROR_NONE : MOUNT_ERROR_INTERNAL,
[email protected]a66a23cb2012-06-19 23:15:33479 MountPointInfo(mount_points_it->second.source_path,
480 mount_points_it->second.mount_path,
481 mount_points_it->second.mount_type,
482 mount_points_it->second.mount_condition));
[email protected]10795ae2012-10-10 07:33:49483
[email protected]4ae73292011-11-15 05:20:18484 std::string path(mount_points_it->second.source_path);
[email protected]10795ae2012-10-10 07:33:49485 if (success)
486 mount_points_.erase(mount_points_it);
487
[email protected]e3c1fc92012-11-15 00:56:46488 DiskMap::iterator disk_iter = disks_.find(path);
489 if (disk_iter != disks_.end()) {
490 DCHECK(disk_iter->second);
491 if (success)
492 disk_iter->second->clear_mount_path();
[email protected]4ae73292011-11-15 05:20:18493 }
[email protected]10795ae2012-10-10 07:33:49494
[email protected]8f919ee2013-03-14 19:53:29495 if (!callback.is_null())
496 callback.Run(success ? MOUNT_ERROR_NONE : MOUNT_ERROR_INTERNAL);
497 }
498
499 void OnUnmountPathForFormat(const std::string& device_path,
500 MountError error_code) {
501 if (error_code == MOUNT_ERROR_NONE &&
502 disks_.find(device_path) != disks_.end()) {
503 FormatUnmountedDevice(device_path);
504 } else {
[email protected]f026c0f2014-05-06 21:52:35505 OnFormatCompleted(FORMAT_ERROR_UNKNOWN, device_path);
[email protected]4ae73292011-11-15 05:20:18506 }
507 }
508
[email protected]e3c1fc92012-11-15 00:56:46509 // Starts device formatting.
510 void FormatUnmountedDevice(const std::string& device_path) {
511 DiskMap::const_iterator disk = disks_.find(device_path);
512 DCHECK(disk != disks_.end() && disk->second->mount_path().empty());
513
Klemen Kozjek46f1c6192017-08-25 19:20:54514 pending_format_changes_[device_path] = {kDefaultFormatVFAT,
515 kDefaultFormattedDeviceName};
516
[email protected]f026c0f2014-05-06 21:52:35517 cros_disks_client_->Format(
Klemen Kozjek46f1c6192017-08-25 19:20:54518 device_path, kDefaultFormatVFAT,
Hidehiko Abec293cdcf2018-02-08 02:10:45519 base::BindOnce(&DiskMountManagerImpl::OnFormatStarted,
520 weak_ptr_factory_.GetWeakPtr(), device_path));
[email protected]e3c1fc92012-11-15 00:56:46521 }
522
[email protected]f026c0f2014-05-06 21:52:35523 // Callback for Format.
Hidehiko Abec293cdcf2018-02-08 02:10:45524 void OnFormatStarted(const std::string& device_path, bool success) {
525 if (!success) {
526 OnFormatCompleted(FORMAT_ERROR_UNKNOWN, device_path);
527 return;
528 }
529
[email protected]f026c0f2014-05-06 21:52:35530 NotifyFormatStatusUpdate(FORMAT_STARTED, FORMAT_ERROR_NONE, device_path);
[email protected]4ae73292011-11-15 05:20:18531 }
532
Hidehiko Abe06ce6dc2017-12-08 19:32:03533 // CrosDisksClient::Observer override.
[email protected]a0278d52014-05-06 03:36:15534 void OnFormatCompleted(FormatError error_code,
Hidehiko Abe06ce6dc2017-12-08 19:32:03535 const std::string& device_path) override {
Klemen Kozjek46f1c6192017-08-25 19:20:54536 auto iter = disks_.find(device_path);
Klemen Kozjekbf5610f2017-08-25 20:20:09537
Klemen Kozjek46f1c6192017-08-25 19:20:54538 // disk might have been removed by now?
539 if (iter != disks_.end()) {
540 Disk* disk = iter->second.get();
541 DCHECK(disk);
542
543 auto pending_change = pending_format_changes_.find(device_path);
Klemen Kozjekbf5610f2017-08-25 20:20:09544 if (pending_change != pending_format_changes_.end() &&
545 error_code == FORMAT_ERROR_NONE) {
546 disk->set_device_label(pending_change->second.volume_name);
547 disk->set_file_system_type(pending_change->second.file_system_type);
Klemen Kozjek46f1c6192017-08-25 19:20:54548 }
549 }
550
Klemen Kozjekbf5610f2017-08-25 20:20:09551 pending_format_changes_.erase(device_path);
552
[email protected]f026c0f2014-05-06 21:52:35553 NotifyFormatStatusUpdate(FORMAT_COMPLETED, error_code, device_path);
[email protected]a0278d52014-05-06 03:36:15554 }
555
Klemen Kozjekbf5610f2017-08-25 20:20:09556 void OnUnmountPathForRename(const std::string& device_path,
557 const std::string& volume_name,
558 MountError error_code) {
559 if (error_code != MOUNT_ERROR_NONE ||
560 disks_.find(device_path) == disks_.end()) {
561 OnRenameCompleted(RENAME_ERROR_UNKNOWN, device_path);
562 return;
563 }
564
565 RenameUnmountedDevice(device_path, volume_name);
566 }
567
568 // Start device renaming
569 void RenameUnmountedDevice(const std::string& device_path,
570 const std::string& volume_name) {
571 DiskMap::const_iterator disk = disks_.find(device_path);
572 DCHECK(disk != disks_.end() && disk->second->mount_path().empty());
573
574 pending_rename_changes_[device_path] = volume_name;
575 cros_disks_client_->Rename(
576 device_path, volume_name,
Hidehiko Abec293cdcf2018-02-08 02:10:45577 base::BindOnce(&DiskMountManagerImpl::OnRenameStarted,
578 weak_ptr_factory_.GetWeakPtr(), device_path));
Klemen Kozjekbf5610f2017-08-25 20:20:09579 }
580
581 // Callback for Rename.
Hidehiko Abec293cdcf2018-02-08 02:10:45582 void OnRenameStarted(const std::string& device_path, bool success) {
583 if (!success) {
584 OnRenameCompleted(RENAME_ERROR_UNKNOWN, device_path);
585 return;
586 }
587
Klemen Kozjekbf5610f2017-08-25 20:20:09588 NotifyRenameStatusUpdate(RENAME_STARTED, RENAME_ERROR_NONE, device_path);
589 }
590
Hidehiko Abe06ce6dc2017-12-08 19:32:03591 // CrosDisksClient::Observer override.
Klemen Kozjekbf5610f2017-08-25 20:20:09592 void OnRenameCompleted(RenameError error_code,
Hidehiko Abe06ce6dc2017-12-08 19:32:03593 const std::string& device_path) override {
Klemen Kozjekbf5610f2017-08-25 20:20:09594 auto iter = disks_.find(device_path);
595
596 // disk might have been removed by now?
597 if (iter != disks_.end()) {
598 Disk* disk = iter->second.get();
599 DCHECK(disk);
600
601 auto pending_change = pending_rename_changes_.find(device_path);
602 if (pending_change != pending_rename_changes_.end() &&
603 error_code == RENAME_ERROR_NONE)
604 disk->set_device_label(pending_change->second);
605 }
606
607 pending_rename_changes_.erase(device_path);
608
609 NotifyRenameStatusUpdate(RENAME_COMPLETED, error_code, device_path);
610 }
611
[email protected]a2e4ee22014-07-11 05:16:35612 // Callback for GetDeviceProperties.
[email protected]4ae73292011-11-15 05:20:18613 void OnGetDeviceProperties(const DiskInfo& disk_info) {
Aga Wronskaddc1a752017-12-01 19:44:02614 if (disk_info.is_virtual())
[email protected]4ae73292011-11-15 05:20:18615 return;
616
617 LOG(WARNING) << "Found disk " << disk_info.device_path();
618 // Delete previous disk info for this path:
619 bool is_new = true;
Klemen Kozjekbf5610f2017-08-25 20:20:09620 std::string base_mount_path = std::string();
[email protected]4ae73292011-11-15 05:20:18621 DiskMap::iterator iter = disks_.find(disk_info.device_path());
622 if (iter != disks_.end()) {
Klemen Kozjekbf5610f2017-08-25 20:20:09623 base_mount_path = iter->second->base_mount_path();
[email protected]4ae73292011-11-15 05:20:18624 disks_.erase(iter);
625 is_new = false;
626 }
yamaguchieaaad982016-10-24 09:46:17627
628 // If the device was mounted by the instance, apply recorded parameter.
629 // Otherwise, default to false.
630 // Lookup by |device_path| which we pass to cros-disks when mounting a
631 // device in |VolumeManager::OnDiskEvent()|.
632 auto access_mode = access_modes_.find(disk_info.device_path());
633 bool write_disabled_by_policy = access_mode != access_modes_.end()
634 && access_mode->second == chromeos::MOUNT_ACCESS_MODE_READ_ONLY;
Aga Wronskaddc1a752017-12-01 19:44:02635 // TODO(agawronska): Add constructor for Disk from DiskInfo. Introduce Disk
636 // builder class for tests.
Klemen Kozjek46f1c6192017-08-25 19:20:54637 Disk* disk = new Disk(
638 disk_info.device_path(), disk_info.mount_path(),
639 write_disabled_by_policy, disk_info.system_path(),
640 disk_info.file_path(), disk_info.label(), disk_info.drive_label(),
641 disk_info.vendor_id(), disk_info.vendor_name(), disk_info.product_id(),
642 disk_info.product_name(), disk_info.uuid(),
643 FindSystemPathPrefix(disk_info.system_path()), disk_info.device_type(),
644 disk_info.total_size_in_bytes(), disk_info.is_drive(),
645 disk_info.is_read_only(), disk_info.has_media(),
646 disk_info.on_boot_device(), disk_info.on_removable_device(),
Klemen Kozjekbf5610f2017-08-25 20:20:09647 disk_info.is_hidden(), disk_info.file_system_type(), base_mount_path);
avi8194ad62016-09-20 16:58:36648 disks_.insert(
649 std::make_pair(disk_info.device_path(), base::WrapUnique(disk)));
Aga Wronskaddc1a752017-12-01 19:44:02650 NotifyDiskStatusUpdate(is_new ? DISK_ADDED : DISK_CHANGED, *disk);
[email protected]4ae73292011-11-15 05:20:18651 }
652
[email protected]a2e4ee22014-07-11 05:16:35653 // Part of EnsureMountInfoRefreshed(). Called after the list of devices are
654 // enumerated.
655 void RefreshAfterEnumerateDevices(const std::vector<std::string>& devices) {
656 std::set<std::string> current_device_set(devices.begin(), devices.end());
[email protected]4ae73292011-11-15 05:20:18657 for (DiskMap::iterator iter = disks_.begin(); iter != disks_.end(); ) {
658 if (current_device_set.find(iter->first) == current_device_set.end()) {
[email protected]4ae73292011-11-15 05:20:18659 disks_.erase(iter++);
660 } else {
661 ++iter;
662 }
663 }
[email protected]a2e4ee22014-07-11 05:16:35664 RefreshDeviceAtIndex(devices, 0);
665 }
666
667 // Part of EnsureMountInfoRefreshed(). Called for each device to refresh info.
668 void RefreshDeviceAtIndex(const std::vector<std::string>& devices,
669 size_t index) {
670 if (index == devices.size()) {
671 // All devices info retrieved. Proceed to enumerate mount point info.
672 cros_disks_client_->EnumerateMountEntries(
673 base::Bind(&DiskMountManagerImpl::RefreshAfterEnumerateMountEntries,
674 weak_ptr_factory_.GetWeakPtr()),
675 base::Bind(&DiskMountManagerImpl::RefreshCompleted,
676 weak_ptr_factory_.GetWeakPtr(), false));
677 return;
678 }
679
680 cros_disks_client_->GetDeviceProperties(
681 devices[index],
682 base::Bind(&DiskMountManagerImpl::RefreshAfterGetDeviceProperties,
683 weak_ptr_factory_.GetWeakPtr(), devices, index + 1),
hirono8067bf02015-08-10 03:12:25684 base::Bind(&DiskMountManagerImpl::RefreshDeviceAtIndex,
685 weak_ptr_factory_.GetWeakPtr(), devices, index + 1));
[email protected]a2e4ee22014-07-11 05:16:35686 }
687
688 // Part of EnsureMountInfoRefreshed().
689 void RefreshAfterGetDeviceProperties(const std::vector<std::string>& devices,
690 size_t next_index,
691 const DiskInfo& disk_info) {
692 OnGetDeviceProperties(disk_info);
693 RefreshDeviceAtIndex(devices, next_index);
694 }
695
696 // Part of EnsureMountInfoRefreshed(). Called after mount entries are listed.
697 void RefreshAfterEnumerateMountEntries(
698 const std::vector<MountEntry>& entries) {
699 for (size_t i = 0; i < entries.size(); ++i)
700 OnMountCompleted(entries[i]);
701 RefreshCompleted(true);
702 }
703
704 // Part of EnsureMountInfoRefreshed(). Called when the refreshing is done.
705 void RefreshCompleted(bool success) {
706 already_refreshed_ = true;
707 for (size_t i = 0; i < refresh_callbacks_.size(); ++i)
708 refresh_callbacks_[i].Run(success);
709 refresh_callbacks_.clear();
[email protected]4ae73292011-11-15 05:20:18710 }
711
Hidehiko Abe06ce6dc2017-12-08 19:32:03712 // CrosDisksClient::Observer override.
713 void OnMountEvent(MountEventType event,
714 const std::string& device_path_arg) override {
[email protected]e24f8762011-12-20 00:10:04715 // Take a copy of the argument so we can modify it below.
716 std::string device_path = device_path_arg;
[email protected]4ae73292011-11-15 05:20:18717 switch (event) {
[email protected]e3c1fc92012-11-15 00:56:46718 case CROS_DISKS_DISK_ADDED: {
[email protected]4ae73292011-11-15 05:20:18719 cros_disks_client_->GetDeviceProperties(
720 device_path,
721 base::Bind(&DiskMountManagerImpl::OnGetDeviceProperties,
722 weak_ptr_factory_.GetWeakPtr()),
Peter Kasting341e1fb2018-02-24 00:03:01723 base::DoNothing());
[email protected]e3c1fc92012-11-15 00:56:46724 break;
[email protected]4ae73292011-11-15 05:20:18725 }
[email protected]e3c1fc92012-11-15 00:56:46726 case CROS_DISKS_DISK_REMOVED: {
[email protected]4ae73292011-11-15 05:20:18727 // Search and remove disks that are no longer present.
728 DiskMountManager::DiskMap::iterator iter = disks_.find(device_path);
729 if (iter != disks_.end()) {
avi8194ad62016-09-20 16:58:36730 Disk* disk = iter->second.get();
Aga Wronskaddc1a752017-12-01 19:44:02731 NotifyDiskStatusUpdate(DISK_REMOVED, *disk);
[email protected]4ae73292011-11-15 05:20:18732 disks_.erase(iter);
733 }
[email protected]e3c1fc92012-11-15 00:56:46734 break;
[email protected]4ae73292011-11-15 05:20:18735 }
[email protected]e3c1fc92012-11-15 00:56:46736 case CROS_DISKS_DEVICE_ADDED: {
[email protected]4ae73292011-11-15 05:20:18737 system_path_prefixes_.insert(device_path);
[email protected]e3c1fc92012-11-15 00:56:46738 NotifyDeviceStatusUpdate(DEVICE_ADDED, device_path);
[email protected]4ae73292011-11-15 05:20:18739 break;
740 }
[email protected]e3c1fc92012-11-15 00:56:46741 case CROS_DISKS_DEVICE_REMOVED: {
[email protected]4ae73292011-11-15 05:20:18742 system_path_prefixes_.erase(device_path);
[email protected]e3c1fc92012-11-15 00:56:46743 NotifyDeviceStatusUpdate(DEVICE_REMOVED, device_path);
[email protected]4ae73292011-11-15 05:20:18744 break;
745 }
[email protected]e3c1fc92012-11-15 00:56:46746 case CROS_DISKS_DEVICE_SCANNED: {
747 NotifyDeviceStatusUpdate(DEVICE_SCANNED, device_path);
[email protected]4ae73292011-11-15 05:20:18748 break;
749 }
[email protected]4ae73292011-11-15 05:20:18750 default: {
751 LOG(ERROR) << "Unknown event: " << event;
[email protected]4ae73292011-11-15 05:20:18752 }
753 }
[email protected]4ae73292011-11-15 05:20:18754 }
755
756 // Notifies all observers about disk status update.
Aga Wronskaddc1a752017-12-01 19:44:02757 void NotifyDiskStatusUpdate(DiskEvent event, const Disk& disk) {
758 for (auto& observer : observers_) {
759 disk.IsAutoMountable() ? observer.OnAutoMountableDiskEvent(event, disk)
760 : observer.OnBootDeviceDiskEvent(event, disk);
761 }
[email protected]4ae73292011-11-15 05:20:18762 }
763
764 // Notifies all observers about device status update.
[email protected]e3c1fc92012-11-15 00:56:46765 void NotifyDeviceStatusUpdate(DeviceEvent event,
[email protected]4ae73292011-11-15 05:20:18766 const std::string& device_path) {
yusukes262cf7e22016-10-14 20:56:53767 for (auto& observer : observers_)
768 observer.OnDeviceEvent(event, device_path);
[email protected]4ae73292011-11-15 05:20:18769 }
770
771 // Notifies all observers about mount completion.
[email protected]e3c1fc92012-11-15 00:56:46772 void NotifyMountStatusUpdate(MountEvent event,
773 MountError error_code,
774 const MountPointInfo& mount_info) {
yusukes262cf7e22016-10-14 20:56:53775 for (auto& observer : observers_)
776 observer.OnMountEvent(event, error_code, mount_info);
[email protected]e3c1fc92012-11-15 00:56:46777 }
778
779 void NotifyFormatStatusUpdate(FormatEvent event,
780 FormatError error_code,
781 const std::string& device_path) {
yusukes262cf7e22016-10-14 20:56:53782 for (auto& observer : observers_)
783 observer.OnFormatEvent(event, error_code, device_path);
[email protected]4ae73292011-11-15 05:20:18784 }
785
Klemen Kozjekbf5610f2017-08-25 20:20:09786 void NotifyRenameStatusUpdate(RenameEvent event,
787 RenameError error_code,
788 const std::string& device_path) {
789 for (auto& observer : observers_)
790 observer.OnRenameEvent(event, error_code, device_path);
791 }
792
[email protected]4ae73292011-11-15 05:20:18793 // Finds system path prefix from |system_path|.
794 const std::string& FindSystemPathPrefix(const std::string& system_path) {
795 if (system_path.empty())
[email protected]8790210c2013-12-02 05:29:53796 return base::EmptyString();
[email protected]4ae73292011-11-15 05:20:18797 for (SystemPathPrefixSet::const_iterator it = system_path_prefixes_.begin();
798 it != system_path_prefixes_.end();
799 ++it) {
800 const std::string& prefix = *it;
brettw95509312015-07-16 23:57:33801 if (base::StartsWith(system_path, prefix, base::CompareCase::SENSITIVE))
[email protected]4ae73292011-11-15 05:20:18802 return prefix;
803 }
[email protected]8790210c2013-12-02 05:29:53804 return base::EmptyString();
[email protected]4ae73292011-11-15 05:20:18805 }
806
[email protected]4ae73292011-11-15 05:20:18807 // Mount event change observers.
Hidehiko Abe06ce6dc2017-12-08 19:32:03808 base::ObserverList<DiskMountManager::Observer> observers_;
[email protected]4ae73292011-11-15 05:20:18809
810 CrosDisksClient* cros_disks_client_;
811
812 // The list of disks found.
813 DiskMountManager::DiskMap disks_;
814
815 DiskMountManager::MountPointMap mount_points_;
816
817 typedef std::set<std::string> SystemPathPrefixSet;
818 SystemPathPrefixSet system_path_prefixes_;
819
[email protected]a2e4ee22014-07-11 05:16:35820 bool already_refreshed_;
821 std::vector<EnsureMountInfoRefreshedCallback> refresh_callbacks_;
822
dcheng0a6e80c2016-04-08 18:37:38823 std::unique_ptr<SuspendUnmountManager> suspend_unmount_manager_;
hirono9f5eae542015-06-22 04:28:41824
yamaguchi6594bf7e12016-08-24 22:16:11825 // Whether the instance attempted to mount a device in read-only mode for
826 // each source path.
827 typedef std::map<std::string, chromeos::MountAccessMode> AccessModeMap;
828 AccessModeMap access_modes_;
829
[email protected]4ae73292011-11-15 05:20:18830 base::WeakPtrFactory<DiskMountManagerImpl> weak_ptr_factory_;
831
832 DISALLOW_COPY_AND_ASSIGN(DiskMountManagerImpl);
833};
834
[email protected]a66a23cb2012-06-19 23:15:33835} // namespace
[email protected]4ae73292011-11-15 05:20:18836
837DiskMountManager::Disk::Disk(const std::string& device_path,
838 const std::string& mount_path,
yamaguchieaaad982016-10-24 09:46:17839 bool write_disabled_by_policy,
[email protected]4ae73292011-11-15 05:20:18840 const std::string& system_path,
841 const std::string& file_path,
842 const std::string& device_label,
843 const std::string& drive_label,
[email protected]202e9fee2012-09-13 20:21:29844 const std::string& vendor_id,
845 const std::string& vendor_name,
846 const std::string& product_id,
847 const std::string& product_name,
[email protected]9c5620d32012-07-31 01:00:38848 const std::string& fs_uuid,
[email protected]4ae73292011-11-15 05:20:18849 const std::string& system_path_prefix,
850 DeviceType device_type,
avi6e1a22d2015-12-21 03:43:20851 uint64_t total_size_in_bytes,
[email protected]4ae73292011-11-15 05:20:18852 bool is_parent,
yamaguchieaaad982016-10-24 09:46:17853 bool is_read_only_hardware,
[email protected]4ae73292011-11-15 05:20:18854 bool has_media,
855 bool on_boot_device,
[email protected]79ed457b2014-07-22 04:07:26856 bool on_removable_device,
Klemen Kozjek46f1c6192017-08-25 19:20:54857 bool is_hidden,
Klemen Kozjekbf5610f2017-08-25 20:20:09858 const std::string& file_system_type,
859 const std::string& base_mount_path)
[email protected]4ae73292011-11-15 05:20:18860 : device_path_(device_path),
861 mount_path_(mount_path),
yamaguchieaaad982016-10-24 09:46:17862 write_disabled_by_policy_(write_disabled_by_policy),
[email protected]4ae73292011-11-15 05:20:18863 system_path_(system_path),
864 file_path_(file_path),
865 device_label_(device_label),
866 drive_label_(drive_label),
[email protected]202e9fee2012-09-13 20:21:29867 vendor_id_(vendor_id),
868 vendor_name_(vendor_name),
869 product_id_(product_id),
870 product_name_(product_name),
[email protected]9c5620d32012-07-31 01:00:38871 fs_uuid_(fs_uuid),
[email protected]4ae73292011-11-15 05:20:18872 system_path_prefix_(system_path_prefix),
873 device_type_(device_type),
874 total_size_in_bytes_(total_size_in_bytes),
875 is_parent_(is_parent),
yamaguchieaaad982016-10-24 09:46:17876 is_read_only_hardware_(is_read_only_hardware),
[email protected]4ae73292011-11-15 05:20:18877 has_media_(has_media),
878 on_boot_device_(on_boot_device),
[email protected]79ed457b2014-07-22 04:07:26879 on_removable_device_(on_removable_device),
Klemen Kozjek46f1c6192017-08-25 19:20:54880 is_hidden_(is_hidden),
Klemen Kozjekbf5610f2017-08-25 20:20:09881 file_system_type_(file_system_type),
882 base_mount_path_(base_mount_path) {}
[email protected]4ae73292011-11-15 05:20:18883
vmpstr2a0c10402016-04-08 21:28:07884DiskMountManager::Disk::Disk(const Disk& other) = default;
885
Chris Watkins2c529d62017-11-29 02:14:41886DiskMountManager::Disk::~Disk() = default;
[email protected]4ae73292011-11-15 05:20:18887
Klemen Kozjekbf5610f2017-08-25 20:20:09888void DiskMountManager::Disk::SetMountPath(const std::string& mount_path) {
889 mount_path_ = mount_path;
890
891 if (base_mount_path_.empty())
892 base_mount_path_ = mount_path;
893}
894
Aga Wronskaddc1a752017-12-01 19:44:02895bool DiskMountManager::Disk::IsAutoMountable() const {
896 // Disks are considered auto-mountable if they are:
897 // 1. Non-virtual
898 // 2. Not on boot device
899 // Only the second condition is checked here, because Disks are created from
900 // non-virtual mount devices only.
901 return !on_boot_device_;
Hidehiko Abe06ce6dc2017-12-08 19:32:03902}
Aga Wronskaddc1a752017-12-01 19:44:02903
Aga Wronska0856cf842017-12-01 20:51:51904bool DiskMountManager::Disk::IsStatefulPartition() const {
905 return mount_path_ == kStatefulPartition;
906}
907
avi8194ad62016-09-20 16:58:36908bool DiskMountManager::AddDiskForTest(std::unique_ptr<Disk> disk) {
[email protected]e3c1fc92012-11-15 00:56:46909 return false;
910}
911
912bool DiskMountManager::AddMountPointForTest(const MountPointInfo& mount_point) {
913 return false;
914}
915
[email protected]4ae73292011-11-15 05:20:18916// static
[email protected]4ae73292011-11-15 05:20:18917std::string DiskMountManager::MountConditionToString(MountCondition condition) {
918 switch (condition) {
919 case MOUNT_CONDITION_NONE:
920 return "";
921 case MOUNT_CONDITION_UNKNOWN_FILESYSTEM:
922 return "unknown_filesystem";
923 case MOUNT_CONDITION_UNSUPPORTED_FILESYSTEM:
924 return "unsupported_filesystem";
925 default:
926 NOTREACHED();
927 }
928 return "";
929}
930
931// static
[email protected]2321d282012-01-31 23:06:59932std::string DiskMountManager::DeviceTypeToString(DeviceType type) {
933 switch (type) {
934 case DEVICE_TYPE_USB:
935 return "usb";
936 case DEVICE_TYPE_SD:
937 return "sd";
938 case DEVICE_TYPE_OPTICAL_DISC:
939 return "optical";
940 case DEVICE_TYPE_MOBILE:
941 return "mobile";
942 default:
943 return "unknown";
944 }
945}
946
947// static
[email protected]4ae73292011-11-15 05:20:18948void DiskMountManager::Initialize() {
[email protected]b307bceb2011-11-17 07:49:55949 if (g_disk_mount_manager) {
950 LOG(WARNING) << "DiskMountManager was already initialized";
951 return;
952 }
[email protected]4ae73292011-11-15 05:20:18953 g_disk_mount_manager = new DiskMountManagerImpl();
[email protected]b307bceb2011-11-17 07:49:55954 VLOG(1) << "DiskMountManager initialized";
955}
956
957// static
958void DiskMountManager::InitializeForTesting(
959 DiskMountManager* disk_mount_manager) {
960 if (g_disk_mount_manager) {
961 LOG(WARNING) << "DiskMountManager was already initialized";
962 return;
963 }
964 g_disk_mount_manager = disk_mount_manager;
965 VLOG(1) << "DiskMountManager initialized";
[email protected]4ae73292011-11-15 05:20:18966}
967
968// static
969void DiskMountManager::Shutdown() {
[email protected]b307bceb2011-11-17 07:49:55970 if (!g_disk_mount_manager) {
971 LOG(WARNING) << "DiskMountManager::Shutdown() called with NULL manager";
972 return;
[email protected]4ae73292011-11-15 05:20:18973 }
[email protected]b307bceb2011-11-17 07:49:55974 delete g_disk_mount_manager;
975 g_disk_mount_manager = NULL;
976 VLOG(1) << "DiskMountManager Shutdown completed";
[email protected]4ae73292011-11-15 05:20:18977}
978
979// static
980DiskMountManager* DiskMountManager::GetInstance() {
981 return g_disk_mount_manager;
982}
983
984} // namespace disks
985} // namespace chromeos