Skip to content

Commit 55a449d

Browse files
committed
Refactor Session to allow callers to mount it themselves
This is a minor refactor of `Session`, to make the API slightly more flexible. Splitting `Mount` into a separate object allows callers to - Create a mount without a Session object - Create a session given an existing /dev/fuse FD One use case for this is when mounting inside containers, when you need to handle the session and mounting in separate processes. Fixes #300
1 parent 12f05bb commit 55a449d

File tree

7 files changed

+256
-244
lines changed

7 files changed

+256
-244
lines changed

examples/notify_inval_entry.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,8 @@ fn main() {
162162
timeout: Duration::from_secs_f32(opts.timeout),
163163
};
164164

165-
let session = fuser::Session::new(fs, opts.mount_point, &options).unwrap();
165+
let session = fuser::spawn_mount2(fs, opts.mount_point, &options).expect("failed to mount");
166166
let notifier = session.notifier();
167-
let _bg = session.spawn().unwrap();
168167

169168
loop {
170169
let mut fname = fname.lock().unwrap();

examples/notify_inval_inode.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,8 @@ fn main() {
200200
lookup_cnt,
201201
};
202202

203-
let session = fuser::Session::new(fs, opts.mount_point, &options).unwrap();
203+
let session = fuser::spawn_mount2(fs, opts.mount_point, &options).expect("failed to mount");
204204
let notifier = session.notifier();
205-
let _bg = session.spawn().unwrap();
206205

207206
loop {
208207
let mut s = fdata.lock().unwrap();

examples/poll.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,6 @@ fn main() {
337337
let fs = FSelFS { data: data.clone() };
338338

339339
let mntpt = std::env::args().nth(1).unwrap();
340-
let session = fuser::Session::new(fs, mntpt, &options).unwrap();
341-
let bg = session.spawn().unwrap();
342-
343-
producer(&data, &bg.notifier());
340+
let session = fuser::spawn_mount2(fs, mntpt, &options).expect("failed to mount");
341+
producer(&data, &session.notifier());
344342
}

src/lib.rs

+61-6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use mount_options::{check_option_conflicts, parse_options_from_args};
1313
use serde::{Deserialize, Serialize};
1414
use std::ffi::OsStr;
1515
use std::io;
16+
use std::os::fd::AsFd;
1617
use std::path::Path;
1718
#[cfg(feature = "abi-7-23")]
1819
use std::time::Duration;
@@ -39,7 +40,7 @@ pub use reply::{
3940
ReplyStatfs, ReplyWrite,
4041
};
4142
pub use request::Request;
42-
pub use session::{BackgroundSession, Session, SessionUnmounter};
43+
pub use session::{BackgroundSession, Mount, Session, SessionACL, Unmounter};
4344
#[cfg(feature = "abi-7-28")]
4445
use std::cmp::max;
4546
#[cfg(feature = "abi-7-13")]
@@ -1008,7 +1009,8 @@ pub fn mount<FS: Filesystem, P: AsRef<Path>>(
10081009
}
10091010

10101011
/// Mount the given filesystem to the given mountpoint. This function will
1011-
/// not return until the filesystem is unmounted.
1012+
/// not return until the filesystem is unmounted. This function requires
1013+
/// CAP_SYS_ADMIN to run.
10121014
///
10131015
/// NOTE: This will eventually replace mount(), once the API is stable
10141016
pub fn mount2<FS: Filesystem, P: AsRef<Path>>(
@@ -1017,7 +1019,10 @@ pub fn mount2<FS: Filesystem, P: AsRef<Path>>(
10171019
options: &[MountOption],
10181020
) -> io::Result<()> {
10191021
check_option_conflicts(options, false)?;
1020-
Session::new(filesystem, mountpoint.as_ref(), options).and_then(|mut se| se.run())
1022+
let mut session = Session::new(filesystem, SessionACL::from_mount_options(options))?;
1023+
let _mount = Mount::new(session.as_fd(), mountpoint, options)?;
1024+
1025+
session.run()
10211026
}
10221027

10231028
/// Mount the given filesystem using fusermount(1). The binary must exist on
@@ -1028,7 +1033,30 @@ pub fn fusermount(
10281033
options: &[MountOption],
10291034
) -> io::Result<()> {
10301035
check_option_conflicts(options, true)?;
1031-
Session::new_fusermount(filesystem, mountpoint, options).and_then(|mut se| se.run())
1036+
1037+
// AutoUnmount requires either AllowRoot or AllowOther; we can inject
1038+
// that option but still block requests at the library level.
1039+
let (device_fd, _mount) = if options.contains(&MountOption::AutoUnmount)
1040+
&& !(options.contains(&MountOption::AllowRoot)
1041+
|| options.contains(&MountOption::AllowOther))
1042+
{
1043+
warn!("Given auto_unmount without allow_root or allow_other; adding allow_other, with userspace permission handling");
1044+
1045+
let mut modified_options = options.to_vec();
1046+
modified_options.push(MountOption::AllowOther);
1047+
1048+
Mount::new_fusermount(mountpoint.as_ref(), &modified_options)?
1049+
} else {
1050+
Mount::new_fusermount(mountpoint.as_ref(), options)?
1051+
};
1052+
1053+
let mut session = Session::from_fd(
1054+
device_fd,
1055+
filesystem,
1056+
SessionACL::from_mount_options(options),
1057+
);
1058+
1059+
session.run()
10321060
}
10331061

10341062
/// Mount the given filesystem to the given mountpoint. This function spawns
@@ -1066,7 +1094,11 @@ pub fn spawn_mount2<'a, FS: Filesystem + Send + 'static + 'a, P: AsRef<Path>>(
10661094
options: &[MountOption],
10671095
) -> io::Result<BackgroundSession> {
10681096
check_option_conflicts(options, false)?;
1069-
Session::new(filesystem, mountpoint.as_ref(), options).and_then(|se| se.spawn())
1097+
1098+
let session = Session::new(filesystem, SessionACL::from_mount_options(options))?;
1099+
let mount = Mount::new(session.as_fd(), &mountpoint, options)?;
1100+
1101+
BackgroundSession::new(session, mount, mountpoint)
10701102
}
10711103

10721104
/// Mount the given filesystem to the given mountpoint. This function spawns
@@ -1084,5 +1116,28 @@ pub fn spawn_fusermount<'a, FS: Filesystem + Send + 'static + 'a>(
10841116
options: &[MountOption],
10851117
) -> io::Result<BackgroundSession> {
10861118
check_option_conflicts(options, true)?;
1087-
Session::new_fusermount(filesystem, mountpoint, options).and_then(|se| se.spawn())
1119+
1120+
// AutoUnmount requires either AllowRoot or AllowOther; we can inject
1121+
// that option but still block requests at the library level.
1122+
let (device_fd, mount) = if options.contains(&MountOption::AutoUnmount)
1123+
&& !(options.contains(&MountOption::AllowRoot)
1124+
|| options.contains(&MountOption::AllowOther))
1125+
{
1126+
warn!("Given auto_unmount without allow_root or allow_other; adding allow_other, with userspace permission handling");
1127+
1128+
let mut modified_options = options.to_vec();
1129+
modified_options.push(MountOption::AllowOther);
1130+
1131+
Mount::new_fusermount(mountpoint.as_ref(), &modified_options)?
1132+
} else {
1133+
Mount::new_fusermount(mountpoint.as_ref(), options)?
1134+
};
1135+
1136+
let session = Session::from_fd(
1137+
device_fd,
1138+
filesystem,
1139+
SessionACL::from_mount_options(options),
1140+
);
1141+
1142+
BackgroundSession::new(session, mount, mountpoint)
10881143
}

0 commit comments

Comments
 (0)