diff --git a/crates/wasi-common/src/fdentry.rs b/crates/wasi-common/src/fdentry.rs index 644e06ffa751..c2c9a719dae8 100644 --- a/crates/wasi-common/src/fdentry.rs +++ b/crates/wasi-common/src/fdentry.rs @@ -10,64 +10,6 @@ use std::ops::{Deref, DerefMut}; use std::path::PathBuf; use std::{fmt, fs, io}; -pub(crate) enum HandleMut<'handle> { - OsHandle(&'handle mut OsHandle), - VirtualFile(&'handle mut dyn VirtualFile), - Stream(OsHandleRef<'handle>), -} - -impl<'descriptor> fmt::Debug for HandleMut<'descriptor> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - HandleMut::OsHandle(file) => { - // coerce to the target debug-printable type - let file: &fs::File = file; - write!(f, "{:?}", file) - } - HandleMut::Stream(stream) => { - // coerce to the target debug-printable type - let file: &fs::File = stream; - write!(f, "{:?}", file) - } - HandleMut::VirtualFile(_) => write!(f, "VirtualFile"), - } - } -} - -pub(crate) enum Handle<'handle> { - OsHandle(&'handle OsHandle), - VirtualFile(&'handle dyn VirtualFile), - Stream(OsHandleRef<'handle>), -} - -impl<'descriptor> Handle<'descriptor> { - pub(crate) fn try_clone(&self) -> io::Result<Descriptor> { - match self { - Handle::OsHandle(file) => file.try_clone().map(|f| OsHandle::from(f).into()), - Handle::Stream(stream) => stream.try_clone().map(|f| OsHandle::from(f).into()), - Handle::VirtualFile(virt) => virt.try_clone().map(Descriptor::VirtualFile), - } - } -} - -impl<'descriptor> fmt::Debug for Handle<'descriptor> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Handle::OsHandle(file) => { - // coerce to the target debug-printable type - let file: &fs::File = file; - write!(f, "{:?}", file) - } - Handle::Stream(stream) => { - // coerce to the target debug-printable type - let file: &fs::File = stream; - write!(f, "{:?}", file) - } - Handle::VirtualFile(_) => write!(f, "VirtualFile"), - } - } -} - pub(crate) enum Descriptor { OsHandle(OsHandle), VirtualFile(Box<dyn VirtualFile>), @@ -101,13 +43,23 @@ impl fmt::Debug for Descriptor { } impl Descriptor { + pub(crate) fn try_clone(&self) -> io::Result<Descriptor> { + match self { + Descriptor::OsHandle(file) => file.try_clone().map(|f| OsHandle::from(f).into()), + Descriptor::VirtualFile(virt) => virt.try_clone().map(Descriptor::VirtualFile), + Descriptor::Stdin => Ok(Descriptor::Stdin), + Descriptor::Stdout => Ok(Descriptor::Stdout), + Descriptor::Stderr => Ok(Descriptor::Stderr), + } + } + /// Return a reference to the `OsHandle` or `VirtualFile` treating it as an /// actual file/dir, and allowing operations which require an actual file and /// not just a stream or socket file descriptor. - pub(crate) fn as_file<'descriptor>(&'descriptor self) -> Result<Handle<'descriptor>> { + pub(crate) fn as_file<'descriptor>(&'descriptor self) -> Result<&'descriptor Descriptor> { match self { - Self::OsHandle(handle) => Ok(Handle::OsHandle(handle)), - Self::VirtualFile(virt) => Ok(Handle::VirtualFile(virt.as_ref())), + Self::OsHandle(_) => Ok(self), + Self::VirtualFile(_) => Ok(self), _ => Err(Error::EBADF), } } @@ -115,34 +67,14 @@ impl Descriptor { /// Like `as_file`, but return a mutable reference. pub(crate) fn as_file_mut<'descriptor>( &'descriptor mut self, - ) -> Result<HandleMut<'descriptor>> { + ) -> Result<&'descriptor mut Descriptor> { match self { - Self::OsHandle(handle) => Ok(HandleMut::OsHandle(handle)), - Self::VirtualFile(virt) => Ok(HandleMut::VirtualFile(virt.as_mut())), + Self::OsHandle(_) => Ok(self), + Self::VirtualFile(_) => Ok(self), _ => Err(Error::EBADF), } } - pub(crate) fn as_handle<'descriptor>(&'descriptor self) -> Handle<'descriptor> { - match self { - Self::VirtualFile(virt) => Handle::VirtualFile(virt.as_ref()), - Self::OsHandle(handle) => Handle::OsHandle(handle), - other @ Self::Stdin | other @ Self::Stderr | other @ Self::Stdout => { - Handle::Stream(other.as_os_handle()) - } - } - } - - pub(crate) fn as_handle_mut<'descriptor>(&'descriptor mut self) -> HandleMut<'descriptor> { - match self { - Self::VirtualFile(virt) => HandleMut::VirtualFile(virt.as_mut()), - Self::OsHandle(handle) => HandleMut::OsHandle(handle), - other @ Self::Stdin | other @ Self::Stderr | other @ Self::Stdout => { - HandleMut::Stream(other.as_os_handle()) - } - } - } - /// Return an `OsHandle`, which may be a stream or socket file descriptor. pub(crate) fn as_os_handle<'descriptor>(&'descriptor self) -> OsHandleRef<'descriptor> { descriptor_as_oshandle(self) diff --git a/crates/wasi-common/src/hostcalls_impl/fs.rs b/crates/wasi-common/src/hostcalls_impl/fs.rs index 13530a7efbb7..adedd18fce26 100644 --- a/crates/wasi-common/src/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/hostcalls_impl/fs.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] use super::fs_helpers::path_get; use crate::ctx::WasiCtx; -use crate::fdentry::{Descriptor, FdEntry, Handle, HandleMut}; +use crate::fdentry::{Descriptor, FdEntry}; use crate::helpers::*; use crate::host::Dirent; use crate::memory::*; @@ -42,13 +42,12 @@ pub(crate) unsafe fn fd_datasync( let file = wasi_ctx .get_fd_entry(fd)? - .as_descriptor(wasi::__WASI_RIGHTS_FD_DATASYNC, 0)? - .as_handle(); + .as_descriptor(wasi::__WASI_RIGHTS_FD_DATASYNC, 0)?; match file { - Handle::OsHandle(fd) => fd.sync_data().map_err(Into::into), - Handle::Stream(stream) => stream.sync_data().map_err(Into::into), - Handle::VirtualFile(virt) => virt.datasync(), + Descriptor::OsHandle(fd) => fd.sync_data().map_err(Into::into), + Descriptor::VirtualFile(virt) => virt.datasync(), + other => other.as_os_handle().sync_data().map_err(Into::into), } } @@ -83,9 +82,9 @@ pub(crate) unsafe fn fd_pread( let buf_size = iovs.iter().map(|v| v.buf_len).sum(); let mut buf = vec![0; buf_size]; let host_nread = match file { - Handle::OsHandle(fd) => hostcalls_impl::fd_pread(&fd, &mut buf, offset)?, - Handle::VirtualFile(virt) => virt.pread(&mut buf, offset)?, - Handle::Stream(_) => { + Descriptor::OsHandle(fd) => hostcalls_impl::fd_pread(&fd, &mut buf, offset)?, + Descriptor::VirtualFile(virt) => virt.pread(&mut buf, offset)?, + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -149,9 +148,9 @@ pub(crate) unsafe fn fd_pwrite( )); } let host_nwritten = match file { - Handle::OsHandle(fd) => hostcalls_impl::fd_pwrite(&fd, &buf, offset)?, - Handle::VirtualFile(virt) => virt.pwrite(buf.as_mut(), offset)?, - Handle::Stream(_) => { + Descriptor::OsHandle(fd) => hostcalls_impl::fd_pwrite(&fd, &buf, offset)?, + Descriptor::VirtualFile(virt) => virt.pwrite(buf.as_mut(), offset)?, + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -266,9 +265,9 @@ pub(crate) unsafe fn fd_seek( _ => return Err(Error::EINVAL), }; let host_newoffset = match file { - HandleMut::OsHandle(fd) => fd.seek(pos)?, - HandleMut::VirtualFile(virt) => virt.seek(pos)?, - HandleMut::Stream(_) => { + Descriptor::OsHandle(fd) => fd.seek(pos)?, + Descriptor::VirtualFile(virt) => virt.seek(pos)?, + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -294,9 +293,9 @@ pub(crate) unsafe fn fd_tell( .as_file_mut()?; let host_offset = match file { - HandleMut::OsHandle(fd) => fd.seek(SeekFrom::Current(0))?, - HandleMut::VirtualFile(virt) => virt.seek(SeekFrom::Current(0))?, - HandleMut::Stream(_) => { + Descriptor::OsHandle(fd) => fd.seek(SeekFrom::Current(0))?, + Descriptor::VirtualFile(virt) => virt.seek(SeekFrom::Current(0))?, + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -317,12 +316,12 @@ pub(crate) unsafe fn fd_fdstat_get( trace!("fd_fdstat_get(fd={:?}, fdstat_ptr={:#x?})", fd, fdstat_ptr); let mut fdstat = dec_fdstat_byref(memory, fdstat_ptr)?; - let wasi_file = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?.as_handle(); + let wasi_file = wasi_ctx.get_fd_entry(fd)?.as_descriptor(0, 0)?; let fs_flags = match wasi_file { - Handle::OsHandle(wasi_fd) => hostcalls_impl::fd_fdstat_get(&wasi_fd)?, - Handle::Stream(stream) => hostcalls_impl::fd_fdstat_get(&stream)?, - Handle::VirtualFile(virt) => virt.fdstat_get(), + Descriptor::OsHandle(wasi_fd) => hostcalls_impl::fd_fdstat_get(&wasi_fd)?, + Descriptor::VirtualFile(virt) => virt.fdstat_get(), + other => hostcalls_impl::fd_fdstat_get(&other.as_os_handle())?, }; let fe = wasi_ctx.get_fd_entry(fd)?; @@ -348,8 +347,8 @@ pub(crate) unsafe fn fd_fdstat_set_flags( .get_fd_entry_mut(fd)? .as_descriptor_mut(wasi::__WASI_RIGHTS_FD_FDSTAT_SET_FLAGS, 0)?; - match descriptor.as_handle_mut() { - HandleMut::OsHandle(handle) => { + match descriptor { + Descriptor::OsHandle(handle) => { let set_result = hostcalls_impl::fd_fdstat_set_flags(&handle, fdflags)?.map(Descriptor::OsHandle); @@ -357,17 +356,18 @@ pub(crate) unsafe fn fd_fdstat_set_flags( *descriptor = new_descriptor; } } - HandleMut::Stream(handle) => { + Descriptor::VirtualFile(handle) => { + handle.fdstat_set_flags(fdflags)?; + } + _ => { let set_result = - hostcalls_impl::fd_fdstat_set_flags(&handle, fdflags)?.map(Descriptor::OsHandle); + hostcalls_impl::fd_fdstat_set_flags(&descriptor.as_os_handle(), fdflags)? + .map(Descriptor::OsHandle); if let Some(new_descriptor) = set_result { *descriptor = new_descriptor; } } - HandleMut::VirtualFile(handle) => { - handle.fdstat_set_flags(fdflags)?; - } }; Ok(()) @@ -411,9 +411,9 @@ pub(crate) unsafe fn fd_sync( .as_descriptor(wasi::__WASI_RIGHTS_FD_SYNC, 0)? .as_file()?; match file { - Handle::OsHandle(fd) => fd.sync_all().map_err(Into::into), - Handle::VirtualFile(virt) => virt.sync(), - Handle::Stream(_) => { + Descriptor::OsHandle(fd) => fd.sync_all().map_err(Into::into), + Descriptor::VirtualFile(virt) => virt.sync(), + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -485,7 +485,7 @@ pub(crate) unsafe fn fd_write( } pub(crate) unsafe fn fd_advise( - wasi_ctx: &WasiCtx, + wasi_ctx: &mut WasiCtx, _memory: &mut [u8], fd: wasi::__wasi_fd_t, offset: wasi::__wasi_filesize_t, @@ -501,14 +501,14 @@ pub(crate) unsafe fn fd_advise( ); let file = wasi_ctx - .get_fd_entry(fd)? - .as_descriptor(wasi::__WASI_RIGHTS_FD_ADVISE, 0)? - .as_handle(); + .get_fd_entry_mut(fd)? + .as_descriptor_mut(wasi::__WASI_RIGHTS_FD_ADVISE, 0)? + .as_file_mut()?; match file { - Handle::OsHandle(fd) => hostcalls_impl::fd_advise(&fd, advice, offset, len), - Handle::VirtualFile(virt) => virt.advise(advice, offset, len), - Handle::Stream(_) => { + Descriptor::OsHandle(fd) => hostcalls_impl::fd_advise(&fd, advice, offset, len), + Descriptor::VirtualFile(virt) => virt.advise(advice, offset, len), + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -531,7 +531,7 @@ pub(crate) unsafe fn fd_allocate( .as_file()?; match file { - Handle::OsHandle(fd) => { + Descriptor::OsHandle(fd) => { let metadata = fd.metadata()?; let current_size = metadata.len(); @@ -547,8 +547,8 @@ pub(crate) unsafe fn fd_allocate( Ok(()) } } - Handle::VirtualFile(virt) => virt.allocate(offset, len), - Handle::Stream(_) => { + Descriptor::VirtualFile(virt) => virt.allocate(offset, len), + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -829,9 +829,9 @@ pub(crate) unsafe fn fd_filestat_get( .as_descriptor(wasi::__WASI_RIGHTS_FD_FILESTAT_GET, 0)? .as_file()?; let host_filestat = match fd { - Handle::OsHandle(fd) => hostcalls_impl::fd_filestat_get(&fd)?, - Handle::VirtualFile(virt) => virt.filestat_get()?, - Handle::Stream(_) => { + Descriptor::OsHandle(fd) => hostcalls_impl::fd_filestat_get(&fd)?, + Descriptor::VirtualFile(virt) => virt.filestat_get()?, + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -868,7 +868,7 @@ pub(crate) unsafe fn fd_filestat_set_times( } pub(crate) fn fd_filestat_set_times_impl( - file: &Handle, + file: &Descriptor, st_atim: wasi::__wasi_timestamp_t, st_mtim: wasi::__wasi_timestamp_t, fst_flags: wasi::__wasi_fstflags_t, @@ -901,9 +901,9 @@ pub(crate) fn fd_filestat_set_times_impl( None }; match file { - Handle::OsHandle(fd) => set_file_handle_times(fd, atim, mtim).map_err(Into::into), - Handle::VirtualFile(virt) => virt.filestat_set_times(atim, mtim), - Handle::Stream(_) => { + Descriptor::OsHandle(fd) => set_file_handle_times(fd, atim, mtim).map_err(Into::into), + Descriptor::VirtualFile(virt) => virt.filestat_set_times(atim, mtim), + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -929,9 +929,9 @@ pub(crate) unsafe fn fd_filestat_set_size( return Err(Error::E2BIG); } match file { - Handle::OsHandle(fd) => fd.set_len(st_size).map_err(Into::into), - Handle::VirtualFile(virt) => virt.filestat_set_size(st_size), - Handle::Stream(_) => { + Descriptor::OsHandle(fd) => fd.set_len(st_size).map_err(Into::into), + Descriptor::VirtualFile(virt) => virt.filestat_set_size(st_size), + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); @@ -1240,11 +1240,11 @@ pub(crate) unsafe fn fd_readdir( } let host_bufused = match file { - HandleMut::OsHandle(file) => { + Descriptor::OsHandle(file) => { copy_entities(hostcalls_impl::fd_readdir(file, cookie)?, host_buf)? } - HandleMut::VirtualFile(virt) => copy_entities(virt.readdir(cookie)?, host_buf)?, - HandleMut::Stream(_) => { + Descriptor::VirtualFile(virt) => copy_entities(virt.readdir(cookie)?, host_buf)?, + _ => { unreachable!( "implementation error: fd should have been checked to not be a stream already" ); diff --git a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs index ca4299089d6d..d4677b014374 100644 --- a/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs +++ b/crates/wasi-common/src/sys/windows/hostcalls_impl/fs.rs @@ -495,7 +495,7 @@ pub(crate) fn path_filestat_set_times( .access_mode(AccessMode::FILE_WRITE_ATTRIBUTES.bits()) .open(path)?; let modifiable_fd = Descriptor::OsHandle(OsHandle::from(file)); - fd_filestat_set_times_impl(&modifiable_fd.as_handle(), st_atim, st_mtim, fst_flags) + fd_filestat_set_times_impl(&modifiable_fd, st_atim, st_mtim, fst_flags) } pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {