mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-24 01:42:13 +00:00
Add start of wasi fs
This commit is contained in:
parent
48b5918895
commit
68f1123ad6
@ -5,4 +5,9 @@ authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.2.1" }
|
||||||
|
# wasmer-runtime-abi = { path = "../runtime-abi" }
|
||||||
|
hashbrown = "0.1.8"
|
||||||
|
generational-arena = "0.2.2"
|
||||||
|
zbox = "0.6.1"
|
||||||
|
log = "0.4.6"
|
@ -1,9 +1,13 @@
|
|||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
mod ptr;
|
mod ptr;
|
||||||
mod state;
|
mod state;
|
||||||
mod syscalls;
|
mod syscalls;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use self::state::WasiState;
|
use self::state::{WasiState, WasiFs};
|
||||||
use self::syscalls::*;
|
use self::syscalls::*;
|
||||||
|
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
@ -21,6 +25,7 @@ pub fn generate_import_object(args: Vec<Vec<u8>>, envs: Vec<Vec<u8>>) -> ImportO
|
|||||||
}
|
}
|
||||||
|
|
||||||
let state = Box::new(WasiState {
|
let state = Box::new(WasiState {
|
||||||
|
fs: WasiFs::new().unwrap(),
|
||||||
args: &args[..],
|
args: &args[..],
|
||||||
envs: &envs[..],
|
envs: &envs[..],
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,182 @@
|
|||||||
|
// use wasmer_runtime_abi::vfs::{
|
||||||
|
// vfs::Vfs,
|
||||||
|
// file_like::{FileLike, Metadata};
|
||||||
|
// };
|
||||||
|
use std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
ops::{Index, IndexMut},
|
||||||
|
rc::Rc,
|
||||||
|
time::SystemTime,
|
||||||
|
};
|
||||||
|
use generational_arena::{Arena, Index as Inode};
|
||||||
|
use hashbrown::hash_map::{HashMap, Entry};
|
||||||
|
use zbox::{
|
||||||
|
RepoOpener,
|
||||||
|
Repo,
|
||||||
|
File,
|
||||||
|
FileType,
|
||||||
|
OpenOptions,
|
||||||
|
};
|
||||||
|
use crate::syscalls::types::*;
|
||||||
|
|
||||||
|
pub const MAX_SYMLINKS: usize = 100;
|
||||||
|
|
||||||
|
pub struct InodeVal {
|
||||||
|
stat: __wasi_filestat_t,
|
||||||
|
is_preopened: bool,
|
||||||
|
name: String,
|
||||||
|
kind: Kind,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Kind {
|
||||||
|
File {
|
||||||
|
handle: File,
|
||||||
|
},
|
||||||
|
Dir {
|
||||||
|
handle: File,
|
||||||
|
/// The entries of a directory are lazily filled.
|
||||||
|
entries: Vec<Inode>,
|
||||||
|
},
|
||||||
|
Symlink {
|
||||||
|
forwarded: Inode,
|
||||||
|
},
|
||||||
|
Buffer {
|
||||||
|
buffer: Vec<u8>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Fd {
|
||||||
|
rights: __wasi_rights_t,
|
||||||
|
flags: __wasi_fdflags_t,
|
||||||
|
offset: u64,
|
||||||
|
inode: Inode,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WasiFs {
|
||||||
|
repo: Repo,
|
||||||
|
name_map: HashMap<String, Inode>,
|
||||||
|
inodes: Arena<InodeVal>,
|
||||||
|
fd_map: HashMap<u32, Fd>,
|
||||||
|
next_fd: Cell<u32>,
|
||||||
|
inode_counter: Cell<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiFs {
|
||||||
|
pub fn new() -> Result<Self, String> {
|
||||||
|
Ok(Self {
|
||||||
|
repo: RepoOpener::new().create(true).open("mem://📂", "very unsafe pwd").map_err(|e| e.to_string())?,
|
||||||
|
name_map: HashMap::new(),
|
||||||
|
inodes: Arena::new(),
|
||||||
|
fd_map: HashMap::new(),
|
||||||
|
next_fd: Cell::new(3),
|
||||||
|
inode_counter: Cell::new(1000),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_inode(&mut self, path: &str) -> Option<Inode> {
|
||||||
|
Some(match self.name_map.entry(path.to_string()) {
|
||||||
|
Entry::Occupied(o) => *o.get(),
|
||||||
|
Entry::Vacant(v) => {
|
||||||
|
let file = if let Ok(file) = OpenOptions::new().read(true).write(true).create(false).open(&mut self.repo, path) {
|
||||||
|
file
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let metadata = file.metadata().unwrap();
|
||||||
|
let inode_index = {
|
||||||
|
let index = self.inode_counter.get();
|
||||||
|
self.inode_counter.replace(index + 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
let systime_to_nanos = |systime: SystemTime| {
|
||||||
|
let duration = systime.duration_since(SystemTime::UNIX_EPOCH).expect("should always be after unix epoch");
|
||||||
|
duration.as_nanos() as u64
|
||||||
|
};
|
||||||
|
|
||||||
|
let inode = self.inodes.insert(InodeVal {
|
||||||
|
stat: __wasi_filestat_t {
|
||||||
|
st_dev: 0,
|
||||||
|
st_ino: inode_index,
|
||||||
|
st_filetype: match metadata.file_type() {
|
||||||
|
FileType::File => __WASI_FILETYPE_REGULAR_FILE,
|
||||||
|
FileType::Dir => __WASI_FILETYPE_DIRECTORY,
|
||||||
|
},
|
||||||
|
st_nlink: 0,
|
||||||
|
st_size: metadata.len() as u64,
|
||||||
|
st_atim: systime_to_nanos(SystemTime::now()),
|
||||||
|
st_mtim: systime_to_nanos(metadata.modified()),
|
||||||
|
st_ctim: systime_to_nanos(metadata.created()),
|
||||||
|
},
|
||||||
|
is_preopened: false,
|
||||||
|
name: path.to_string(),
|
||||||
|
kind: match metadata.file_type() {
|
||||||
|
FileType::File => Kind::File {
|
||||||
|
handle: file,
|
||||||
|
},
|
||||||
|
FileType::Dir => Kind::Dir {
|
||||||
|
handle: file,
|
||||||
|
entries: Vec::new(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
v.insert(inode);
|
||||||
|
inode
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filestat_inode(&self, inode: Inode, flags: __wasi_lookupflags_t) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
|
let inode_val = &self.inodes[inode];
|
||||||
|
if let (true, Kind::Symlink { mut forwarded }) = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0, &inode_val.kind) {
|
||||||
|
// Time to follow the symlink.
|
||||||
|
let mut counter = 0;
|
||||||
|
|
||||||
|
while counter <= MAX_SYMLINKS {
|
||||||
|
let inode_val = &self.inodes[forwarded];
|
||||||
|
if let &Kind::Symlink { forwarded: new_forwarded } = &inode_val.kind {
|
||||||
|
counter += 1;
|
||||||
|
forwarded = new_forwarded;
|
||||||
|
} else {
|
||||||
|
return Ok(inode_val.stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(__WASI_EMLINK)
|
||||||
|
} else {
|
||||||
|
Ok(inode_val.stat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filestat_path(
|
||||||
|
&mut self,
|
||||||
|
preopened_fd: __wasi_fd_t,
|
||||||
|
flags: __wasi_lookupflags_t,
|
||||||
|
path: &str,
|
||||||
|
) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
|
warn!("Should use preopned_fd: {}", preopened_fd);
|
||||||
|
let inode = if let Some(inode) = self.get_inode(path) {
|
||||||
|
inode
|
||||||
|
} else {
|
||||||
|
return Err(__WASI_EINVAL);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.filestat_inode(inode, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn filestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_filestat_t, __wasi_errno_t> {
|
||||||
|
let fd = if let Some(fd) = self.fd_map.get(&fd) {
|
||||||
|
fd
|
||||||
|
} else {
|
||||||
|
return Err(__WASI_EBADF);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.filestat_inode(fd.inode, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct WasiState<'a> {
|
pub struct WasiState<'a> {
|
||||||
// vfs: Vfs,
|
pub fs: WasiFs,
|
||||||
pub args: &'a [Vec<u8>],
|
pub args: &'a [Vec<u8>],
|
||||||
pub envs: &'a [Vec<u8>],
|
pub envs: &'a [Vec<u8>],
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
mod types;
|
pub mod types;
|
||||||
|
|
||||||
use self::types::*;
|
use self::types::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -185,7 +185,20 @@ pub fn fd_fdstat_get(
|
|||||||
fd: __wasi_fd_t,
|
fd: __wasi_fd_t,
|
||||||
buf: WasmPtr<__wasi_fdstat_t>,
|
buf: WasmPtr<__wasi_fdstat_t>,
|
||||||
) -> __wasi_errno_t {
|
) -> __wasi_errno_t {
|
||||||
unimplemented!()
|
let mut state = get_wasi_state(ctx);
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
|
let stat = match state.fs.filestat_fd(fd) {
|
||||||
|
Ok(stat) => stat,
|
||||||
|
Err(errno) => return errno,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(buf) = buf.deref(memory) {
|
||||||
|
buf.set(stat);
|
||||||
|
__WASI_ESUCCESS
|
||||||
|
} else {
|
||||||
|
__WASI_EFAULT
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn fd_fdstat_set_flags(
|
pub fn fd_fdstat_set_flags(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user