blob: 36dcfcc3c441c3da28e09aed8ab8f1dcd0cb5d8e [file] [log] [blame]
Sergei Datsenko0f014d22018-04-04 16:37:22 +10001// Copyright 2018 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cros-disks/fuse_mount_manager.h"
6
Anand K Mistryad958eb2019-10-02 13:03:31 +10007#include <sys/mount.h>
8
Sergei Datsenko0f014d22018-04-04 16:37:22 +10009#include <utility>
10
Qijiang Fan713061e2021-03-08 15:45:12 +090011#include <base/check.h>
Sergei Datsenko0f014d22018-04-04 16:37:22 +100012#include <base/files/file_path.h>
13#include <base/logging.h>
Simon Glass2b1da092020-05-21 12:24:16 -060014#include <brillo/process/process_reaper.h>
Sergei Datsenko0f014d22018-04-04 16:37:22 +100015
Sam McNallyc56ae312018-05-22 13:14:27 +100016#include "cros-disks/drivefs_helper.h"
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100017#include "cros-disks/fuse_mounter.h"
Sergei Datsenko0f014d22018-04-04 16:37:22 +100018#include "cros-disks/platform.h"
François Degros8b4e31e2019-07-29 11:39:19 +100019#include "cros-disks/quote.h"
Anand K Mistry110478e2019-10-29 15:24:11 +110020#include "cros-disks/smbfs_helper.h"
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100021#include "cros-disks/sshfs_helper.h"
22#include "cros-disks/uri.h"
Sergei Datsenko0f014d22018-04-04 16:37:22 +100023
Sergei Datsenko0f014d22018-04-04 16:37:22 +100024namespace cros_disks {
25
Ben Chan213c6d92019-04-10 16:21:52 -070026FUSEMountManager::FUSEMountManager(const std::string& mount_root,
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100027 const std::string& working_dirs_root,
Sergei Datsenko0f014d22018-04-04 16:37:22 +100028 Platform* platform,
Sergei Datsenkoa910bba2019-06-18 13:31:59 +100029 Metrics* metrics,
30 brillo::ProcessReaper* process_reaper)
31 : MountManager(mount_root, platform, metrics, process_reaper),
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100032 working_dirs_root_(working_dirs_root) {}
Sergei Datsenko0f014d22018-04-04 16:37:22 +100033
Sam McNally8a71c5c2019-03-15 15:51:37 +110034FUSEMountManager::~FUSEMountManager() {
35 UnmountAll();
36}
Sergei Datsenko0f014d22018-04-04 16:37:22 +100037
38bool FUSEMountManager::Initialize() {
39 if (!MountManager::Initialize())
40 return false;
41
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100042 if (!platform()->DirectoryExists(working_dirs_root_) &&
43 !platform()->CreateDirectory(working_dirs_root_)) {
44 LOG(ERROR) << "Can't create writable FUSE directory";
45 return false;
46 }
47 if (!platform()->SetOwnership(working_dirs_root_, getuid(), getgid()) ||
48 !platform()->SetPermissions(working_dirs_root_, 0755)) {
49 LOG(ERROR) << "Can't set up writable FUSE directory";
50 return false;
51 }
52
Sergei Datsenko0f014d22018-04-04 16:37:22 +100053 // Register specific FUSE mount helpers here.
Sergei Datsenkoa910bba2019-06-18 13:31:59 +100054 RegisterHelper(std::make_unique<DrivefsHelper>(platform(), process_reaper()));
Sergei Datsenko71ba50a2020-11-27 14:33:39 +110055 RegisterHelper(std::make_unique<SshfsHelper>(
56 platform(), process_reaper(), base::FilePath(working_dirs_root_)));
Anand K Mistry110478e2019-10-29 15:24:11 +110057 RegisterHelper(std::make_unique<SmbfsHelper>(platform(), process_reaper()));
Sergei Datsenko0f014d22018-04-04 16:37:22 +100058
59 return true;
60}
61
Anand K Mistryd0a05232020-01-24 14:04:18 +110062std::unique_ptr<MountPoint> FUSEMountManager::DoMount(
Ben Chan213c6d92019-04-10 16:21:52 -070063 const std::string& source,
64 const std::string& fuse_type,
65 const std::vector<std::string>& options,
Anand K Mistry25a5f852020-01-14 17:08:39 +110066 const base::FilePath& mount_path,
Anand K Mistry25a5f852020-01-14 17:08:39 +110067 MountErrorType* error) {
Sergei Datsenko0f014d22018-04-04 16:37:22 +100068 CHECK(!mount_path.empty()) << "Invalid mount path argument";
69
Sergei Datsenkobcd8e462018-04-20 15:44:56 +100070 Uri uri = Uri::Parse(source);
François Degros15a44a82019-11-19 14:01:08 +110071 CHECK(uri.valid()) << "Source " << quote(source) << " is not a URI";
72
Sergei Datsenko25898b12020-11-26 08:07:15 +110073 base::FilePath dir_name;
74 const Mounter* selected_helper = nullptr;
Sergei Datsenko0f014d22018-04-04 16:37:22 +100075 for (const auto& helper : helpers_) {
Sergei Datsenko25898b12020-11-26 08:07:15 +110076 if (helper->CanMount(source, options, &dir_name)) {
Sergei Datsenko0f014d22018-04-04 16:37:22 +100077 selected_helper = helper.get();
78 break;
79 }
80 }
81
82 if (!selected_helper) {
François Degrosca450862021-01-14 14:40:02 +110083 LOG(ERROR) << "Cannot find FUSE module for " << redact(source)
84 << " of type " << quote(fuse_type);
Anand K Mistry25a5f852020-01-14 17:08:39 +110085 *error = MOUNT_ERROR_UNKNOWN_FILESYSTEM;
86 return nullptr;
Sergei Datsenko0f014d22018-04-04 16:37:22 +100087 }
88
Sergei Datsenkof3ebcc32020-12-07 23:47:56 +110089 auto mountpoint = selected_helper->Mount(source, mount_path, options, error);
Sergei Datsenko25898b12020-11-26 08:07:15 +110090 LOG_IF(ERROR, *error != MOUNT_ERROR_NONE)
François Degrosca450862021-01-14 14:40:02 +110091 << "Cannot mount " << redact(source) << " of type " << quote(fuse_type)
92 << ": " << *error;
93
Sergei Datsenko25898b12020-11-26 08:07:15 +110094 return mountpoint;
Sergei Datsenko0f014d22018-04-04 16:37:22 +100095}
96
Ben Chan213c6d92019-04-10 16:21:52 -070097bool FUSEMountManager::CanMount(const std::string& source) const {
Sergei Datsenko25898b12020-11-26 08:07:15 +110098 base::FilePath dir;
Sergei Datsenko0f014d22018-04-04 16:37:22 +100099 for (const auto& helper : helpers_) {
Sergei Datsenko25898b12020-11-26 08:07:15 +1100100 if (helper->CanMount(source, {}, &dir))
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000101 return true;
102 }
103 return false;
104}
105
Ben Chan213c6d92019-04-10 16:21:52 -0700106std::string FUSEMountManager::SuggestMountPath(
107 const std::string& source) const {
François Degros15a44a82019-11-19 14:01:08 +1100108 Uri uri = Uri::Parse(source);
109 if (!uri.valid()) {
Sergei Datsenkobcd8e462018-04-20 15:44:56 +1000110 return "";
111 }
François Degros15a44a82019-11-19 14:01:08 +1100112
Sergei Datsenko25898b12020-11-26 08:07:15 +1100113 base::FilePath dir;
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000114 for (const auto& helper : helpers_) {
Sergei Datsenko25898b12020-11-26 08:07:15 +1100115 if (helper->CanMount(source, {}, &dir))
116 return mount_root().Append(dir).value();
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000117 }
Ben Chan213c6d92019-04-10 16:21:52 -0700118 base::FilePath base_name = base::FilePath(source).BaseName();
Anand K Mistry30e32fa2020-02-04 10:07:57 +1100119 return mount_root().Append(base_name).value();
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000120}
121
Sergei Datsenko25898b12020-11-26 08:07:15 +1100122void FUSEMountManager::RegisterHelper(std::unique_ptr<Mounter> helper) {
Sergei Datsenko0f014d22018-04-04 16:37:22 +1000123 helpers_.push_back(std::move(helper));
124}
125
126} // namespace cros_disks