fn safe_main()

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(())
}