Skip to content

Commit

Permalink
Merge branch 'ioctl' into 'main'
Browse files Browse the repository at this point in the history
Ioctl

See merge request repositories/wasi_ext_lib!11
  • Loading branch information
GPlaczek committed Aug 2, 2023
2 parents 515114b + b1ae824 commit 44ac505
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 89 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
source $HOME/.cargo/env
CLIPPY_OUT=${TMPDIR:-/tmp}/cargo-clippy-log.out
cargo clippy --target wasm32-wasi --features hterm --quiet 2> ${CLIPPY_OUT}
cargo clippy --target wasm32-wasi --quiet 2>> ${CLIPPY_OUT}
cat ${CLIPPY_OUT}
if [ -s ${CLIPPY_OUT} ]; then
echo "There were cargo-clippy warnings. Please fix."
Expand Down
29 changes: 15 additions & 14 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed={CLIB_DIR}/wasi_ext_lib.c");
println!("cargo:rerun-if-changed=src/lib.rs");
bindgen::Builder::default()
.header(format!("{CLIB_DIR}/wasi_ext_lib.h"))
.clang_arg(format!(
"--sysroot={}/share/wasi-sysroot",
env!("WASI_SDK_PATH")
))
.clang_arg("-DHTERM")
.clang_arg("-fvisibility=default")
.allowlist_file(format!("{CLIB_DIR}/wasi_ext_lib.h"))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings")
.write_to_file("src/wasi_ext_lib_generated.rs")
.expect("could not write bindings");
let mut bgen = bindgen::Builder::default().header(format!("{CLIB_DIR}/wasi_ext_lib.h"));
if cfg!(feature = "hterm") {
bgen = bgen.clang_arg("-DHTERM");
}
bgen.clang_arg(format!(
"--sysroot={}/share/wasi-sysroot",
env!("WASI_SDK_PATH")
))
.clang_arg("-fvisibility=default")
.allowlist_file(format!("{CLIB_DIR}/wasi_ext_lib.h"))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings")
.write_to_file("src/wasi_ext_lib_generated.rs")
.expect("could not write bindings");
}
44 changes: 16 additions & 28 deletions c_lib/wasi_ext_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,33 +152,6 @@ int wasi_ext_set_echo(int should_echo) {
}

#ifdef HTERM
int wasi_ext_hterm_set(const char *attrib, const char *val) {
JsonNode *root = json_mkobject();
json_append_member(root, "method", json_mkstring("set"));
json_append_member(root, "attrib", json_mkstring(attrib));
json_append_member(root, "val", json_mkstring(val));

char *serialized = json_stringify(0, root, " ");
json_delete(root);

int err = __syscall("hterm", serialized, NULL, 0);
free(serialized);
return err;
}

int wasi_ext_hterm_get(const char *attrib, char *val, size_t val_len) {
JsonNode *root = json_mkobject();
json_append_member(root, "method", json_mkstring("get"));
json_append_member(root, "attrib", json_mkstring(attrib));

char *serialized = json_stringify(0, root, " ");
json_delete(root);

int err = __syscall("hterm", serialized, (uint8_t *)val, val_len);
free(serialized);
return err;
}

int wasi_ext_event_source_fd(uint32_t event_mask) {
JsonNode *root = json_mkobject();
json_append_member(root, "event_mask", json_mknumber(event_mask));
Expand Down Expand Up @@ -273,4 +246,19 @@ int wasi_ext_kill(int pid, int sig) {
free(serialized);

return -err;
}
}

int wasi_ext_ioctl(int fd, unsigned int cmd, void *arg) {
JsonNode *root = json_mkobject();
json_append_member(root, "fd", json_mknumber(fd));
json_append_member(root, "cmd", json_mknumber(cmd));

char *serialized = json_stringify(0, root, " ");
json_delete(root);

int err = __syscall("ioctl", serialized, arg, _IOGS(cmd));

free(serialized);

return -err;
}
35 changes: 33 additions & 2 deletions c_lib/wasi_ext_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,40 @@
#ifndef c_bindings_wasi_ext_lib_h_INCLUDED
#define c_bindings_wasi_ext_lib_h_INCLUDED

#define _IOC_NONE 0U
#define _IOC_WRITE 1U
#define _IOC_READ 2U

#define _IORW_OFF 30
#define _IOS_OFF 16
#define _IOM_OFF 8
#define _IOF_OFF 0

#define _IORW_MASK 0xc0000000
#define _IOS_MASK 0x3fff0000
#define _IOM_MASK 0x0000ff00
#define _IOF_MASK 0x000000ff

#define _IOC(rw, maj, func, size) \
(rw << _IORW_OFF | size << _IOS_OFF | maj << _IOM_OFF | func << _IOF_OFF)

#define _IO(maj, func) _IOC(_IOC_NONE, maj, func, 0)
#define _IOW(maj, func, size) _IOC(_IOC_WRITE, maj, func, size)
#define _IOR(maj, func, size) _IOC(_IOC_READ, maj, func, size)
#define _IOWR(maj, func, size) _IOC(_IOC_WRITE | _IOC_READ, maj, func, size)

#define _IOGRW(mn) ((mn & _IORW_MASK) >> _IORW_OFF)
#define _IOGS(mn) ((mn & _IOS_MASK) >> _IOS_OFF)
#define _IOGM(mn) ((mn & _IOM_MASK) >> _IOM_OFF)
#define _IOGF(mn) ((mn & _IOF_MASK) >> _IOF_OFF)

