mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-23 13:41:32 +00:00
refactor everything
This commit is contained in:
@ -1,148 +1,151 @@
|
||||
use std::cmp::{Eq, Ord, Ordering, PartialEq};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Display;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use wasmer_runtime_abi::vfs::device_file;
|
||||
use wasmer_runtime_abi::vfs::file_like::{FileLike, Metadata};
|
||||
use wasmer_runtime_abi::vfs::vfs::Vfs;
|
||||
|
||||
pub type Fd = i32;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VirtualFd(pub Fd);
|
||||
|
||||
impl Ord for VirtualFd {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.0.cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for VirtualFd {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.0.cmp(&other.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for VirtualFd {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for VirtualFd {}
|
||||
|
||||
impl Display for VirtualFd {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
write!(f, "Fd({})", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum FileHandle {
|
||||
VirtualFile(Fd),
|
||||
Socket(Fd),
|
||||
Vf(Rc<RefCell<dyn FileLike>>),
|
||||
}
|
||||
|
||||
pub type Map<K, V> = BTreeMap<K, V>;
|
||||
pub type FdMap = Map<VirtualFd, FileHandle>;
|
||||
|
||||
pub struct EmscriptenVfs {
|
||||
pub fd_map: FdMap,
|
||||
pub fd_map: BTreeMap<i32, FileHandle>,
|
||||
pub vfs: Vfs,
|
||||
}
|
||||
|
||||
impl EmscriptenVfs {
|
||||
pub fn new(vfs: Vfs) -> Self {
|
||||
let mut fd_map = FdMap::new();
|
||||
pub fn new(mut vfs: Vfs) -> Self {
|
||||
let mut fd_map = BTreeMap::new();
|
||||
|
||||
vfs.fd_map
|
||||
.keys()
|
||||
.map(|handle| (handle, handle))
|
||||
.for_each(|(virtual_handle, handle)| {
|
||||
let vfd = VirtualFd(*virtual_handle);
|
||||
fd_map.insert(vfd, FileHandle::VirtualFile(*handle));
|
||||
});
|
||||
let stdin = Rc::new(RefCell::new(device_file::Stdin));
|
||||
vfs.create_device_file("/dev/stdin", stdin.clone());
|
||||
fd_map.insert(0, FileHandle::Vf(stdin));
|
||||
|
||||
// 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 stdout = Rc::new(RefCell::new(device_file::Stdout));
|
||||
vfs.create_device_file("/dev/stdout", stdout.clone());
|
||||
fd_map.insert(1, FileHandle::Vf(stdout));
|
||||
|
||||
let stdin_fd = VirtualFd(0);
|
||||
let stdin_handle = FileHandle::VirtualFile(0);
|
||||
let stdout_fd = VirtualFd(1);
|
||||
let stdout_handle = FileHandle::VirtualFile(1);
|
||||
let stderr_fd = VirtualFd(2);
|
||||
let stderr_handle = FileHandle::VirtualFile(2);
|
||||
|
||||
fd_map.insert(stdin_fd, stdin_handle);
|
||||
fd_map.insert(stdout_fd, stdout_handle);
|
||||
fd_map.insert(stderr_fd, stderr_handle);
|
||||
let stderr = Rc::new(RefCell::new(device_file::Stderr));
|
||||
vfs.create_device_file("/dev/stderr", stderr.clone());
|
||||
fd_map.insert(2, FileHandle::Vf(stderr));
|
||||
|
||||
EmscriptenVfs { fd_map, vfs }
|
||||
}
|
||||
|
||||
pub fn close(&mut self, vfd: &VirtualFd) -> () {
|
||||
match self.fd_map.get(&vfd) {
|
||||
Some(FileHandle::VirtualFile(handle)) => {
|
||||
self.vfs.close(handle).unwrap();
|
||||
}
|
||||
Some(FileHandle::Socket(fd)) => unsafe {
|
||||
libc::close(*fd);
|
||||
},
|
||||
None => panic!(),
|
||||
}
|
||||
self.fd_map.remove(&vfd);
|
||||
pub fn make_dir<P: AsRef<Path>>(&mut self, path: P) -> () {
|
||||
self.vfs.make_dir(path);
|
||||
}
|
||||
|
||||
pub fn next_lowest_fd(&self) -> VirtualFd {
|
||||
next_lowest(&self.fd_map)
|
||||
}
|
||||
|
||||
pub fn get_host_socket_fd(&self, vfd: &VirtualFd) -> Option<Fd> {
|
||||
match self.fd_map.get(&vfd) {
|
||||
Some(FileHandle::Socket(fd)) => {
|
||||
if *fd < 0 {
|
||||
panic!()
|
||||
}
|
||||
Some(*fd)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_virtual_file_handle(&self, vfd: VirtualFd) -> Option<Fd> {
|
||||
match self.fd_map.get(&vfd) {
|
||||
Some(FileHandle::VirtualFile(fd)) => Some(*fd),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_file<P: AsRef<std::path::Path>>(&mut self, path: P) -> VirtualFd {
|
||||
let fd = self.vfs.open_file(path).unwrap();
|
||||
let vfd = VirtualFd(fd);
|
||||
let file = FileHandle::VirtualFile(fd);
|
||||
self.fd_map.insert(vfd.clone(), file);
|
||||
vfd
|
||||
}
|
||||
|
||||
pub fn new_socket_fd(&mut self, host_fd: Fd) -> VirtualFd {
|
||||
let vfd = self.next_lowest_fd();
|
||||
if host_fd < 0 {
|
||||
panic!()
|
||||
}
|
||||
self.fd_map.insert(vfd.clone(), FileHandle::Socket(host_fd));
|
||||
vfd
|
||||
}
|
||||
}
|
||||
|
||||
fn next_lowest(fd_map: &FdMap) -> VirtualFd {
|
||||
let mut next_lowest_fd = 0;
|
||||
for (vfd, _) in fd_map.iter() {
|
||||
let host_fd = vfd.0;
|
||||
if host_fd == next_lowest_fd {
|
||||
next_lowest_fd += 1;
|
||||
} else if host_fd < next_lowest_fd {
|
||||
panic!("Should not be here.");
|
||||
pub fn path_metadata<P: AsRef<Path>>(&mut self, path: P) -> Option<Metadata> {
|
||||
if let Some(file) = self.vfs.open_file(path) {
|
||||
RefCell::borrow(&file).metadata().ok()
|
||||
} else {
|
||||
break;
|
||||
None
|
||||
}
|
||||
}
|
||||
VirtualFd(next_lowest_fd)
|
||||
|
||||
pub fn close_file_descriptor(&mut self, fd: i32) -> i32 {
|
||||
match self.fd_map.remove(&fd) {
|
||||
Some(FileHandle::Vf(_)) => 0,
|
||||
Some(FileHandle::Socket(fd)) => unsafe { libc::close(fd) },
|
||||
_ => -1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_lowest_fd_raw(&self) -> i32 {
|
||||
let fd_map = &self.fd_map;
|
||||
let mut next_lowest_fd = 0;
|
||||
for (vfd, _) in fd_map.iter() {
|
||||
let host_fd = *vfd;
|
||||
if host_fd == next_lowest_fd {
|
||||
next_lowest_fd += 1;
|
||||
} else if host_fd < next_lowest_fd {
|
||||
panic!("Should not be here.");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
next_lowest_fd
|
||||
}
|
||||
|
||||
pub fn get_host_socket_fd(&self, fd: i32) -> Option<Fd> {
|
||||
match self.fd_map.get(&fd) {
|
||||
Some(FileHandle::Socket(fd)) => Some(*fd),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_file<P: AsRef<std::path::Path>>(&mut self, path: P) -> i32 {
|
||||
match self.vfs.open_file(path) {
|
||||
Some(file) => {
|
||||
let fd = self.next_lowest_fd_raw();
|
||||
let handle = FileHandle::Vf(file);
|
||||
self.fd_map.insert(fd, handle);
|
||||
fd
|
||||
}
|
||||
None => -1,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_file(
|
||||
&mut self,
|
||||
fd: i32,
|
||||
buf_slice: &mut [u8],
|
||||
count: usize,
|
||||
) -> Result<usize, EmscriptenVfsError> {
|
||||
match self.fd_map.get(&fd) {
|
||||
Some(FileHandle::Vf(file)) => {
|
||||
let mut mut_ref = RefCell::borrow_mut(file);
|
||||
mut_ref
|
||||
.write_file(buf_slice, 0)
|
||||
.map_err(|e| EmscriptenVfsError::Io(e))
|
||||
}
|
||||
Some(FileHandle::Socket(host_fd)) => unsafe {
|
||||
let result = libc::write(*host_fd, buf_slice.as_ptr() as _, count as _);
|
||||
if result == -1 {
|
||||
Err(EmscriptenVfsError::Errno(errno::errno()))
|
||||
} else {
|
||||
Ok(result as usize)
|
||||
}
|
||||
},
|
||||
_ => Err(EmscriptenVfsError::FileSystemError),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_file(&self, fd: i32, buf_slice: &mut [u8]) -> usize {
|
||||
match self.fd_map.get(&fd) {
|
||||
Some(FileHandle::Vf(file)) => {
|
||||
let count = {
|
||||
let mut result = RefCell::borrow_mut(&file);
|
||||
let result = result.read(buf_slice);
|
||||
result.unwrap()
|
||||
};
|
||||
count as _
|
||||
}
|
||||
Some(FileHandle::Socket(host_fd)) => unsafe {
|
||||
let buf_addr = buf_slice.as_ptr() as _;
|
||||
libc::write(*host_fd, buf_addr, buf_slice.len()) as usize
|
||||
},
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_socket_fd(&mut self, host_fd: Fd) -> Fd {
|
||||
let fd = self.next_lowest_fd_raw();
|
||||
self.fd_map.insert(fd, FileHandle::Socket(host_fd));
|
||||
fd
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EmscriptenVfsError {
|
||||
Io(io::Error),
|
||||
Errno(errno::Errno),
|
||||
FileSystemError,
|
||||
}
|
||||
|
Reference in New Issue
Block a user