blob: 0cede65134a72399f9ab7da93268ee511d769d65 [file] [log] [blame]
Ben Chan1e5a0cb2012-03-22 00:41:52 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Ben Chan8dcede82011-07-25 20:56:13 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Chand30e7432011-11-28 13:43:17 -08005// Implements cros-disks::MountManager. See mount-manager.h for details.
6
Ben Chan5ccd9fe2013-11-13 18:28:27 -08007#include "cros-disks/mount_manager.h"
Ben Chan8dcede82011-07-25 20:56:13 -07008
9#include <sys/mount.h>
10#include <unistd.h>
11
12#include <algorithm>
Sergei Datsenko7e7c7642021-01-08 19:15:34 +110013#include <unordered_set>
Ben Chan632c9f82011-10-11 12:22:16 -070014#include <utility>
Ben Chan8dcede82011-07-25 20:56:13 -070015
Qijiang Fan713061e2021-03-08 15:45:12 +090016#include <base/check.h>
Ben Chan97e20d42014-02-05 18:38:07 -080017#include <base/files/file_path.h>
Sergei Datsenko0f014d22018-04-04 16:37:22 +100018#include <base/files/file_util.h>
Ben Chan8dcede82011-07-25 20:56:13 -070019#include <base/logging.h>
Mike Frysinger38ae98d2012-04-11 12:03:44 -040020#include <base/stl_util.h>
Ben Chan97e20d42014-02-05 18:38:07 -080021#include <base/strings/string_util.h>
Ben Chan8dcede82011-07-25 20:56:13 -070022
François Degrosbf7bb592019-07-12 09:49:52 +100023#include "cros-disks/error_logger.h"
Tatsuhisa Yamaguchi5a6a3032016-08-19 20:03:54 +090024#include "cros-disks/mount_options.h"
Anand K Mistrye9a60fb2019-11-07 16:41:03 +110025#include "cros-disks/mounter.h"
Ben Chan32e4b4b2014-07-23 16:18:37 -070026#include "cros-disks/platform.h"
François Degros8b4e31e2019-07-29 11:39:19 +100027#include "cros-disks/quote.h"
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100028#include "cros-disks/uri.h"
Ben Chan8dcede82011-07-25 20:56:13 -070029
Anand K Mistry40cff452019-07-30 10:24:48 +100030namespace cros_disks {
Ben Chan460439f2011-09-13 09:16:28 -070031namespace {
Ben Chan8dcede82011-07-25 20:56:13 -070032
Ben Chan9ed09e32011-11-22 16:24:06 -080033// Permissions to set on the mount root directory (u+rwx,og+rx).
Ben Chan460439f2011-09-13 09:16:28 -070034const mode_t kMountRootDirectoryPermissions =
Ben Chan8dcede82011-07-25 20:56:13 -070035 S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
Ben Chan09c90d02012-04-25 22:09:09 -070036// Prefix of the mount label option.
Sergei Datsenko7e7c7642021-01-08 19:15:34 +110037const char kMountOptionMountLabelPrefix[] = "mountlabel";
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +090038// Literal for mount option: "remount".
39const char kMountOptionRemount[] = "remount";
Ben Chan9ed09e32011-11-22 16:24:06 -080040// Maximum number of trials on creating a mount directory using
41// Platform::CreateOrReuseEmptyDirectoryWithFallback().
Ben Chand30e7432011-11-28 13:43:17 -080042// A value of 100 seems reasonable and enough to handle directory name
43// collisions under common scenarios.
44const unsigned kMaxNumMountTrials = 100;
Ben Chan460439f2011-09-13 09:16:28 -070045
46} // namespace
47
Ben Chan213c6d92019-04-10 16:21:52 -070048MountManager::MountManager(const std::string& mount_root,
Ben Chande0e3f62017-09-26 06:28:39 -070049 Platform* platform,
Sergei Datsenkoa910bba2019-06-18 13:31:59 +100050 Metrics* metrics,
51 brillo::ProcessReaper* process_reaper)
Anand K Mistry09f2db12019-11-07 17:06:56 +110052 : mount_root_(base::FilePath(mount_root)),
Sergei Datsenkoa910bba2019-06-18 13:31:59 +100053 platform_(platform),
54 metrics_(metrics),
55 process_reaper_(process_reaper) {
Ben Chan8dcede82011-07-25 20:56:13 -070056 CHECK(!mount_root_.empty()) << "Invalid mount root directory";
Anand K Mistry09f2db12019-11-07 17:06:56 +110057 CHECK(mount_root_.IsAbsolute()) << "Mount root not absolute path";
Ben Chan8dcede82011-07-25 20:56:13 -070058 CHECK(platform_) << "Invalid platform object";
Ben Chanbe2b4a72011-11-08 13:42:23 -080059 CHECK(metrics_) << "Invalid metrics object";
Ben Chan8dcede82011-07-25 20:56:13 -070060}
61
62MountManager::~MountManager() {
Ben Chana4c75062011-11-11 09:47:55 -080063 // UnmountAll() should be called from a derived class instead of this base
Anand K Mistry2481ce82020-01-24 14:46:53 +110064 // class as UnmountAll() calls MountPoint::Unmount() which may call back into
65 // a derived class.
Ben Chan8dcede82011-07-25 20:56:13 -070066}
67
68bool MountManager::Initialize() {
Anand K Mistry09f2db12019-11-07 17:06:56 +110069 return platform_->CreateDirectory(mount_root_.value()) &&
70 platform_->SetOwnership(mount_root_.value(), getuid(), getgid()) &&
71 platform_->SetPermissions(mount_root_.value(),
72 kMountRootDirectoryPermissions);
Ben Chan8dcede82011-07-25 20:56:13 -070073}
74
Ben Chanb3bf8d12013-04-23 13:57:55 -070075bool MountManager::StartSession() {
Ben Chan8dcede82011-07-25 20:56:13 -070076 return true;
77}
78
Ben Chanb3bf8d12013-04-23 13:57:55 -070079bool MountManager::StopSession() {
Sam McNally8a71c5c2019-03-15 15:51:37 +110080 return UnmountAll();
Ben Chan8dcede82011-07-25 20:56:13 -070081}
82
Ben Chan213c6d92019-04-10 16:21:52 -070083MountErrorType MountManager::Mount(const std::string& source_path,
84 const std::string& filesystem_type,
Sergei Datsenko7e7c7642021-01-08 19:15:34 +110085 std::vector<std::string> options,
Ben Chan213c6d92019-04-10 16:21:52 -070086 std::string* mount_path) {
Sergei Datsenko0f014d22018-04-04 16:37:22 +100087 // Source is not necessary a path, but if it is let's resolve it to
88 // some real underlying object.
Ben Chan213c6d92019-04-10 16:21:52 -070089 std::string real_path;
Jorge Lucangeli Obes0a388a22020-04-06 11:43:21 -040090 if (Uri::IsUri(source_path) || !ResolvePath(source_path, &real_path)) {
Sergei Datsenko0f014d22018-04-04 16:37:22 +100091 real_path = source_path;
92 }
93
94 if (real_path.empty()) {
95 LOG(ERROR) << "Failed to mount an invalid path";
Ben Chanfcb2fc02011-11-21 09:44:07 -080096 return MOUNT_ERROR_INVALID_ARGUMENT;
Ben Chan8dcede82011-07-25 20:56:13 -070097 }
98 if (!mount_path) {
99 LOG(ERROR) << "Invalid mount path argument";
Ben Chanfcb2fc02011-11-21 09:44:07 -0800100 return MOUNT_ERROR_INVALID_ARGUMENT;
Ben Chan8dcede82011-07-25 20:56:13 -0700101 }
102
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100103 if (RemoveParamsEqualTo(&options, kMountOptionRemount) == 0) {
104 return MountNewSource(real_path, filesystem_type, std::move(options),
105 mount_path);
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900106 } else {
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100107 return Remount(real_path, filesystem_type, std::move(options), mount_path);
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900108 }
109}
110
Ben Chan213c6d92019-04-10 16:21:52 -0700111MountErrorType MountManager::Remount(const std::string& source_path,
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100112 const std::string& /*filesystem_type*/,
113 std::vector<std::string> options,
Ben Chan213c6d92019-04-10 16:21:52 -0700114 std::string* mount_path) {
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100115 MountPoint* mount_point = FindMountBySource(source_path);
116 if (!mount_point) {
François Degros8b4e31e2019-07-29 11:39:19 +1000117 LOG(WARNING) << "Path " << quote(source_path) << " is not mounted yet";
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900118 return MOUNT_ERROR_PATH_NOT_MOUNTED;
119 }
120
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100121 bool read_only = IsReadOnlyMount(options);
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900122
123 // Perform the underlying mount operation.
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100124 MountErrorType error_type = mount_point->Remount(read_only);
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900125 if (error_type != MOUNT_ERROR_NONE) {
Sergei Datsenko0ba12032021-01-07 08:51:14 +1100126 LOG(ERROR) << "Cannot remount path " << quote(source_path) << ": "
127 << error_type;
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900128 return error_type;
129 }
130
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100131 *mount_path = mount_point->path().value();
François Degros8b4e31e2019-07-29 11:39:19 +1000132 LOG(INFO) << "Path " << quote(source_path) << " on " << quote(*mount_path)
Sergei Datsenko3928f782020-12-31 09:14:04 +1100133 << " is remounted";
Tatsuhisa Yamaguchib670bd12016-09-28 23:06:44 +0900134 return error_type;
135}
136
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100137MountErrorType MountManager::MountNewSource(const std::string& source_path,
138 const std::string& filesystem_type,
139 std::vector<std::string> options,
140 std::string* mount_path) {
141 MountPoint* mp = FindMountBySource(source_path);
142 if (mp) {
143 // TODO(dats): Some obscure legacy. Why is this even needed?
144 if (mount_path->empty() || mp->path().value() == *mount_path) {
François Degrosc309d932021-02-04 15:12:30 +1100145 LOG(WARNING) << "Source " << redact(source_path)
146 << " is already mounted to " << redact(mp->path());
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100147 *mount_path = mp->path().value();
148 return GetMountErrorOfReservedMountPath(mp->path());
Ben Chan8dcede82011-07-25 20:56:13 -0700149 }
François Degrosc309d932021-02-04 15:12:30 +1100150 LOG(ERROR) << "Source " << redact(source_path) << " is already mounted to "
151 << redact(mp->path());
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100152 return MOUNT_ERROR_PATH_ALREADY_MOUNTED;
Ben Chan8dcede82011-07-25 20:56:13 -0700153 }
154
Ben Chan213c6d92019-04-10 16:21:52 -0700155 std::string mount_label;
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100156 if (GetParamValue(options, kMountOptionMountLabelPrefix, &mount_label)) {
157 RemoveParamsWithSameName(&options, kMountOptionMountLabelPrefix);
158 }
Ben Chan09c90d02012-04-25 22:09:09 -0700159
Ben Chand30e7432011-11-28 13:43:17 -0800160 // Create a directory and set up its ownership/permissions for mounting
161 // the source path. If an error occurs, ShouldReserveMountPathOnError()
162 // is not called to reserve the mount path as a reserved mount path still
163 // requires a proper mount directory.
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100164 base::FilePath actual_mount_path(*mount_path);
165 MountErrorType error =
166 CreateMountPathForSource(source_path, mount_label, &actual_mount_path);
167 if (error != MOUNT_ERROR_NONE) {
168 return error;
Ben Chan8dcede82011-07-25 20:56:13 -0700169 }
170
Ben Chand30e7432011-11-28 13:43:17 -0800171 // Perform the underlying mount operation. If an error occurs,
172 // ShouldReserveMountPathOnError() is called to check if the mount path
173 // should be reserved.
Anand K Mistryf41a6962019-12-19 17:41:04 +1100174 MountErrorType error_type = MOUNT_ERROR_UNKNOWN;
Nigel Taoca7a4ef2021-05-14 11:44:25 +1000175 std::unique_ptr<MountPoint> mount_point =
176 DoMount(source_path, filesystem_type, std::move(options),
177 base::FilePath(actual_mount_path), &error_type);
Ben Chanfcb2fc02011-11-21 09:44:07 -0800178 if (error_type == MOUNT_ERROR_NONE) {
François Degros8b4e31e2019-07-29 11:39:19 +1000179 LOG(INFO) << "Path " << quote(source_path) << " is mounted to "
180 << quote(actual_mount_path);
Anand K Mistryf41a6962019-12-19 17:41:04 +1100181 DCHECK(mount_point);
Ben Chanf8692882011-08-21 10:15:30 -0700182 } else if (ShouldReserveMountPathOnError(error_type)) {
François Degros8b4e31e2019-07-29 11:39:19 +1000183 LOG(INFO) << "Reserving mount path " << quote(actual_mount_path) << " for "
184 << quote(source_path);
Anand K Mistryf41a6962019-12-19 17:41:04 +1100185 DCHECK(!mount_point);
Ben Chan632c9f82011-10-11 12:22:16 -0700186 ReserveMountPath(actual_mount_path, error_type);
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100187 // Create dummy mount point to associate with the mount path.
Anand K Mistryf1bd0862019-12-20 11:54:55 +1100188 mount_point = MountPoint::CreateLeaking(base::FilePath(actual_mount_path));
Ben Chan8dcede82011-07-25 20:56:13 -0700189 } else {
François Degrosca450862021-01-14 14:40:02 +1100190 LOG(ERROR) << "Cannot mount " << redact(source_path) << " of type "
191 << quote(filesystem_type) << ": " << error_type;
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100192 platform_->RemoveEmptyDirectory(actual_mount_path.value());
Ben Chanf8692882011-08-21 10:15:30 -0700193 return error_type;
Ben Chan8dcede82011-07-25 20:56:13 -0700194 }
Ben Chanf8692882011-08-21 10:15:30 -0700195
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100196 mount_states_.insert({source_path, std::move(mount_point)});
197 *mount_path = actual_mount_path.value();
Ben Chan8dcede82011-07-25 20:56:13 -0700198 return error_type;
199}
200
Anand K Mistry5a6d5fa2019-11-05 17:21:48 +1100201MountErrorType MountManager::Unmount(const std::string& path) {
Ben Chan9ed09e32011-11-22 16:24:06 -0800202 // Determine whether the path is a source path or a mount path.
François Degrosa9d39052020-02-20 12:20:00 +1100203 // Is path a source path?
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100204 MountPoint* mount_point = FindMountBySource(path);
205 if (!mount_point) {
François Degrosa9d39052020-02-20 12:20:00 +1100206 // Not a source path. Is path a mount path?
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100207 mount_point = FindMountByMountPath(base::FilePath(path));
208 if (!mount_point) {
François Degrosa9d39052020-02-20 12:20:00 +1100209 // Not a mount path either.
Ben Chanfcb2fc02011-11-21 09:44:07 -0800210 return MOUNT_ERROR_PATH_NOT_MOUNTED;
Ben Chan8dcede82011-07-25 20:56:13 -0700211 }
Ben Chan8dcede82011-07-25 20:56:13 -0700212 }
213
Ben Chanfcb2fc02011-11-21 09:44:07 -0800214 MountErrorType error_type = MOUNT_ERROR_NONE;
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100215 if (IsMountPathReserved(mount_point->path())) {
216 LOG(INFO) << "Removing mount path '" << mount_point->path()
Ben Chanf8692882011-08-21 10:15:30 -0700217 << "' from the reserved list";
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100218 UnreserveMountPath(mount_point->path());
Ben Chan8dcede82011-07-25 20:56:13 -0700219 } else {
Anand K Mistrye9a60fb2019-11-07 16:41:03 +1100220 error_type = mount_point->Unmount();
Sergei Datsenko2879b5c2019-09-26 13:47:40 +1000221
François Degrosa9d39052020-02-20 12:20:00 +1100222 switch (error_type) {
223 case MOUNT_ERROR_NONE:
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100224 LOG(INFO) << "Unmounted " << quote(mount_point->path());
François Degrosa9d39052020-02-20 12:20:00 +1100225 break;
François Degros9a391e12019-07-19 15:23:23 +1000226
François Degrosa9d39052020-02-20 12:20:00 +1100227 case MOUNT_ERROR_PATH_NOT_MOUNTED:
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100228 LOG(WARNING) << "Not mounted " << quote(mount_point->path());
François Degrosa9d39052020-02-20 12:20:00 +1100229 break;
230
231 default:
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100232 LOG(ERROR) << "Cannot unmount " << quote(mount_point->path()) << ": "
François Degrosa9d39052020-02-20 12:20:00 +1100233 << error_type;
234 return error_type;
Sergei Datsenko2879b5c2019-09-26 13:47:40 +1000235 }
Ben Chan8dcede82011-07-25 20:56:13 -0700236 }
Ben Chanf8692882011-08-21 10:15:30 -0700237
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100238 platform_->RemoveEmptyDirectory(mount_point->path().value());
239 for (auto it = mount_states_.begin(); it != mount_states_.end(); ++it) {
240 if (it->second.get() == mount_point) {
241 mount_states_.erase(it);
242 break;
243 }
244 }
Ben Chan8dcede82011-07-25 20:56:13 -0700245 return error_type;
246}
247
248bool MountManager::UnmountAll() {
249 bool all_umounted = true;
Anand K Mistrye9a60fb2019-11-07 16:41:03 +1100250
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100251 // Enumerate all the mount paths and then unmount, as calling Unmount()
Anand K Mistrye9a60fb2019-11-07 16:41:03 +1100252 // modifies the cache.
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100253
254 std::vector<std::string> paths;
255 paths.reserve(mount_states_.size());
François Degrosa9d39052020-02-20 12:20:00 +1100256 for (const auto& entry : mount_states_) {
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100257 paths.push_back(entry.second->path().value());
Anand K Mistrye9a60fb2019-11-07 16:41:03 +1100258 }
259
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100260 for (const auto& source_path : paths) {
Anand K Mistrye9a60fb2019-11-07 16:41:03 +1100261 if (Unmount(source_path) != MOUNT_ERROR_NONE) {
Ben Chan8dcede82011-07-25 20:56:13 -0700262 all_umounted = false;
263 }
264 }
François Degrosa9d39052020-02-20 12:20:00 +1100265
Ben Chan8dcede82011-07-25 20:56:13 -0700266 return all_umounted;
267}
268
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100269bool MountManager::ResolvePath(const std::string& path,
270 std::string* real_path) {
271 return platform_->GetRealPath(path, real_path);
272}
273
274MountPoint* MountManager::FindMountBySource(const std::string& source) {
Sergei Datsenko0ba12032021-01-07 08:51:14 +1100275 const auto it = mount_states_.find(source);
276 if (it == mount_states_.end())
277 return nullptr;
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100278 return it->second.get();
Sergei Datsenko0ba12032021-01-07 08:51:14 +1100279}
280
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100281MountPoint* MountManager::FindMountByMountPath(const base::FilePath& path) {
282 for (auto& entry : mount_states_) {
283 if (entry.second->path() == path)
284 return entry.second.get();
Anand K Mistrye9a60fb2019-11-07 16:41:03 +1100285 }
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100286 return nullptr;
Ben Chan8dcede82011-07-25 20:56:13 -0700287}
288
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100289bool MountManager::RemoveMount(MountPoint* mount_point) {
François Degrosa9d39052020-02-20 12:20:00 +1100290 for (auto it = mount_states_.begin(); it != mount_states_.end(); ++it) {
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100291 if (it->second.get() == mount_point) {
François Degrosa9d39052020-02-20 12:20:00 +1100292 mount_states_.erase(it);
Ben Chan8dcede82011-07-25 20:56:13 -0700293 return true;
294 }
295 }
296 return false;
297}
298
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100299MountErrorType MountManager::CreateMountPathForSource(
300 const std::string& source,
301 const std::string& label,
302 base::FilePath* mount_path) {
303 base::FilePath actual_mount_path = *mount_path;
304 if (actual_mount_path.empty()) {
305 actual_mount_path = base::FilePath(SuggestMountPath(source));
306 if (!label.empty()) {
307 // Replace the basename(|actual_mount_path|) with |label|.
308 actual_mount_path = actual_mount_path.DirName().Append(label);
309 }
310 }
311
312 if (!IsValidMountPath(base::FilePath(actual_mount_path))) {
313 LOG(ERROR) << "Mount path " << quote(actual_mount_path) << " is invalid";
314 return MOUNT_ERROR_INVALID_PATH;
315 }
316
317 bool mount_path_created;
318 if (!mount_path->empty()) {
319 mount_path_created =
320 !IsMountPathReserved(actual_mount_path) &&
321 platform_->CreateOrReuseEmptyDirectory(actual_mount_path.value());
322 } else {
323 std::unordered_set<std::string> reserved_paths;
324 for (const auto& entry : reserved_mount_paths_) {
325 reserved_paths.insert(entry.first.value());
326 }
327 std::string path = actual_mount_path.value();
328 mount_path_created = platform_->CreateOrReuseEmptyDirectoryWithFallback(
329 &path, kMaxNumMountTrials, reserved_paths);
330 if (mount_path_created)
331 actual_mount_path = base::FilePath(path);
332 }
333 if (!mount_path_created) {
334 LOG(ERROR) << "Cannot create directory " << quote(actual_mount_path)
335 << " to mount " << quote(source);
336 return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
337 }
338
339 *mount_path = actual_mount_path;
340 return MOUNT_ERROR_NONE;
341}
342
343bool MountManager::IsMountPathReserved(const base::FilePath& mount_path) const {
Qijiang Fan52439042020-06-17 15:34:38 +0900344 return base::Contains(reserved_mount_paths_, mount_path);
Ben Chanf8692882011-08-21 10:15:30 -0700345}
346
Ben Chan632c9f82011-10-11 12:22:16 -0700347MountErrorType MountManager::GetMountErrorOfReservedMountPath(
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100348 const base::FilePath& mount_path) const {
François Degrosa9d39052020-02-20 12:20:00 +1100349 const auto it = reserved_mount_paths_.find(mount_path);
350 return it != reserved_mount_paths_.end() ? it->second : MOUNT_ERROR_NONE;
Ben Chan632c9f82011-10-11 12:22:16 -0700351}
352
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100353void MountManager::ReserveMountPath(base::FilePath mount_path,
Ben Chan632c9f82011-10-11 12:22:16 -0700354 MountErrorType error_type) {
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100355 reserved_mount_paths_.insert({std::move(mount_path), error_type});
Ben Chanf8692882011-08-21 10:15:30 -0700356}
357
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100358void MountManager::UnreserveMountPath(const base::FilePath& mount_path) {
Ben Chanf8692882011-08-21 10:15:30 -0700359 reserved_mount_paths_.erase(mount_path);
360}
361
Ben Chan213c6d92019-04-10 16:21:52 -0700362std::vector<MountEntry> MountManager::GetMountEntries() const {
363 std::vector<MountEntry> mount_entries;
François Degrosa9d39052020-02-20 12:20:00 +1100364 mount_entries.reserve(mount_states_.size());
Tatsuhisa Yamaguchi5a6a3032016-08-19 20:03:54 +0900365 for (const auto& entry : mount_states_) {
Ben Chan213c6d92019-04-10 16:21:52 -0700366 const std::string& source_path = entry.first;
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100367 const MountPoint& mount_point = *entry.second;
368
369 mount_entries.push_back(
370 {GetMountErrorOfReservedMountPath(mount_point.path()), source_path,
371 GetMountSourceType(), mount_point.path().value(),
372 mount_point.is_read_only()});
Ben Chan8fb742b2014-04-28 23:46:57 -0700373 }
Ben Chan7dfb8102017-10-17 15:47:37 -0700374 return mount_entries;
Ben Chan8fb742b2014-04-28 23:46:57 -0700375}
376
Ben Chanf8692882011-08-21 10:15:30 -0700377bool MountManager::ShouldReserveMountPathOnError(
378 MountErrorType error_type) const {
379 return false;
380}
381
Sergei Datsenko7e7c7642021-01-08 19:15:34 +1100382bool MountManager::IsPathImmediateChildOfParent(const base::FilePath& path,
383 const base::FilePath& parent) {
Ben Chan213c6d92019-04-10 16:21:52 -0700384 std::vector<std::string> path_components, parent_components;
Anand K Mistry09f2db12019-11-07 17:06:56 +1100385 path.StripTrailingSeparators().GetComponents(&path_components);
386 parent.StripTrailingSeparators().GetComponents(&parent_components);
Ben Chan8dcede82011-07-25 20:56:13 -0700387 if (path_components.size() != parent_components.size() + 1)
388 return false;
389
Ben Chan213c6d92019-04-10 16:21:52 -0700390 if (path_components.back() == base::FilePath::kCurrentDirectory ||
391 path_components.back() == base::FilePath::kParentDirectory) {
Ben Chan8698d232018-06-04 21:44:30 -0700392 return false;
393 }
394
Ben Chan8dcede82011-07-25 20:56:13 -0700395 return std::equal(parent_components.begin(), parent_components.end(),
396 path_components.begin());
397}
398
Anand K Mistry09f2db12019-11-07 17:06:56 +1100399bool MountManager::IsValidMountPath(const base::FilePath& mount_path) const {
Ben Chanadc5d002014-03-12 15:02:26 -0700400 return IsPathImmediateChildOfParent(mount_path, mount_root_);
401}
402
Ben Chan8dcede82011-07-25 20:56:13 -0700403} // namespace cros_disks