From 630d4bde13a12d17a6e2adf09f4b4c117446ac18 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Thu, 21 Mar 2019 10:20:59 -0700 Subject: [PATCH] re-organize modules for syscalls, windows is in bad shape --- lib/emscripten/src/env/unix/mod.rs | 3 +- lib/emscripten/src/syscalls/emscripten_vfs.rs | 16 +- lib/emscripten/src/syscalls/mod.rs | 106 -- .../src/syscalls/{unix.rs => unix/host_fs.rs} | 248 +++-- lib/emscripten/src/syscalls/unix/mod.rs | 129 +++ lib/emscripten/src/syscalls/unix/vfs.rs | 911 ++++++++++++++++++ .../src/syscalls/windows/host_fs.rs | 35 + .../syscalls/{windows.rs => windows/mod.rs} | 12 + .../src/syscalls/{ => windows}/vfs.rs | 54 +- lib/runtime-abi/src/vfs/device_file.rs | 30 +- lib/runtime-abi/src/vfs/vfs.rs | 17 +- 11 files changed, 1238 insertions(+), 323 deletions(-) rename lib/emscripten/src/syscalls/{unix.rs => unix/host_fs.rs} (82%) create mode 100644 lib/emscripten/src/syscalls/unix/mod.rs create mode 100644 lib/emscripten/src/syscalls/unix/vfs.rs create mode 100644 lib/emscripten/src/syscalls/windows/host_fs.rs rename lib/emscripten/src/syscalls/{windows.rs => windows/mod.rs} (96%) rename lib/emscripten/src/syscalls/{ => windows}/vfs.rs (95%) diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs index 539dbc65d..dd693979a 100644 --- a/lib/emscripten/src/env/unix/mod.rs +++ b/lib/emscripten/src/env/unix/mod.rs @@ -139,7 +139,8 @@ pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> i32 { unsafe { sysconf(name) as i32 } // TODO review i64 } -pub fn _initgroups(_ctx: &mut Ctx, user_offset: u32, gid: u32) -> c_int { +/// initgroups +pub fn _initgroups(_ctx: &mut Ctx, _user_offset: u32, _gid: u32) -> c_int { 0 } diff --git a/lib/emscripten/src/syscalls/emscripten_vfs.rs b/lib/emscripten/src/syscalls/emscripten_vfs.rs index 8be7e777f..a8c9f54a8 100644 --- a/lib/emscripten/src/syscalls/emscripten_vfs.rs +++ b/lib/emscripten/src/syscalls/emscripten_vfs.rs @@ -1,10 +1,6 @@ -use crate::syscalls::emscripten_vfs::FileHandle::{Socket, VirtualFile}; -use crate::varargs::VarArgs; use std::cmp::{Eq, Ord, Ordering, PartialEq}; use std::collections::BTreeMap; -use std::env::home_dir; use std::fmt::Display; -use wasmer_runtime_abi::vfs::device_file; use wasmer_runtime_abi::vfs::vfs::Vfs; pub type Fd = i32; @@ -63,10 +59,10 @@ impl EmscriptenVfs { fd_map.insert(vfd, FileHandle::VirtualFile(*handle)); }); -// let _ = repo.create_dir(PathBuf::from("/dev/")); -// let stdin = repo.create_file(PathBuf::from("/dev/stdin"))?; -// let stdout = repo.create_file(PathBuf::from("/dev/stdout"))?; -// let stderr = repo.create_file(PathBuf::from("/dev/stderr"))?; + // let _ = repo.create_dir(PathBuf::from("/dev/")); + // let stdin = repo.create_file(PathBuf::from("/dev/stdin"))?; + // let stdout = repo.create_file(PathBuf::from("/dev/stdout"))?; + // let stderr = repo.create_file(PathBuf::from("/dev/stderr"))?; let stdin_fd = VirtualFd(0); let stdin_handle = FileHandle::VirtualFile(0); @@ -85,8 +81,8 @@ impl EmscriptenVfs { pub fn close(&mut self, vfd: &VirtualFd) -> () { match self.fd_map.get(&vfd) { Some(FileHandle::VirtualFile(handle)) => { - self.vfs.close(handle); - }, + self.vfs.close(handle).unwrap(); + } Some(FileHandle::Socket(fd)) => unsafe { libc::close(*fd); }, diff --git a/lib/emscripten/src/syscalls/mod.rs b/lib/emscripten/src/syscalls/mod.rs index 4308f7ae1..e5f35001f 100644 --- a/lib/emscripten/src/syscalls/mod.rs +++ b/lib/emscripten/src/syscalls/mod.rs @@ -4,9 +4,6 @@ mod unix; #[cfg(windows)] mod windows; -#[cfg(feature = "vfs")] -mod vfs; - #[cfg(feature = "vfs")] mod emscripten_vfs; @@ -16,9 +13,6 @@ pub use self::unix::*; #[cfg(windows)] pub use self::windows::*; -#[cfg(feature = "vfs")] -pub use self::vfs::*; - #[cfg(feature = "vfs")] pub use self::emscripten_vfs::*; @@ -60,42 +54,6 @@ pub fn ___syscall1(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) { } } -/// read -#[cfg(not(feature = "vfs"))] -pub fn ___syscall3(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { - // -> ssize_t - debug!("emscripten::___syscall3 (read) {}", _which); - let fd: i32 = varargs.get(ctx); - let buf: u32 = varargs.get(ctx); - let count: i32 = varargs.get(ctx); - debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count); - let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void; - let ret = unsafe { libc::read(fd, buf_addr, count as _) }; - debug!("=> ret: {}", ret); - ret as _ -} - -/// write -#[cfg(not(feature = "vfs"))] -pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall4 (write) {}", _which); - let fd: i32 = varargs.get(ctx); - let buf: u32 = varargs.get(ctx); - let count: i32 = varargs.get(ctx); - debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count); - let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void; - unsafe { write(fd, buf_addr, count as _) as i32 } -} - -/// close -#[cfg(not(feature = "vfs"))] -pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall6 (close) {}", _which); - let fd: i32 = varargs.get(ctx); - debug!("fd: {}", fd); - unsafe { libc::close(fd) } -} - // chdir pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall12 (chdir) {}", _which); @@ -114,13 +72,6 @@ pub fn ___syscall10(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { -1 } -/// chmod -#[cfg(not(feature = "vfs"))] -pub fn ___syscall15(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { - debug!("emscripten::___syscall15"); - -1 -} - // getpid pub fn ___syscall20(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall20 (getpid)"); @@ -140,48 +91,11 @@ pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int unsafe { rmdir(pathname_addr) } } -// pipe -pub fn ___syscall42(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall42 (pipe)"); - // offset to a file descriptor, which contains a read end and write end, 2 integers - let fd_offset: u32 = varargs.get(ctx); - - let emscripten_memory = ctx.memory(0); - - // convert the file descriptor into a vec with two slots - let mut fd_vec: Vec = emscripten_memory.view()[((fd_offset / 4) as usize)..] - .iter() - .map(|pipe_end: &std::cell::Cell| pipe_end.get()) - .take(2) - .collect(); - - // get it as a mutable pointer - let fd_ptr = fd_vec.as_mut_ptr(); - - // call pipe and store the pointers in this array - #[cfg(target_os = "windows")] - let result: c_int = unsafe { libc::pipe(fd_ptr, 2048, 0) }; - #[cfg(not(target_os = "windows"))] - let result: c_int = unsafe { libc::pipe(fd_ptr) }; - result -} - pub fn ___syscall60(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall60"); -1 } -/// dup2 -#[cfg(not(feature = "vfs"))] -pub fn ___syscall63(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall63 (dup2) {}", _which); - - let src: i32 = varargs.get(ctx); - let dst: i32 = varargs.get(ctx); - - unsafe { libc::dup2(src, dst) } -} - // getppid pub fn ___syscall64(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall64 (getppid)"); @@ -394,26 +308,6 @@ pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in 0 } -/// fstat64 -#[cfg(not(feature = "vfs"))] -pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall197 (fstat64) {}", _which); - let fd: c_int = varargs.get(ctx); - let buf: u32 = varargs.get(ctx); - - unsafe { - let mut stat = std::mem::zeroed(); - let ret = libc::fstat(fd, &mut stat); - debug!("ret: {}", ret); - if ret != 0 { - return ret; - } - copy_stat_into_wasm(ctx, buf, &stat); - } - - 0 -} - pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall220"); -1 diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix/host_fs.rs similarity index 82% rename from lib/emscripten/src/syscalls/unix.rs rename to lib/emscripten/src/syscalls/unix/host_fs.rs index 5307f75a1..90be093e3 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix/host_fs.rs @@ -2,78 +2,51 @@ use crate::varargs::VarArgs; /// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32 /// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html use libc::{ - accept, - bind, - // ENOTTY, - c_char, - c_int, - c_void, - // fcntl, setsockopt, getppid - connect, - dup2, - fcntl, - getgid, - getpeername, - getsockname, - getsockopt, - in_addr_t, - in_port_t, - ioctl, - // iovec, - listen, - msghdr, - pid_t, - // readv, - recvfrom, - recvmsg, - // ENOTTY, - rusage, - sa_family_t, - // writev, - select, - sendmsg, - sendto, - setpgid, - setsockopt, - sockaddr, - socket, - socklen_t, - uname, - utsname, - EINVAL, - // sockaddr_in, - FIOCLEX, - FIONBIO, - F_GETFD, - F_SETFD, - SOL_SOCKET, - SO_REUSEADDR, - TIOCGWINSZ, + accept, bind, c_char, c_int, c_void, connect, dup2, fcntl, getgid, getpeername, getsockname, + getsockopt, in_addr_t, in_port_t, ioctl, listen, msghdr, pid_t, recvfrom, recvmsg, sa_family_t, + select, sendmsg, sendto, setsockopt, sockaddr, socket, socklen_t, EINVAL, FIOCLEX, FIONBIO, + F_GETFD, F_SETFD, SOL_SOCKET, SO_REUSEADDR, TIOCGWINSZ, }; use wasmer_runtime_core::vm::Ctx; -use std::{mem, slice}; - -// Linking to functions that are not provided by rust libc -#[cfg(target_os = "macos")] -#[link(name = "c")] -extern "C" { - pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t; -} - -#[cfg(not(target_os = "macos"))] -use libc::wait4; +use std::slice; // Another conditional constant for name resolution: Macos et iOS use // SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. // Other platforms do otherwise. +use crate::utils::copy_stat_into_wasm; #[cfg(target_os = "darwin")] use libc::SO_NOSIGPIPE; + #[cfg(not(target_os = "darwin"))] const SO_NOSIGPIPE: c_int = 0; +/// read +pub fn ___syscall3(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { + // -> ssize_t + debug!("emscripten::___syscall3 (read) {}", _which); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: i32 = varargs.get(ctx); + debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void; + let ret = unsafe { libc::read(fd, buf_addr, count as _) }; + debug!("=> ret: {}", ret); + ret as _ +} + +/// write +pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall4 (write) {}", _which); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: i32 = varargs.get(ctx); + debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void; + unsafe { libc::write(fd, buf_addr, count as _) as i32 } +} + /// open -#[cfg(not(feature = "vfs"))] pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall5 (open) {}", _which); let pathname: u32 = varargs.get(ctx); @@ -89,8 +62,21 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int fd } -// chown -#[cfg(not(feature = "vfs"))] +/// close +pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall6 (close) {}", _which); + let fd: i32 = varargs.get(ctx); + debug!("fd: {}", fd); + unsafe { libc::close(fd) } +} + +/// chmod +pub fn ___syscall15(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { + debug!("emscripten::___syscall15"); + -1 +} + +/// chown pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); @@ -103,8 +89,7 @@ pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in unsafe { libc::chown(pathname_addr, owner, group) } } -// mkdir -#[cfg(not(feature = "vfs"))] +/// mkdir pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", _which); let pathname: u32 = varargs.get(ctx); @@ -113,11 +98,47 @@ pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int unsafe { libc::mkdir(pathname_addr, mode as _) } } +/// pipe +pub fn ___syscall42(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall42 (pipe)"); + // offset to a file descriptor, which contains a read end and write end, 2 integers + let fd_offset: u32 = varargs.get(ctx); + + let emscripten_memory = ctx.memory(0); + + // convert the file descriptor into a vec with two slots + let mut fd_vec: Vec = emscripten_memory.view()[((fd_offset / 4) as usize)..] + .iter() + .map(|pipe_end: &std::cell::Cell| pipe_end.get()) + .take(2) + .collect(); + + // get it as a mutable pointer + let fd_ptr = fd_vec.as_mut_ptr(); + + // call pipe and store the pointers in this array + #[cfg(target_os = "windows")] + let result: c_int = unsafe { libc::pipe(fd_ptr, 2048, 0) }; + #[cfg(not(target_os = "windows"))] + let result: c_int = unsafe { libc::pipe(fd_ptr) }; + result +} + +/// dup2 +pub fn ___syscall63(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall63 (dup2) {}", _which); + + let src: i32 = varargs.get(ctx); + let dst: i32 = varargs.get(ctx); + + unsafe { libc::dup2(src, dst) } +} + // getgid //#[cfg(not(feature = "vfs"))] pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (getgid)"); - let result = unsafe { + let result = unsafe { // Maybe fix: Emscripten returns 0 always getgid() as i32 }; @@ -169,7 +190,6 @@ pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_ } /// ioctl -#[cfg(not(feature = "vfs"))] pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall54 (ioctl) {}", _which); let fd: i32 = varargs.get(ctx); @@ -212,7 +232,6 @@ pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int } // socketcall -#[cfg(not(feature = "vfs"))] #[allow(clippy::cast_ptr_alignment)] pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall102 (socketcall) {}", _which); @@ -253,21 +272,13 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in ioctl(fd, FIOCLEX); }; - let err = errno::errno(); + let _err = errno::errno(); -// type T = u32; -// let payload = 1 as *const T as _; - let result = unsafe { - setsockopt( - fd, - SOL_SOCKET, - SO_NOSIGPIPE, - 0 as *const _, - 4, - ) - }; + // type T = u32; + // let payload = 1 as *const T as _; + let _result = unsafe { setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, 0 as *const _, 4) }; - let err2 = errno::errno(); + let _err2 = errno::errno(); debug!( "=> domain: {} (AF_INET/2), type: {} (SOCK_STREAM/1), protocol: {} = fd: {}", @@ -286,12 +297,10 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in // Debug received address let _proper_address = address as *const GuestSockaddrIn; - unsafe { - debug!( + debug!( "=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}", - (*_proper_address).sin_family, (*_proper_address).sin_port, (*_proper_address).sin_addr.s_addr + unsafe { (*_proper_address).sin_family }, unsafe { (*_proper_address).sin_port }, unsafe { (*_proper_address).sin_addr.s_addr } ); - } let status = unsafe { bind(socket, address, address_len) }; // debug!("=> status: {}", status); debug!( @@ -341,24 +350,13 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let fd = unsafe { accept(socket, address, address_len_addr) }; - use bit_field::BitArray; - unsafe { let address_linux = emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut LinuxSockAddr; (*address_linux).sa_family = (*address).sa_family as u16; (*address_linux).sa_data = (*address).sa_data; -// let sa_data = (*address).sa_data; -// let sa_data_slice: &[i8] = slice::from_raw_parts((*address).sa_data, 14); - let x = (*address).sa_data[0]; - let y = (*address).sa_data[1]; - let raw_family: [i8; 2] = [x, y]; - let zz = std::mem::transmute::<[i8; 2], i16>(raw_family); - -// let sin_family = &sa_data_slice[0..2]; -// let sin_port = &sa_data_slice[2..4]; let _proper_address = address as *const GuestSockaddrIn; - let x = 10; + let _x = 10; }; // set_cloexec @@ -483,7 +481,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in } /// pread -#[cfg(not(feature = "vfs"))] pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", _which); let fd: i32 = varargs.get(ctx); @@ -501,7 +498,6 @@ pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in } /// pwrite -#[cfg(not(feature = "vfs"))] pub fn ___syscall181(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall181 (pwrite) {}", _which); let fd: i32 = varargs.get(ctx); @@ -522,26 +518,7 @@ pub fn ___syscall181(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in status } -/// wait4 -#[allow(clippy::cast_ptr_alignment)] -pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t { - debug!("emscripten::___syscall114 (wait4)"); - let pid: pid_t = varargs.get(ctx); - let status: u32 = varargs.get(ctx); - let options: c_int = varargs.get(ctx); - let rusage: u32 = varargs.get(ctx); - let status_addr = emscripten_memory_pointer!(ctx.memory(0), status) as *mut c_int; - let rusage_addr = emscripten_memory_pointer!(ctx.memory(0), rusage) as *mut rusage; - let res = unsafe { wait4(pid, status_addr, options, rusage_addr) }; - debug!( - "=> pid: {}, status: {:?}, options: {}, rusage: {:?} = pid: {}", - pid, status_addr, options, rusage_addr, res - ); - res -} - // select -#[cfg(not(feature = "vfs"))] #[allow(clippy::cast_ptr_alignment)] pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall142 (newselect) {}", _which); @@ -559,7 +536,7 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let nfds = nfds as _; let readfds_slice = unsafe { slice::from_raw_parts_mut(readfds_set_u8_ptr, nfds) }; - let writefds_slice = unsafe { slice::from_raw_parts_mut(writefds_set_u8_ptr, nfds) }; + let _writefds_slice = unsafe { slice::from_raw_parts_mut(writefds_set_u8_ptr, nfds) }; let nfds = nfds as _; use bit_field::BitArray; @@ -578,34 +555,35 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in // let rd = unsafe { libc::read(bits[0], 0 as *mut _, 0)}; - let err = errno::errno(); + let _err = errno::errno(); let result = unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) }; assert!(nfds <= 64, "`nfds` must be less than or equal to 64"); assert!(exceptfds == 0, "`exceptfds` is not supporrted"); - let err = errno::errno(); - debug!("gah again: {}", err); + let _err = errno::errno(); + debug!("gah again: {}", _err); result // unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) } } -// setpgid -pub fn ___syscall57(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall57 (setpgid) {}", _which); - let pid: i32 = varargs.get(ctx); - let pgid: i32 = varargs.get(ctx); - unsafe { setpgid(pid, pgid) } -} - -/// uname -// NOTE: Wondering if we should return custom utsname, like Emscripten. -pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { - debug!("emscripten::___syscall122 (uname) {}", _which); +/// fstat64 +pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall197 (fstat64) {}", _which); + let fd: c_int = varargs.get(ctx); let buf: u32 = varargs.get(ctx); - debug!("=> buf: {}", buf); - let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut utsname; - unsafe { uname(buf_addr) } + + unsafe { + let mut stat = std::mem::zeroed(); + let ret = libc::fstat(fd, &mut stat); + debug!("ret: {}", ret); + if ret != 0 { + return ret; + } + copy_stat_into_wasm(ctx, buf, &stat); + } + + 0 } diff --git a/lib/emscripten/src/syscalls/unix/mod.rs b/lib/emscripten/src/syscalls/unix/mod.rs new file mode 100644 index 000000000..d326ce18a --- /dev/null +++ b/lib/emscripten/src/syscalls/unix/mod.rs @@ -0,0 +1,129 @@ +use crate::varargs::VarArgs; + +#[cfg(not(feature = "vfs"))] +pub mod host_fs; + +#[cfg(feature = "vfs")] +pub mod vfs; + +#[cfg(not(feature = "vfs"))] +pub use host_fs::*; + +#[cfg(feature = "vfs")] +pub use vfs::*; + +/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32 +/// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html +use libc::{ + c_int, dup2, fcntl, getgid, pid_t, rusage, setpgid, uname, utsname, EINVAL, F_GETFD, F_SETFD, +}; +use wasmer_runtime_core::vm::Ctx; + +// Linking to functions that are not provided by rust libc +#[cfg(target_os = "macos")] +#[link(name = "c")] +extern "C" { + pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t; +} + +#[cfg(not(target_os = "macos"))] +use libc::wait4; + +// Another conditional constant for name resolution: Macos et iOS use +// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. +// Other platforms do otherwise. +//#[cfg(target_os = "darwin")] +//use libc::SO_NOSIGPIPE; +//#[cfg(not(target_os = "darwin"))] +//const SO_NOSIGPIPE: c_int = 0; + +// getgid +//#[cfg(not(feature = "vfs"))] +pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { + debug!("emscripten::___syscall201 (getgid)"); + let result = unsafe { + // Maybe fix: Emscripten returns 0 always + getgid() as i32 + }; + result +} + +// getgid32 +pub fn ___syscall202(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { + // gid_t + debug!("emscripten::___syscall202 (getgid32)"); + unsafe { + // Maybe fix: Emscripten returns 0 always + getgid() as _ + } +} + +/// dup3 +pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t { + // Implementation based on description at https://linux.die.net/man/2/dup3 + debug!("emscripten::___syscall330 (dup3)"); + let oldfd: c_int = varargs.get(ctx); + let newfd: c_int = varargs.get(ctx); + let flags: c_int = varargs.get(ctx); + + if oldfd == newfd { + return EINVAL; + } + + let res = unsafe { dup2(oldfd, newfd) }; + + // Set flags on newfd (https://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html) + let mut old_flags = unsafe { fcntl(newfd, F_GETFD, 0) }; + + if old_flags > 0 { + old_flags |= flags; + } else if old_flags == 0 { + old_flags &= !flags; + } + + unsafe { + fcntl(newfd, F_SETFD, old_flags); + } + + debug!( + "=> oldfd: {}, newfd: {}, flags: {} = pid: {}", + oldfd, newfd, flags, res + ); + res +} + +/// wait4 +#[allow(clippy::cast_ptr_alignment)] +pub fn ___syscall114(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> pid_t { + debug!("emscripten::___syscall114 (wait4)"); + let pid: pid_t = varargs.get(ctx); + let status: u32 = varargs.get(ctx); + let options: c_int = varargs.get(ctx); + let rusage: u32 = varargs.get(ctx); + let status_addr = emscripten_memory_pointer!(ctx.memory(0), status) as *mut c_int; + let rusage_addr = emscripten_memory_pointer!(ctx.memory(0), rusage) as *mut rusage; + let res = unsafe { wait4(pid, status_addr, options, rusage_addr) }; + debug!( + "=> pid: {}, status: {:?}, options: {}, rusage: {:?} = pid: {}", + pid, status_addr, options, rusage_addr, res + ); + res +} + +/// setpgid +pub fn ___syscall57(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall57 (setpgid) {}", _which); + let pid: i32 = varargs.get(ctx); + let pgid: i32 = varargs.get(ctx); + unsafe { setpgid(pid, pgid) } +} + +/// uname +// NOTE: Wondering if we should return custom utsname, like Emscripten. +pub fn ___syscall122(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall122 (uname) {}", _which); + let buf: u32 = varargs.get(ctx); + debug!("=> buf: {}", buf); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut utsname; + unsafe { uname(buf_addr) } +} diff --git a/lib/emscripten/src/syscalls/unix/vfs.rs b/lib/emscripten/src/syscalls/unix/vfs.rs new file mode 100644 index 000000000..1caf0ecb7 --- /dev/null +++ b/lib/emscripten/src/syscalls/unix/vfs.rs @@ -0,0 +1,911 @@ +use crate::utils::{copy_stat_into_wasm, read_string_from_wasm}; +use crate::varargs::VarArgs; +use libc::stat; +use std::os::raw::c_int; +use std::slice; +use wasmer_runtime_core::vm::Ctx; + +// Another conditional constant for name resolution: Macos et iOS use +// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. +// Other platforms do otherwise. +use crate::syscalls::emscripten_vfs::FileHandle::{Socket, VirtualFile}; +use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd}; +#[cfg(target_os = "darwin")] +use libc::SO_NOSIGPIPE; +use std::ffi::c_void; + +#[cfg(not(target_os = "darwin"))] +const SO_NOSIGPIPE: c_int = 0; + +/// read +pub fn ___syscall3(ctx: &mut Ctx, _: i32, mut varargs: VarArgs) -> i32 { + debug!("emscripten::___syscall3 (read - vfs)",); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: i32 = varargs.get(ctx); + + debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count); + + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut u8; + let mut buf_slice = unsafe { slice::from_raw_parts_mut(buf_addr, count as _) }; + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(fd); + let virtual_file_handle = vfs.get_virtual_file_handle(vfd).unwrap(); + + let ret = vfs + .vfs + .read_file(virtual_file_handle as _, &mut buf_slice) + .unwrap(); + debug!("=> read syscall returns: {}", ret); + ret as _ +} + +/// write +pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall4 (write - vfs) {}", _which); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: i32 = varargs.get(ctx); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf); + + let buf_slice = unsafe { slice::from_raw_parts_mut(buf_addr, count as _) }; + let vfd = VirtualFd(fd); + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + + let count: usize = match vfs.fd_map.get(&vfd) { + Some(FileHandle::VirtualFile(handle)) => { + vfs.vfs + .write_file(*handle as _, buf_slice, count as _, 0) + .unwrap(); + count as usize + } + Some(FileHandle::Socket(host_fd)) => unsafe { + libc::write(*host_fd, buf_addr as _, count as _) as usize + }, + None => panic!(), + }; + + let string = read_string_from_wasm(ctx.memory(0), buf); + + debug!( + "=> fd: {} (host {}), buf: {}, count: {}\n", + vfd.0, fd, buf, count + ); + debug!("=> data:\n \"{}\"", string); + count as c_int +} + +/// open +pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall5 (open vfs) {}", _which); + let pathname: u32 = varargs.get(ctx); + let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8; + let path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() }; + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let fd = vfs.vfs.open_file(path_str).unwrap(); + let virtual_file_handle = FileHandle::VirtualFile(fd); + let virtual_fd = vfs.next_lowest_fd(); + let fd = virtual_fd.0; + assert!( + !vfs.fd_map.contains_key(&virtual_fd), + "Emscripten vfs should not contain file descriptor." + ); + vfs.fd_map.insert(virtual_fd, virtual_file_handle); + debug!("=> opening `{}` with new virtual fd: {}", path_str, fd); + debug!("{}", path_str); + return fd as _; +} + +/// close +pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall6 (close vfs) {}", _which); + let fd: i32 = varargs.get(ctx); + debug!("closing virtual fd {}...", fd); + + // let emscripten_data = crate::env::get_emscripten_data(ctx); + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(fd); + + match vfs.fd_map.get(&vfd) { + Some(VirtualFile(handle)) => { + vfs.vfs.close(handle).unwrap(); + vfs.fd_map.remove(&vfd); + 0 + } + Some(Socket(host_fd)) => unsafe { + let result = libc::close(*host_fd); + if result == 0 { + vfs.fd_map.remove(&vfd); + 0 + } else { + -1 + } + }, + _ => -1, + } +} + +/// chmod +pub fn ___syscall15(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { + debug!("emscripten::___syscall15 (chmod)"); + debug!("chmod always returns 0."); + 0 +} + +// mkdir +pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall39 (mkdir vfs) {}", _which); + let pathname: u32 = varargs.get(ctx); + let _mode: u32 = varargs.get(ctx); + let path = read_string_from_wasm(ctx.memory(0), pathname); + let root = std::path::PathBuf::from("/"); + let absolute_path = root.join(&path); + // debug!("mkdir: {}", absolute_path.display()); + let emscripten_data = crate::env::get_emscripten_data(ctx); + let ret = if let Some(vfs) = &mut emscripten_data.vfs { + match vfs.vfs.make_dir(&absolute_path) { + Ok(_) => 0, + Err(_) => -1, + } + } else { + -1 + }; + // debug!("mkdir returns {}", ret); + ret +} + +/// pipe +pub fn ___syscall42(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall42 (pipe)"); + // offset to a file descriptor, which contains a read end and write end, 2 integers + let fd_offset: u32 = varargs.get(ctx); + + let emscripten_memory = ctx.memory(0); + + // convert the file descriptor into a vec with two slots + let mut fd_vec: Vec = emscripten_memory.view()[((fd_offset / 4) as usize)..] + .iter() + .map(|pipe_end: &std::cell::Cell| pipe_end.get()) + .take(2) + .collect(); + + // get it as a mutable pointer + let fd_ptr = fd_vec.as_mut_ptr(); + + // call pipe and store the pointers in this array + #[cfg(target_os = "windows")] + let result: c_int = unsafe { libc::pipe(fd_ptr, 2048, 0) }; + #[cfg(not(target_os = "windows"))] + let result: c_int = unsafe { libc::pipe(fd_ptr) }; + result +} + +/// ioctl +pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall54 (ioctl) {}", _which); + let fd: i32 = varargs.get(ctx); + let request: u32 = varargs.get(ctx); + debug!("virtual fd: {}, op: {}", fd, request); + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(fd); + + let host_fd = match vfs.fd_map.get(&vfd) { + Some(Socket(host_fd)) => *host_fd, + Some(_) => 0, + _ => panic!("Should not ioctl on a vbox file."), + }; + + // Got the equivalents here: https://code.woboq.org/linux/linux/include/uapi/asm-generic/ioctls.h.html + match request as _ { + 21537 => { + // FIONBIO + let argp: u32 = varargs.get(ctx); + let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void; + let ret = unsafe { libc::ioctl(host_fd, libc::FIONBIO, argp_ptr) }; + debug!("ret(FIONBIO): {}", ret); + ret + // 0 + } + 21523 => { + // TIOCGWINSZ + let argp: u32 = varargs.get(ctx); + let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void; + let ret = unsafe { libc::ioctl(host_fd, libc::TIOCGWINSZ, argp_ptr) }; + debug!("ret(TIOCGWINSZ): {} (harcoded to 0)", ret); + // ret + // TODO: We hardcode the value to have emscripten tests pass, as for some reason + // when the capturer is active, ioctl returns -1 instead of 0 + if ret == -1 { + 0 + } else { + ret + } + } + _ => { + debug!( + "emscripten::___syscall54 -> non implemented case {}", + request + ); + 0 + } + } +} + +/// dup2 +pub fn ___syscall63(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall63 (dup2) {}", _which); + + let src: i32 = varargs.get(ctx); + let dst: i32 = varargs.get(ctx); + + let src = VirtualFd(src); + let dst = VirtualFd(dst); + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + + // if the src is a valid file descriptor, then continue + if !vfs.fd_map.contains_key(&src) { + return -1; + } + // if src and dst are identical, do nothing + if src == dst { + return 0; + } + // test if the destination needs to closed first, if so, close it atomically (or fake it) + if vfs.fd_map.contains_key(&dst) { + vfs.close(&dst); + } + + let dst_file_handle = match vfs.fd_map.get(&src) { + Some(FileHandle::VirtualFile(handle)) => { + let new_handle: i32 = vfs.vfs.duplicate_handle(handle); + FileHandle::VirtualFile(new_handle) + } + Some(FileHandle::Socket(src_host_fd)) => unsafe { + // get a dst file descriptor, or just use the underlying dup syscall + let dst_host_fd = libc::dup(*src_host_fd); + if dst_host_fd == -1 { + panic!() + } + FileHandle::Socket(dst_host_fd) + }, + None => panic!(), + }; + + vfs.fd_map.insert(dst.clone(), dst_file_handle); + + let dst = dst.0; + + debug!("emscripten::___syscall63 (dup2) returns {}", dst); + + dst +} + +/// pread +pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall180 (pread) {}", _which); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: i32 = varargs.get(ctx); + let offset: i32/*i64*/ = varargs.get(ctx); + // debug!( + // "=> fd: {}, buf_offset: {}, count: {}, offset: {}", + // fd, buf, count, offset + // ); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut u8; + let buf_slice = unsafe { slice::from_raw_parts_mut(buf_addr, count as _) }; + let mut buf_slice_with_offset: &mut [u8] = &mut buf_slice[(offset as usize)..]; + + // let emscripten_data = crate::env::get_emscripten_data(ctx); + // let ret = match &mut emscripten_data.vfs { + // Some(vfs) => vfs.vfs.read_file(fd as _, &mut buf_slice_with_offset).unwrap(), + // None => 0, + // }; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(fd); + let virtual_file_handle = vfs.get_virtual_file_handle(vfd).unwrap(); + let ret = vfs + .vfs + .read_file(virtual_file_handle as _, &mut buf_slice_with_offset) + .unwrap(); + + // debug!("=> pread returns: {}", ret); + ret as _ +} + +/// pwrite +pub fn ___syscall181(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall181 (pwrite) {}", _which); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: u32 = varargs.get(ctx); + let offset: i32 = varargs.get(ctx); + + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf); + + let buf_slice = unsafe { slice::from_raw_parts_mut(buf_addr, count as _) }; + + // let emscripten_data = crate::env::get_emscripten_data(ctx); + // let count = if let Some(vfs) = &mut emscripten_data.vfs { + // vfs.vfs.write_file(fd as _, buf_slice, count as _, offset as _) + // .unwrap() + // } else { + // 0 + // }; + + let vfd = VirtualFd(fd); + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let virtual_file_handle = vfs.get_virtual_file_handle(vfd).unwrap(); + vfs.vfs + .write_file(virtual_file_handle as _, buf_slice, count as _, offset as _) + .unwrap(); + + count as _ +} + +// stat64 +#[cfg(feature = "vfs")] +pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall195 (stat64) {}", _which); + let pathname: u32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let path_string = read_string_from_wasm(ctx.memory(0), pathname); + debug!("path extract for `stat` syscall: {}", &path_string); + let path = std::path::PathBuf::from(path_string); + + let emscripten_data = crate::env::get_emscripten_data(ctx); + let ret = match &mut emscripten_data.vfs { + Some(vfs) => { + let metadata = vfs.vfs.get_path_metadata(&path).unwrap(); + let len = metadata.len(); + unsafe { + let mut stat: stat = std::mem::zeroed(); + stat.st_size = len as _; + debug!("stat size: {}", len); + copy_stat_into_wasm(ctx, buf, &stat as _); + } + 0 + } + None => -1, + }; + debug!("stat return: {}", ret); + ret +} + +/// fstat64 +pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall197 (fstat64) {}", _which); + let fd: c_int = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(fd); + let ret = match vfs.fd_map.get(&vfd) { + Some(FileHandle::VirtualFile(internal_handle)) => { + let metadata = vfs.vfs.get_file_metadata(internal_handle).unwrap(); + let len = metadata.len; + let mode = if metadata.is_file { + libc::S_IFREG + } else { + libc::S_IFDIR + }; + unsafe { + let mut stat: stat = std::mem::zeroed(); + stat.st_mode = mode as _; + stat.st_size = len as _; + debug!("fstat size: {}", len); + copy_stat_into_wasm(ctx, buf, &stat as _); + } + 0 + } + Some(FileHandle::Socket(_host_fd)) => panic!(), + None => -1, + }; + debug!("fstat return: {}", ret); + ret +} + +// getgid +//pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { +// debug!("emscripten::___syscall201 (getgid)"); +// 0 +//} + +// socketcall +#[allow(clippy::cast_ptr_alignment)] +pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall102 (socketcall) {}", _which); + let call: u32 = varargs.get(ctx); + let mut socket_varargs: VarArgs = varargs.get(ctx); + + #[cfg(target_os = "windows")] + type libc_sa_family_t = u16; + #[cfg(not(target_os = "windows"))] + type libc_sa_family_t = libc::sa_family_t; + + #[cfg(target_os = "windows")] + type libc_in_port_t = u16; + #[cfg(not(target_os = "windows"))] + type libc_in_port_t = libc::in_port_t; + + #[cfg(target_os = "windows")] + type libc_in_addr_t = u32; + #[cfg(not(target_os = "windows"))] + type libc_in_addr_t = libc::in_addr_t; + + #[repr(C)] + pub struct GuestSockaddrIn { + pub sin_family: libc_sa_family_t, // u16 + pub sin_port: libc_in_port_t, // u16 + pub sin_addr: GuestInAddr, // u32 + pub sin_zero: [u8; 8], // u8 * 8 + // 2 + 2 + 4 + 8 = 16 + } + + #[repr(C)] + pub struct GuestInAddr { + pub s_addr: libc_in_addr_t, // u32 + } + + pub struct LinuxSockAddr { + pub sa_family: u16, + pub sa_data: [libc::c_char; 14], + } + + match call { + 1 => { + debug!("socket: socket"); + // socket (domain: c_int, ty: c_int, protocol: c_int) -> c_int + let domain: i32 = socket_varargs.get(ctx); + let ty: i32 = socket_varargs.get(ctx); + let protocol: i32 = socket_varargs.get(ctx); + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + + let _test_errno = errno::errno(); + + // create the host socket + let host_fd = unsafe { libc::socket(domain, ty, protocol) }; + let vfd = vfs.new_socket_fd(host_fd); + + debug!("--- host fd from libc::socket: {} ---", host_fd); + debug!("--- reference fd in vfs from libc::socket: {} ---", vfd); + + // set_cloexec + let _ioctl_result = unsafe { libc::ioctl(host_fd, libc::FIOCLEX) }; + + use libc::{setsockopt, SOL_SOCKET}; + + let _err = errno::errno(); + + type T = u32; + let payload = 1 as *const T as _; + let _setsockopt_result = unsafe { + setsockopt( + host_fd, + SOL_SOCKET, + SO_NOSIGPIPE, + payload, + std::mem::size_of::() as libc::socklen_t, + ) + }; + + let _err2 = errno::errno(); + + debug!( + "=> domain: {} (AF_INET/2), type: {} (SOCK_STREAM/1), protocol: {} = fd: {}", + domain, ty, protocol, vfd + ); + + vfd.0 as _ + } + 2 => { + debug!("socket: bind"); + // bind (socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int + // TODO: Emscripten has a different signature. + let socket: i32 = socket_varargs.get(ctx); + let address: u32 = socket_varargs.get(ctx); + let address_len = socket_varargs.get(ctx); + let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut libc::sockaddr; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + // Debug received address + let _proper_address = address as *const GuestSockaddrIn; + let _other_proper_address = address as *const libc::sockaddr; + unsafe { + debug!( + "=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}", + (*_proper_address).sin_family, (*_proper_address).sin_port, (*_proper_address).sin_addr.s_addr + ); + } + let status = unsafe { libc::bind(host_socket_fd as _, address, address_len) }; + // debug!("=> status: {}", status); + debug!( + "=> socketfd: {}, address: {:?}, address_len: {} = status: {}", + socket, address, address_len, status + ); + status + // -1 + } + 3 => { + debug!("socket: connect"); + // connect (socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int + // TODO: Emscripten has a different signature. + let socket: i32 = socket_varargs.get(ctx); + let address: u32 = socket_varargs.get(ctx); + let address_len = socket_varargs.get(ctx); + let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut libc::sockaddr; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + unsafe { libc::connect(host_socket_fd as _, address, address_len) } + } + 4 => { + debug!("socket: listen"); + // listen (socket: c_int, backlog: c_int) -> c_int + let socket: i32 = socket_varargs.get(ctx); + let backlog: i32 = socket_varargs.get(ctx); + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + let status = unsafe { libc::listen(host_socket_fd, backlog) }; + debug!( + "=> socketfd: {}, backlog: {} = status: {}", + socket, backlog, status + ); + status + } + 5 => { + debug!("socket: accept"); + let socket: i32 = socket_varargs.get(ctx); + let address_addr: u32 = socket_varargs.get(ctx); + let address_len: u32 = socket_varargs.get(ctx); + let address = + emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut libc::sockaddr; + let address_len_addr = + emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut libc::socklen_t; + + let host_socket_fd = { + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + host_socket_fd + }; + + debug!( + "=> socket: {}(host {}), address: {:?}, address_len: {}", + socket, host_socket_fd, address, address_len + ); + + let new_accept_host_fd = + unsafe { libc::accept(host_socket_fd, address, address_len_addr) }; + + unsafe { + let address_linux = + emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut LinuxSockAddr; + (*address_linux).sa_family = (*address).sa_family as u16; + (*address_linux).sa_data = (*address).sa_data; + }; + + // set_cloexec + let _ioctl_result = unsafe { libc::ioctl(new_accept_host_fd, libc::FIOCLEX) }; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let new_vfd = vfs.new_socket_fd(new_accept_host_fd); + + debug!("new accept fd: {}(host {})", new_vfd.0, new_accept_host_fd); + + new_vfd.0 as _ + } + 6 => { + debug!("socket: getsockname"); + // getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int + let socket: i32 = socket_varargs.get(ctx); + let address: u32 = socket_varargs.get(ctx); + let address_len: u32 = socket_varargs.get(ctx); + let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut libc::sockaddr; + let address_len_addr = + emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut libc::socklen_t; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + unsafe { libc::getsockname(host_socket_fd as _, address, address_len_addr) } + } + 7 => { + debug!("socket: getpeername"); + // getpeername (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int + let socket: i32 = socket_varargs.get(ctx); + let address: u32 = socket_varargs.get(ctx); + let address_len: u32 = socket_varargs.get(ctx); + let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut libc::sockaddr; + let address_len_addr = + emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut libc::socklen_t; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + unsafe { libc::getpeername(host_socket_fd as _, address, address_len_addr) } + } + 11 => { + debug!("socket: sendto"); + // sendto (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t + let socket: i32 = socket_varargs.get(ctx); + let buf: u32 = socket_varargs.get(ctx); + let flags = socket_varargs.get(ctx); + let len: i32 = socket_varargs.get(ctx); + let address: u32 = socket_varargs.get(ctx); + let address_len = socket_varargs.get(ctx); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as _; + let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut libc::sockaddr; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + unsafe { + libc::sendto( + host_socket_fd as _, + buf_addr, + flags, + len, + address, + address_len, + ) as i32 + } + } + 12 => { + debug!("socket: recvfrom"); + // recvfrom (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t + let socket: i32 = socket_varargs.get(ctx); + let buf: u32 = socket_varargs.get(ctx); + let len: i32 = socket_varargs.get(ctx); + let flags = socket_varargs.get(ctx); + let address: u32 = socket_varargs.get(ctx); + let address_len: u32 = socket_varargs.get(ctx); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as _; + let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut libc::sockaddr; + let address_len_addr = + emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut libc::socklen_t; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + unsafe { + libc::recvfrom( + host_socket_fd, + buf_addr, + flags, + len, + address, + address_len_addr, + ) as i32 + } + } + 14 => { + debug!("socket: setsockopt"); + // NOTE: Emscripten seems to be passing the wrong values to this syscall + // level: Em passes 1 as SOL_SOCKET; SOL_SOCKET is 0xffff in BSD + // name: Em passes SO_ACCEPTCONN, but Nginx complains about REUSEADDR + // https://github.com/openbsd/src/blob/master/sys/sys/socket.h#L156 + // setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int + + let socket = socket_varargs.get(ctx); + // SOL_SOCKET = 0xffff (BSD, Linux) + let level: i32 = libc::SOL_SOCKET; + // SO_REUSEADDR = 0x4 (BSD, Linux) + let name: i32 = libc::SO_REUSEADDR; + let _: u32 = socket_varargs.get(ctx); + let value: u32 = socket_varargs.get(ctx); + let option_len = socket_varargs.get(ctx); + let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; // Endian problem + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + let ret = unsafe { + libc::setsockopt(host_socket_fd as _, level, name, value_addr, option_len) + }; + + debug!("=> socketfd: {}, level: {} (SOL_SOCKET/0xffff), name: {} (SO_REUSEADDR/4), value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret); + ret + } + 15 => { + debug!("socket: getsockopt"); + // getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int + use libc::socklen_t; + let socket = socket_varargs.get(ctx); + let level: i32 = socket_varargs.get(ctx); + let name: i32 = socket_varargs.get(ctx); + let value: u32 = socket_varargs.get(ctx); + let option_len: u32 = socket_varargs.get(ctx); + let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; + let option_len_addr = + emscripten_memory_pointer!(ctx.memory(0), option_len) as *mut socklen_t; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + let result = unsafe { + libc::getsockopt(host_socket_fd, level, name, value_addr, option_len_addr) + }; + + if result == -1 { + let err = errno::errno(); + debug!("socket: getsockopt -- error -- {}", err); + } + + result + } + 16 => { + debug!("socket: sendmsg"); + // sendmsg (fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t + let socket: i32 = socket_varargs.get(ctx); + let msg: u32 = socket_varargs.get(ctx); + let flags: i32 = socket_varargs.get(ctx); + let msg_addr = emscripten_memory_pointer!(ctx.memory(0), msg) as *const libc::msghdr; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + unsafe { libc::sendmsg(host_socket_fd as _, msg_addr, flags) as i32 } + } + 17 => { + debug!("socket: recvmsg"); + // recvmsg (fd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t + let socket: i32 = socket_varargs.get(ctx); + let msg: u32 = socket_varargs.get(ctx); + let flags: i32 = socket_varargs.get(ctx); + let msg_addr = emscripten_memory_pointer!(ctx.memory(0), msg) as *mut libc::msghdr; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfd = VirtualFd(socket); + let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); + + unsafe { libc::recvmsg(host_socket_fd as _, msg_addr, flags) as i32 } + } + _ => { + // others + -1 + } + } +} + +/// select +#[allow(clippy::cast_ptr_alignment)] +pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall142 (newselect) {}", _which); + + let nfds: i32 = varargs.get(ctx); + let readfds: u32 = varargs.get(ctx); + let writefds: u32 = varargs.get(ctx); + let _exceptfds: u32 = varargs.get(ctx); + let timeout: i32 = varargs.get(ctx); + + assert!(nfds <= 64, "`nfds` must be less than or equal to 64"); + // assert_eq!(exceptfds, 0, "`exceptfds` is not supporrted"); + + let readfds_set_ptr = emscripten_memory_pointer!(ctx.memory(0), readfds) as *mut _; + let readfds_set_u8_ptr = readfds_set_ptr as *mut u8; + let writefds_set_ptr = emscripten_memory_pointer!(ctx.memory(0), writefds) as *mut _; + let writefds_set_u8_ptr = writefds_set_ptr as *mut u8; + + let nfds = nfds as _; + let readfds_slice = unsafe { slice::from_raw_parts_mut(readfds_set_u8_ptr, nfds) }; + let _writefds_slice = unsafe { slice::from_raw_parts_mut(writefds_set_u8_ptr, nfds) }; + + use bit_field::BitArray; + + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + + let mut file_descriptors_to_watch = vec![]; + for virtual_fd in 0..nfds { + let bit_flag = readfds_slice.get_bit(virtual_fd as usize); + if !bit_flag { + continue; + } + file_descriptors_to_watch.push(virtual_fd); + } + + let mut count = 0; + let mut max = -1; + + let mut read_mappings = vec![]; + + for virtual_fd in 0..nfds { + let bit_flag = readfds_slice.get_bit(virtual_fd); + if !bit_flag { + continue; + } + let virtual_file = vfs.fd_map.get(&VirtualFd(virtual_fd as _)); + match virtual_file { + Some(FileHandle::VirtualFile(_fd)) => { + count = count + 1; + } + Some(FileHandle::Socket(host_fd)) => { + count = count + 1; + let virtual_fd = virtual_fd as i32; + let fd = *host_fd; + if fd > max { + max = fd; + } + read_mappings.push((virtual_fd, fd)); + } + None => {} + }; + } + + for mapping in read_mappings.clone() { + let (virtual_fd, fd) = mapping; + unsafe { + libc::FD_CLR(virtual_fd, readfds_set_ptr); + libc::FD_SET(fd, readfds_set_ptr); + } + } + + // #[repr(C)] + // pub struct timeval { + // pub tv_sec: libc::c_long, // time t + // pub tv_usec: libc::c_long, // long int + // } + + let timeval_ptr = emscripten_memory_pointer!(ctx.memory(0), timeout) as *mut libc::timeval; + let mut tval = unsafe { + libc::timeval { + tv_sec: (*timeval_ptr).tv_sec, + tv_usec: (*timeval_ptr).tv_usec, + } + }; + let _tval_ptr: *mut libc::timeval = &mut tval; + + let sz = max as i32 + 1; + // let result = unsafe { libc::select(sz, readfds_set_ptr, writefds_set_ptr, 0 as _, timeval_ptr as *mut libc::timeval) }; + let result = unsafe { libc::select(sz, readfds_set_ptr, writefds_set_ptr, 0 as _, 0 as _) }; + + assert!(nfds <= 64, "`nfds` must be less than or equal to 64"); + // assert!(exceptfds == 0, "`exceptfds` is not supporrted"); + + let err = errno::errno(); + debug!("gah again: {}", err); + + // let len = read_mappings.len(); + + for mapping in read_mappings { + let (virtual_fd, fd) = mapping; + unsafe { + libc::FD_CLR(fd, readfds_set_ptr); + libc::FD_SET(virtual_fd, readfds_set_ptr); + } + } + + for input in file_descriptors_to_watch { + unsafe { + let in_set = libc::FD_ISSET(input as _, readfds_set_ptr); + assert!(in_set); + } + } + + result +} + +// chown +pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall212 (chown) {}", _which); + let _pathname: u32 = varargs.get(ctx); + let _owner: u32 = varargs.get(ctx); + let _group: u32 = varargs.get(ctx); + debug!("syscall `chown` always returns 0"); + 0 +} diff --git a/lib/emscripten/src/syscalls/windows/host_fs.rs b/lib/emscripten/src/syscalls/windows/host_fs.rs new file mode 100644 index 000000000..f4cc6a8bb --- /dev/null +++ b/lib/emscripten/src/syscalls/windows/host_fs.rs @@ -0,0 +1,35 @@ +/// read +#[cfg(not(feature = "vfs"))] +pub fn ___syscall3(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { + // -> ssize_t + debug!("emscripten::___syscall3 (read) {}", _which); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: i32 = varargs.get(ctx); + debug!("=> fd: {}, buf_offset: {}, count: {}", fd, buf, count); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *mut c_void; + let ret = unsafe { libc::read(fd, buf_addr, count as _) }; + debug!("=> ret: {}", ret); + ret as _ +} + +/// write +#[cfg(not(feature = "vfs"))] +pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall4 (write) {}", _which); + let fd: i32 = varargs.get(ctx); + let buf: u32 = varargs.get(ctx); + let count: i32 = varargs.get(ctx); + debug!("=> fd: {}, buf: {}, count: {}", fd, buf, count); + let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as *const c_void; + unsafe { write(fd, buf_addr, count as _) as i32 } +} + +/// close +#[cfg(not(feature = "vfs"))] +pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall6 (close) {}", _which); + let fd: i32 = varargs.get(ctx); + debug!("fd: {}", fd); + unsafe { libc::close(fd) } +} diff --git a/lib/emscripten/src/syscalls/windows.rs b/lib/emscripten/src/syscalls/windows/mod.rs similarity index 96% rename from lib/emscripten/src/syscalls/windows.rs rename to lib/emscripten/src/syscalls/windows/mod.rs index d672f2cce..29612d915 100644 --- a/lib/emscripten/src/syscalls/windows.rs +++ b/lib/emscripten/src/syscalls/windows/mod.rs @@ -1,3 +1,15 @@ +#[cfg(not(feature = "vfs"))] +pub mod host_fs; + +#[cfg(feature = "vfs")] +pub mod vfs; + +#[cfg(not(feature = "vfs"))] +pub use host_fs::*; + +#[cfg(feature = "vfs")] +pub use vfs::*; + use crate::env::get_emscripten_data; use crate::utils::copy_cstr_into_wasm; use crate::varargs::VarArgs; diff --git a/lib/emscripten/src/syscalls/vfs.rs b/lib/emscripten/src/syscalls/windows/vfs.rs similarity index 95% rename from lib/emscripten/src/syscalls/vfs.rs rename to lib/emscripten/src/syscalls/windows/vfs.rs index 3ddbaa7e2..d91935b52 100644 --- a/lib/emscripten/src/syscalls/vfs.rs +++ b/lib/emscripten/src/syscalls/windows/vfs.rs @@ -1,18 +1,15 @@ -use crate::emscripten_set_up_memory; -use crate::env::get_emscripten_data; -use crate::syscalls::emscripten_vfs::FileHandle::{Socket, VirtualFile}; -use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd}; use crate::utils::{copy_stat_into_wasm, read_string_from_wasm}; use crate::varargs::VarArgs; use libc::stat; use std::os::raw::c_int; use std::slice; -use wasmer_runtime_abi::vfs::vfs::Fd; use wasmer_runtime_core::vm::Ctx; // Another conditional constant for name resolution: Macos et iOS use // SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. // Other platforms do otherwise. +use crate::syscalls::emscripten_vfs::FileHandle::{Socket, VirtualFile}; +use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd}; #[cfg(target_os = "darwin")] use libc::SO_NOSIGPIPE; use std::ffi::c_void; @@ -106,7 +103,7 @@ pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int debug!("closing virtual fd {}...", fd); // let emscripten_data = crate::env::get_emscripten_data(ctx); - let mut vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); + let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); let vfd = VirtualFd(fd); match vfs.fd_map.get(&vfd) { @@ -376,7 +373,7 @@ pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in } 0 } - Some(FileHandle::Socket(host_fd)) => panic!(), + Some(FileHandle::Socket(_host_fd)) => panic!(), None => -1, }; debug!("fstat return: {}", ret); @@ -440,7 +437,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); - let test_errno = errno::errno(); + let _test_errno = errno::errno(); // create the host socket let host_fd = unsafe { libc::socket(domain, ty, protocol) }; @@ -450,15 +447,15 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in debug!("--- reference fd in vfs from libc::socket: {} ---", vfd); // set_cloexec - let ioctl_result = unsafe { libc::ioctl(host_fd, libc::FIOCLEX) }; + let _ioctl_result = unsafe { libc::ioctl(host_fd, libc::FIOCLEX) }; - use libc::{setsockopt, socklen_t, SOL_SOCKET}; + use libc::{setsockopt, SOL_SOCKET}; - let err = errno::errno(); + let _err = errno::errno(); type T = u32; let payload = 1 as *const T as _; - let setsockopt_result = unsafe { + let _setsockopt_result = unsafe { setsockopt( host_fd, SOL_SOCKET, @@ -468,7 +465,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in ) }; - let err2 = errno::errno(); + let _err2 = errno::errno(); debug!( "=> domain: {} (AF_INET/2), type: {} (SOCK_STREAM/1), protocol: {} = fd: {}", @@ -490,9 +487,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let vfd = VirtualFd(socket); let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); - let thinfy = libc::AF_INET; - let thinfy2 = libc::AF_UNIX; - // Debug received address let _proper_address = address as *const GuestSockaddrIn; let _other_proper_address = address as *const libc::sockaddr; @@ -501,7 +495,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in "=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}", (*_proper_address).sin_family, (*_proper_address).sin_port, (*_proper_address).sin_addr.s_addr ); - let ex = 10; } let status = unsafe { libc::bind(host_socket_fd as _, address, address_len) }; // debug!("=> status: {}", status); @@ -572,11 +565,10 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut LinuxSockAddr; (*address_linux).sa_family = (*address).sa_family as u16; (*address_linux).sa_data = (*address).sa_data; - let x = 10; }; // set_cloexec - let ioctl_result = unsafe { libc::ioctl(new_accept_host_fd, libc::FIOCLEX) }; + let _ioctl_result = unsafe { libc::ioctl(new_accept_host_fd, libc::FIOCLEX) }; let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); let new_vfd = vfs.new_socket_fd(new_accept_host_fd); @@ -597,7 +589,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); let vfd = VirtualFd(socket); - let socket_fd = vfs.fd_map.get(&vfd).unwrap(); let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); unsafe { libc::getsockname(host_socket_fd as _, address, address_len_addr) } @@ -685,7 +676,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let socket = socket_varargs.get(ctx); // SOL_SOCKET = 0xffff (BSD, Linux) let level: i32 = libc::SOL_SOCKET; - let x_level: u32 = socket_varargs.get(ctx); // SO_REUSEADDR = 0x4 (BSD, Linux) let name: i32 = libc::SO_REUSEADDR; let _: u32 = socket_varargs.get(ctx); @@ -701,8 +691,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in libc::setsockopt(host_socket_fd as _, level, name, value_addr, option_len) }; - let bf = unsafe { slice::from_raw_parts(value_addr as *const u8, option_len as _) }; - debug!("=> socketfd: {}, level: {} (SOL_SOCKET/0xffff), name: {} (SO_REUSEADDR/4), value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret); ret } @@ -790,7 +778,7 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let nfds = nfds as _; let readfds_slice = unsafe { slice::from_raw_parts_mut(readfds_set_u8_ptr, nfds) }; - let writefds_slice = unsafe { slice::from_raw_parts_mut(writefds_set_u8_ptr, nfds) }; + let _writefds_slice = unsafe { slice::from_raw_parts_mut(writefds_set_u8_ptr, nfds) }; use bit_field::BitArray; @@ -817,19 +805,17 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in } let virtual_file = vfs.fd_map.get(&VirtualFd(virtual_fd as _)); match virtual_file { - Some(FileHandle::VirtualFile(fd)) => { + Some(FileHandle::VirtualFile(_fd)) => { count = count + 1; } Some(FileHandle::Socket(host_fd)) => { count = count + 1; - unsafe { - let virtual_fd = virtual_fd as i32; - let fd = *host_fd; - if fd > max { - max = fd; - } - read_mappings.push((virtual_fd, fd)); - }; + let virtual_fd = virtual_fd as i32; + let fd = *host_fd; + if fd > max { + max = fd; + } + read_mappings.push((virtual_fd, fd)); } None => {} }; @@ -856,7 +842,7 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in tv_usec: (*timeval_ptr).tv_usec, } }; - let mut tval_ptr: *mut libc::timeval = &mut tval; + let _tval_ptr: *mut libc::timeval = &mut tval; let sz = max as i32 + 1; // let result = unsafe { libc::select(sz, readfds_set_ptr, writefds_set_ptr, 0 as _, timeval_ptr as *mut libc::timeval) }; diff --git a/lib/runtime-abi/src/vfs/device_file.rs b/lib/runtime-abi/src/vfs/device_file.rs index 334e8e959..4d7579f95 100644 --- a/lib/runtime-abi/src/vfs/device_file.rs +++ b/lib/runtime-abi/src/vfs/device_file.rs @@ -6,7 +6,7 @@ pub struct Stdout; pub struct Stderr; impl FileLike for Stdin { - fn write(&mut self, buf: &[u8], _count: usize, _offset: usize) -> Result { + fn write(&mut self, _buf: &[u8], _count: usize, _offset: usize) -> Result { unimplemented!() } @@ -22,31 +22,3 @@ impl FileLike for Stdin { unimplemented!() } } - -//impl FileLike for Stdout { -// fn read(&mut self, buf: &mut [u8]) -> Result { -// unimplemented!() -// } -// -// fn close(self) -> Result<(), Error> { -// unimplemented!() -// } -// -// fn metadata(&self) -> Result { -// unimplemented!() -// } -//} -// -//impl FileLike for Stderr { -// fn read(&mut self, buf: &mut [u8]) -> Result { -// unimplemented!() -// } -// -// fn close(self) -> Result<(), Error> { -// unimplemented!() -// } -// -// fn metadata(&self) -> Result { -// unimplemented!() -// } -//} diff --git a/lib/runtime-abi/src/vfs/vfs.rs b/lib/runtime-abi/src/vfs/vfs.rs index 6a4344975..e6db09d41 100644 --- a/lib/runtime-abi/src/vfs/vfs.rs +++ b/lib/runtime-abi/src/vfs/vfs.rs @@ -46,22 +46,22 @@ impl Vfs { // TODO: What to do about the creation of the device files? let _ = repo.create_dir(PathBuf::from("/dev/")); - let stdin = repo.create_file(PathBuf::from("/dev/stdin"))?; - let stdout = repo.create_file(PathBuf::from("/dev/stdout"))?; - let stderr = repo.create_file(PathBuf::from("/dev/stderr"))?; + let _stdin = repo.create_file(PathBuf::from("/dev/stdin"))?; + let _stdout = repo.create_file(PathBuf::from("/dev/stdout"))?; + let _stderr = repo.create_file(PathBuf::from("/dev/stderr"))?; use crate::vfs::device_file; fd_map.insert(0, Rc::new(device_file::Stdin {})); fd_map.insert(1, Rc::new(device_file::Stdin {})); // TODO FIX ME fd_map.insert(2, Rc::new(device_file::Stdin {})); - let errors = tar::Archive::new(tar_bytes) + let _errors = tar::Archive::new(tar_bytes) .entries()? .map(|entry| { let mut entry: tar::Entry = entry?; let path = entry.path()?; let path = convert_to_absolute_path(path); - let result = match (entry.header().entry_type(), path.parent()) { + let _result = match (entry.header().entry_type(), path.parent()) { (EntryType::Regular, Some(parent)) => { if let Err(e) = repo.create_dir_all(parent) { if e == zbox::Error::AlreadyExists || e == zbox::Error::IsRoot { @@ -91,6 +91,8 @@ impl Vfs { }) .collect::>>(); + // let import_errors = errors.iter().filter_map(|e| e.err()).collect::>(); + let vfs = Vfs { repo, fd_map, @@ -242,10 +244,9 @@ impl Vfs { .ok_or(VfsError::FileWithFileDescriptorNotExist(fd))?; let file = Rc::get_mut(&mut file); match file { - Some(file) => file.write(buf, count, offset), - None => Ok(count) // BAD!!! Switch to Rc + Some(file) => file.write(buf, count, offset), + None => Ok(count), // BAD!!! Switch to Rc } - } }