add mapdir for emscripten; implement getdents, etc.

This commit is contained in:
Mark McCaskey
2019-05-24 18:00:07 -07:00
parent dcf0a7cc4b
commit fc15bc58f6
8 changed files with 176 additions and 31 deletions

View File

@ -10,7 +10,8 @@ pub use self::unix::*;
#[cfg(windows)]
pub use self::windows::*;
use super::utils::copy_stat_into_wasm;
use crate::utils::{copy_stat_into_wasm, get_cstr_path, get_current_directory};
use super::varargs::VarArgs;
use byteorder::{ByteOrder, LittleEndian};
/// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32
@ -94,13 +95,17 @@ pub fn ___syscall6(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
pub fn ___syscall12(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall12 (chdir) {}", _which);
let path_addr: i32 = varargs.get(ctx);
unsafe {
let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8;
let _path = std::ffi::CStr::from_ptr(path_ptr);
let ret = chdir(path_ptr);
debug!("=> path: {:?}, ret: {}", _path, ret);
let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path_addr) as *const i8;
let real_path = get_cstr_path(ctx, path_ptr)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(path_ptr);
let ret = unsafe { chdir(real_path) };
debug!(
"=> path: {:?}, ret: {}",
unsafe { std::ffi::CStr::from_ptr(real_path) },
ret
}
);
ret
}
pub fn ___syscall10(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
@ -126,11 +131,17 @@ pub fn ___syscall38(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
let new_path_addr: u32 = varargs.get(ctx);
let old_path = emscripten_memory_pointer!(ctx.memory(0), old_path_addr) as *const i8;
let new_path = emscripten_memory_pointer!(ctx.memory(0), new_path_addr) as *const i8;
let result = unsafe { rename(old_path, new_path) };
let real_old_path = get_cstr_path(ctx, old_path)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(old_path);
let real_new_path = get_cstr_path(ctx, new_path)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(new_path);
let result = unsafe { rename(real_old_path, real_new_path) };
debug!(
"=> old_path: {}, new_path: {}, result: {}",
unsafe { std::ffi::CStr::from_ptr(old_path).to_str().unwrap() },
unsafe { std::ffi::CStr::from_ptr(new_path).to_str().unwrap() },
unsafe { std::ffi::CStr::from_ptr(real_old_path).to_str().unwrap() },
unsafe { std::ffi::CStr::from_ptr(real_new_path).to_str().unwrap() },
result
);
result
@ -141,7 +152,10 @@ pub fn ___syscall40(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
debug!("emscripten::___syscall40 (rmdir)");
let pathname: u32 = varargs.get(ctx);
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
unsafe { rmdir(pathname_addr) }
let real_path = get_cstr_path(ctx, pathname_addr)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(pathname_addr);
unsafe { rmdir(real_path) }
}
// pipe
@ -224,10 +238,9 @@ pub fn ___syscall110(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
// getcwd
pub fn ___syscall183(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
debug!("emscripten::___syscall183");
use std::env;
let buf_offset: c_int = varargs.get(ctx);
let _size: c_int = varargs.get(ctx);
let path = env::current_dir();
let path = get_current_directory(ctx);
let path_string = path.unwrap().display().to_string();
let len = path_string.len();
unsafe {
@ -401,15 +414,18 @@ pub fn ___syscall195(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
let buf: u32 = varargs.get(ctx);
let pathname_addr = emscripten_memory_pointer!(ctx.memory(0), pathname) as *const i8;
let real_path = get_cstr_path(ctx, pathname_addr)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(pathname_addr);
unsafe {
let mut _stat: stat = std::mem::zeroed();
let ret = stat(pathname_addr, &mut _stat);
let ret = stat(real_path, &mut _stat);
debug!(
"=> pathname: {}, buf: {}, path: {} = {}\nlast os error: {}",
pathname,
buf,
std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap(),
std::ffi::CStr::from_ptr(real_path).to_str().unwrap(),
ret,
Error::last_os_error()
);
@ -440,11 +456,6 @@ pub fn ___syscall197(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
0
}
pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall220");
-1
}
// fcntl64
pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall221 (fcntl64) {}", _which);
@ -457,7 +468,7 @@ pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
// |FNONBLOCK - 0x04
debug!("=> fd: {}, cmd: {}", _fd, cmd);
match cmd {
2 => 0,
1 | 2 => 0,
13 | 14 => 0, // pretend file locking worked
_ => -1,
}

View File

@ -43,6 +43,7 @@ use libc::{
pid_t,
pread,
pwrite,
readdir,
// readv,
recvfrom,
recvmsg,
@ -108,8 +109,11 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
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;
let _path_str = unsafe { std::ffi::CStr::from_ptr(pathname_addr).to_str().unwrap() };
let fd = unsafe { open(pathname_addr, flags, mode) };
let real_path = utils::get_cstr_path(ctx, pathname_addr)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(pathname_addr);
let _path_str = unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() };
let fd = unsafe { open(real_path, flags, mode) };
debug!(
"=> pathname: {}, flags: {}, mode: {} = fd: {}\npath: {}\nlast os error: {}",
pathname,
@ -160,11 +164,17 @@ pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
let path2_ptr: c_int = varargs.get(ctx);
let path1 = emscripten_memory_pointer!(ctx.memory(0), path1_ptr) as *mut i8;
let path2 = emscripten_memory_pointer!(ctx.memory(0), path2_ptr) as *mut i8;
let result = unsafe { symlink(path1, path2) };
let real_path1 = utils::get_cstr_path(ctx, path1)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(path1);
let real_path2 = utils::get_cstr_path(ctx, path2)
.map(|cstr| cstr.as_c_str() as *const _ as *const i8)
.unwrap_or(path2);
let result = unsafe { symlink(real_path1, real_path2) };
debug!(
"=> path1: {}, path2: {}, result: {}",
unsafe { std::ffi::CStr::from_ptr(path1).to_str().unwrap() },
unsafe { std::ffi::CStr::from_ptr(path2).to_str().unwrap() },
unsafe { std::ffi::CStr::from_ptr(real_path1).to_str().unwrap() },
unsafe { std::ffi::CStr::from_ptr(real_path2).to_str().unwrap() },
result,
);
result
@ -796,6 +806,81 @@ pub fn ___syscall196(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
0
}
// getdents
// dirent structure is
// i64, i64, u16 (280), i8, [i8; 256]
pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
debug!("emscripten::___syscall220");
let fd: i32 = varargs.get(ctx);
let dirp_addr: i32 = varargs.get(ctx);
let count: u32 = varargs.get(ctx);
//let dir = dbg!(emscripten_memory_pointer!(ctx.memory(0), dbg!(fd)) as *mut libc::DIR);
let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8;
let mut pos = 0;
// need to persist stream across calls?
let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) };
dbg!("Start loop");
while pos + 280 <= dbg!(count) as usize {
dbg!("Pre readdir");
let dirent = unsafe { readdir(dir) };
dbg!("post readdir");
if dirent.is_null() {
break;
}
dbg!("dirent is not null");
unsafe {
*(dirp.add(pos) as *mut u64) = dbg!((*dirent).d_ino);
#[cfg(not(target_os = "macos"))]
{
*(dirp.add(pos + 8) as *mut u64) = 280 //dbg!((*dirent).d_off);
}
#[cfg(target_os = "macos")]
{
*(dirp.add(pos + 8) as *mut u64) = if pos + 280 > count as usize {
count.into()
} else {
dbg!((*dirent).d_seekoff);
pos as u64 + 56 //280
}; //;
}
dbg!((*dirent).d_namlen);
*(dirp.add(pos + 16) as *mut u16) = 280; //dbg!((*dirent).d_reclen);
*(dirp.add(pos + 18) as *mut u8) = dbg!((*dirent).d_type);
let upper_bound = std::cmp::min((*dirent).d_reclen, 255) as usize;
let mut i = 0;
while i < upper_bound {
*(dirp.add(pos + 19 + i) as *mut i8) = (*dirent).d_name[i];
//dbg!((*dirent).d_name[i] as u8 as char);
//dbg!((*dirent).d_name[i] as u8 as char);
i += 1;
}
*(dirp.add(pos + 19 + i) as *mut i8) = 0 as i8;
}
dbg!("dirent written to memory");
pos += 280;
/*unsafe {
eprintln!(
"{}",
std::ffi::CStr::from_bytes_with_nul_unchecked({
let arr = *(dirent as *const u8 as *const [u8; 256]);
&arr.to_vec()
.into_iter()
.map(|b| b as u8)
.collect::<Vec<u8>>()[..20]
})
.to_str()
.unwrap()
);
}*/
}
dbg!(pos as i32)
}
/// fallocate
pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall324 (fallocate) {}", _which);

View File

@ -251,6 +251,12 @@ pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
-1
}
// getdents
pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall220");
-1
}
/// fchown
pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall207 (fchown) {}", _which);