mirror of
https://github.com/fluencelabs/wasmer
synced 2025-07-31 15:22:03 +00:00
refactor wasi state file to hide boilerplate
This commit is contained in:
@@ -5,6 +5,10 @@
|
||||
// vfs::Vfs,
|
||||
// file_like::{FileLike, Metadata};
|
||||
// };
|
||||
|
||||
mod types;
|
||||
|
||||
pub use self::types::*;
|
||||
use crate::syscalls::types::*;
|
||||
use generational_arena::Arena;
|
||||
pub use generational_arena::Index as Inode;
|
||||
@@ -13,7 +17,7 @@ use std::{
|
||||
borrow::Borrow,
|
||||
cell::Cell,
|
||||
fs,
|
||||
io::{self, Read, Seek, Write},
|
||||
io::{self, Write},
|
||||
path::{Path, PathBuf},
|
||||
time::SystemTime,
|
||||
};
|
||||
@@ -34,332 +38,6 @@ pub unsafe fn get_wasi_state(ctx: &mut Ctx) -> &mut WasiState {
|
||||
/// the number of symlinks that can be traversed when resolving a path
|
||||
pub const MAX_SYMLINKS: u32 = 128;
|
||||
|
||||
/// Error type for external users
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[allow(dead_code)]
|
||||
// dead code beacuse this is for external use
|
||||
pub enum WasiFsError {
|
||||
/// The fd given as a base was not a directory so the operation was not possible
|
||||
BaseNotDirectory,
|
||||
/// Expected a file but found not a file
|
||||
NotAFile,
|
||||
/// The fd given was not usable
|
||||
InvalidFd,
|
||||
/// File exists
|
||||
AlreadyExists,
|
||||
/// Something failed when doing IO. These errors can generally not be handled.
|
||||
/// It may work if tried again.
|
||||
IOError,
|
||||
/// A WASI error without an external name. If you encounter this it means
|
||||
/// that there's probably a bug on our side (maybe as simple as forgetting to wrap
|
||||
/// this error, but perhaps something broke)
|
||||
UnknownError(__wasi_errno_t),
|
||||
}
|
||||
|
||||
impl WasiFsError {
|
||||
pub fn from_wasi_err(err: __wasi_errno_t) -> WasiFsError {
|
||||
match err {
|
||||
__WASI_EBADF => WasiFsError::InvalidFd,
|
||||
__WASI_EEXIST => WasiFsError::AlreadyExists,
|
||||
__WASI_EIO => WasiFsError::IOError,
|
||||
_ => WasiFsError::UnknownError(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait relies on your file closing when it goes out of scope via `Drop`
|
||||
pub trait WasiFile: std::fmt::Debug + Write + Read + Seek {
|
||||
/// the last time the file was accessed in nanoseconds as a UNIX timestamp
|
||||
fn last_accessed(&self) -> __wasi_timestamp_t;
|
||||
/// the last time the file was modified in nanoseconds as a UNIX timestamp
|
||||
fn last_modified(&self) -> __wasi_timestamp_t;
|
||||
/// the time at which the file was created in nanoseconds as a UNIX timestamp
|
||||
fn created_time(&self) -> __wasi_timestamp_t;
|
||||
/// set the last time the file was accessed in nanoseconds as a UNIX timestamp
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_last_accessed(&self, _last_accessed: __wasi_timestamp_t) {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::set_last_accessed for your type before then");
|
||||
}
|
||||
/// set the last time the file was modified in nanoseconds as a UNIX timestamp
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_last_modified(&self, _last_modified: __wasi_timestamp_t) {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::set_last_modified for your type before then");
|
||||
}
|
||||
/// set the time at which the file was created in nanoseconds as a UNIX timestamp
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_created_time(&self, _created_time: __wasi_timestamp_t) {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::set_created_time for your type before then");
|
||||
}
|
||||
/// the size of the file in bytes
|
||||
fn size(&self) -> u64;
|
||||
/// Change the size of the file, if the `new_size` is greater than the current size
|
||||
/// the extra bytes will be allocated and zeroed
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_len(&mut self, _new_size: __wasi_filesize_t) -> Option<()> {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::allocate for your type before then");
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for fs::File {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
self.metadata()
|
||||
.unwrap()
|
||||
.accessed()
|
||||
.ok()
|
||||
.and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok())
|
||||
.map(|ct| ct.as_nanos() as u64)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn set_last_accessed(&self, _last_accessed: __wasi_timestamp_t) {
|
||||
// TODO: figure out how to do this
|
||||
}
|
||||
|
||||
fn last_modified(&self) -> u64 {
|
||||
self.metadata()
|
||||
.unwrap()
|
||||
.modified()
|
||||
.ok()
|
||||
.and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok())
|
||||
.map(|ct| ct.as_nanos() as u64)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn set_last_modified(&self, _last_modified: __wasi_timestamp_t) {
|
||||
// TODO: figure out how to do this
|
||||
}
|
||||
|
||||
fn created_time(&self) -> u64 {
|
||||
self.metadata()
|
||||
.unwrap()
|
||||
.created()
|
||||
.ok()
|
||||
.and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok())
|
||||
.map(|ct| ct.as_nanos() as u64)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn set_created_time(&self, _created_time: __wasi_timestamp_t) {
|
||||
// TODO: figure out how to do this
|
||||
}
|
||||
|
||||
fn size(&self) -> u64 {
|
||||
self.metadata().unwrap().len()
|
||||
}
|
||||
|
||||
fn set_len(&mut self, new_size: __wasi_filesize_t) -> Option<()> {
|
||||
fs::File::set_len(self, new_size).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stdout(std::io::Stdout);
|
||||
impl Read for Stdout {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Seek for Stdout {
|
||||
fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not seek stdout",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.0.flush()
|
||||
}
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.0.write_all(buf)
|
||||
}
|
||||
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
self.0.write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for Stdout {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn last_modified(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn created_time(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn size(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stderr(std::io::Stderr);
|
||||
impl Read for Stderr {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Seek for Stderr {
|
||||
fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not seek stderr",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.0.flush()
|
||||
}
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.0.write_all(buf)
|
||||
}
|
||||
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
self.0.write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for Stderr {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn last_modified(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn created_time(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn size(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stdin(std::io::Stdin);
|
||||
impl Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
self.0.read_to_string(buf)
|
||||
}
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
self.0.read_exact(buf)
|
||||
}
|
||||
}
|
||||
impl Seek for Stdin {
|
||||
fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not seek stdin",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Write for Stdin {
|
||||
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
fn write_fmt(&mut self, _fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for Stdin {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn last_modified(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn created_time(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn size(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Think about using this
|
||||
trait WasiFdBacking: std::fmt::Debug {
|
||||
fn get_stat(&self) -> &__wasi_filestat_t;
|
||||
fn get_stat_mut(&mut self) -> &mut __wasi_filestat_t;
|
||||
fn is_preopened(&self) -> bool;
|
||||
fn get_name(&self) -> &str;
|
||||
}
|
||||
*/
|
||||
|
||||
/// A file that Wasi knows about that may or may not be open
|
||||
#[derive(Debug)]
|
||||
pub struct InodeVal {
|
396
lib/wasi/src/state/types.rs
Normal file
396
lib/wasi/src/state/types.rs
Normal file
@@ -0,0 +1,396 @@
|
||||
/// types for use in the WASI filesystem
|
||||
use crate::syscalls::types::*;
|
||||
use std::{
|
||||
fs,
|
||||
io::{self, Read, Seek, Write},
|
||||
path::PathBuf,
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
/// Error type for external users
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[allow(dead_code)]
|
||||
// dead code beacuse this is for external use
|
||||
pub enum WasiFsError {
|
||||
/// The fd given as a base was not a directory so the operation was not possible
|
||||
BaseNotDirectory,
|
||||
/// Expected a file but found not a file
|
||||
NotAFile,
|
||||
/// The fd given was not usable
|
||||
InvalidFd,
|
||||
/// File exists
|
||||
AlreadyExists,
|
||||
/// Something failed when doing IO. These errors can generally not be handled.
|
||||
/// It may work if tried again.
|
||||
IOError,
|
||||
/// A WASI error without an external name. If you encounter this it means
|
||||
/// that there's probably a bug on our side (maybe as simple as forgetting to wrap
|
||||
/// this error, but perhaps something broke)
|
||||
UnknownError(__wasi_errno_t),
|
||||
}
|
||||
|
||||
impl WasiFsError {
|
||||
pub fn from_wasi_err(err: __wasi_errno_t) -> WasiFsError {
|
||||
match err {
|
||||
__WASI_EBADF => WasiFsError::InvalidFd,
|
||||
__WASI_EEXIST => WasiFsError::AlreadyExists,
|
||||
__WASI_EIO => WasiFsError::IOError,
|
||||
_ => WasiFsError::UnknownError(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait relies on your file closing when it goes out of scope via `Drop`
|
||||
pub trait WasiFile: std::fmt::Debug + Write + Read + Seek {
|
||||
/// the last time the file was accessed in nanoseconds as a UNIX timestamp
|
||||
fn last_accessed(&self) -> __wasi_timestamp_t;
|
||||
/// the last time the file was modified in nanoseconds as a UNIX timestamp
|
||||
fn last_modified(&self) -> __wasi_timestamp_t;
|
||||
/// the time at which the file was created in nanoseconds as a UNIX timestamp
|
||||
fn created_time(&self) -> __wasi_timestamp_t;
|
||||
/// set the last time the file was accessed in nanoseconds as a UNIX timestamp
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_last_accessed(&self, _last_accessed: __wasi_timestamp_t) {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::set_last_accessed for your type before then");
|
||||
}
|
||||
/// set the last time the file was modified in nanoseconds as a UNIX timestamp
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_last_modified(&self, _last_modified: __wasi_timestamp_t) {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::set_last_modified for your type before then");
|
||||
}
|
||||
/// set the time at which the file was created in nanoseconds as a UNIX timestamp
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_created_time(&self, _created_time: __wasi_timestamp_t) {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::set_created_time for your type before then");
|
||||
}
|
||||
/// the size of the file in bytes
|
||||
fn size(&self) -> u64;
|
||||
/// Change the size of the file, if the `new_size` is greater than the current size
|
||||
/// the extra bytes will be allocated and zeroed
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn set_len(&mut self, _new_size: __wasi_filesize_t) -> Option<()> {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::allocate for your type before then");
|
||||
}
|
||||
|
||||
/// Request deletion of the file
|
||||
// TODO: stablize this in 0.7.0 by removing default impl
|
||||
fn unlink(&mut self) -> Option<()> {
|
||||
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::unlink for your type before then");
|
||||
}
|
||||
}
|
||||
|
||||
/// A thin wrapper around `std::fs::File`
|
||||
#[derive(Debug)]
|
||||
pub struct HostFile {
|
||||
pub inner: fs::File,
|
||||
pub host_path: PathBuf,
|
||||
}
|
||||
|
||||
impl HostFile {
|
||||
/// creates a new host file from a `std::fs::File` and a path
|
||||
pub fn new(file: fs::File, host_path: PathBuf) -> Self {
|
||||
Self {
|
||||
inner: file,
|
||||
host_path,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> fs::Metadata {
|
||||
self.inner.metadata().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for HostFile {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.inner.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.inner.read_to_end(buf)
|
||||
}
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
self.inner.read_to_string(buf)
|
||||
}
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
self.inner.read_exact(buf)
|
||||
}
|
||||
}
|
||||
impl Seek for HostFile {
|
||||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||
self.inner.seek(pos)
|
||||
}
|
||||
}
|
||||
impl Write for HostFile {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.inner.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.inner.flush()
|
||||
}
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.inner.write_all(buf)
|
||||
}
|
||||
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
self.inner.write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for HostFile {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
self.metadata()
|
||||
.accessed()
|
||||
.ok()
|
||||
.and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok())
|
||||
.map(|ct| ct.as_nanos() as u64)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn set_last_accessed(&self, _last_accessed: __wasi_timestamp_t) {
|
||||
// TODO: figure out how to do this
|
||||
}
|
||||
|
||||
fn last_modified(&self) -> u64 {
|
||||
self.metadata()
|
||||
.modified()
|
||||
.ok()
|
||||
.and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok())
|
||||
.map(|ct| ct.as_nanos() as u64)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn set_last_modified(&self, _last_modified: __wasi_timestamp_t) {
|
||||
// TODO: figure out how to do this
|
||||
}
|
||||
|
||||
fn created_time(&self) -> u64 {
|
||||
self.metadata()
|
||||
.created()
|
||||
.ok()
|
||||
.and_then(|ct| ct.duration_since(SystemTime::UNIX_EPOCH).ok())
|
||||
.map(|ct| ct.as_nanos() as u64)
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn set_created_time(&self, _created_time: __wasi_timestamp_t) {
|
||||
// TODO: figure out how to do this
|
||||
}
|
||||
|
||||
fn size(&self) -> u64 {
|
||||
self.metadata().len()
|
||||
}
|
||||
|
||||
fn set_len(&mut self, new_size: __wasi_filesize_t) -> Option<()> {
|
||||
fs::File::set_len(&self.inner, new_size).ok()
|
||||
}
|
||||
|
||||
fn unlink(&mut self) -> Option<()> {
|
||||
std::fs::remove_file(&self.host_path).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stdout(pub std::io::Stdout);
|
||||
impl Read for Stdout {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stdout",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Seek for Stdout {
|
||||
fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not seek stdout",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.0.flush()
|
||||
}
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.0.write_all(buf)
|
||||
}
|
||||
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
self.0.write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for Stdout {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn last_modified(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn created_time(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn size(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stderr(pub std::io::Stderr);
|
||||
impl Read for Stderr {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
fn read_exact(&mut self, _buf: &mut [u8]) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not read from stderr",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Seek for Stderr {
|
||||
fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not seek stderr",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.0.flush()
|
||||
}
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.0.write_all(buf)
|
||||
}
|
||||
fn write_fmt(&mut self, fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
self.0.write_fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for Stderr {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn last_modified(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn created_time(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn size(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stdin(pub std::io::Stdin);
|
||||
impl Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.0.read_to_end(buf)
|
||||
}
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
self.0.read_to_string(buf)
|
||||
}
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
self.0.read_exact(buf)
|
||||
}
|
||||
}
|
||||
impl Seek for Stdin {
|
||||
fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not seek stdin",
|
||||
))
|
||||
}
|
||||
}
|
||||
impl Write for Stdin {
|
||||
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
fn write_fmt(&mut self, _fmt: ::std::fmt::Arguments) -> io::Result<()> {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"can not write to stdin",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl WasiFile for Stdin {
|
||||
fn last_accessed(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn last_modified(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn created_time(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
fn size(&self) -> u64 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: Think about using this
|
||||
trait WasiFdBacking: std::fmt::Debug {
|
||||
fn get_stat(&self) -> &__wasi_filestat_t;
|
||||
fn get_stat_mut(&mut self) -> &mut __wasi_filestat_t;
|
||||
fn is_preopened(&self) -> bool;
|
||||
fn get_name(&self) -> &str;
|
||||
}
|
||||
*/
|
@@ -9,8 +9,8 @@ use self::types::*;
|
||||
use crate::{
|
||||
ptr::{Array, WasmPtr},
|
||||
state::{
|
||||
self, host_file_type_to_wasi_file_type, Fd, Inode, InodeVal, Kind, WasiFile, WasiState,
|
||||
MAX_SYMLINKS,
|
||||
self, host_file_type_to_wasi_file_type, Fd, HostFile, Inode, InodeVal, Kind, WasiFile,
|
||||
WasiState, MAX_SYMLINKS,
|
||||
},
|
||||
ExitCode,
|
||||
};
|
||||
@@ -342,6 +342,7 @@ pub fn fd_allocate(
|
||||
Kind::Dir { .. } | Kind::Root { .. } => return __WASI_EISDIR,
|
||||
}
|
||||
state.fs.inodes[inode].stat.st_size = new_size;
|
||||
debug!("New file size: {}", new_size);
|
||||
|
||||
__WASI_ESUCCESS
|
||||
}
|
||||
@@ -420,6 +421,11 @@ pub fn fd_fdstat_get(
|
||||
);
|
||||
let mut state = get_wasi_state(ctx);
|
||||
let memory = ctx.memory(0);
|
||||
let fd_entry = wasi_try!(state.fs.get_fd(fd)).clone();
|
||||
if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_FILESTAT_GET) {
|
||||
return __WASI_EACCES;
|
||||
}
|
||||
|
||||
let stat = wasi_try!(state.fs.fdstat(fd));
|
||||
let buf = wasi_try!(buf_ptr.deref(memory));
|
||||
|
||||
@@ -1559,9 +1565,10 @@ pub fn path_open(
|
||||
.create(o_flags & __WASI_O_CREAT != 0)
|
||||
.truncate(o_flags & __WASI_O_TRUNC != 0);
|
||||
|
||||
*handle = Some(Box::new(wasi_try!(open_options
|
||||
.open(&path)
|
||||
.map_err(|_| __WASI_EIO))));
|
||||
*handle = Some(Box::new(HostFile::new(
|
||||
wasi_try!(open_options.open(&path).map_err(|_| __WASI_EIO)),
|
||||
path.to_path_buf(),
|
||||
)));
|
||||
}
|
||||
Kind::Buffer { .. } => unimplemented!("wasi::path_open for Buffer type files"),
|
||||
Kind::Dir { .. } | Kind::Root { .. } => {
|
||||
@@ -1618,14 +1625,13 @@ pub fn path_open(
|
||||
.write(true)
|
||||
.create_new(true);
|
||||
|
||||
Some(
|
||||
Box::new(wasi_try!(open_options.open(&new_file_host_path).map_err(
|
||||
|e| {
|
||||
debug!("Error opening file {}", e);
|
||||
__WASI_EIO
|
||||
}
|
||||
))) as Box<dyn WasiFile>,
|
||||
)
|
||||
Some(Box::new(HostFile::new(
|
||||
wasi_try!(open_options.open(&new_file_host_path).map_err(|e| {
|
||||
debug!("Error opening file {}", e);
|
||||
__WASI_EIO
|
||||
})),
|
||||
new_file_host_path.clone(),
|
||||
)) as Box<dyn WasiFile>)
|
||||
};
|
||||
|
||||
let new_inode = {
|
||||
@@ -1812,6 +1818,7 @@ pub fn path_unlink_file(
|
||||
|
||||
let base_dir = wasi_try!(state.fs.fd_map.get(&fd).ok_or(__WASI_EBADF));
|
||||
let path_str = wasi_try!(path.get_utf8_string(memory, path_len).ok_or(__WASI_EINVAL));
|
||||
debug!("Requested file: {}", path_str);
|
||||
|
||||
let inode = wasi_try!(state.fs.get_inode_at_path(fd, path_str, false));
|
||||
let (parent_inode, childs_name) =
|
||||
|
Reference in New Issue
Block a user