diff --git a/crates/wasi-common/src/file.rs b/crates/wasi-common/src/file.rs index 65fba7cd4a..b8eadb3673 100644 --- a/crates/wasi-common/src/file.rs +++ b/crates/wasi-common/src/file.rs @@ -4,30 +4,38 @@ use std::any::Any; use std::cell::{Ref, RefMut}; use std::ops::{Deref, DerefMut}; +#[wiggle::async_trait] pub trait WasiFile { fn as_any(&self) -> &dyn Any; - fn datasync(&self) -> Result<(), Error>; // write op - fn sync(&self) -> Result<(), Error>; // file op - fn get_filetype(&self) -> Result; // file op - fn get_fdflags(&self) -> Result; // file op - fn set_fdflags(&mut self, flags: FdFlags) -> Result<(), Error>; // file op - fn get_filestat(&self) -> Result; // split out get_length as a read & write op, rest is a file op - fn set_filestat_size(&self, _size: u64) -> Result<(), Error>; // write op - fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error>; // file op - fn allocate(&self, offset: u64, len: u64) -> Result<(), Error>; // write op - fn set_times( + async fn datasync(&self) -> Result<(), Error>; // write op + async fn sync(&self) -> Result<(), Error>; // file op + async fn get_filetype(&self) -> Result; // file op + async fn get_fdflags(&self) -> Result; // file op + async fn set_fdflags(&mut self, flags: FdFlags) -> Result<(), Error>; // file op + async fn get_filestat(&self) -> Result; // split out get_length as a read & write op, rest is a file op + async fn set_filestat_size(&self, _size: u64) -> Result<(), Error>; // write op + async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error>; // file op + async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error>; // write op + async fn set_times( &self, atime: Option, mtime: Option, ) -> Result<(), Error>; - fn read_vectored(&self, bufs: &mut [std::io::IoSliceMut]) -> Result; // read op - fn read_vectored_at(&self, bufs: &mut [std::io::IoSliceMut], offset: u64) - -> Result; // file op - fn write_vectored(&self, bufs: &[std::io::IoSlice]) -> Result; // write op - fn write_vectored_at(&self, bufs: &[std::io::IoSlice], offset: u64) -> Result; // file op - fn seek(&self, pos: std::io::SeekFrom) -> Result; // file op that generates a new stream from a file will supercede this - fn peek(&self, buf: &mut [u8]) -> Result; // read op - fn num_ready_bytes(&self) -> Result; // read op + async fn read_vectored<'a>(&self, bufs: &mut [std::io::IoSliceMut<'a>]) -> Result; // read op + async fn read_vectored_at<'a>( + &self, + bufs: &mut [std::io::IoSliceMut<'a>], + offset: u64, + ) -> Result; // file op + async fn write_vectored<'a>(&self, bufs: &[std::io::IoSlice<'a>]) -> Result; // write op + async fn write_vectored_at<'a>( + &self, + bufs: &[std::io::IoSlice<'a>], + offset: u64, + ) -> Result; // file op + async fn seek(&self, pos: std::io::SeekFrom) -> Result; // file op that generates a new stream from a file will supercede this + async fn peek(&self, buf: &mut [u8]) -> Result; // read op + async fn num_ready_bytes(&self) -> Result; // read op } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -111,11 +119,11 @@ impl FileEntry { Ok(()) } - pub fn get_fdstat(&self) -> Result { + pub async fn get_fdstat(&self) -> Result { Ok(FdStat { - filetype: self.file.get_filetype()?, + filetype: self.file.get_filetype().await?, caps: self.caps, - flags: self.file.get_fdflags()?, + flags: self.file.get_fdflags().await?, }) } } diff --git a/crates/wasi-common/src/pipe.rs b/crates/wasi-common/src/pipe.rs index 8bbc8d73b7..5e5d418767 100644 --- a/crates/wasi-common/src/pipe.rs +++ b/crates/wasi-common/src/pipe.rs @@ -105,30 +105,31 @@ impl From<&str> for ReadPipe> { } } +#[wiggle::async_trait] impl WasiFile for ReadPipe { fn as_any(&self) -> &dyn Any { self } - fn datasync(&self) -> Result<(), Error> { + async fn datasync(&self) -> Result<(), Error> { Ok(()) // trivial: no implementation needed } - fn sync(&self) -> Result<(), Error> { + async fn sync(&self) -> Result<(), Error> { Ok(()) // trivial } - fn get_filetype(&self) -> Result { + async fn get_filetype(&self) -> Result { Ok(FileType::Pipe) } - fn get_fdflags(&self) -> Result { + async fn get_fdflags(&self) -> Result { Ok(FdFlags::empty()) } - fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> { + async fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> { Err(Error::badf()) } - fn get_filestat(&self) -> Result { + async fn get_filestat(&self) -> Result { Ok(Filestat { device_id: 0, inode: 0, - filetype: self.get_filetype()?, + filetype: self.get_filetype().await?, nlink: 0, size: 0, // XXX no way to get a size out of a Read :( atim: None, @@ -136,42 +137,50 @@ impl WasiFile for ReadPipe { ctim: None, }) } - fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { + async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { Err(Error::badf()) } - fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> { + async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> { Err(Error::badf()) } - fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> { + async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> { Err(Error::badf()) } - fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result { + async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result { let n = self.borrow().read_vectored(bufs)?; Ok(n.try_into()?) } - fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut], offset: u64) -> Result { + async fn read_vectored_at<'a>( + &self, + bufs: &mut [io::IoSliceMut<'a>], + offset: u64, + ) -> Result { Err(Error::badf()) } - fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result { + async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result { Err(Error::badf()) } - fn write_vectored_at(&self, bufs: &[io::IoSlice], offset: u64) -> Result { + async fn write_vectored_at<'a>( + &self, + bufs: &[io::IoSlice<'a>], + offset: u64, + ) -> Result { Err(Error::badf()) } - fn seek(&self, pos: std::io::SeekFrom) -> Result { + async fn seek(&self, pos: std::io::SeekFrom) -> Result { Err(Error::badf()) } - fn peek(&self, buf: &mut [u8]) -> Result { + async fn peek(&self, buf: &mut [u8]) -> Result { Err(Error::badf()) } - fn set_times( + async fn set_times( &self, atime: Option, mtime: Option, ) -> Result<(), Error> { Err(Error::badf()) } - fn num_ready_bytes(&self) -> Result { + async fn num_ready_bytes(&self) -> Result { Ok(0) } } @@ -249,30 +258,31 @@ impl WritePipe>> { } } +#[wiggle::async_trait] impl WasiFile for WritePipe { fn as_any(&self) -> &dyn Any { self } - fn datasync(&self) -> Result<(), Error> { + async fn datasync(&self) -> Result<(), Error> { Ok(()) } - fn sync(&self) -> Result<(), Error> { + async fn sync(&self) -> Result<(), Error> { Ok(()) } - fn get_filetype(&self) -> Result { + async fn get_filetype(&self) -> Result { Ok(FileType::Pipe) } - fn get_fdflags(&self) -> Result { + async fn get_fdflags(&self) -> Result { Ok(FdFlags::APPEND) } - fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> { + async fn set_fdflags(&mut self, _fdflags: FdFlags) -> Result<(), Error> { Err(Error::badf()) } - fn get_filestat(&self) -> Result { + async fn get_filestat(&self) -> Result { Ok(Filestat { device_id: 0, inode: 0, - filetype: self.get_filetype()?, + filetype: self.get_filetype().await?, nlink: 0, size: 0, // XXX no way to get a size out of a Write :( atim: None, @@ -280,42 +290,50 @@ impl WasiFile for WritePipe { ctim: None, }) } - fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { + async fn set_filestat_size(&self, _size: u64) -> Result<(), Error> { Err(Error::badf()) } - fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> { + async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> { Err(Error::badf()) } - fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> { + async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> { Err(Error::badf()) } - fn read_vectored(&self, bufs: &mut [io::IoSliceMut]) -> Result { + async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result { Err(Error::badf()) } - fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut], offset: u64) -> Result { + async fn read_vectored_at<'a>( + &self, + bufs: &mut [io::IoSliceMut<'a>], + offset: u64, + ) -> Result { Err(Error::badf()) } - fn write_vectored(&self, bufs: &[io::IoSlice]) -> Result { + async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result { let n = self.borrow().write_vectored(bufs)?; Ok(n.try_into()?) } - fn write_vectored_at(&self, bufs: &[io::IoSlice], offset: u64) -> Result { + async fn write_vectored_at<'a>( + &self, + bufs: &[io::IoSlice<'a>], + offset: u64, + ) -> Result { Err(Error::badf()) } - fn seek(&self, pos: std::io::SeekFrom) -> Result { + async fn seek(&self, pos: std::io::SeekFrom) -> Result { Err(Error::badf()) } - fn peek(&self, buf: &mut [u8]) -> Result { + async fn peek(&self, buf: &mut [u8]) -> Result { Err(Error::badf()) } - fn set_times( + async fn set_times( &self, atime: Option, mtime: Option, ) -> Result<(), Error> { Err(Error::badf()) } - fn num_ready_bytes(&self) -> Result { + async fn num_ready_bytes(&self) -> Result { Ok(0) } } diff --git a/crates/wasi-common/src/snapshots/preview_0.rs b/crates/wasi-common/src/snapshots/preview_0.rs index a428c3f7ea..362789bc35 100644 --- a/crates/wasi-common/src/snapshots/preview_0.rs +++ b/crates/wasi-common/src/snapshots/preview_0.rs @@ -422,7 +422,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { } async fn fd_filestat_get(&self, fd: types::Fd) -> Result { - Ok(Snapshot1::fd_filestat_get(self, fd.into())?.into()).await + Ok(Snapshot1::fd_filestat_get(self, fd.into()).await?.into()) } async fn fd_filestat_set_size( @@ -473,7 +473,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .map(|s| IoSliceMut::new(&mut *s)) .collect(); - let bytes_read = f.read_vectored(&mut ioslices)?; + let bytes_read = f.read_vectored(&mut ioslices).await?; Ok(types::Size::try_from(bytes_read)?) } @@ -502,7 +502,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .map(|s| IoSliceMut::new(&mut *s)) .collect(); - let bytes_read = f.read_vectored_at(&mut ioslices, offset)?; + let bytes_read = f.read_vectored_at(&mut ioslices, offset).await?; Ok(types::Size::try_from(bytes_read)?) } @@ -527,7 +527,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .iter() .map(|s| IoSlice::new(s.deref())) .collect(); - let bytes_written = f.write_vectored(&ioslices)?; + let bytes_written = f.write_vectored(&ioslices).await?; Ok(types::Size::try_from(bytes_written)?) } @@ -556,7 +556,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx { .iter() .map(|s| IoSlice::new(s.deref())) .collect(); - let bytes_written = f.write_vectored_at(&ioslices, offset)?; + let bytes_written = f.write_vectored_at(&ioslices, offset).await?; Ok(types::Size::try_from(bytes_written)?) } diff --git a/crates/wasi-common/src/snapshots/preview_1.rs b/crates/wasi-common/src/snapshots/preview_1.rs index 1d5315b723..4d1189f761 100644 --- a/crates/wasi-common/src/snapshots/preview_1.rs +++ b/crates/wasi-common/src/snapshots/preview_1.rs @@ -22,6 +22,9 @@ use wiggle::GuestPtr; wiggle::from_witx!({ witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"], errors: { errno => Error }, + // Note: not every function actually needs to be async, however, nearly all of them do, and + // keeping that set the same in this macro and the wasmtime_wiggle / lucet_wiggle macros is + // tedious, and there is no cost to having a sync function be async in this case. async: * }); @@ -261,7 +264,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { self.table() .get_file(u32::from(fd))? .get_cap(FileCaps::ADVISE)? - .advise(offset, len, advice.into())?; + .advise(offset, len, advice.into()) + .await?; Ok(()) } @@ -274,7 +278,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { self.table() .get_file(u32::from(fd))? .get_cap(FileCaps::ALLOCATE)? - .allocate(offset, len)?; + .allocate(offset, len) + .await?; Ok(()) } @@ -308,7 +313,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { self.table() .get_file(u32::from(fd))? .get_cap(FileCaps::DATASYNC)? - .datasync()?; + .datasync() + .await?; Ok(()) } @@ -317,7 +323,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let fd = u32::from(fd); if table.is::(fd) { let file_entry: Ref = table.get(fd)?; - let fdstat = file_entry.get_fdstat()?; + let fdstat = file_entry.get_fdstat().await?; Ok(types::Fdstat::from(&fdstat)) } else if table.is::(fd) { let dir_entry: Ref = table.get(fd)?; @@ -333,6 +339,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .get_file_mut(u32::from(fd))? .get_cap(FileCaps::FDSTAT_SET_FLAGS)? .set_fdflags(FdFlags::from(flags)) + .await } async fn fd_fdstat_set_rights( @@ -364,7 +371,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { let filestat = table .get_file(fd)? .get_cap(FileCaps::FILESTAT_GET)? - .get_filestat()?; + .get_filestat() + .await?; Ok(filestat.into()) } else if table.is::(fd) { let filestat = table @@ -385,7 +393,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { self.table() .get_file(u32::from(fd))? .get_cap(FileCaps::FILESTAT_SET_SIZE)? - .set_filestat_size(size)?; + .set_filestat_size(size) + .await?; Ok(()) } @@ -413,6 +422,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .expect("checked that entry is file") .get_cap(FileCaps::FILESTAT_SET_TIMES)? .set_times(atim, mtim) + .await } else if table.is::(fd) { table .get_dir(fd) @@ -446,7 +456,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .map(|s| IoSliceMut::new(&mut *s)) .collect(); - let bytes_read = f.read_vectored(&mut ioslices)?; + let bytes_read = f.read_vectored(&mut ioslices).await?; Ok(types::Size::try_from(bytes_read)?) } @@ -475,7 +485,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .map(|s| IoSliceMut::new(&mut *s)) .collect(); - let bytes_read = f.read_vectored_at(&mut ioslices, offset)?; + let bytes_read = f.read_vectored_at(&mut ioslices, offset).await?; Ok(types::Size::try_from(bytes_read)?) } @@ -500,7 +510,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .iter() .map(|s| IoSlice::new(s.deref())) .collect(); - let bytes_written = f.write_vectored(&ioslices)?; + let bytes_written = f.write_vectored(&ioslices).await?; Ok(types::Size::try_from(bytes_written)?) } @@ -529,7 +539,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .iter() .map(|s| IoSlice::new(s.deref())) .collect(); - let bytes_written = f.write_vectored_at(&ioslices, offset)?; + let bytes_written = f.write_vectored_at(&ioslices, offset).await?; Ok(types::Size::try_from(bytes_written)?) } @@ -610,7 +620,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .table() .get_file(u32::from(fd))? .get_cap(required_caps)? - .seek(whence)?; + .seek(whence) + .await?; Ok(newoffset) } @@ -618,7 +629,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { self.table() .get_file(u32::from(fd))? .get_cap(FileCaps::SYNC)? - .sync()?; + .sync() + .await?; Ok(()) } @@ -628,7 +640,8 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx { .table() .get_file(u32::from(fd))? .get_cap(FileCaps::TELL)? - .seek(std::io::SeekFrom::Current(0))?; + .seek(std::io::SeekFrom::Current(0)) + .await?; Ok(offset) }