use crate::handle::{Handle, HandleRights}; use crate::wasi::types::Filetype; use crate::wasi::{Errno, Result}; use std::ops::Deref; use std::path::PathBuf; use std::rc::Rc; pub(crate) struct EntryHandle(Rc); impl EntryHandle { pub(crate) fn new(handle: T) -> Self { Self(Rc::new(handle)) } pub(crate) fn get(&self) -> Self { Self(Rc::clone(&self.0)) } } impl From> for EntryHandle { fn from(handle: Box) -> Self { Self(handle.into()) } } impl Deref for EntryHandle { type Target = dyn Handle; fn deref(&self) -> &Self::Target { &*self.0 } } /// An abstraction struct serving as a wrapper for a `Handle` object. /// /// Here, the `handle` field stores an instance of `Handle` type (such as a file descriptor, or /// stdin handle), and accessing it can only be done via the provided `Entry::as_handle` method /// which require a set of base and inheriting rights to be specified, verifying whether the stored /// `Handle` object is valid for the rights specified. pub(crate) struct Entry { handle: EntryHandle, pub(crate) preopen_path: Option, // TODO: directories } impl Entry { pub(crate) fn new(handle: EntryHandle) -> Self { let preopen_path = None; Self { handle, preopen_path, } } pub(crate) fn get_file_type(&self) -> Filetype { self.handle.get_file_type() } pub(crate) fn get_rights(&self) -> HandleRights { self.handle.get_rights() } pub(crate) fn set_rights(&self, rights: HandleRights) { self.handle.set_rights(rights) } /// Convert this `Entry` into a `Handle` object provided the specified /// `rights` rights are set on this `Entry` object. /// /// The `Entry` can only be converted into a valid `Handle` object if /// the specified set of base rights, and inheriting rights encapsulated within `rights` /// `HandleRights` structure is a subset of rights attached to this `Entry`. The check is /// performed using `Entry::validate_rights` method. If the check fails, `Errno::Notcapable` /// is returned. pub(crate) fn as_handle(&self, rights: &HandleRights) -> Result { self.validate_rights(rights)?; Ok(self.handle.get()) } /// Check if this `Entry` object satisfies the specified `HandleRights`; i.e., if /// rights attached to this `Entry` object are a superset. /// /// Upon unsuccessful check, `Errno::Notcapable` is returned. pub(crate) fn validate_rights(&self, rights: &HandleRights) -> Result<()> { let this_rights = self.handle.get_rights(); if this_rights.contains(rights) { Ok(()) } else { log::trace!( " | validate_rights failed: required rights = {}; actual rights = {}", rights, this_rights, ); Err(Errno::Notcapable) } } }