-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add skeleton reimplementation of sandboxfs in Rust (#23)
This change adds a barebones reimplementation of sandboxfs in Rust. As things are now, the new version does nothing: it just provides trivial command-line processing and mounts an empty FUSE file system. However, this change puts all pieces in place to continue development of this new version. In particular, this adjusts the Travis CI configuration to support running the exact same integration tests as we run for the Go implementation against the new code, and currently blacklists all of them because the new code passes none.
- Loading branch information
Showing
9 changed files
with
340 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,5 @@ | |
/.gopath | ||
/.gopath-tools | ||
/bazel-* | ||
Cargo.lock | ||
target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[package] | ||
authors = ["Julio Merino <[email protected]>"] | ||
categories = ["filesystems"] | ||
description = "A virtual file system for sandboxing" | ||
homepage = "https://github.com/bazelbuild/sandboxfs" | ||
keywords = ["bazel", "filesystem", "fuse", "sandboxing"] | ||
license = "Apache-2.0" | ||
name = "sandboxfs" | ||
readme = "README.md" | ||
repository = "https://github.com/bazelbuild/sandboxfs" | ||
version = "0.1.0" | ||
|
||
[badges] | ||
travis-ci = { repository = "bazelbuild/sandboxfs", branch = "master" } | ||
|
||
[dependencies] | ||
env_logger = "0.5" | ||
failure = "0.1" | ||
fuse = "0.3" | ||
getopts = "0.2" | ||
log = "0.4" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright 2018 Google Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy | ||
// of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations | ||
// under the License. | ||
|
||
extern crate fuse; | ||
#[macro_use] extern crate log; | ||
|
||
use std::ffi::OsStr; | ||
use std::io; | ||
use std::path::Path; | ||
|
||
/// FUSE file system implementation of sandboxfs. | ||
struct SandboxFS { | ||
} | ||
|
||
impl SandboxFS { | ||
/// Creates a new `SandboxFS` instance. | ||
fn new() -> SandboxFS { | ||
SandboxFS {} | ||
} | ||
} | ||
|
||
impl fuse::Filesystem for SandboxFS { | ||
} | ||
|
||
/// Mounts a new sandboxfs instance on the given `mount_point`. | ||
pub fn mount(mount_point: &Path) -> io::Result<()> { | ||
let options = ["-o", "ro", "-o", "fsname=sandboxfs"] | ||
.iter() | ||
.map(|o| o.as_ref()) | ||
.collect::<Vec<&OsStr>>(); | ||
let fs = SandboxFS::new(); | ||
info!("Mounting file system onto {:?}", mount_point); | ||
fuse::mount(fs, &mount_point, &options) | ||
.map_err(|e| io::Error::new(e.kind(), format!("mount on {:?} failed: {}", mount_point, e))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright 2018 Google Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
// use this file except in compliance with the License. You may obtain a copy | ||
// of the License at: | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations | ||
// under the License. | ||
|
||
extern crate env_logger; | ||
#[macro_use] extern crate failure; | ||
extern crate getopts; | ||
extern crate sandboxfs; | ||
|
||
use failure::Error; | ||
use getopts::Options; | ||
use std::env; | ||
use std::path::Path; | ||
use std::process; | ||
use std::result::Result; | ||
|
||
/// Execution failure due to a user-triggered error. | ||
#[derive(Debug, Fail)] | ||
#[fail(display = "{}", message)] | ||
struct UsageError { | ||
message: String, | ||
} | ||
|
||
/// Obtains the program name from the execution's first argument, or returns a default if the | ||
/// program name cannot be determined for whatever reason. | ||
fn program_name(args: &[String], default: &'static str) -> String { | ||
let default = String::from(default); | ||
match args.get(0) { | ||
Some(arg0) => match Path::new(arg0).file_name() { | ||
Some(basename) => match basename.to_str() { | ||
Some(basename) => String::from(basename), | ||
None => default, | ||
}, | ||
None => default, | ||
}, | ||
None => default, | ||
} | ||
} | ||
|
||
/// Prints program usage information to stdout. | ||
fn usage(program: &str, opts: &Options) { | ||
let brief = format!("Usage: {} [options] MOUNT_POINT", program); | ||
print!("{}", opts.usage(&brief)); | ||
} | ||
|
||
/// Program's entry point. This is a "safe" version of `main` in the sense that this doesn't | ||
/// directly handle errors: all errors are returned to the caller for consistent reporter to the | ||
/// user depending on their type. | ||
fn safe_main(program: &str, args: &[String]) -> Result<(), Error> { | ||
env_logger::init(); | ||
|
||
let mut opts = Options::new(); | ||
opts.optflag("", "help", "prints usage information and exits"); | ||
let matches = opts.parse(args)?; | ||
|
||
if matches.opt_present("help") { | ||
usage(&program, &opts); | ||
return Ok(()); | ||
} | ||
|
||
let mount_point = if matches.free.len() == 1 { | ||
&matches.free[0] | ||
} else { | ||
return Err(Error::from(UsageError { message: "invalid number of arguments".to_string() })); | ||
}; | ||
|
||
sandboxfs::mount(Path::new(mount_point))?; | ||
Ok(()) | ||
} | ||
|
||
/// Program's entry point. This delegates to `safe_main` for all program logic and is just in | ||
/// charge of consistently formatting and reporting all possible errors to the caller. | ||
fn main() { | ||
let args: Vec<String> = env::args().collect(); | ||
let program = program_name(&args, "sandboxfs"); | ||
|
||
if let Err(err) = safe_main(&program, &args[1..]) { | ||
if let Some(err) = err.downcast_ref::<UsageError>() { | ||
eprintln!("Usage error: {}", err); | ||
eprintln!("Type {} --help for more information", program); | ||
process::exit(2); | ||
} else if let Some(err) = err.downcast_ref::<getopts::Fail>() { | ||
eprintln!("Usage error: {}", err); | ||
eprintln!("Type {} --help for more information", program); | ||
process::exit(2); | ||
} else { | ||
eprintln!("{}: {}", program, err); | ||
process::exit(1); | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_program_name_uses_default_on_errors() { | ||
assert_eq!("default", program_name(&[], "default")); | ||
} | ||
|
||
#[test] | ||
fn test_program_name_uses_file_name_only() { | ||
assert_eq!("b", program_name(&["a/b".to_string()], "unused")); | ||
assert_eq!("foo", program_name(&["./x/y/foo".to_string()], "unused")); | ||
} | ||
} |