#include <stdlib.h>

// Ioctl magic numbers
const unsigned int TIOCGWINSZ = _IOR(1, 0, 8);
const unsigned int TIOCSRAW = _IOW(1, 1, 4);
const unsigned int TIOCSECHO = _IOW(1, 2, 4);

enum RedirectType { READ, WRITE, APPEND };

struct Redirect {
Expand Down Expand Up @@ -36,8 +68,6 @@ int wasi_ext_set_env(const char *, const char *);
int wasi_ext_getpid();
int wasi_ext_set_echo(int);
#ifdef HTERM
int wasi_ext_hterm_get(const char *, char *, size_t);
int wasi_ext_hterm_set(const char *, const char *);
int wasi_ext_event_source_fd(uint32_t);
int wasi_ext_attach_sigint(int32_t);
#endif
Expand All @@ -46,5 +76,6 @@ int wasi_ext_spawn(const char *, const char *const *, size_t,
const struct Env *, size_t, int, const struct Redirect *,
size_t n_redirects, int *);
int wasi_ext_kill(int, int);
int wasi_ext_ioctl(int, unsigned int, void *);

#endif
76 changes: 31 additions & 45 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ use std::collections::HashMap;
use std::convert::AsRef;
use std::convert::From;
use std::env;
use std::ffi::CString;
use std::ffi::{c_uint, c_void, CString};
use std::fs;
use std::os::wasi::ffi::OsStrExt;
#[cfg(feature = "hterm")]
use std::os::wasi::prelude::RawFd;
use std::path::Path;
use std::ptr;
use std::str;

mod wasi_ext_lib_generated;

#[cfg(feature = "hterm")]
pub use wasi_ext_lib_generated::{
WasiEvents, WASI_EVENTS_MASK_SIZE, WASI_EVENTS_NUM, WASI_EVENT_SIGINT, WASI_EVENT_WINCH,
WasiEvents, TIOCGWINSZ, TIOCSECHO, TIOCSRAW, WASI_EVENTS_MASK_SIZE, WASI_EVENTS_NUM,
WASI_EVENT_SIGINT, WASI_EVENT_WINCH,
};

pub use wasi::SIGNAL_KILL;
Expand All @@ -35,6 +36,13 @@ pub enum Redirect<'a> {
Append((wasi::Fd, &'a str)),
}

#[repr(u32)]
pub enum IoctlNum {
GetScreenSize = wasi_ext_lib_generated::TIOCGWINSZ,
SetRaw = wasi_ext_lib_generated::TIOCSRAW,
SetEcho = wasi_ext_lib_generated::TIOCSECHO,
}

enum CStringRedirect {
Read((wasi::Fd, CString)),
Write((wasi::Fd, CString)),
Expand Down Expand Up @@ -165,48 +173,6 @@ pub fn set_echo(should_echo: bool) -> Result<(), ExitCode> {
}
}

#[cfg(feature = "hterm")]
pub fn hterm(attrib: &str, val: Option<&str>) -> Result<Option<String>, ExitCode> {
match val {
Some(value) => {
match unsafe {
wasi_ext_lib_generated::wasi_ext_hterm_set(
CString::new(attrib).unwrap().as_c_str().as_ptr() as *const i8,
CString::new(value).unwrap().as_c_str().as_ptr() as *const i8,
)
} {
0 => Ok(None),
e => Err(e),
}
}
None => {
const OUTPUT_LEN: usize = 256;
let mut buf = [0u8; OUTPUT_LEN];
match unsafe {
wasi_ext_lib_generated::wasi_ext_hterm_get(
CString::new(attrib).unwrap().as_c_str().as_ptr() as *const i8,
buf.as_mut_ptr() as *mut i8,
OUTPUT_LEN,
)
} {
0 => Ok(Some(
str::from_utf8(
&buf[..match buf.iter().position(|&i| i == 0) {
Some(x) => x,
None => {
return Err(wasi::ERRNO_ILSEQ.raw().into());
}
}],
)
.expect("Could not read syscall output")
.to_string(),
)),
e => Err(e),
}
}
}
}

#[cfg(feature = "hterm")]
pub fn event_source_fd(event_mask: WasiEvents) -> Result<RawFd, ExitCode> {
let result = unsafe { wasi_ext_lib_generated::wasi_ext_event_source_fd(event_mask) };
Expand Down Expand Up @@ -305,3 +271,23 @@ pub fn kill(pid: Pid, signal: wasi::Signal) -> Result<(), ExitCode> {
Ok(())
}
}

pub fn ioctl<T>(fd: RawFd, command: IoctlNum, arg: Option<&mut T>) -> Result<(), ExitCode> {
let result = if let Some(arg) = arg {
unsafe {
let arg_ptr: *mut c_void = arg as *mut T as *mut c_void;
wasi_ext_lib_generated::wasi_ext_ioctl(fd, command as c_uint, arg_ptr)
}
} else {
unsafe {
let null_ptr = ptr::null_mut::<T>() as *mut c_void;
wasi_ext_lib_generated::wasi_ext_ioctl(fd, command as c_uint, null_ptr)
}
};

if result < 0 {
Err(-result)
} else {
Ok(())
}
}

0 comments on commit 44ac505

Please sign in to comment.