cargo fmt

This commit is contained in:
Julius Michaelis
2021-08-04 08:52:06 +09:00
parent ed18febfce
commit de8a663df8
5 changed files with 102 additions and 51 deletions

View File

@@ -1,13 +1,13 @@
//! The logic for the Wasmer CLI tool. //! The logic for the Wasmer CLI tool.
#[cfg(target_os = "linux")]
use crate::commands::Binfmt;
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
use crate::commands::Compile; use crate::commands::Compile;
#[cfg(all(feature = "staticlib", feature = "compiler"))] #[cfg(all(feature = "staticlib", feature = "compiler"))]
use crate::commands::CreateExe; use crate::commands::CreateExe;
#[cfg(feature = "wast")] #[cfg(feature = "wast")]
use crate::commands::Wast; use crate::commands::Wast;
#[cfg(target_os = "linux")]
use crate::commands::Binfmt;
use crate::commands::{Cache, Config, Inspect, Run, SelfUpdate, Validate}; use crate::commands::{Cache, Config, Inspect, Run, SelfUpdate, Validate};
use crate::error::PrettyError; use crate::error::PrettyError;
use anyhow::Result; use anyhow::Result;
@@ -112,8 +112,7 @@ pub fn wasmer_main() {
let args = std::env::args().collect::<Vec<_>>(); let args = std::env::args().collect::<Vec<_>>();
let binpath = args.get(0).map(|s| s.as_ref()).unwrap_or(""); let binpath = args.get(0).map(|s| s.as_ref()).unwrap_or("");
let command = args.get(1); let command = args.get(1);
let options = if cfg!(target_os = "linux") && binpath.ends_with("wasmer-binfmt-interpreter") let options = if cfg!(target_os = "linux") && binpath.ends_with("wasmer-binfmt-interpreter") {
{
WasmerCLIOptions::Run(Run::from_binfmt_args()) WasmerCLIOptions::Run(Run::from_binfmt_args())
} else { } else {
match command.unwrap_or(&"".to_string()).as_ref() { match command.unwrap_or(&"".to_string()).as_ref() {

View File

@@ -1,4 +1,6 @@
//! The commands available in the Wasmer binary. //! The commands available in the Wasmer binary.
#[cfg(target_os = "linux")]
mod binfmt;
mod cache; mod cache;
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
mod compile; mod compile;
@@ -11,15 +13,13 @@ mod self_update;
mod validate; mod validate;
#[cfg(feature = "wast")] #[cfg(feature = "wast")]
mod wast; mod wast;
#[cfg(target_os = "linux")]
mod binfmt;
#[cfg(target_os = "linux")]
pub use binfmt::*;
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
pub use compile::*; pub use compile::*;
#[cfg(all(feature = "staticlib", feature = "compiler"))] #[cfg(all(feature = "staticlib", feature = "compiler"))]
pub use create_exe::*; pub use create_exe::*;
#[cfg(feature = "wast")] #[cfg(feature = "wast")]
pub use wast::*; pub use wast::*;
#[cfg(target_os = "linux")]
pub use binfmt::*;
pub use {cache::*, config::*, inspect::*, run::*, self_update::*, validate::*}; pub use {cache::*, config::*, inspect::*, run::*, self_update::*, validate::*};

View File

@@ -1,14 +1,14 @@
use structopt::StructOpt;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use std::env; use std::env;
use std::path::{PathBuf, Path};
use std::fs; use std::fs;
use std::io::Write; use std::io::Write;
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
use structopt::StructOpt;
use Action::*; use Action::*;
#[derive(StructOpt,Clone,Copy)] #[derive(StructOpt, Clone, Copy)]
enum Action { enum Action {
/// Register wasmer as binfmt interpreter /// Register wasmer as binfmt interpreter
Register, Register,
@@ -43,7 +43,11 @@ fn seccheck(path: &Path) -> Result<()> {
} }
let m = std::fs::metadata(path) let m = std::fs::metadata(path)
.with_context(|| format!("Can't check permissions of {}", path.to_string_lossy()))?; .with_context(|| format!("Can't check permissions of {}", path.to_string_lossy()))?;
anyhow::ensure!(m.mode() & 0o2 == 0 || m.mode() & 0o1000 != 0, "{} is world writeable and not sticky", path.to_string_lossy()); anyhow::ensure!(
m.mode() & 0o2 == 0 || m.mode() & 0o1000 != 0,
"{} is world writeable and not sticky",
path.to_string_lossy()
);
Ok(()) Ok(())
} }
@@ -58,41 +62,68 @@ impl Binfmt {
Register | Reregister => { Register | Reregister => {
temp_dir = tempfile::tempdir().context("Make temporary directory")?; temp_dir = tempfile::tempdir().context("Make temporary directory")?;
seccheck(temp_dir.path())?; seccheck(temp_dir.path())?;
let bin_path_orig: PathBuf = env::args_os().nth(0).map(Into::into).filter(|p: &PathBuf| p.exists()) let bin_path_orig: PathBuf = env::args_os()
.nth(0)
.map(Into::into)
.filter(|p: &PathBuf| p.exists())
.context("Cannot get path to wasmer executable")?; .context("Cannot get path to wasmer executable")?;
let bin_path = temp_dir.path().join("wasmer-binfmt-interpreter"); let bin_path = temp_dir.path().join("wasmer-binfmt-interpreter");
fs::copy(&bin_path_orig, &bin_path) fs::copy(&bin_path_orig, &bin_path).context("Copy wasmer binary to temp folder")?;
.context("Copy wasmer binary to temp folder")?; let bin_path = fs::canonicalize(&bin_path).with_context(|| {
let bin_path = fs::canonicalize(&bin_path) format!(
.with_context(|| format!("Couldn't get absolute path for {}", bin_path.to_string_lossy()))?; "Couldn't get absolute path for {}",
bin_path.to_string_lossy()
)
})?;
Some([ Some([
[b":wasm32:M::\\x00asm\\x01\\x00\\x00::".as_ref(), bin_path.as_os_str().as_bytes(), b":PFC"].concat(), [
[b":wasm32-wat:E::wat::".as_ref(), bin_path.as_os_str().as_bytes(), b":PFC"].concat(), b":wasm32:M::\\x00asm\\x01\\x00\\x00::".as_ref(),
bin_path.as_os_str().as_bytes(),
b":PFC",
]
.concat(),
[
b":wasm32-wat:E::wat::".as_ref(),
bin_path.as_os_str().as_bytes(),
b":PFC",
]
.concat(),
]) ])
}, }
_ => None _ => None,
}; };
let wasm_registration = self.binfmt_misc.join("wasm32"); let wasm_registration = self.binfmt_misc.join("wasm32");
let wat_registration = self.binfmt_misc.join("wasm32-wat"); let wat_registration = self.binfmt_misc.join("wasm32-wat");
match self.action { match self.action {
Reregister | Unregister => { Reregister | Unregister => {
let unregister = [wasm_registration, wat_registration].iter().map(|registration| { let unregister = [wasm_registration, wat_registration]
if registration.exists() { .iter()
let mut registration = fs::OpenOptions::new() .map(|registration| {
.write(true) if registration.exists() {
.open(registration).context("Open existing binfmt entry to remove")?; let mut registration = fs::OpenOptions::new()
registration.write_all(b"-1").context("Couldn't write binfmt unregister request")?; .write(true)
Ok(true) .open(registration)
} else { .context("Open existing binfmt entry to remove")?;
eprintln!("Warning: {} does not exist, not unregistered.", registration.to_string_lossy()); registration
Ok(false) .write_all(b"-1")
} .context("Couldn't write binfmt unregister request")?;
}).collect::<Vec<_>>().into_iter().collect::<Result<Vec<_>>>()?; Ok(true)
} else {
eprintln!(
"Warning: {} does not exist, not unregistered.",
registration.to_string_lossy()
);
Ok(false)
}
})
.collect::<Vec<_>>()
.into_iter()
.collect::<Result<Vec<_>>>()?;
match (self.action, unregister.into_iter().any(|b| b)) { match (self.action, unregister.into_iter().any(|b| b)) {
(Unregister, false) => bail!("Nothing unregistered"), (Unregister, false) => bail!("Nothing unregistered"),
_ => () _ => (),
} }
}, }
_ => (), _ => (),
}; };
if let Some(specs) = specs { if let Some(specs) = specs {
@@ -100,14 +131,22 @@ impl Binfmt {
// Approximate. ELF parsing for a proper check feels like overkill here. // Approximate. ELF parsing for a proper check feels like overkill here.
eprintln!("Warning: wasmer has been compiled for glibc, and is thus likely dynamically linked. Invoking wasm binaries in chroots or mount namespaces (lxc, docker, ...) may not work."); eprintln!("Warning: wasmer has been compiled for glibc, and is thus likely dynamically linked. Invoking wasm binaries in chroots or mount namespaces (lxc, docker, ...) may not work.");
} }
specs.iter().map(|spec| { specs
let register = self.binfmt_misc.join("register"); .iter()
let mut register = fs::OpenOptions::new() .map(|spec| {
.write(true) let register = self.binfmt_misc.join("register");
.open(register).context("Open binfmt misc for registration")?; let mut register = fs::OpenOptions::new()
register.write_all(&spec).context("Couldn't register binfmt")?; .write(true)
Ok(()) .open(register)
}).collect::<Vec<_>>().into_iter().collect::<Result<Vec<_>>>()?; .context("Open binfmt misc for registration")?;
register
.write_all(&spec)
.context("Couldn't register binfmt")?;
Ok(())
})
.collect::<Vec<_>>()
.into_iter()
.collect::<Result<Vec<_>>>()?;
} }
Ok(()) Ok(())
} }

