Files
wasmer/lib/emscripten/src/syscalls/unix/host_fs.rs

607 lines
23 KiB
Rust
Raw Normal View History

use crate::utils::{copy_stat_into_wasm, read_string_from_wasm};
use crate::varargs::VarArgs;
2019-03-21 11:54:55 -07:00
use libc::{c_int, c_void, ioctl, sockaddr, socklen_t};
use std::slice;
2019-01-23 01:27:13 -06:00
use wasmer_runtime_core::vm::Ctx;
/// read
pub fn ___syscall3(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
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
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
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);
let flags: i32 = varargs.get(ctx);
let mode: u32 = varargs.get(ctx);
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
let _path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
2019-03-13 14:22:32 -07:00
let fd = unsafe { libc::open(pathname_addr, flags, mode) };
debug!(
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}",
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
pathname, flags, mode, fd, _path_str
);
fd
}
/// 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
}
/// mkdir
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall39 (mkdir) {}", _which);
2019-01-24 13:04:12 -08:00
let pathname: u32 = varargs.get(ctx);
let mode: u32 = varargs.get(ctx);
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
2019-03-21 08:55:23 -07:00
unsafe { libc::mkdir(pathname_addr, mode as _) }
2018-11-22 18:00:05 +01:00
}
/// 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<c_int> = emscripten_memory.view()[((fd_offset / 4) as usize)..]
.iter()
.map(|pipe_end: &std::cell::Cell<c_int>| 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
}
2018-11-28 01:47:46 +01:00
/// ioctl
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall54 (ioctl) {}", _which);
2019-01-24 13:04:12 -08:00
let fd: i32 = varargs.get(ctx);
let request: u32 = varargs.get(ctx);
2018-11-29 00:11:36 -05:00
debug!("fd: {}, op: {}", fd, request);
// Got the equivalents here: https://code.woboq.org/linux/linux/include/uapi/asm-generic/ioctls.h.html
2018-11-29 00:11:36 -05:00
match request as _ {
2018-12-15 00:46:11 -06:00
21537 => {
// FIONBIO
2019-01-24 13:04:12 -08:00
let argp: u32 = varargs.get(ctx);
let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void;
2019-03-21 11:54:55 -07:00
let ret = unsafe { ioctl(fd, libc::FIONBIO, argp_ptr) };
2018-12-10 18:42:23 -08:00
debug!("ret(FIONBIO): {}", ret);
2018-11-29 15:48:47 -05:00
ret
2018-12-10 18:42:23 -08:00
// 0
2018-12-15 00:46:11 -06:00
}
21523 => {
// TIOCGWINSZ
2019-01-24 13:04:12 -08:00
let argp: u32 = varargs.get(ctx);
let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void;
2019-03-21 11:54:55 -07:00
let ret = unsafe { ioctl(fd, libc::TIOCGWINSZ, argp_ptr) };
2018-12-10 18:42:23 -08:00
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
2018-12-15 00:46:11 -06:00
} else {
2018-12-10 18:42:23 -08:00
ret
}
2018-12-15 00:46:11 -06:00
}
_ => {
2018-12-15 00:46:11 -06:00
debug!(
"emscripten::___syscall54 -> non implemented case {}",
request
);
0
}
2018-11-29 00:11:36 -05:00
}
2018-11-24 15:55:21 +01:00
}
2019-03-21 12:12:58 -07:00
/// 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) }
}
2018-11-28 01:47:46 +01:00
// socketcall
2019-01-18 00:33:46 -06:00
#[allow(clippy::cast_ptr_alignment)]
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall102 (socketcall) {}", _which);
2019-01-24 13:04:12 -08:00
let call: u32 = varargs.get(ctx);
let mut socket_varargs: VarArgs = varargs.get(ctx);
2018-11-27 15:19:10 +01:00
#[repr(C)]
pub struct GuestSockaddrIn {
2019-03-21 11:54:55 -07:00
pub sin_family: libc::sa_family_t,
// u16
2019-03-21 11:05:29 -07:00
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
}
2018-11-27 15:19:10 +01:00
#[repr(C)]
pub struct GuestInAddr {
2019-03-21 11:05:29 -07:00
pub s_addr: libc::in_addr_t, // u32
}
2018-11-27 15:19:10 +01:00
// debug!("GuestSockaddrIn = {}", size_of::<GuestSockaddrIn>());
2018-12-05 16:16:17 -08:00
pub struct LinuxSockAddr {
pub sa_family: u16,
2019-03-21 11:00:49 -07:00
pub sa_data: [libc::c_char; 14],
2018-12-05 16:16:17 -08:00
}
2018-11-24 15:55:21 +01:00
match call {
2018-11-26 20:29:26 -08:00
1 => {
2018-11-28 01:47:46 +01:00
debug!("socket: socket");
2019-03-21 11:00:49 -07:00
// 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;
2018-11-26 20:29:26 -08:00
// socket (domain: c_int, ty: c_int, protocol: c_int) -> c_int
2019-01-24 13:04:12 -08:00
let domain: i32 = socket_varargs.get(ctx);
let ty: i32 = socket_varargs.get(ctx);
let protocol: i32 = socket_varargs.get(ctx);
2019-03-21 11:54:55 -07:00
let fd = unsafe { libc::socket(domain, ty, protocol) };
// set_cloexec
unsafe {
2019-03-21 11:54:55 -07:00
ioctl(fd, libc::FIOCLEX);
};
2019-01-17 15:43:33 +01:00
let _err = errno::errno();
2019-03-21 11:00:49 -07:00
let _result =
2019-03-21 11:54:55 -07:00
unsafe { libc::setsockopt(fd, libc::SOL_SOCKET, SO_NOSIGPIPE, 0 as *const _, 4) };
let _err2 = errno::errno();
2019-03-21 08:55:23 -07:00
2018-11-28 13:25:56 -08:00
debug!(
"=> domain: {} (AF_INET/2), type: {} (SOCK_STREAM/1), protocol: {} = fd: {}",
domain, ty, protocol, fd
2018-11-28 13:25:56 -08:00
);
fd as _
2018-11-26 20:29:26 -08:00
}
2 => {
2018-11-28 01:47:46 +01:00
debug!("socket: bind");
2018-11-26 20:29:26 -08:00
// bind (socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int
2018-11-24 15:55:21 +01:00
// TODO: Emscripten has a different signature.
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let address: u32 = socket_varargs.get(ctx);
let address_len = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
2019-01-17 15:43:33 +01:00
// Debug received address
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
let _proper_address = address as *const GuestSockaddrIn;
debug!(
"=> address.sin_family: {:?}, address.sin_port: {:?}, address.sin_addr.s_addr: {:?}",
unsafe { (*_proper_address).sin_family }, unsafe { (*_proper_address).sin_port }, unsafe { (*_proper_address).sin_addr.s_addr }
);
2019-03-21 11:00:49 -07:00
let status = unsafe { libc::bind(socket, address, address_len) };
// debug!("=> status: {}", status);
2018-11-28 13:25:56 -08:00
debug!(
"=> socketfd: {}, address: {:?}, address_len: {} = status: {}",
socket, address, address_len, status
);
2018-11-27 15:19:10 +01:00
status
// -1
2018-11-26 20:29:26 -08:00
}
3 => {
2018-11-28 01:47:46 +01:00
debug!("socket: connect");
2018-11-26 20:29:26 -08:00
// connect (socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int
2018-11-24 15:55:21 +01:00
// TODO: Emscripten has a different signature.
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let address: u32 = socket_varargs.get(ctx);
let address_len = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
2019-03-21 11:54:55 -07:00
unsafe { libc::connect(socket, address, address_len) }
2018-11-26 20:29:26 -08:00
}
4 => {
2018-11-28 01:47:46 +01:00
debug!("socket: listen");
2018-11-26 20:29:26 -08:00
// listen (socket: c_int, backlog: c_int) -> c_int
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let backlog: i32 = socket_varargs.get(ctx);
2019-03-21 11:05:29 -07:00
let status = unsafe { libc::listen(socket, backlog) };
2018-11-28 13:25:56 -08:00
debug!(
"=> socketfd: {}, backlog: {} = status: {}",
socket, backlog, status
);
2018-11-27 15:19:10 +01:00
status
2018-11-26 20:29:26 -08:00
}
5 => {
2018-11-28 01:47:46 +01:00
debug!("socket: accept");
2018-11-26 20:29:26 -08:00
// accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
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 sockaddr;
2018-12-15 00:46:11 -06:00
debug!(
"=> socket: {}, address: {:?}, address_len: {}",
socket, address, address_len
);
2019-01-24 15:30:13 -08:00
let address_len_addr =
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
// let mut address_len_addr: socklen_t = 0;
2019-03-21 11:00:49 -07:00
let fd = unsafe { libc::accept(socket, address, address_len_addr) };
unsafe {
2019-01-24 15:30:13 -08:00
let address_linux =
emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut LinuxSockAddr;
2018-12-05 16:16:17 -08:00
(*address_linux).sa_family = (*address).sa_family as u16;
(*address_linux).sa_data = (*address).sa_data;
2019-03-21 08:55:23 -07:00
let _proper_address = address as *const GuestSockaddrIn;
let _x = 10;
2018-12-05 16:16:17 -08:00
};
2019-01-17 15:43:33 +01:00
// set_cloexec
unsafe {
2019-03-21 11:54:55 -07:00
ioctl(fd, libc::FIOCLEX);
};
2019-01-17 14:35:56 +01:00
2018-11-29 15:48:47 -05:00
debug!("fd: {}", fd);
2019-01-17 15:43:33 +01:00
fd as _
2018-11-26 20:29:26 -08:00
}
6 => {
2018-11-28 01:47:46 +01:00
debug!("socket: getsockname");
2018-11-26 20:29:26 -08:00
// getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
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 sockaddr;
2019-01-24 15:30:13 -08:00
let address_len_addr =
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
2019-03-21 11:05:29 -07:00
unsafe { libc::getsockname(socket, address, address_len_addr) }
2018-11-26 20:29:26 -08:00
}
7 => {
2018-11-28 01:47:46 +01:00
debug!("socket: getpeername");
2018-11-26 20:29:26 -08:00
// getpeername (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
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 sockaddr;
2019-01-24 15:30:13 -08:00
let address_len_addr =
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
2019-03-21 11:05:29 -07:00
unsafe { libc::getpeername(socket, address, address_len_addr) }
2018-11-26 20:29:26 -08:00
}
11 => {
2018-11-28 01:47:46 +01:00
debug!("socket: sendto");
2018-11-26 20:29:26 -08:00
// sendto (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let buf: u32 = socket_varargs.get(ctx);
let flags = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
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 _;
2019-01-24 13:04:12 -08:00
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
2019-03-21 11:54:55 -07:00
unsafe { libc::sendto(socket, buf_addr, flags, len, address, address_len) as i32 }
2018-11-26 20:29:26 -08:00
}
12 => {
2018-11-28 01:47:46 +01:00
debug!("socket: recvfrom");
2018-11-26 20:29:26 -08:00
// recvfrom (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let buf: u32 = socket_varargs.get(ctx);
let flags = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
let len: i32 = 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 _;
2019-01-24 13:04:12 -08:00
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
2019-01-24 15:30:13 -08:00
let address_len_addr =
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
2019-03-21 11:54:55 -07:00
unsafe {
libc::recvfrom(socket, buf_addr, flags, len, address, address_len_addr) as i32
}
2018-11-26 20:29:26 -08:00
}
14 => {
2018-11-28 01:47:46 +01:00
debug!("socket: setsockopt");
2018-11-27 15:19:10 +01:00
// 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
2018-11-26 20:29:26 -08:00
// setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int
2019-01-17 15:43:33 +01:00
let socket = socket_varargs.get(ctx);
2019-01-17 15:43:33 +01:00
// SOL_SOCKET = 0xffff (BSD, Linux)
2019-03-21 11:54:55 -07:00
let level: i32 = libc::SOL_SOCKET;
2019-01-24 13:04:12 -08:00
let _: u32 = socket_varargs.get(ctx);
2019-01-17 15:43:33 +01:00
// SO_REUSEADDR = 0x4 (BSD, Linux)
2019-03-21 11:54:55 -07:00
let name: i32 = libc::SO_REUSEADDR;
2019-01-24 13:04:12 -08:00
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
2019-03-21 11:54:55 -07:00
let ret = unsafe { libc::setsockopt(socket, level, name, value_addr, option_len) };
2018-11-27 15:19:10 +01:00
2018-11-28 01:47:46 +01:00
debug!("=> socketfd: {}, level: {} (SOL_SOCKET/0xffff), name: {} (SO_REUSEADDR/4), value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret);
2018-11-27 15:19:10 +01:00
ret
2018-11-26 20:29:26 -08:00
}
15 => {
2018-11-28 01:47:46 +01:00
debug!("socket: getsockopt");
2018-11-26 20:29:26 -08:00
// getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
2019-01-24 13:04:12 -08:00
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 _;
2019-01-24 15:30:13 -08:00
let option_len_addr =
emscripten_memory_pointer!(ctx.memory(0), option_len) as *mut socklen_t;
2019-03-21 11:54:55 -07:00
let result =
unsafe { libc::getsockopt(socket, level, name, value_addr, option_len_addr) };
2019-03-21 08:55:23 -07:00
result
2018-11-26 20:29:26 -08:00
}
16 => {
2018-11-28 01:47:46 +01:00
debug!("socket: sendmsg");
2018-11-26 20:29:26 -08:00
// sendmsg (fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t
2019-01-24 13:04:12 -08:00
let socket: i32 = socket_varargs.get(ctx);
let msg: u32 = socket_varargs.get(ctx);
let flags: i32 = socket_varargs.get(ctx);
2019-03-21 11:05:29 -07:00
let msg_addr = emscripten_memory_pointer!(ctx.memory(0), msg) as *const libc::msghdr;
2019-03-21 11:54:55 -07:00
unsafe { libc::sendmsg(socket, msg_addr, flags) as i32 }
2018-11-26 20:29:26 -08:00
}
17 => {
2018-11-28 01:47:46 +01:00
debug!("socket: recvmsg");
2018-11-26 20:29:26 -08:00
// recvmsg (fd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t
2019-01-24 13:04:12 -08:00
let socket: i32 = socket_varargs.get(ctx);
let msg: u32 = socket_varargs.get(ctx);
let flags: i32 = socket_varargs.get(ctx);
2019-03-21 11:05:29 -07:00
let msg_addr = emscripten_memory_pointer!(ctx.memory(0), msg) as *mut libc::msghdr;
2019-03-21 11:54:55 -07:00
unsafe { libc::recvmsg(socket, msg_addr, flags) as i32 }
2018-11-26 20:29:26 -08:00
}
_ => {
// others
2018-11-24 15:55:21 +01:00
-1
2018-11-26 20:29:26 -08:00
}
2018-11-24 15:55:21 +01:00
}
2018-11-21 20:58:32 -08:00
}
// select
#[allow(clippy::cast_ptr_alignment)]
fix(emscripten) Various warning fixes and cleanups (#266) * fix(emscripten) Remove unused imports. This patch removes unused imports reported by `rustc` as warnings. * fix(emscripten) Allow unreachable patterns in `_clock_gettime`. The compiler thinks `CLOCK_MONOTONIC_COARSE` is unreachable, which is not always the case. Add an attribute to allow unreachable patterns to remove the warning. * fix(emscripten) Rename unused variables. This patch renames various unused variables by appending an underscore to them. * fix(emscripten) Declare `table` as immutable. The `table` variable in `EmscriptenGlobals::new` was declared as mutable, but it's never mutated. * fix(emscripten) Remove an unnecessary `unsafe` block. * fix(emscripten) Remove duplicate definition of `SO_NOSIGPIPE`. The `SO_NOSIGPIPE` constant is defined in `syscalls/mod.rs` and `syscalls/unix.rs`. It's never used in the first case. We can safely remove it in this file, and keep it in `unix.rs`. * fix(emscripten) `read_string_from_wasm` is used only on Windows. Mark `read_string_from_wasm` as possible deadcode, since it's used only on Windows. * fix(emscripten) Remove `DYNAMICTOP_PTR_DIFF`, `stacktop`, `stack_max`, `dynamic_base` and `dynamic_ptr`. Four functions and one constant are used together but never used inside or outside this file. They are deadcode. * fix(emscripten) Remove `infinity` and `nan` fields of `EmscriptenGlobalsData`. Those fields are never used. * fix(emscripten) Allow non snake case in `emscripten_target.rs`. Many functions in this file don't follow the snake case style for Rust function names. The reason is that we want the names to match the emscripten symbol names; even if a mapping is done in `lib.rs`, it's easier to get the same names. * fix(emscripten) Rename `STATIC_TOP` to `static_top`. This variable is not a constant.
2019-03-12 22:00:33 +01:00
pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall142 (newselect) {}", _which);
2019-01-24 23:58:54 -06:00
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);
2019-01-24 23:58:54 -06:00
2019-03-21 08:55:23 -07:00
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) };
2019-03-21 08:55:23 -07:00
let nfds = nfds as _;
use bit_field::BitArray;
let mut bits = vec![];
for virtual_fd in 0..nfds {
let bit_flag = readfds_slice.get_bit(virtual_fd as usize);
if !bit_flag {
continue;
}
bits.push(virtual_fd);
}
2019-01-24 23:58:54 -06:00
let readfds_ptr = emscripten_memory_pointer!(ctx.memory(0), readfds) as _;
let writefds_ptr = emscripten_memory_pointer!(ctx.memory(0), writefds) as _;
2019-01-24 23:58:54 -06:00
let _err = errno::errno();
2019-03-21 08:55:23 -07:00
2019-03-21 11:54:55 -07:00
let result = unsafe { libc::select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) };
2019-03-21 08:55:23 -07:00
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);
2019-03-21 08:55:23 -07:00
result
}
2019-03-21 12:12:58 -07:00
// writev
#[allow(clippy::cast_ptr_alignment)]
pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
// -> ssize_t
debug!("emscripten::___syscall146 (writev) {}", _which);
let fd: i32 = varargs.get(ctx);
let iov: i32 = varargs.get(ctx);
let iovcnt: i32 = varargs.get(ctx);
#[repr(C)]
struct GuestIovec {
iov_base: i32,
iov_len: i32,
}
debug!("=> fd: {}, iov: {}, iovcnt = {}", fd, iov, iovcnt);
let mut ret = 0;
unsafe {
for i in 0..iovcnt {
let guest_iov_addr =
emscripten_memory_pointer!(ctx.memory(0), (iov + i * 8)) as *mut GuestIovec;
let iov_base = emscripten_memory_pointer!(ctx.memory(0), (*guest_iov_addr).iov_base)
as *const c_void;
let iov_len = (*guest_iov_addr).iov_len as _;
// debug!("=> iov_addr: {:?}, {:?}", iov_base, iov_len);
let curr = libc::write(fd, iov_base, iov_len);
if curr < 0 {
return -1;
}
ret += curr;
}
// debug!(" => ret: {}", ret);
ret as _
}
}
2019-03-21 11:00:49 -07:00
/// 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: u32 = varargs.get(ctx);
{
let zero: u32 = varargs.get(ctx);
assert_eq!(zero, 0);
}
let offset: i64 = varargs.get(ctx);
let buf_ptr = emscripten_memory_pointer!(ctx.memory(0), buf) as _;
let pread_result = unsafe { libc::pread(fd, buf_ptr, count as _, offset) as _ };
let _data_string = read_string_from_wasm(ctx.memory(0), buf);
pread_result
}
/// 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 zero: u32 = varargs.get(ctx);
assert_eq!(zero, 0);
}
let offset: i64 = varargs.get(ctx);
let buf_ptr = emscripten_memory_pointer!(ctx.memory(0), buf) as _;
let status = unsafe { libc::pwrite(fd, buf_ptr, count as _, offset) as _ };
debug!(
"=> fd: {}, buf: {}, count: {}, offset: {} = status:{}",
fd, buf, count, offset, status
);
status
}
/// stat64
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 pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
unsafe {
let mut _stat: libc::stat = std::mem::zeroed();
let ret = libc::stat(pathname_addr, &mut _stat);
debug!("ret: {}", ret);
if ret != 0 {
return ret;
}
copy_stat_into_wasm(ctx, buf, &_stat);
}
0
2019-01-24 23:58:54 -06:00
}
/// 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);
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
}
2019-03-21 11:00:49 -07:00
/// dup3
2019-03-21 11:54:55 -07:00
pub fn ___syscall330(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> libc::pid_t {
2019-03-21 11:00:49 -07:00
// 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 {
2019-03-21 11:54:55 -07:00
return libc::EINVAL;
2019-03-21 11:00:49 -07:00
}
let res = unsafe { libc::dup2(oldfd, newfd) };
// Set flags on newfd (https://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html)
2019-03-21 11:54:55 -07:00
let mut old_flags = unsafe { libc::fcntl(newfd, libc::F_GETFD, 0) };
2019-03-21 11:00:49 -07:00
if old_flags > 0 {
old_flags |= flags;
} else if old_flags == 0 {
old_flags &= !flags;
}
unsafe {
2019-03-21 11:54:55 -07:00
libc::fcntl(newfd, libc::F_SETFD, old_flags);
2019-03-21 11:00:49 -07:00
}
debug!(
"=> oldfd: {}, newfd: {}, flags: {} = pid: {}",
oldfd, newfd, flags, res
);
res
}