mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
fix putenv and setenv for windows (#140)
This commit is contained in:
parent
2fbd38bd5d
commit
83df3ad35f
11
lib/emscripten/src/env/mod.rs
vendored
Normal file
11
lib/emscripten/src/env/mod.rs
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#[cfg(unix)]
|
||||||
|
mod unix;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
mod windows;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub use self::unix::*;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub use self::windows::*;
|
@ -7,8 +7,8 @@ use std::ffi::CStr;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
use super::utils::{allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
|
use crate::utils::{allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
|
||||||
use super::EmscriptenData;
|
use crate::EmscriptenData;
|
||||||
use wasmer_runtime_core::vm::Ctx;
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
pub fn _getaddrinfo(_one: i32, _two: i32, _three: i32, _four: i32, _ctx: &mut Ctx) -> i32 {
|
pub fn _getaddrinfo(_one: i32, _two: i32, _three: i32, _four: i32, _ctx: &mut Ctx) -> i32 {
|
218
lib/emscripten/src/env/windows/mod.rs
vendored
Normal file
218
lib/emscripten/src/env/windows/mod.rs
vendored
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
|
||||||
|
use libc::{
|
||||||
|
c_int,
|
||||||
|
c_long,
|
||||||
|
getenv,
|
||||||
|
//sysconf, unsetenv,
|
||||||
|
};
|
||||||
|
|
||||||
|
use core::slice;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::mem;
|
||||||
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
|
use crate::utils::{
|
||||||
|
allocate_on_stack, copy_cstr_into_wasm, copy_terminated_array_of_cstrs, read_string_from_wasm,
|
||||||
|
};
|
||||||
|
use crate::EmscriptenData;
|
||||||
|
use wasmer_runtime_core::memory::Memory;
|
||||||
|
use wasmer_runtime_core::vm::Ctx;
|
||||||
|
|
||||||
|
#[link(name = "c")]
|
||||||
|
extern "C" {
|
||||||
|
#[link_name = "_putenv"]
|
||||||
|
pub fn putenv(s: *const c_char) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _getaddrinfo(_one: i32, _two: i32, _three: i32, _four: i32, _ctx: &mut Ctx) -> i32 {
|
||||||
|
debug!("emscripten::_getaddrinfo");
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[no_mangle]
|
||||||
|
/// emscripten: _getenv // (name: *const char) -> *const c_char;
|
||||||
|
pub fn _getenv(name: i32, ctx: &mut Ctx) -> u32 {
|
||||||
|
debug!("emscripten::_getenv");
|
||||||
|
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
|
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as _;
|
||||||
|
|
||||||
|
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
||||||
|
|
||||||
|
let c_str: *mut c_char = unsafe { getenv(name_addr as _) } as _;
|
||||||
|
if c_str.is_null() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { copy_cstr_into_wasm(ctx, c_str) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int);
|
||||||
|
pub fn _setenv(name: u32, value: u32, overwrite: u32, ctx: &mut Ctx) -> c_int {
|
||||||
|
debug!("emscripten::_setenv");
|
||||||
|
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name);
|
||||||
|
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value);
|
||||||
|
// setenv does not exist on windows, so we hack it with _putenv
|
||||||
|
let name = read_string_from_wasm(ctx.memory(0), name);
|
||||||
|
let value = read_string_from_wasm(ctx.memory(0), value);
|
||||||
|
let putenv_string = format!("{}={}", name, value);
|
||||||
|
let putenv_cstring = CString::new(putenv_string).unwrap();
|
||||||
|
let putenv_raw_ptr = putenv_cstring.as_ptr();
|
||||||
|
debug!("=> name({:?})", name);
|
||||||
|
debug!("=> value({:?})", value);
|
||||||
|
unsafe { putenv(putenv_raw_ptr) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emscripten: _putenv // (name: *const char);
|
||||||
|
pub fn _putenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||||
|
debug!("emscripten::_putenv");
|
||||||
|
|
||||||
|
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name) as *const c_char;
|
||||||
|
|
||||||
|
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
||||||
|
unsafe { putenv(name_addr) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emscripten: _unsetenv // (name: *const char);
|
||||||
|
pub fn _unsetenv(name: c_int, ctx: &mut Ctx) -> c_int {
|
||||||
|
debug!("emscripten::_unsetenv");
|
||||||
|
|
||||||
|
let name_addr = emscripten_memory_pointer!(ctx.memory(0), name);
|
||||||
|
|
||||||
|
debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
|
||||||
|
|
||||||
|
unsafe { unsetenv(name_addr) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
pub fn _getpwnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||||
|
debug!("emscripten::_getpwnam {}", name_ptr);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct GuestPasswd {
|
||||||
|
pw_name: u32,
|
||||||
|
pw_passwd: u32,
|
||||||
|
pw_uid: u32,
|
||||||
|
pw_gid: u32,
|
||||||
|
pw_gecos: u32,
|
||||||
|
pw_dir: u32,
|
||||||
|
pw_shell: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = unsafe {
|
||||||
|
let memory_name_ptr = emscripten_memory_pointer!(ctx.memory(0), name_ptr) as *const c_char;
|
||||||
|
CStr::from_ptr(memory_name_ptr)
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let passwd = &*libc_getpwnam(name.as_ptr());
|
||||||
|
let passwd_struct_offset = call_malloc(mem::size_of::<GuestPasswd>() as _, ctx);
|
||||||
|
|
||||||
|
let passwd_struct_ptr =
|
||||||
|
emscripten_memory_pointer!(ctx.memory(0), passwd_struct_offset) as *mut GuestPasswd;
|
||||||
|
(*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(ctx, passwd.pw_name);
|
||||||
|
(*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(ctx, passwd.pw_passwd);
|
||||||
|
(*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(ctx, passwd.pw_gecos);
|
||||||
|
(*passwd_struct_ptr).pw_dir = copy_cstr_into_wasm(ctx, passwd.pw_dir);
|
||||||
|
(*passwd_struct_ptr).pw_shell = copy_cstr_into_wasm(ctx, passwd.pw_shell);
|
||||||
|
(*passwd_struct_ptr).pw_uid = passwd.pw_uid;
|
||||||
|
(*passwd_struct_ptr).pw_gid = passwd.pw_gid;
|
||||||
|
|
||||||
|
passwd_struct_offset as c_int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
pub fn _getgrnam(name_ptr: c_int, ctx: &mut Ctx) -> c_int {
|
||||||
|
debug!("emscripten::_getgrnam {}", name_ptr);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct GuestGroup {
|
||||||
|
gr_name: u32,
|
||||||
|
gr_passwd: u32,
|
||||||
|
gr_gid: u32,
|
||||||
|
gr_mem: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = unsafe {
|
||||||
|
let memory_name_ptr = emscripten_memory_pointer!(ctx.memory(0), name_ptr) as *const c_char;
|
||||||
|
CStr::from_ptr(memory_name_ptr)
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let group = &*libc_getgrnam(name.as_ptr());
|
||||||
|
let group_struct_offset = call_malloc(mem::size_of::<GuestGroup>() as _, ctx);
|
||||||
|
|
||||||
|
let group_struct_ptr =
|
||||||
|
emscripten_memory_pointer!(ctx.memory(0), group_struct_offset) as *mut GuestGroup;
|
||||||
|
(*group_struct_ptr).gr_name = copy_cstr_into_wasm(ctx, group.gr_name);
|
||||||
|
(*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(ctx, group.gr_passwd);
|
||||||
|
(*group_struct_ptr).gr_gid = group.gr_gid;
|
||||||
|
(*group_struct_ptr).gr_mem = copy_terminated_array_of_cstrs(ctx, group.gr_mem);
|
||||||
|
|
||||||
|
group_struct_offset as c_int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_malloc(size: u32, ctx: &mut Ctx) -> u32 {
|
||||||
|
get_emscripten_data(ctx).malloc.call(size).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_memalign(alignment: u32, size: u32, ctx: &mut Ctx) -> u32 {
|
||||||
|
get_emscripten_data(ctx)
|
||||||
|
.memalign
|
||||||
|
.call(alignment, size)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_memset(pointer: u32, value: u32, size: u32, ctx: &mut Ctx) -> u32 {
|
||||||
|
get_emscripten_data(ctx)
|
||||||
|
.memset
|
||||||
|
.call(pointer, value, size)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_emscripten_data(ctx: &mut Ctx) -> &mut EmscriptenData {
|
||||||
|
unsafe { &mut *(ctx.data as *mut EmscriptenData) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _getpagesize(_ctx: &mut Ctx) -> u32 {
|
||||||
|
debug!("emscripten::_getpagesize");
|
||||||
|
16384
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
pub fn ___build_environment(environ: c_int, ctx: &mut Ctx) {
|
||||||
|
debug!("emscripten::___build_environment {}", environ);
|
||||||
|
const MAX_ENV_VALUES: u32 = 64;
|
||||||
|
const TOTAL_ENV_SIZE: u32 = 1024;
|
||||||
|
let environment = emscripten_memory_pointer!(ctx.memory(0), environ) as *mut c_int;
|
||||||
|
unsafe {
|
||||||
|
let (pool_offset, _pool_slice): (u32, &mut [u8]) =
|
||||||
|
allocate_on_stack(TOTAL_ENV_SIZE as u32, ctx);
|
||||||
|
let (env_offset, _env_slice): (u32, &mut [u8]) =
|
||||||
|
allocate_on_stack((MAX_ENV_VALUES * 4) as u32, ctx);
|
||||||
|
let env_ptr = emscripten_memory_pointer!(ctx.memory(0), env_offset) as *mut c_int;
|
||||||
|
let mut _pool_ptr = emscripten_memory_pointer!(ctx.memory(0), pool_offset) as *mut c_int;
|
||||||
|
*env_ptr = pool_offset as i32;
|
||||||
|
*environment = env_offset as i32;
|
||||||
|
|
||||||
|
// *env_ptr = 0;
|
||||||
|
};
|
||||||
|
// unsafe {
|
||||||
|
// *env_ptr = 0;
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _sysconf(name: c_int, _ctx: &mut Ctx) -> c_long {
|
||||||
|
debug!("emscripten::_sysconf {}", name);
|
||||||
|
// TODO: Implement like emscripten expects regarding memory/page size
|
||||||
|
unsafe { sysconf(name) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ___assert_fail(a: c_int, b: c_int, c: c_int, d: c_int, _ctx: &mut Ctx) {
|
||||||
|
debug!("emscripten::___assert_fail {} {} {} {}", a, b, c, d);
|
||||||
|
// TODO: Implement like emscripten expects regarding memory/page size
|
||||||
|
// TODO raise an error
|
||||||
|
}
|
@ -4,7 +4,9 @@ use libc::stat;
|
|||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
use std::os::raw::c_int;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
use wasmer_runtime_core::memory::Memory;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
module::Module,
|
module::Module,
|
||||||
structures::TypedIndex,
|
structures::TypedIndex,
|
||||||
@ -54,11 +56,11 @@ pub unsafe fn copy_cstr_into_wasm(ctx: &mut Ctx, cstr: *const c_char) -> u32 {
|
|||||||
let s = CStr::from_ptr(cstr).to_str().unwrap();
|
let s = CStr::from_ptr(cstr).to_str().unwrap();
|
||||||
let cstr_len = s.len();
|
let cstr_len = s.len();
|
||||||
let space_offset = env::call_malloc((cstr_len as u32) + 1, ctx);
|
let space_offset = env::call_malloc((cstr_len as u32) + 1, ctx);
|
||||||
let raw_memory = emscripten_memory_pointer!(ctx.memory(0), space_offset) as *mut u8;
|
let raw_memory = emscripten_memory_pointer!(ctx.memory(0), space_offset) as *mut c_char;
|
||||||
let slice = slice::from_raw_parts_mut(raw_memory, cstr_len);
|
let slice = slice::from_raw_parts_mut(raw_memory, cstr_len);
|
||||||
|
|
||||||
for (byte, loc) in s.bytes().zip(slice.iter_mut()) {
|
for (byte, loc) in s.bytes().zip(slice.iter_mut()) {
|
||||||
*loc = byte;
|
*loc = byte as _;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Appending null byte won't work, because there is CStr::from_ptr(cstr)
|
// TODO: Appending null byte won't work, because there is CStr::from_ptr(cstr)
|
||||||
@ -155,6 +157,14 @@ pub unsafe fn copy_stat_into_wasm(ctx: &mut Ctx, buf: u32, stat: &stat) {
|
|||||||
(*stat_ptr).st_ino = stat.st_ino as _;
|
(*stat_ptr).st_ino = stat.st_ino as _;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_string_from_wasm(memory: &Memory, offset: u32) -> String {
|
||||||
|
memory.view::<u8>()[(offset as usize)..]
|
||||||
|
.iter()
|
||||||
|
.take_while(|cell| cell.get() != 0)
|
||||||
|
.map(|cell| cell.get() as char)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::is_emscripten_module;
|
use super::is_emscripten_module;
|
||||||
|
Loading…
Reference in New Issue
Block a user