View File

@@ -424,7 +424,8 @@ impl Run {
pub fn from_binfmt_args() -> Run { pub fn from_binfmt_args() -> Run {
Self::from_binfmt_args_fallible().unwrap_or_else(|e| { Self::from_binfmt_args_fallible().unwrap_or_else(|e| {
crate::error::PrettyError::report::<()>( crate::error::PrettyError::report::<()>(
Err(e).context("Failed to set up wasmer binfmt invocation")) Err(e).context("Failed to set up wasmer binfmt invocation"),
)
}) })
} }
@@ -432,7 +433,7 @@ impl Run {
fn from_binfmt_args_fallible() -> Result<Run> { fn from_binfmt_args_fallible() -> Result<Run> {
let argv = std::env::args_os().collect::<Vec<_>>(); let argv = std::env::args_os().collect::<Vec<_>>();
let (_interpreter, executable, original_executable, args) = match &argv[..] { let (_interpreter, executable, original_executable, args) = match &argv[..] {
[a, b, c, d@..] => (a,b,c,d), [a, b, c, d @ ..] => (a, b, c, d),
_ => { _ => {
bail!("Wasmer binfmt interpreter needs at least three arguments (including $0) - must be registered as binfmt interpreter with the CFP flags. (Got arguments: {:?})", argv); bail!("Wasmer binfmt interpreter needs at least three arguments (including $0) - must be registered as binfmt interpreter with the CFP flags. (Got arguments: {:?})", argv);
} }
@@ -440,10 +441,22 @@ impl Run {
// TODO: Optimally, args and env would be passed as an UTF-8 Vec. // TODO: Optimally, args and env would be passed as an UTF-8 Vec.
// (Can be pulled out of std::os::unix::ffi::OsStrExt) // (Can be pulled out of std::os::unix::ffi::OsStrExt)
// But I don't want to duplicate or rewrite run.rs today. // But I don't want to duplicate or rewrite run.rs today.
let args = args.iter().enumerate().map(|(i, s)| { let args = args
s.clone().into_string().map_err(|s| anyhow!("Cannot convert argument {} ({:?}) to UTF-8 string", i + 1, s)) .iter()
}).collect::<Result<Vec<_>>>()?; .enumerate()
let original_executable = original_executable.clone().into_string() .map(|(i, s)| {
s.clone().into_string().map_err(|s| {
anyhow!(
"Cannot convert argument {} ({:?}) to UTF-8 string",
i + 1,
s
)
})
})
.collect::<Result<Vec<_>>>()?;
let original_executable = original_executable
.clone()
.into_string()
.map_err(|s| anyhow!("Cannot convert executable name {:?} to UTF-8 string", s))?; .map_err(|s| anyhow!("Cannot convert executable name {:?} to UTF-8 string", s))?;
let store = StoreOptions::default(); let store = StoreOptions::default();
// TODO: store.compiler.features.all = true; ? // TODO: store.compiler.features.all = true; ?
@@ -453,7 +466,7 @@ impl Run {
command_name: Some(original_executable), command_name: Some(original_executable),
store: store, store: store,
wasi: Wasi::for_binfmt_interpreter()?, wasi: Wasi::for_binfmt_interpreter()?,
.. Self::default() ..Self::default()
}) })
} }
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]

View File

@@ -104,7 +104,7 @@ impl Wasi {
deny_multiple_wasi_versions: true, deny_multiple_wasi_versions: true,
env_vars: env::vars().collect(), env_vars: env::vars().collect(),
pre_opened_directories: vec![dir], pre_opened_directories: vec![dir],
.. Self::default() ..Self::default()
}) })
} }
} }