push the error types conversion all the way through

This commit is contained in:
Pat Hickey
2021-01-22 15:29:09 -08:00
parent 1d8070b734
commit 423973a8ea
6 changed files with 59 additions and 38 deletions

View File

@@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
use wasi_c2::{ use wasi_c2::{
dir::{ReaddirCursor, ReaddirEntity, WasiDir}, dir::{ReaddirCursor, ReaddirEntity, WasiDir},
file::{FdFlags, FileCaps, FileType, Filestat, OFlags, WasiFile}, file::{FdFlags, FileCaps, FileType, Filestat, OFlags, WasiFile},
Error, Error, ErrorExt,
}; };
pub struct Dir(cap_std::fs::Dir); pub struct Dir(cap_std::fs::Dir);
@@ -118,7 +118,10 @@ impl WasiDir for Dir {
let meta = entry.metadata()?; let meta = entry.metadata()?;
let inode = meta.ino(); let inode = meta.ino();
let filetype = filetype_from(&meta.file_type()); let filetype = filetype_from(&meta.file_type());
let name = entry.file_name().into_string().map_err(|_| Error::Ilseq)?; let name = entry
.file_name()
.into_string()
.map_err(|_| Error::illegal_byte_sequence().context("filename"))?;
let namelen = name.as_bytes().len().try_into()?; let namelen = name.as_bytes().len().try_into()?;
Ok((filetype, inode, namelen, name)) Ok((filetype, inode, namelen, name))
}), }),
@@ -189,7 +192,7 @@ impl WasiDir for Dir {
let dest_dir = dest_dir let dest_dir = dest_dir
.as_any() .as_any()
.downcast_ref::<Self>() .downcast_ref::<Self>()
.ok_or(Error::NotCapable)?; .ok_or(Error::badf().context("failed downcast to cap-std Dir"))?;
self.0 self.0
.rename(Path::new(src_path), &dest_dir.0, Path::new(dest_path))?; .rename(Path::new(src_path), &dest_dir.0, Path::new(dest_path))?;
Ok(()) Ok(())
@@ -204,7 +207,7 @@ impl WasiDir for Dir {
let target_dir = target_dir let target_dir = target_dir
.as_any() .as_any()
.downcast_ref::<Self>() .downcast_ref::<Self>()
.ok_or(Error::NotCapable)?; .ok_or(Error::badf().context("failed downcast to cap-std Dir"))?;
let src_path = Path::new(src_path); let src_path = Path::new(src_path);
let target_path = Path::new(target_path); let target_path = Path::new(target_path);
self.0.hard_link(src_path, &target_dir.0, target_path)?; self.0.hard_link(src_path, &target_dir.0, target_path)?;

View File

@@ -77,26 +77,26 @@ impl WasiFile for File {
} }
fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> { fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> {
let n = self.0.read_vectored(bufs)?; let n = self.0.read_vectored(bufs)?;
Ok(n.try_into().map_err(|_| Error::Overflow)?) Ok(n.try_into()?)
} }
fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut], offset: u64) -> Result<u64, Error> { fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut], offset: u64) -> Result<u64, Error> {
let n = self.0.read_vectored_at(bufs, offset)?; let n = self.0.read_vectored_at(bufs, offset)?;
Ok(n.try_into().map_err(|_| Error::Overflow)?) Ok(n.try_into()?)
} }
fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result<u64, Error> { fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result<u64, Error> {
let n = self.0.write_vectored(bufs)?; let n = self.0.write_vectored(bufs)?;
Ok(n.try_into().map_err(|_| Error::Overflow)?) Ok(n.try_into()?)
} }
fn write_vectored_at(&self, bufs: &[io::IoSlice], offset: u64) -> Result<u64, Error> { fn write_vectored_at(&self, bufs: &[io::IoSlice], offset: u64) -> Result<u64, Error> {
let n = self.0.write_vectored_at(bufs, offset)?; let n = self.0.write_vectored_at(bufs, offset)?;
Ok(n.try_into().map_err(|_| Error::Overflow)?) Ok(n.try_into()?)
} }
fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> { fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
Ok(self.0.seek(pos)?) Ok(self.0.seek(pos)?)
} }
fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> { fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
let n = self.0.peek(buf)?; let n = self.0.peek(buf)?;
Ok(n.try_into().map_err(|_| Error::Overflow)?) Ok(n.try_into()?)
} }
fn num_ready_bytes(&self) -> Result<u64, Error> { fn num_ready_bytes(&self) -> Result<u64, Error> {
Ok(self.0.num_ready_bytes()?) Ok(self.0.num_ready_bytes()?)

View File

@@ -8,7 +8,7 @@ use wasi_c2::{
subscription::{RwEventFlags, Subscription}, subscription::{RwEventFlags, Subscription},
Poll, WasiSched, Poll, WasiSched,
}, },
Error, Error, ErrorExt,
}; };
use poll::{PollFd, PollFlags}; use poll::{PollFd, PollFlags};
@@ -25,12 +25,16 @@ impl WasiSched for SyncSched {
for s in poll.rw_subscriptions() { for s in poll.rw_subscriptions() {
match s { match s {
Subscription::Read(f) => { Subscription::Read(f) => {
let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(Error::Inval)?; let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(
Error::invalid_argument().context("read subscription fd downcast failed"),
)?;
pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLIN) }); pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLIN) });
} }
Subscription::Write(f) => { Subscription::Write(f) => {
let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(Error::Inval)?; let raw_fd = wasi_file_raw_fd(f.file.deref()).ok_or(
Error::invalid_argument().context("write subscription fd downcast failed"),
)?;
pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLOUT) }); pollfds.push(unsafe { PollFd::new(raw_fd, PollFlags::POLLOUT) });
} }
Subscription::MonotonicClock { .. } => unreachable!(), Subscription::MonotonicClock { .. } => unreachable!(),
@@ -45,7 +49,7 @@ impl WasiSched for SyncSched {
.unwrap_or(Duration::from_secs(0)); .unwrap_or(Duration::from_secs(0));
(duration.as_millis() + 1) // XXX try always rounding up? (duration.as_millis() + 1) // XXX try always rounding up?
.try_into() .try_into()
.map_err(|_| Error::Overflow)? .map_err(|_| Error::overflow().context("poll timeout"))?
} else { } else {
libc::c_int::max_value() libc::c_int::max_value()
}; };
@@ -78,9 +82,9 @@ impl WasiSched for SyncSched {
_ => unreachable!(), _ => unreachable!(),
}; };
if revents.contains(PollFlags::POLLNVAL) { if revents.contains(PollFlags::POLLNVAL) {
rwsub.error(Error::Badf); rwsub.error(Error::badf());
} else if revents.contains(PollFlags::POLLERR) { } else if revents.contains(PollFlags::POLLERR) {
rwsub.error(Error::Io); rwsub.error(Error::io());
} else if revents.contains(PollFlags::POLLHUP) { } else if revents.contains(PollFlags::POLLHUP) {
rwsub.complete(nbytes, RwEventFlags::HANGUP); rwsub.complete(nbytes, RwEventFlags::HANGUP);
} else { } else {

View File

@@ -13,7 +13,7 @@ use std::os::windows::io::{AsRawHandle, RawHandle};
use unsafe_io::AsUnsafeFile; use unsafe_io::AsUnsafeFile;
use wasi_c2::{ use wasi_c2::{
file::{FdFlags, FileType, Filestat, WasiFile}, file::{FdFlags, FileType, Filestat, WasiFile},
Error, Error, ErrorExt,
}; };
pub struct Stdin(std::io::Stdin); pub struct Stdin(std::io::Stdin);
@@ -40,7 +40,7 @@ impl WasiFile for Stdin {
Ok(FdFlags::empty()) Ok(FdFlags::empty())
} }
unsafe fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> { unsafe fn reopen_with_fdflags(&self, _fdflags: FdFlags) -> Result<Box<dyn WasiFile>, Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn get_filestat(&self) -> Result<Filestat, Error> { fn get_filestat(&self) -> Result<Filestat, Error> {
let meta = self.0.as_file_view().metadata()?; let meta = self.0.as_file_view().metadata()?;
@@ -56,32 +56,32 @@ impl WasiFile for Stdin {
}) })
} }
fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> { fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn allocate(&self, _offset: u64, _len: u64) -> Result<(), Error> { fn allocate(&self, _offset: u64, _len: u64) -> Result<(), Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> { fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> {
let n = self.0.as_file_view().read_vectored(bufs)?; let n = self.0.as_file_view().read_vectored(bufs)?;
Ok(n.try_into().map_err(|_| Error::Overflow)?) Ok(n.try_into().map_err(|_| Error::range())?)
} }
fn read_vectored_at(&self, _bufs: &mut [io::IoSliceMut], _offset: u64) -> Result<u64, Error> { fn read_vectored_at(&self, _bufs: &mut [io::IoSliceMut], _offset: u64) -> Result<u64, Error> {
Err(Error::Spipe) Err(Error::seek_pipe())
} }
fn write_vectored(&self, _bufs: &[io::IoSlice]) -> Result<u64, Error> { fn write_vectored(&self, _bufs: &[io::IoSlice]) -> Result<u64, Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn write_vectored_at(&self, _bufs: &[io::IoSlice], _offset: u64) -> Result<u64, Error> { fn write_vectored_at(&self, _bufs: &[io::IoSlice], _offset: u64) -> Result<u64, Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> { fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> {
Err(Error::Spipe) Err(Error::seek_pipe())
} }
fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> { fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> {
Err(Error::Spipe) Err(Error::seek_pipe())
} }
fn set_times( fn set_times(
&self, &self,
@@ -132,7 +132,7 @@ macro_rules! wasi_file_write_impl {
&self, &self,
_fdflags: FdFlags, _fdflags: FdFlags,
) -> Result<Box<dyn WasiFile>, Error> { ) -> Result<Box<dyn WasiFile>, Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn get_filestat(&self) -> Result<Filestat, Error> { fn get_filestat(&self) -> Result<Filestat, Error> {
let meta = self.0.as_file_view().metadata()?; let meta = self.0.as_file_view().metadata()?;
@@ -148,36 +148,36 @@ macro_rules! wasi_file_write_impl {
}) })
} }
fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> { fn advise(&self, _offset: u64, _len: u64, _advice: Advice) -> Result<(), Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn allocate(&self, _offset: u64, _len: u64) -> Result<(), Error> { fn allocate(&self, _offset: u64, _len: u64) -> Result<(), Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn read_vectored(&self, _bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> { fn read_vectored(&self, _bufs: &mut [io::IoSliceMut]) -> Result<u64, Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn read_vectored_at( fn read_vectored_at(
&self, &self,
_bufs: &mut [io::IoSliceMut], _bufs: &mut [io::IoSliceMut],
_offset: u64, _offset: u64,
) -> Result<u64, Error> { ) -> Result<u64, Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result<u64, Error> { fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result<u64, Error> {
let n = self.0.as_file_view().write_vectored(bufs)?; let n = self.0.as_file_view().write_vectored(bufs)?;
Ok(n.try_into().map_err(|_| Error::Overflow)?) Ok(n.try_into().map_err(|c| Error::range().context(c))?)
} }
fn write_vectored_at(&self, _bufs: &[io::IoSlice], _offset: u64) -> Result<u64, Error> { fn write_vectored_at(&self, _bufs: &[io::IoSlice], _offset: u64) -> Result<u64, Error> {
Err(Error::Spipe) Err(Error::seek_pipe())
} }
fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> { fn seek(&self, _pos: std::io::SeekFrom) -> Result<u64, Error> {
Err(Error::Spipe) Err(Error::seek_pipe())
} }
fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> { fn peek(&self, _buf: &mut [u8]) -> Result<u64, Error> {
Err(Error::Badf) Err(Error::badf())
} }
fn set_times( fn set_times(
&self, &self,

View File

@@ -21,6 +21,9 @@ pub enum ErrorKind {
/// Errno::Inval: Invalid argument /// Errno::Inval: Invalid argument
#[error("Inval: Invalid argument")] #[error("Inval: Invalid argument")]
Inval, Inval,
/// Errno::Io: I/O error
#[error("Io: I/O error")]
Io,
/// Errno::Nametoolong: Filename too long /// Errno::Nametoolong: Filename too long
#[error("Nametoolong: Filename too long")] #[error("Nametoolong: Filename too long")]
Nametoolong, Nametoolong,
@@ -50,6 +53,7 @@ pub trait ErrorExt {
fn exist() -> Self; fn exist() -> Self;
fn illegal_byte_sequence() -> Self; fn illegal_byte_sequence() -> Self;
fn invalid_argument() -> Self; fn invalid_argument() -> Self;
fn io() -> Self;
fn name_too_long() -> Self; fn name_too_long() -> Self;
fn not_dir() -> Self; fn not_dir() -> Self;
fn not_supported() -> Self; fn not_supported() -> Self;
@@ -75,6 +79,9 @@ impl ErrorExt for Error {
fn invalid_argument() -> Self { fn invalid_argument() -> Self {
ErrorKind::Inval.into() ErrorKind::Inval.into()
} }
fn io() -> Self {
ErrorKind::Io.into()
}
fn name_too_long() -> Self { fn name_too_long() -> Self {
ErrorKind::Nametoolong.into() ErrorKind::Nametoolong.into()
} }

View File

@@ -79,6 +79,7 @@ impl From<ErrorKind> for types::Errno {
ErrorKind::Exist => Errno::Exist, ErrorKind::Exist => Errno::Exist,
ErrorKind::Ilseq => Errno::Ilseq, ErrorKind::Ilseq => Errno::Ilseq,
ErrorKind::Inval => Errno::Inval, ErrorKind::Inval => Errno::Inval,
ErrorKind::Io => Errno::Io,
ErrorKind::Nametoolong => Errno::Nametoolong, ErrorKind::Nametoolong => Errno::Nametoolong,
ErrorKind::Notdir => Errno::Notdir, ErrorKind::Notdir => Errno::Notdir,
ErrorKind::Notsup => Errno::Notsup, ErrorKind::Notsup => Errno::Notsup,
@@ -141,9 +142,15 @@ impl TryFrom<std::io::Error> for types::Errno {
libc::EOVERFLOW => Ok(types::Errno::Overflow), libc::EOVERFLOW => Ok(types::Errno::Overflow),
libc::EILSEQ => Ok(types::Errno::Ilseq), libc::EILSEQ => Ok(types::Errno::Ilseq),
libc::ENOTSUP => Ok(types::Errno::Notsup), libc::ENOTSUP => Ok(types::Errno::Notsup),
_ => Err(anyhow!(err).context("Unknown raw OS error")), code => Err(anyhow!(err).context(format!("Unknown raw OS error: {}", code))),
},
None => match err.kind() {
std::io::ErrorKind::NotFound => Ok(types::Errno::Noent),
std::io::ErrorKind::PermissionDenied => Ok(types::Errno::Perm),
std::io::ErrorKind::AlreadyExists => Ok(types::Errno::Exist),
std::io::ErrorKind::InvalidInput => Ok(types::Errno::Ilseq),
k => Err(anyhow!(err).context(format!("No raw OS error. Unhandled kind: {:?}", k))),
}, },
None => Err(anyhow!(err).context("No raw OS error")),
} }
} }
} }