From 9d99bfb81f140fb0c61ce1c525c6aa38c770858e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Saparelli?= Date: Tue, 26 Jul 2022 23:28:17 +1200 Subject: [PATCH] Add function and example program detecting WASI runability (#250) --- examples/detect-wasi.rs | 13 +++++++++++++ src/lib.rs | 1 + src/miniwasi.wasm | Bin 0 -> 97 bytes src/miniwasi.wast | 10 ++++++++++ src/wasi.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+) create mode 100644 examples/detect-wasi.rs create mode 100755 src/miniwasi.wasm create mode 100644 src/miniwasi.wast create mode 100644 src/wasi.rs diff --git a/examples/detect-wasi.rs b/examples/detect-wasi.rs new file mode 100644 index 00000000..d3224fce --- /dev/null +++ b/examples/detect-wasi.rs @@ -0,0 +1,13 @@ +use std::process::exit; + +use cargo_binstall::wasi::detect_wasi_runability; + +fn main() { + if detect_wasi_runability().unwrap() { + println!("WASI is runnable!"); + exit(0); + } else { + println!("WASI is not runnable"); + exit(1); + } +} diff --git a/src/lib.rs b/src/lib.rs index 29ccb8f4..60691853 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ pub mod bins; pub mod binstall; pub mod fetchers; pub mod metafiles; +pub mod wasi; mod target; pub use target::*; diff --git a/src/miniwasi.wasm b/src/miniwasi.wasm new file mode 100755 index 0000000000000000000000000000000000000000..56dcdc6a2625727e16fa6b3ecbd0107de4f4bd4d GIT binary patch literal 97 zcmWN|O$vY@5C+h1Ci>q5K_}<}9ifw$gpdnU9LZXB^?LgUEsg+C!yCQW0G?^eTC9>& t2RVFFA)3pYytEe^dE6!6^;M^ literal 0 HcmV?d00001 diff --git a/src/miniwasi.wast b/src/miniwasi.wast new file mode 100644 index 00000000..93655cfd --- /dev/null +++ b/src/miniwasi.wast @@ -0,0 +1,10 @@ +(module + (memory $0 0) + (export "memory" (memory $0)) + (export "_start" (func $0)) + (import "wasi_snapshot_preview1" "proc_exit" (func $exit (param i32))) + (func $0 + (call $exit (i32.const 0)) + (unreachable) + ) +) diff --git a/src/wasi.rs b/src/wasi.rs new file mode 100644 index 00000000..c1c1340f --- /dev/null +++ b/src/wasi.rs @@ -0,0 +1,40 @@ +use std::{fs::File, io::Write, process::Command}; +#[cfg(unix)] +use std::{fs::Permissions, os::unix::fs::PermissionsExt}; + +use tempfile::tempdir; + +use crate::errors::BinstallError; + +const WASI_PROGRAM: &[u8] = include_bytes!("miniwasi.wasm"); + +/// Detect the ability to run WASI +/// +/// This attempts to run a small embedded WASI program, and returns true if no errors happened. +/// Errors returned by the `Result` are I/O errors from the establishment of the context, not +/// errors from the run attempt. +/// +/// On Linux, you can configure your system to run WASI programs using a binfmt directive. Under +/// systemd, write the below to `/etc/binfmt.d/wasi.conf`, with `/usr/bin/wasmtime` optionally +/// replaced with the path to your WASI runtime of choice: +/// +/// ```plain +/// :wasi:M::\x00asm::/usr/bin/wasmtime: +/// ``` +pub fn detect_wasi_runability() -> Result { + let progdir = tempdir()?; + let prog = progdir.path().join("miniwasi.wasm"); + + { + let mut progfile = File::create(&prog)?; + progfile.write_all(WASI_PROGRAM)?; + + #[cfg(unix)] + progfile.set_permissions(Permissions::from_mode(0o777))?; + } + + match Command::new(prog).output() { + Ok(out) => Ok(out.status.success() && out.stdout.is_empty() && out.stderr.is_empty()), + Err(_) => Ok(false), + } +}