From 6db24fd08fa6f675e1b4ef818f8684602fd58730 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Mon, 14 Sep 2020 16:27:33 -0700 Subject: [PATCH] handle: re-export all of the wasi types used by handles --- crates/wasi-common/src/entry.rs | 2 +- crates/wasi-common/src/handle.rs | 197 +++++++++++++++--- .../src/snapshots/wasi_snapshot_preview1.rs | 16 +- crates/wasi-common/src/wasi.rs | 147 +------------ 4 files changed, 180 insertions(+), 182 deletions(-) diff --git a/crates/wasi-common/src/entry.rs b/crates/wasi-common/src/entry.rs index 8e65f4ec5a..780734f292 100644 --- a/crates/wasi-common/src/entry.rs +++ b/crates/wasi-common/src/entry.rs @@ -5,7 +5,7 @@ use std::ops::Deref; use std::path::PathBuf; use std::rc::Rc; -pub(crate) struct EntryHandle(Rc); +pub struct EntryHandle(Rc); impl EntryHandle { #[allow(dead_code)] diff --git a/crates/wasi-common/src/handle.rs b/crates/wasi-common/src/handle.rs index 72f0a7db1b..ccb549703c 100644 --- a/crates/wasi-common/src/handle.rs +++ b/crates/wasi-common/src/handle.rs @@ -1,4 +1,7 @@ -use crate::wasi::types::{self, Rights}; +pub use crate::wasi::types::{ + Advice, Dircookie, Dirent, Fdflags, Fdstat, Filedelta, Filesize, Filestat, Filetype, Fstflags, + Lookupflags, Oflags, Prestat, PrestatDir, Rights, Size, Timestamp, Whence, +}; use crate::{Error, Result}; use std::any::Any; use std::fmt; @@ -82,13 +85,13 @@ impl fmt::Display for HandleRights { pub trait Handle { fn as_any(&self) -> &dyn Any; fn try_clone(&self) -> io::Result>; - fn get_file_type(&self) -> types::Filetype; + fn get_file_type(&self) -> Filetype; fn get_rights(&self) -> HandleRights { HandleRights::empty() } fn set_rights(&self, rights: HandleRights); fn is_directory(&self) -> bool { - self.get_file_type() == types::Filetype::Directory + self.get_file_type() == Filetype::Directory } /// Test whether this descriptor is considered a tty within WASI. /// Note that since WASI itself lacks an `isatty` syscall and relies @@ -97,41 +100,36 @@ pub trait Handle { let file_type = self.get_file_type(); let rights = self.get_rights(); let required_rights = HandleRights::from_base(Rights::FD_SEEK | Rights::FD_TELL); - file_type == types::Filetype::CharacterDevice && rights.contains(&required_rights) + file_type == Filetype::CharacterDevice && rights.contains(&required_rights) } // TODO perhaps should be a separate trait? // FdOps - fn advise( - &self, - _advice: types::Advice, - _offset: types::Filesize, - _len: types::Filesize, - ) -> Result<()> { + fn advise(&self, _advice: Advice, _offset: Filesize, _len: Filesize) -> Result<()> { Err(Error::Badf) } - fn allocate(&self, _offset: types::Filesize, _len: types::Filesize) -> Result<()> { + fn allocate(&self, _offset: Filesize, _len: Filesize) -> Result<()> { Err(Error::Badf) } fn datasync(&self) -> Result<()> { Err(Error::Inval) } - fn fdstat_get(&self) -> Result { - Ok(types::Fdflags::empty()) + fn fdstat_get(&self) -> Result { + Ok(Fdflags::empty()) } - fn fdstat_set_flags(&self, _fdflags: types::Fdflags) -> Result<()> { + fn fdstat_set_flags(&self, _fdflags: Fdflags) -> Result<()> { Err(Error::Badf) } - fn filestat_get(&self) -> Result { + fn filestat_get(&self) -> Result { Err(Error::Badf) } - fn filestat_set_size(&self, _st_size: types::Filesize) -> Result<()> { + fn filestat_set_size(&self, _st_size: Filesize) -> Result<()> { Err(Error::Badf) } fn filestat_set_times( &self, - _atim: types::Timestamp, - _mtim: types::Timestamp, - _fst_flags: types::Fstflags, + _atim: Timestamp, + _mtim: Timestamp, + _fst_flags: Fstflags, ) -> Result<()> { Err(Error::Badf) } @@ -146,8 +144,8 @@ pub trait Handle { } fn readdir<'a>( &'a self, - _cookie: types::Dircookie, - ) -> Result> + 'a>> { + _cookie: Dircookie, + ) -> Result> + 'a>> { Err(Error::Badf) } fn seek(&self, _offset: SeekFrom) -> Result { @@ -164,15 +162,15 @@ pub trait Handle { fn create_directory(&self, _path: &str) -> Result<()> { Err(Error::Acces) } - fn filestat_get_at(&self, _path: &str, _follow: bool) -> Result { + fn filestat_get_at(&self, _path: &str, _follow: bool) -> Result { Err(Error::Acces) } fn filestat_set_times_at( &self, _path: &str, - _atim: types::Timestamp, - _mtim: types::Timestamp, - _fst_flags: types::Fstflags, + _atim: Timestamp, + _mtim: Timestamp, + _fst_flags: Fstflags, _follow: bool, ) -> Result<()> { Err(Error::Acces) @@ -182,8 +180,8 @@ pub trait Handle { _path: &str, _read: bool, _write: bool, - _oflags: types::Oflags, - _fd_flags: types::Fdflags, + _oflags: Oflags, + _fd_flags: Fdflags, ) -> Result> { Err(Error::Acces) } @@ -215,3 +213,148 @@ pub trait Handle { Err(Error::Acces) } } + +impl From for Filetype { + fn from(ftype: std::fs::FileType) -> Self { + if ftype.is_file() { + Self::RegularFile + } else if ftype.is_dir() { + Self::Directory + } else if ftype.is_symlink() { + Self::SymbolicLink + } else { + Self::Unknown + } + } +} + +pub(crate) trait AsBytes { + fn as_bytes(&self) -> Result>; +} + +impl AsBytes for Dirent { + fn as_bytes(&self) -> Result> { + use std::convert::TryInto; + use wiggle::GuestType; + + assert_eq!( + Self::guest_size(), + std::mem::size_of::() as _, + "guest repr of Dirent and host repr should match" + ); + + let offset = Self::guest_size().try_into()?; + let mut bytes: Vec = Vec::with_capacity(offset); + bytes.resize(offset, 0); + let ptr = bytes.as_mut_ptr() as *mut Self; + unsafe { ptr.write_unaligned(self.clone()) }; + Ok(bytes) + } +} + +pub(crate) trait RightsExt: Sized { + fn block_device_base() -> Self; + fn block_device_inheriting() -> Self; + fn character_device_base() -> Self; + fn character_device_inheriting() -> Self; + fn directory_base() -> Self; + fn directory_inheriting() -> Self; + fn regular_file_base() -> Self; + fn regular_file_inheriting() -> Self; + fn socket_base() -> Self; + fn socket_inheriting() -> Self; + fn tty_base() -> Self; + fn tty_inheriting() -> Self; +} + +impl RightsExt for Rights { + // Block and character device interaction is outside the scope of + // WASI. Simply allow everything. + fn block_device_base() -> Self { + Self::all() + } + fn block_device_inheriting() -> Self { + Self::all() + } + fn character_device_base() -> Self { + Self::all() + } + fn character_device_inheriting() -> Self { + Self::all() + } + + // Only allow directory operations on directories. Directories can only + // yield file descriptors to other directories and files. + fn directory_base() -> Self { + Self::FD_FDSTAT_SET_FLAGS + | Self::FD_SYNC + | Self::FD_ADVISE + | Self::PATH_CREATE_DIRECTORY + | Self::PATH_CREATE_FILE + | Self::PATH_LINK_SOURCE + | Self::PATH_LINK_TARGET + | Self::PATH_OPEN + | Self::FD_READDIR + | Self::PATH_READLINK + | Self::PATH_RENAME_SOURCE + | Self::PATH_RENAME_TARGET + | Self::PATH_FILESTAT_GET + | Self::PATH_FILESTAT_SET_SIZE + | Self::PATH_FILESTAT_SET_TIMES + | Self::FD_FILESTAT_GET + | Self::FD_FILESTAT_SET_TIMES + | Self::PATH_SYMLINK + | Self::PATH_UNLINK_FILE + | Self::PATH_REMOVE_DIRECTORY + | Self::POLL_FD_READWRITE + } + fn directory_inheriting() -> Self { + Self::all() ^ Self::SOCK_SHUTDOWN + } + + // Operations that apply to regular files. + fn regular_file_base() -> Self { + Self::FD_DATASYNC + | Self::FD_READ + | Self::FD_SEEK + | Self::FD_FDSTAT_SET_FLAGS + | Self::FD_SYNC + | Self::FD_TELL + | Self::FD_WRITE + | Self::FD_ADVISE + | Self::FD_ALLOCATE + | Self::FD_FILESTAT_GET + | Self::FD_FILESTAT_SET_SIZE + | Self::FD_FILESTAT_SET_TIMES + | Self::POLL_FD_READWRITE + } + fn regular_file_inheriting() -> Self { + Self::empty() + } + + // Operations that apply to sockets and socket pairs. + fn socket_base() -> Self { + Self::FD_READ + | Self::FD_FDSTAT_SET_FLAGS + | Self::FD_WRITE + | Self::FD_FILESTAT_GET + | Self::POLL_FD_READWRITE + | Self::SOCK_SHUTDOWN + } + fn socket_inheriting() -> Self { + Self::all() + } + + // Operations that apply to TTYs. + fn tty_base() -> Self { + Self::FD_READ + | Self::FD_FDSTAT_SET_FLAGS + | Self::FD_WRITE + | Self::FD_FILESTAT_GET + | Self::POLL_FD_READWRITE + } + fn tty_inheriting() -> Self { + Self::empty() + } +} +pub(crate) const DIRCOOKIE_START: Dircookie = 0; diff --git a/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs b/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs index 0836491265..15dc7e3109 100644 --- a/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs +++ b/crates/wasi-common/src/snapshots/wasi_snapshot_preview1.rs @@ -1,9 +1,9 @@ use crate::entry::{Entry, EntryHandle}; -use crate::handle::HandleRights; -use crate::sys::clock; +use crate::handle::{AsBytes, HandleRights}; +use crate::sys::{clock, poll}; +use crate::wasi::types; use crate::wasi::wasi_snapshot_preview1::WasiSnapshotPreview1; -use crate::wasi::{types, AsBytes}; -use crate::{path, poll, Error, Result, WasiCtx}; +use crate::{path, sched, Error, Result, WasiCtx}; use std::convert::TryInto; use std::io::{self, SeekFrom}; use std::ops::Deref; @@ -681,7 +681,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { } let mut events = Vec::new(); - let mut timeout: Option = None; + let mut timeout: Option = None; let mut fd_events = Vec::new(); // As mandated by the WASI spec: @@ -699,7 +699,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { delay_ns = tracing::field::debug(delay), "poll_oneoff" ); - let current = poll::ClockEventData { + let current = sched::ClockEventData { delay, userdata: subscription.userdata, }; @@ -728,7 +728,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { continue; } }; - fd_events.push(poll::FdEventData { + fd_events.push(sched::FdEventData { handle: entry.as_handle(&required_rights)?, r#type: types::Eventtype::FdRead, userdata: subscription.userdata, @@ -754,7 +754,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx { continue; } }; - fd_events.push(poll::FdEventData { + fd_events.push(sched::FdEventData { handle: entry.as_handle(&required_rights)?, r#type: types::Eventtype::FdWrite, userdata: subscription.userdata, diff --git a/crates/wasi-common/src/wasi.rs b/crates/wasi-common/src/wasi.rs index e87ac2fec9..2ae7257e66 100644 --- a/crates/wasi-common/src/wasi.rs +++ b/crates/wasi-common/src/wasi.rs @@ -1,4 +1,4 @@ -use crate::{Error, Result, WasiCtx}; +use crate::{Error, WasiCtx}; use tracing::debug; wiggle::from_witx!({ @@ -88,151 +88,6 @@ impl From for Errno { } } -impl From for types::Filetype { - fn from(ftype: std::fs::FileType) -> Self { - if ftype.is_file() { - Self::RegularFile - } else if ftype.is_dir() { - Self::Directory - } else if ftype.is_symlink() { - Self::SymbolicLink - } else { - Self::Unknown - } - } -} - -pub(crate) trait AsBytes { - fn as_bytes(&self) -> Result>; -} - -impl AsBytes for types::Dirent { - fn as_bytes(&self) -> Result> { - use std::convert::TryInto; - use wiggle::GuestType; - - assert_eq!( - Self::guest_size(), - std::mem::size_of::() as _, - "guest repr of types::Dirent and host repr should match" - ); - - let offset = Self::guest_size().try_into()?; - let mut bytes: Vec = Vec::with_capacity(offset); - bytes.resize(offset, 0); - let ptr = bytes.as_mut_ptr() as *mut Self; - unsafe { ptr.write_unaligned(self.clone()) }; - Ok(bytes) - } -} - -pub(crate) trait RightsExt: Sized { - fn block_device_base() -> Self; - fn block_device_inheriting() -> Self; - fn character_device_base() -> Self; - fn character_device_inheriting() -> Self; - fn directory_base() -> Self; - fn directory_inheriting() -> Self; - fn regular_file_base() -> Self; - fn regular_file_inheriting() -> Self; - fn socket_base() -> Self; - fn socket_inheriting() -> Self; - fn tty_base() -> Self; - fn tty_inheriting() -> Self; -} - -impl RightsExt for types::Rights { - // Block and character device interaction is outside the scope of - // WASI. Simply allow everything. - fn block_device_base() -> Self { - Self::all() - } - fn block_device_inheriting() -> Self { - Self::all() - } - fn character_device_base() -> Self { - Self::all() - } - fn character_device_inheriting() -> Self { - Self::all() - } - - // Only allow directory operations on directories. Directories can only - // yield file descriptors to other directories and files. - fn directory_base() -> Self { - Self::FD_FDSTAT_SET_FLAGS - | Self::FD_SYNC - | Self::FD_ADVISE - | Self::PATH_CREATE_DIRECTORY - | Self::PATH_CREATE_FILE - | Self::PATH_LINK_SOURCE - | Self::PATH_LINK_TARGET - | Self::PATH_OPEN - | Self::FD_READDIR - | Self::PATH_READLINK - | Self::PATH_RENAME_SOURCE - | Self::PATH_RENAME_TARGET - | Self::PATH_FILESTAT_GET - | Self::PATH_FILESTAT_SET_SIZE - | Self::PATH_FILESTAT_SET_TIMES - | Self::FD_FILESTAT_GET - | Self::FD_FILESTAT_SET_TIMES - | Self::PATH_SYMLINK - | Self::PATH_UNLINK_FILE - | Self::PATH_REMOVE_DIRECTORY - | Self::POLL_FD_READWRITE - } - fn directory_inheriting() -> Self { - Self::all() ^ Self::SOCK_SHUTDOWN - } - - // Operations that apply to regular files. - fn regular_file_base() -> Self { - Self::FD_DATASYNC - | Self::FD_READ - | Self::FD_SEEK - | Self::FD_FDSTAT_SET_FLAGS - | Self::FD_SYNC - | Self::FD_TELL - | Self::FD_WRITE - | Self::FD_ADVISE - | Self::FD_ALLOCATE - | Self::FD_FILESTAT_GET - | Self::FD_FILESTAT_SET_SIZE - | Self::FD_FILESTAT_SET_TIMES - | Self::POLL_FD_READWRITE - } - fn regular_file_inheriting() -> Self { - Self::empty() - } - - // Operations that apply to sockets and socket pairs. - fn socket_base() -> Self { - Self::FD_READ - | Self::FD_FDSTAT_SET_FLAGS - | Self::FD_WRITE - | Self::FD_FILESTAT_GET - | Self::POLL_FD_READWRITE - | Self::SOCK_SHUTDOWN - } - fn socket_inheriting() -> Self { - Self::all() - } - - // Operations that apply to TTYs. - fn tty_base() -> Self { - Self::FD_READ - | Self::FD_FDSTAT_SET_FLAGS - | Self::FD_WRITE - | Self::FD_FILESTAT_GET - | Self::POLL_FD_READWRITE - } - fn tty_inheriting() -> Self { - Self::empty() - } -} -pub(crate) const DIRCOOKIE_START: types::Dircookie = 0; - impl crate::fdpool::Fd for types::Fd { fn as_raw(&self) -> u32 { (*self).into()