diff --git a/Makefile.linux b/Makefile.linux index 64ca88b21c..304554b028 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -35,16 +35,16 @@ install-dirs: copy-debug: copy-debug-spfs copy-debug-spk copy-debug-spfs: debug-spfs install-dirs - sudo cp -f $(CARGO_TARGET_DIR)/debug/spfs* '$(DESTDIR)$(bindir)' + for bin in $(CARGO_TARGET_DIR)/debug/spfs*; do sudo install -p -m 755 $$bin '$(DESTDIR)$(bindir)'; done copy-debug-spk: debug install-dirs - sudo cp -f $(CARGO_TARGET_DIR)/debug/spk '$(DESTDIR)$(bindir)' + sudo install -p -m 755 $(CARGO_TARGET_DIR)/debug/spk '$(DESTDIR)$(bindir)' copy-release: release install-dirs - sudo cp -f $(CARGO_TARGET_DIR)/release/spk $(CARGO_TARGET_DIR)/release/spfs* '$(DESTDIR)$(bindir)' + sudo install -p -m 755 $(CARGO_TARGET_DIR)/release/spk '$(DESTDIR)$(bindir)' copy-spfs: release-spfs install-dirs - sudo cp -f $(CARGO_TARGET_DIR)/release/spfs* '$(DESTDIR)$(bindir)' + for bin in $(CARGO_TARGET_DIR)/release/spfs*; do sudo install -p -m 755 $$bin '$(DESTDIR)$(bindir)'; done setcap: sudo setcap 'cap_dac_override,cap_fowner+ep' '$(DESTDIR)$(bindir)/spfs-clean' diff --git a/crates/spfs-cli/cmd-fuse/src/cmd_fuse.rs b/crates/spfs-cli/cmd-fuse/src/cmd_fuse.rs index ab73d51213..3011c32527 100644 --- a/crates/spfs-cli/cmd-fuse/src/cmd_fuse.rs +++ b/crates/spfs-cli/cmd-fuse/src/cmd_fuse.rs @@ -14,13 +14,13 @@ use tokio::signal::unix::{signal, SignalKind}; // The runtime setup process manages the current namespace // which operates only on the current thread. For this reason // we must use a single threaded async runtime, if any. -fn main() -> Result<()> { +fn main() { // because this function exits right away it does not // properly handle destruction of data, so we put the actual // logic into a separate function/scope - std::process::exit(main2()?) + std::process::exit(main2()) } -fn main2() -> Result { +fn main2() -> i32 { let mut opt = CmdFuse::parse(); opt.logging .log_file @@ -31,13 +31,24 @@ fn main2() -> Result { let config = match spfs::get_config() { Err(err) => { tracing::error!(err = ?err, "failed to load config"); - return Ok(1); + return 1; } Ok(config) => config, }; let result = opt.run(&config); - - spfs_cli_common::handle_result!(result) + let result = spfs_cli_common::handle_result!(result); + // a regular main function that returns an error prints + // that message to stdout. Because there is rarely + // any way to view stderr for this mount process, + // we explicitly log the error to tracing so that + // it will appear in the fuse log and syslog. + match result { + Ok(code) => code, + Err(err) => { + tracing::error!("{err:?}"); + 1 + } + } } /// Run a fuse @@ -97,12 +108,12 @@ impl CmdFuse { let calling_gid = nix::unistd::getegid(); // these will cause conflicts later on if their counterpart is also provided - let required_opts = vec![ - MountOption::RO, - MountOption::NoDev, - MountOption::NoSuid, - MountOption::CUSTOM("nonempty".into()), - ]; + let mut required_opts = vec![MountOption::RO, MountOption::NoDev, MountOption::NoSuid]; + if !fuse3_available() { + // the nonempty option became a default and was removed in + // fuse3 but is still needed for fuse2 + required_opts.push(MountOption::CUSTOM("nonempty".into())); + } let mut opts = Config { root_mode: 0o777, uid: calling_uid, @@ -303,3 +314,8 @@ fn parse_options_from_args(args: &[String]) -> Vec { }) .collect() } + +/// Checks if fusermount3 is available to be used on this system +fn fuse3_available() -> bool { + spfs::which("fusermount3").is_some() +} diff --git a/crates/spfs/src/monitor.rs b/crates/spfs/src/monitor.rs index db635d5efa..5339afefc5 100644 --- a/crates/spfs/src/monitor.rs +++ b/crates/spfs/src/monitor.rs @@ -39,7 +39,7 @@ pub fn spawn_monitor_for_runtime(rt: &runtime::Runtime) -> Result return Err(Error::MissingBinary("spfs")), + None => return Err(Error::MissingBinary("spfs-monitor")), Some(exe) => exe, };