diff --git a/config/full.toml b/config/full.toml index b710d5ab..1ff6f7d8 100644 --- a/config/full.toml +++ b/config/full.toml @@ -213,3 +213,6 @@ exclusive = true # don't allow other users to access the mount point file-access = "read" # Default: "forbidden" for hot/cold repos, else "read" mount-point = "~/mnt" snapshot-path = "latest:/dir" # Default: not set - if not set, generate a virtual tree with all snapshots using path-template +options = [ + "kernel_cache", # Default: ["kernel_cache] +] diff --git a/src/commands/mount.rs b/src/commands/mount.rs index 33511592..54e4761c 100644 --- a/src/commands/mount.rs +++ b/src/commands/mount.rs @@ -6,7 +6,10 @@ mod fusefs; use fusefs::FuseFS; -use std::{ffi::OsStr, path::PathBuf}; +use std::{ + ffi::{OsStr, OsString}, + path::PathBuf, +}; use crate::{repository::CliIndexedRepo, status_err, Application, RusticConfig, RUSTIC_APP}; @@ -49,6 +52,19 @@ pub struct MountCmd { #[clap(value_name = "SNAPSHOT[:PATH]")] #[merge(strategy=conflate::option::overwrite_none)] snapshot_path: Option, + + /// Other options to use for mount + #[clap(skip)] + options: MountOpts, +} + +#[derive(Clone, Command, Debug, Serialize, Deserialize, Merge)] +pub(crate) struct MountOpts(#[merge(strategy = conflate::vec::ignore)] pub(crate) Vec); + +impl Default for MountOpts { + fn default() -> Self { + Self(vec![OsStr::new("kernel_cache")]) + } } impl Override for MountCmd { @@ -91,6 +107,7 @@ impl MountCmd { .path_template .clone() .unwrap_or_else(|| "[{hostname}]/[{label}]/{time}".to_string()); + let time_template = config .mount .time_template @@ -112,21 +129,13 @@ impl MountCmd { )? }; - let name_opt = format!("fsname=rusticfs:{}", repo.config().id); - let mut options = vec![ - OsStr::new("-o"), - OsStr::new(&name_opt), - OsStr::new("-o"), - OsStr::new("kernel_cache"), - ]; + let mut options = self.options.0; + + options.extend_from_slice(&[OsStr::new(&format!("fsname=rusticfs:{}", repo.config().id))]); if !config.mount.exclusive { - options.extend_from_slice(&[ - OsStr::new("-o"), - OsStr::new("allow_other"), - OsStr::new("-o"), - OsStr::new("default_permissions"), - ]); + options + .extend_from_slice(&[OsStr::new("allow_other"), OsStr::new("default_permissions")]); } let file_access = config.mount.file_access.as_ref().map_or_else( @@ -141,6 +150,16 @@ impl MountCmd { )?; let fs = FuseMT::new(FuseFS::new(repo, vfs, file_access), 1); + + // Sort and deduplicate options + options.sort_unstable(); + options.dedup(); + + // join options into a single comma-delimited string and prepent "-o " + // this should be parsed just fine by fuser, here + // https://github.com/cberner/fuser/blob/9f6ced73a36f1d99846e28be9c5e4903939ee9d5/src/mnt/mount_options.rs#L157 + let options = OsStr::new(&format!("-o {}", options.join(","))); + mount(fs, mount_point, &options)?; Ok(())