diff --git a/Cargo.lock b/Cargo.lock index f8ab7e1..72b826b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -112,6 +121,7 @@ dependencies = [ name = "clone-shim" version = "0.1.0" dependencies = [ + "bincode", "clap 3.1.15", "close_fds", "criterion", diff --git a/Cargo.toml b/Cargo.toml index d10cffd..cc1b6a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ exitcode = "1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +bincode = "1.3" ipnetwork = "0.18" libc = "0.2.117" diff --git a/src/error.rs b/src/error.rs index 700ecd5..abdcab4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -15,6 +15,9 @@ pub enum Error { #[error("json: {0}")] Json(#[from] serde_json::Error), + #[error("bincode: {0}")] + Bincode(#[from] bincode::Error), + #[error("bad pipe specification: a pipe must have exactly one reader and one writer: {0}")] BadPipe(String), diff --git a/src/lib.rs b/src/lib.rs index 0733e5e..8a7e6d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,25 @@ use nix::fcntl::OFlag; use nix::sys::socket; use nix::unistd; +pub struct PackArgs<'a> { + pub spec: &'a Path, + pub binary: &'a Path, + pub output: &'a Path, +} + +pub fn pack(args: &PackArgs) -> Result<()> { + let spec: Specification = if args.spec.ends_with(".json") { + let f = std::fs::File::open(args.spec)?; + Ok(serde_json::from_reader(f)?) + } else { + Err(Error::BadSpecType) + }?; + + let spec_bin = bincode::serialize(&spec)?; + + Ok(()) +} + pub struct RunArgs<'a> { pub spec: Option<&'a Path>, pub debug: bool, diff --git a/src/main.rs b/src/main.rs index f6c0b92..8c2a277 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use log::{error, info}; -use clone_shim::{run, RunArgs}; +use clone_shim::{pack, run, PackArgs, RunArgs}; use std::path::Path; @@ -12,12 +12,39 @@ fn main() { .version(env!("GIT_HASH")) .author("Jake Hillion ") .about("Launch a void process application.") + .subcommand_negates_reqs(true) .trailing_var_arg(true) + .subcommand( + Command::new("pack") + .arg( + Arg::new("spec") + .long("specification") + .short('s') + .help("Provide the specification to pack as an external JSON file.") + .takes_value(true) + .required(true), + ) + .arg( + Arg::new("binary") + .long("binary") + .short('b') + .help("Provide the binary to pack.") + .takes_value(true) + .required(true), + ) + .arg( + Arg::new("output") + .long("out") + .short('o') + .help("Location of the output file") + .takes_value(true), + ), + ) .arg( Arg::new("spec") .long("specification") .short('s') - .help("Provide the specification as an external JSON file.") + .help("Provide the specification to launch as an external JSON file.") .takes_value(true), ) .arg( @@ -55,8 +82,30 @@ fn main() { env_logger::init_from_env(env); // launch process - // execute shimmed process - std::process::exit({ + + let code = if let Some(matches) = matches.subcommand_matches("pack") { + // execute binary packing procedure + let args = PackArgs { + spec: Path::new(matches.value_of("spec").expect("spec required")), + binary: Path::new(matches.value_of("binary").expect("binary required")), + output: matches + .value_of("output") + .map(Path::new) + .unwrap_or_else(|| Path::new("a.out")), + }; + + match pack(&args) { + Ok(_) => { + info!("binary packed successfully"); + exitcode::OK + } + Err(e) => { + error!("error packing binary: {}", e); + 1 + } + } + } else { + // execute shimmed process let (binary, binary_args) = { let mut argv = matches.values_of("binary").unwrap(); @@ -83,5 +132,7 @@ fn main() { -1 } } - }) + }; + + std::process::exit(code); }