Path: blob/main/crates/wasi/src/p3/filesystem/mod.rs
3092 views
mod host;12use crate::TrappableError;3use crate::filesystem::{WasiFilesystem, WasiFilesystemView};4use crate::p3::bindings::filesystem::{preopens, types};5use wasmtime::component::Linker;67pub type FilesystemResult<T> = Result<T, FilesystemError>;8pub type FilesystemError = TrappableError<types::ErrorCode>;910/// Add all WASI interfaces from this module into the `linker` provided.11///12/// This function will add all interfaces implemented by this module to the13/// [`Linker`], which corresponds to the `wasi:filesystem/imports` world supported by14/// this module.15///16/// This is low-level API for advanced use cases,17/// [`wasmtime_wasi::p3::add_to_linker`](crate::p3::add_to_linker) can be used instead18/// to add *all* wasip3 interfaces (including the ones from this module) to the `linker`.19///20/// # Example21///22/// ```23/// use wasmtime::{Engine, Result, Store, Config};24/// use wasmtime::component::{Linker, ResourceTable};25/// use wasmtime_wasi::filesystem::{WasiFilesystemCtx, WasiFilesystemCtxView, WasiFilesystemView};26///27/// fn main() -> Result<()> {28/// let mut config = Config::new();29/// config.wasm_component_model_async(true);30/// let engine = Engine::new(&config)?;31///32/// let mut linker = Linker::<MyState>::new(&engine);33/// wasmtime_wasi::p3::filesystem::add_to_linker(&mut linker)?;34/// // ... add any further functionality to `linker` if desired ...35///36/// let mut store = Store::new(37/// &engine,38/// MyState::default(),39/// );40///41/// // ... use `linker` to instantiate within `store` ...42///43/// Ok(())44/// }45///46/// #[derive(Default)]47/// struct MyState {48/// filesystem: WasiFilesystemCtx,49/// table: ResourceTable,50/// }51///52/// impl WasiFilesystemView for MyState {53/// fn filesystem(&mut self) -> WasiFilesystemCtxView<'_> {54/// WasiFilesystemCtxView {55/// ctx: &mut self.filesystem,56/// table: &mut self.table,57/// }58/// }59/// }60/// ```61pub fn add_to_linker<T>(linker: &mut Linker<T>) -> wasmtime::Result<()>62where63T: WasiFilesystemView + 'static,64{65types::add_to_linker::<_, WasiFilesystem>(linker, T::filesystem)?;66preopens::add_to_linker::<_, WasiFilesystem>(linker, T::filesystem)?;67Ok(())68}6970impl<'a> From<&'a std::io::Error> for types::ErrorCode {71fn from(err: &'a std::io::Error) -> Self {72crate::filesystem::ErrorCode::from(err).into()73}74}7576impl From<std::io::Error> for types::ErrorCode {77fn from(err: std::io::Error) -> Self {78Self::from(&err)79}80}8182impl From<std::io::Error> for FilesystemError {83fn from(error: std::io::Error) -> Self {84types::ErrorCode::from(error).into()85}86}8788impl From<crate::filesystem::ErrorCode> for types::ErrorCode {89fn from(error: crate::filesystem::ErrorCode) -> Self {90match error {91crate::filesystem::ErrorCode::Access => Self::Access,92crate::filesystem::ErrorCode::Already => Self::Already,93crate::filesystem::ErrorCode::BadDescriptor => Self::BadDescriptor,94crate::filesystem::ErrorCode::Busy => Self::Busy,95crate::filesystem::ErrorCode::Exist => Self::Exist,96crate::filesystem::ErrorCode::FileTooLarge => Self::FileTooLarge,97crate::filesystem::ErrorCode::IllegalByteSequence => Self::IllegalByteSequence,98crate::filesystem::ErrorCode::InProgress => Self::InProgress,99crate::filesystem::ErrorCode::Interrupted => Self::Interrupted,100crate::filesystem::ErrorCode::Invalid => Self::Invalid,101crate::filesystem::ErrorCode::Io => Self::Io,102crate::filesystem::ErrorCode::IsDirectory => Self::IsDirectory,103crate::filesystem::ErrorCode::Loop => Self::Loop,104crate::filesystem::ErrorCode::TooManyLinks => Self::TooManyLinks,105crate::filesystem::ErrorCode::NameTooLong => Self::NameTooLong,106crate::filesystem::ErrorCode::NoEntry => Self::NoEntry,107crate::filesystem::ErrorCode::InsufficientMemory => Self::InsufficientMemory,108crate::filesystem::ErrorCode::InsufficientSpace => Self::InsufficientSpace,109crate::filesystem::ErrorCode::NotDirectory => Self::NotDirectory,110crate::filesystem::ErrorCode::NotEmpty => Self::NotEmpty,111crate::filesystem::ErrorCode::Unsupported => Self::Unsupported,112crate::filesystem::ErrorCode::Overflow => Self::Overflow,113crate::filesystem::ErrorCode::NotPermitted => Self::NotPermitted,114crate::filesystem::ErrorCode::Pipe => Self::Pipe,115crate::filesystem::ErrorCode::InvalidSeek => Self::InvalidSeek,116}117}118}119120impl From<crate::filesystem::ErrorCode> for FilesystemError {121fn from(error: crate::filesystem::ErrorCode) -> Self {122types::ErrorCode::from(error).into()123}124}125126impl From<wasmtime::component::ResourceTableError> for FilesystemError {127fn from(error: wasmtime::component::ResourceTableError) -> Self {128Self::trap(error)129}130}131132impl From<types::Advice> for system_interface::fs::Advice {133fn from(advice: types::Advice) -> Self {134match advice {135types::Advice::Normal => Self::Normal,136types::Advice::Sequential => Self::Sequential,137types::Advice::Random => Self::Random,138types::Advice::WillNeed => Self::WillNeed,139types::Advice::DontNeed => Self::DontNeed,140types::Advice::NoReuse => Self::NoReuse,141}142}143}144145impl From<types::OpenFlags> for crate::filesystem::OpenFlags {146fn from(flags: types::OpenFlags) -> Self {147let mut out = Self::empty();148if flags.contains(types::OpenFlags::CREATE) {149out |= Self::CREATE;150}151if flags.contains(types::OpenFlags::DIRECTORY) {152out |= Self::DIRECTORY;153}154if flags.contains(types::OpenFlags::EXCLUSIVE) {155out |= Self::EXCLUSIVE;156}157if flags.contains(types::OpenFlags::TRUNCATE) {158out |= Self::TRUNCATE;159}160out161}162}163164impl From<types::PathFlags> for crate::filesystem::PathFlags {165fn from(flags: types::PathFlags) -> Self {166let mut out = Self::empty();167if flags.contains(types::PathFlags::SYMLINK_FOLLOW) {168out |= Self::SYMLINK_FOLLOW;169}170out171}172}173174impl From<crate::filesystem::DescriptorFlags> for types::DescriptorFlags {175fn from(flags: crate::filesystem::DescriptorFlags) -> Self {176let mut out = Self::empty();177if flags.contains(crate::filesystem::DescriptorFlags::READ) {178out |= Self::READ;179}180if flags.contains(crate::filesystem::DescriptorFlags::WRITE) {181out |= Self::WRITE;182}183if flags.contains(crate::filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) {184out |= Self::FILE_INTEGRITY_SYNC;185}186if flags.contains(crate::filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) {187out |= Self::DATA_INTEGRITY_SYNC;188}189if flags.contains(crate::filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) {190out |= Self::REQUESTED_WRITE_SYNC;191}192if flags.contains(crate::filesystem::DescriptorFlags::MUTATE_DIRECTORY) {193out |= Self::MUTATE_DIRECTORY;194}195out196}197}198199impl From<types::DescriptorFlags> for crate::filesystem::DescriptorFlags {200fn from(flags: types::DescriptorFlags) -> Self {201let mut out = Self::empty();202if flags.contains(types::DescriptorFlags::READ) {203out |= Self::READ;204}205if flags.contains(types::DescriptorFlags::WRITE) {206out |= Self::WRITE;207}208if flags.contains(types::DescriptorFlags::FILE_INTEGRITY_SYNC) {209out |= Self::FILE_INTEGRITY_SYNC;210}211if flags.contains(types::DescriptorFlags::DATA_INTEGRITY_SYNC) {212out |= Self::DATA_INTEGRITY_SYNC;213}214if flags.contains(types::DescriptorFlags::REQUESTED_WRITE_SYNC) {215out |= Self::REQUESTED_WRITE_SYNC;216}217if flags.contains(types::DescriptorFlags::MUTATE_DIRECTORY) {218out |= Self::MUTATE_DIRECTORY;219}220out221}222}223224impl From<crate::filesystem::MetadataHashValue> for types::MetadataHashValue {225fn from(226crate::filesystem::MetadataHashValue { lower, upper }: crate::filesystem::MetadataHashValue,227) -> Self {228Self { lower, upper }229}230}231232impl From<crate::filesystem::DescriptorStat> for types::DescriptorStat {233fn from(234crate::filesystem::DescriptorStat {235type_,236link_count,237size,238data_access_timestamp,239data_modification_timestamp,240status_change_timestamp,241}: crate::filesystem::DescriptorStat,242) -> Self {243Self {244type_: type_.into(),245link_count,246size,247data_access_timestamp: data_access_timestamp.map(Into::into),248data_modification_timestamp: data_modification_timestamp.map(Into::into),249status_change_timestamp: status_change_timestamp.map(Into::into),250}251}252}253254impl From<crate::filesystem::DescriptorType> for types::DescriptorType {255fn from(ty: crate::filesystem::DescriptorType) -> Self {256match ty {257crate::filesystem::DescriptorType::Unknown => Self::Unknown,258crate::filesystem::DescriptorType::BlockDevice => Self::BlockDevice,259crate::filesystem::DescriptorType::CharacterDevice => Self::CharacterDevice,260crate::filesystem::DescriptorType::Directory => Self::Directory,261crate::filesystem::DescriptorType::SymbolicLink => Self::SymbolicLink,262crate::filesystem::DescriptorType::RegularFile => Self::RegularFile,263}264}265}266267impl From<cap_std::fs::FileType> for types::DescriptorType {268fn from(ft: cap_std::fs::FileType) -> Self {269use cap_fs_ext::FileTypeExt as _;270if ft.is_dir() {271Self::Directory272} else if ft.is_symlink() {273Self::SymbolicLink274} else if ft.is_block_device() {275Self::BlockDevice276} else if ft.is_char_device() {277Self::CharacterDevice278} else if ft.is_file() {279Self::RegularFile280} else {281Self::Unknown282}283}284}285286287