Ben Chan | 1e5a0cb | 2012-03-22 00:41:52 -0700 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Ben Chan | bdc3974 | 2011-05-11 17:51:26 -0700 | [diff] [blame] | 5 | #ifndef CROS_DISKS_DISK_MANAGER_H_ |
| 6 | #define CROS_DISKS_DISK_MANAGER_H_ |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 7 | |
| 8 | #include <libudev.h> |
Ben Chan | bdc3974 | 2011-05-11 17:51:26 -0700 | [diff] [blame] | 9 | |
Ben Chan | cc3145d | 2011-04-28 14:50:05 -0700 | [diff] [blame] | 10 | #include <map> |
Eric Caruso | 99d04cb | 2017-03-06 17:43:32 -0800 | [diff] [blame] | 11 | #include <memory> |
Ben Chan | 4288836 | 2011-06-09 18:16:24 -0700 | [diff] [blame] | 12 | #include <set> |
Ben Chan | f51ff00 | 2011-04-25 12:41:57 -0700 | [diff] [blame] | 13 | #include <string> |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 14 | #include <vector> |
| 15 | |
Ben Chan | 86a9cee | 2014-07-14 12:17:12 -0700 | [diff] [blame] | 16 | #include <base/callback.h> |
Ben Chan | 3b832b9 | 2014-09-02 19:39:57 -0700 | [diff] [blame] | 17 | #include <base/macros.h> |
Ben Chan | e31d2aa | 2011-06-15 13:52:59 -0700 | [diff] [blame] | 18 | #include <gtest/gtest_prod.h> |
| 19 | |
Ben Chan | ff92fa3 | 2017-10-17 16:17:15 -0700 | [diff] [blame] | 20 | #include "cros-disks/disk.h" |
Ben Chan | 5ccd9fe | 2013-11-13 18:28:27 -0800 | [diff] [blame] | 21 | #include "cros-disks/mount_manager.h" |
Ben Chan | 6e72692 | 2011-06-28 15:54:32 -0700 | [diff] [blame] | 22 | |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 23 | namespace cros_disks { |
| 24 | |
Ben Chan | 1e5a0cb | 2012-03-22 00:41:52 -0700 | [diff] [blame] | 25 | class DeviceEjector; |
Sergei Datsenko | 1682189 | 2019-04-05 11:26:38 +1100 | [diff] [blame] | 26 | class DiskMonitor; |
Sergei Datsenko | 3cf72cb | 2019-04-01 11:27:50 +1100 | [diff] [blame] | 27 | class MounterCompat; |
Ben Chan | 29be915 | 2011-07-25 14:39:48 -0700 | [diff] [blame] | 28 | class Platform; |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 29 | |
Ben Chan | 55c2022 | 2017-11-10 13:35:58 -0800 | [diff] [blame] | 30 | struct Filesystem; |
| 31 | |
Sergei Datsenko | 1682189 | 2019-04-05 11:26:38 +1100 | [diff] [blame] | 32 | // The DiskManager is responsible for mounting removable media. |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 33 | // |
| 34 | // This class is designed to run within a single-threaded GMainLoop application |
| 35 | // and should not be considered thread safe. |
Sergei Datsenko | 1682189 | 2019-04-05 11:26:38 +1100 | [diff] [blame] | 36 | class DiskManager : public MountManager { |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 37 | public: |
Ben Chan | de0e3f6 | 2017-09-26 06:28:39 -0700 | [diff] [blame] | 38 | DiskManager(const std::string& mount_root, |
| 39 | Platform* platform, |
| 40 | Metrics* metrics, |
Sergei Datsenko | a910bba | 2019-06-18 13:31:59 +1000 | [diff] [blame] | 41 | brillo::ProcessReaper* process_reaper, |
Sergei Datsenko | 1682189 | 2019-04-05 11:26:38 +1100 | [diff] [blame] | 42 | DiskMonitor* disk_monitor, |
Ben Chan | de0e3f6 | 2017-09-26 06:28:39 -0700 | [diff] [blame] | 43 | DeviceEjector* device_ejector); |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 44 | ~DiskManager() override; |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 45 | |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 46 | // Initializes the disk manager and registers default filesystems. |
| 47 | // Returns true on success. |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 48 | bool Initialize() override; |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 49 | |
| 50 | // Returns true if mounting |source_path| is supported. |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 51 | bool CanMount(const std::string& source_path) const override; |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 52 | |
| 53 | // Returns the type of mount sources supported by the manager. |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 54 | MountSourceType GetMountSourceType() const override { |
Ben Chan | 6d0b272 | 2011-11-18 08:24:14 -0800 | [diff] [blame] | 55 | return MOUNT_SOURCE_REMOVABLE_DEVICE; |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 56 | } |
| 57 | |
Ben Chan | 1e5a0cb | 2012-03-22 00:41:52 -0700 | [diff] [blame] | 58 | // Unmounts all mounted paths. |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 59 | bool UnmountAll() override; |
Ben Chan | 1e5a0cb | 2012-03-22 00:41:52 -0700 | [diff] [blame] | 60 | |
Ben Chan | e31d2aa | 2011-06-15 13:52:59 -0700 | [diff] [blame] | 61 | // Registers a set of default filesystems to the disk manager. |
| 62 | void RegisterDefaultFilesystems(); |
| 63 | |
| 64 | // Registers a filesystem to the disk manager. |
| 65 | // Subsequent registrations of the same filesystem type are ignored. |
| 66 | void RegisterFilesystem(const Filesystem& filesystem); |
| 67 | |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 68 | protected: |
| 69 | // Mounts |source_path| to |mount_path| as |filesystem_type| with |options|. |
Anand K Mistry | d0a0523 | 2020-01-24 14:04:18 +1100 | [diff] [blame^] | 70 | std::unique_ptr<MountPoint> DoMount(const std::string& source_path, |
| 71 | const std::string& filesystem_type, |
| 72 | const std::vector<std::string>& options, |
| 73 | const base::FilePath& mount_path, |
| 74 | MountOptions* applied_options, |
| 75 | MountErrorType* error) override; |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 76 | |
Anand K Mistry | 5a6d5fa | 2019-11-05 17:21:48 +1100 | [diff] [blame] | 77 | // Unmounts |path|. |
| 78 | MountErrorType DoUnmount(const std::string& path) override; |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 79 | |
| 80 | // Returns a suggested mount path for a source path. |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 81 | std::string SuggestMountPath(const std::string& source_path) const override; |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 82 | |
Ben Chan | f869288 | 2011-08-21 10:15:30 -0700 | [diff] [blame] | 83 | // Returns true to reserve a mount path on errors due to unknown or |
| 84 | // unsupported filesystems. |
Ben Chan | 1c6c194 | 2014-08-12 09:48:29 -0700 | [diff] [blame] | 85 | bool ShouldReserveMountPathOnError(MountErrorType error_type) const override; |
Ben Chan | f869288 | 2011-08-21 10:15:30 -0700 | [diff] [blame] | 86 | |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 87 | private: |
Anand K Mistry | c7eba32 | 2020-01-15 17:45:38 +1100 | [diff] [blame] | 88 | // MountPoint implementation that ejects the device on unmount. |
| 89 | class EjectingMountPoint; |
| 90 | |
Ben Chan | e31d2aa | 2011-06-15 13:52:59 -0700 | [diff] [blame] | 91 | // Creates an appropriate mounter object for a given filesystem. |
Sergei Datsenko | 3cf72cb | 2019-04-01 11:27:50 +1100 | [diff] [blame] | 92 | std::unique_ptr<MounterCompat> CreateMounter( |
Ben Chan | de0e3f6 | 2017-09-26 06:28:39 -0700 | [diff] [blame] | 93 | const Disk& disk, |
| 94 | const Filesystem& filesystem, |
| 95 | const std::string& target_path, |
| 96 | const std::vector<std::string>& options) const; |
Ben Chan | e31d2aa | 2011-06-15 13:52:59 -0700 | [diff] [blame] | 97 | |
Ben Chan | 29be915 | 2011-07-25 14:39:48 -0700 | [diff] [blame] | 98 | // Returns a Filesystem object if a given filesystem type is supported. |
Eric Caruso | e25c4a5 | 2017-03-06 15:49:04 -0800 | [diff] [blame] | 99 | // Otherwise, it returns NULL. This pointer is owned by the DiskManager. |
Ben Chan | 29be915 | 2011-07-25 14:39:48 -0700 | [diff] [blame] | 100 | const Filesystem* GetFilesystem(const std::string& filesystem_type) const; |
| 101 | |
Anand K Mistry | c7eba32 | 2020-01-15 17:45:38 +1100 | [diff] [blame] | 102 | // Ejects media for the device |device_file|. Return true if the eject process |
| 103 | // has started or |eject_device_on_unmount_| is false, or false if the eject |
| 104 | // process failed. |
| 105 | bool EjectDevice(const std::string& device_file); |
Ben Chan | b5d7122 | 2012-10-03 12:55:16 -0700 | [diff] [blame] | 106 | |
Anand K Mistry | c7eba32 | 2020-01-15 17:45:38 +1100 | [diff] [blame] | 107 | // If |disk| is an optical disk, wrap |mount_point| in a wrapper that ejects |
| 108 | // the disk on a successful unmount. If |disk| is not an optical disk, returns |
| 109 | // |mount_point|. This is exposed as a function to allow ejecting behaviour to |
| 110 | // be tested. |
| 111 | std::unique_ptr<MountPoint> MaybeWrapMountPointForEject( |
| 112 | std::unique_ptr<MountPoint> mount_point, const Disk& disk); |
Ben Chan | 1e5a0cb | 2012-03-22 00:41:52 -0700 | [diff] [blame] | 113 | |
Sergei Datsenko | 1682189 | 2019-04-05 11:26:38 +1100 | [diff] [blame] | 114 | DiskMonitor* const disk_monitor_; |
| 115 | DeviceEjector* const device_ejector_; |
Ben Chan | cc3145d | 2011-04-28 14:50:05 -0700 | [diff] [blame] | 116 | |
Ben Chan | 1e5a0cb | 2012-03-22 00:41:52 -0700 | [diff] [blame] | 117 | // Set to true if devices should be ejected upon unmount. |
| 118 | bool eject_device_on_unmount_; |
| 119 | |
Sergei Datsenko | 1682189 | 2019-04-05 11:26:38 +1100 | [diff] [blame] | 120 | // A mapping from a mount path to the corresponding device that should |
Ben Chan | b5d7122 | 2012-10-03 12:55:16 -0700 | [diff] [blame] | 121 | // be ejected on unmount. |
Sergei Datsenko | 1682189 | 2019-04-05 11:26:38 +1100 | [diff] [blame] | 122 | std::map<std::string, Disk> devices_to_eject_on_unmount_; |
Ben Chan | 4288836 | 2011-06-09 18:16:24 -0700 | [diff] [blame] | 123 | |
Ben Chan | e31d2aa | 2011-06-15 13:52:59 -0700 | [diff] [blame] | 124 | // A set of supported filesystems indexed by filesystem type. |
| 125 | std::map<std::string, Filesystem> filesystems_; |
| 126 | |
Ben Chan | af455a0 | 2013-01-08 15:29:22 -0800 | [diff] [blame] | 127 | FRIEND_TEST(DiskManagerTest, CreateExFATMounter); |
Ben Chan | b1ac5a8 | 2011-08-02 17:53:55 -0700 | [diff] [blame] | 128 | FRIEND_TEST(DiskManagerTest, CreateNTFSMounter); |
Anand K Mistry | 6b19a97 | 2018-09-11 11:14:59 +1000 | [diff] [blame] | 129 | FRIEND_TEST(DiskManagerTest, CreateVFATSystemMounter); |
| 130 | FRIEND_TEST(DiskManagerTest, CreateExt4SystemMounter); |
Ben Chan | 29be915 | 2011-07-25 14:39:48 -0700 | [diff] [blame] | 131 | FRIEND_TEST(DiskManagerTest, GetFilesystem); |
Ben Chan | e31d2aa | 2011-06-15 13:52:59 -0700 | [diff] [blame] | 132 | FRIEND_TEST(DiskManagerTest, RegisterFilesystem); |
Ben Chan | 8dcede8 | 2011-07-25 20:56:13 -0700 | [diff] [blame] | 133 | FRIEND_TEST(DiskManagerTest, DoMountDiskWithNonexistentSourcePath); |
Anand K Mistry | 43575af | 2019-11-05 13:41:41 +1100 | [diff] [blame] | 134 | FRIEND_TEST(DiskManagerTest, DoUnmountDiskWithBusyRetry); |
Anand K Mistry | c7eba32 | 2020-01-15 17:45:38 +1100 | [diff] [blame] | 135 | FRIEND_TEST(DiskManagerTest, EjectDevice); |
| 136 | FRIEND_TEST(DiskManagerTest, EjectDeviceWhenUnmountFailed); |
| 137 | FRIEND_TEST(DiskManagerTest, EjectDeviceWhenExplicitlyDisabled); |
| 138 | FRIEND_TEST(DiskManagerTest, EjectDeviceWhenReleased); |
Ben Chan | e31d2aa | 2011-06-15 13:52:59 -0700 | [diff] [blame] | 139 | |
| 140 | DISALLOW_COPY_AND_ASSIGN(DiskManager); |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 141 | }; |
| 142 | |
Ben Chan | bdc3974 | 2011-05-11 17:51:26 -0700 | [diff] [blame] | 143 | } // namespace cros_disks |
Ryan Cairns | ea6505f | 2011-04-10 19:54:53 -0700 | [diff] [blame] | 144 | |
Ben Chan | bdc3974 | 2011-05-11 17:51:26 -0700 | [diff] [blame] | 145 | #endif // CROS_DISKS_DISK_MANAGER_H_ |