Skip to content

oxidevm_bridge_v1

oxidevm_bridge_v1 is a small set of WebAssembly function imports that host.kit.wasi serves beside WASI Preview1. Rust programs use them through the oxidevm-bridge crate. Programs in other languages can import them directly; this page is the contract.

  • The module name is oxidevm_bridge_v1. A program that imports another major, such as oxidevm_bridge_v2, or a name not listed here is refused before it starts.
  • Every function takes and returns i32. Unsigned values are passed in i32: 0xFFFFFFFF arrives as -1 and is read as unsigned. Every function returns a WASI errno, 0 for success.
  • Results go to caller-provided out-pointers. Every range is checked against linear memory before any side effect, and nothing is written on failure.
  • Integers in records are little-endian. A string is UTF-8 without NUL. A list is count: u32 followed by count entries of length: u32, bytes.
  • Handles belong to one run, are never reused while it lasts, and count against the run’s 256 entries together with its descriptors. A stale or forged handle is BADF.
  • A function whose capability the module does not declare returns NOSYS (52).
Function Signature Result
process_info (out: *mut [u32; 4]) -> errno pid, parent (0 when none), uid, gid, as the VM reported them when the process started. Needs process.info.
process_cwd (buffer: *mut u8, len: u32, out_len: *mut u32) -> errno Copies up to len bytes of the caller’s absolute working directory and writes its full length. WASI Preview1 has no working directory; a program can pass this to wasi-libc’s chdir before main.
Function Signature Result
command_run (request: *const u8, len: u32, out_handle: *mut u32, out_sizes: *mut [u32; 2]) -> errno Runs a native program to completion with piped standard streams; writes a result handle and the stdout and stderr sizes. Needs process.sync.
result_status (handle: u32, out: *mut [u32; 3]) -> errno pid, kind (0 exited, 1 signaled), value (the exit code or signal number), never truncated.
result_read (handle: u32, stream: u32, offset: u32, buffer: *mut u8, len: u32, out_read: *mut u32) -> errno Copies retained output of stream (1 stdout, 2 stderr) from offset.
result_close (handle: u32) -> errno Releases the handle and its retained bytes.

The command_run request is, in order:

Field Encoding Bound
executable string absolute path, at most 4,095 bytes
args list of strings at most 63 (argv is at most 64 with the executable)
cwd u8 present flag, then a string
env u8 present flag, then a list of KEY=VALUE when present it is the whole environment
stdin bytes (u32 length, bytes) at most 5 MiB
timeout_ms u32 1 to 180,000
stdout_limit, stderr_limit u32 each at most 1 MiB each

The command runs once, and its output is retained until the program closes the handle, within 8 MiB per run, so nothing runs twice to learn a size. The child belongs to the program. It is killed and reaped when its deadline passes, and when the program’s process ends for any reason. Children it forks itself follow ordinary Linux rules, and capture still ends at the deadline when one of them holds a pipe open.

Errno Meaning
INVAL (28) A malformed request or a value out of bounds; nothing was started.
NOENT (44), ACCES (2), NOEXEC (45) The executable is missing, not permitted or not executable; nothing was started.
TIMEDOUT (73) The deadline passed; the child was killed and reaped.
TOOBIG (1) An output passed its limit; the child was killed and reaped.
MFILE (33), NOMEM (48) The run’s handle table or its retained-output budget is full.
Function Signature Result
net_connect (request: *const u8, len: u32, out_handle: *mut u32) -> errno kind: u8 (0 TCP, 1 TCP with TLS, 2 Unix), then a host string and port: u16 (and for TLS an ALPN list of at most 8), or a Unix path of at most 107 bytes. Needs net.vm or net.internet.
net_read (handle: u32, buffer: *mut u8, len: u32, timeout_ms: u32, out_read: *mut u32) -> errno At most 64 KiB per call; 0 bytes is the peer’s end of stream. timeout_ms 0 to 86,400,000, or 0xFFFFFFFF for none.
net_write (handle: u32, buffer: *const u8, len: u32, out_written: *mut u32) -> errno At most 64 KiB per call. A closed peer is PIPE, never SIGPIPE.
net_shutdown (handle: u32, how: u32) -> errno 1 read, 2 write, 3 both.
net_close (handle: u32) -> errno

Connections use the module process’s own VM sockets and its declared reach. A destination beyond the reach is ACCES before any traffic. TLS is verified against the VM’s /etc/ssl/cert.pem. Socket errors keep their meaning: CONNREFUSED (14), CONNRESET (15), NOENT (44) for a missing Unix socket, TIMEDOUT (73).