in src/main.rs [198:301]
fn safe_main(program: &str, args: &[String]) -> Fallible<()> {
env_logger::init();
let cpus = num_cpus::get();
let mut opts = Options::new();
opts.optopt("", "allow", concat!("specifies who should have access to the file system",
" (default: self)"), "other|root|self");
opts.optopt("", "cpu_profile", "enables CPU profiling and writes a profile to the given path",
"PATH");
opts.optflag("", "help", "prints usage information and exits");
opts.optopt("", "input",
&format!("where to read reconfiguration data from ({} for stdin)", DEFAULT_INOUT),
"PATH");
opts.optmulti("", "mapping", "type and locations of a mapping", "TYPE:PATH:UNDERLYING_PATH");
opts.optflag("", "node_cache", "enables the path-based node cache (known broken)");
opts.optopt("", "output",
&format!("where to write the reconfiguration status to ({} for stdout)", DEFAULT_INOUT),
"PATH");
opts.optopt("", "reconfig_threads",
&format!("number of reconfiguration threads (default: {})", cpus), "COUNT");
opts.optopt("", "ttl",
&format!("how long the kernel is allowed to keep file metadata (default: {})", DEFAULT_TTL),
&format!("TIME{}", SECONDS_SUFFIX));
opts.optflag("", "version", "prints version information and exits");
opts.optflag("", "xattrs", "enables support for extended attributes");
let matches = opts.parse(args)?;
if matches.opt_present("help") {
usage(&program, &opts);
return Ok(());
}
if matches.opt_present("version") {
version();
return Ok(());
}
let mut options = vec!("-o", "fsname=sandboxfs");
// TODO(jmmv): Support passing in arbitrary FUSE options from the command line, like "-o ro".
if let Some(value) = matches.opt_str("allow") {
for arg in parse_allow(&value)? {
options.push(arg);
}
}
let mappings = parse_mappings(matches.opt_strs("mapping"))?;
let ttl = match matches.opt_str("ttl") {
Some(value) => parse_duration(&value)?,
None => parse_duration(DEFAULT_TTL).expect(
"default value for flag is not accepted by the parser; this is a bug in the value"),
};
let input = {
let input_flag = matches.opt_str("input");
sandboxfs::open_input(file_flag(&input_flag))
.with_context(|_| format!("Failed to open reconfiguration input '{}'",
input_flag.unwrap_or_else(|| DEFAULT_INOUT.to_owned())))?
};
let output = {
let output_flag = matches.opt_str("output");
sandboxfs::open_output(file_flag(&output_flag))
.with_context(|_| format!("Failed to open reconfiguration output '{}'",
output_flag.unwrap_or_else(|| DEFAULT_INOUT.to_owned())))?
};
let reconfig_threads = match matches.opt_str("reconfig_threads") {
Some(value) => {
match value.parse::<usize>() {
Ok(n) => n,
Err(e) => return Err(UsageError {
message: format!("invalid thread count {}: {}", value, e)
}.into()),
}
},
None => cpus,
};
let mount_point = if matches.free.len() == 1 {
Path::new(&matches.free[0])
} else {
return Err(UsageError { message: "invalid number of arguments".to_string() }.into());
};
let node_cache: sandboxfs::ArcCache = if matches.opt_present("node_cache") {
warn!("Using --node_cache is known to be broken under certain scenarios; see the manpage");
Arc::from(sandboxfs::PathCache::default())
} else {
Arc::from(sandboxfs::NoCache::default())
};
let _profiler;
if let Some(path) = matches.opt_str("cpu_profile") {
_profiler = sandboxfs::ScopedProfiler::start(&path).context("Failed to start CPU profile")?;
};
sandboxfs::mount(
mount_point, &options, &mappings, ttl, node_cache, matches.opt_present("xattrs"),
input, output, reconfig_threads)
.with_context(|_| format!("Failed to mount {}", mount_point.display()))?;
Ok(())
}