Path: blob/main/crates/wasi/src/p3/filesystem/mod.rs
1692 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.async_support(true);30/// config.wasm_component_model_async(true);31/// let engine = Engine::new(&config)?;32///33/// let mut linker = Linker::<MyState>::new(&engine);34/// wasmtime_wasi::p3::filesystem::add_to_linker(&mut linker)?;35/// // ... add any further functionality to `linker` if desired ...36///37/// let mut store = Store::new(38/// &engine,39/// MyState::default(),40/// );41///42/// // ... use `linker` to instantiate within `store` ...43///44/// Ok(())45/// }46///47/// #[derive(Default)]48/// struct MyState {49/// filesystem: WasiFilesystemCtx,50/// table: ResourceTable,51/// }52///53/// impl WasiFilesystemView for MyState {54/// fn filesystem(&mut self) -> WasiFilesystemCtxView<'_> {55/// WasiFilesystemCtxView {56/// ctx: &mut self.filesystem,57/// table: &mut self.table,58/// }59/// }60/// }61/// ```62pub fn add_to_linker<T>(linker: &mut Linker<T>) -> wasmtime::Result<()>63where64T: WasiFilesystemView + 'static,65{66types::add_to_linker::<_, WasiFilesystem>(linker, T::filesystem)?;67preopens::add_to_linker::<_, WasiFilesystem>(linker, T::filesystem)?;68Ok(())69}7071impl<'a> From<&'a std::io::Error> for types::ErrorCode {72fn from(err: &'a std::io::Error) -> Self {73crate::filesystem::ErrorCode::from(err).into()74}75}7677impl From<std::io::Error> for types::ErrorCode {78fn from(err: std::io::Error) -> Self {79Self::from(&err)80}81}8283impl From<std::io::Error> for FilesystemError {84fn from(error: std::io::Error) -> Self {85types::ErrorCode::from(error).into()86}87}8889impl From<crate::filesystem::ErrorCode> for types::ErrorCode {90fn from(error: crate::filesystem::ErrorCode) -> Self {91match error {92crate::filesystem::ErrorCode::Access => Self::Access,93crate::filesystem::ErrorCode::Already => Self::Already,94crate::filesystem::ErrorCode::BadDescriptor => Self::BadDescriptor,95crate::filesystem::ErrorCode::Busy => Self::Busy,96crate::filesystem::ErrorCode::Exist => Self::Exist,97crate::filesystem::ErrorCode::FileTooLarge => Self::FileTooLarge,98crate::filesystem::ErrorCode::IllegalByteSequence => Self::IllegalByteSequence,99crate::filesystem::ErrorCode::InProgress => Self::InProgress,100crate::filesystem::ErrorCode::Interrupted => Self::Interrupted,101crate::filesystem::ErrorCode::Invalid => Self::Invalid,102crate::filesystem::ErrorCode::Io => Self::Io,103crate::filesystem::ErrorCode::IsDirectory => Self::IsDirectory,104crate::filesystem::ErrorCode::Loop => Self::Loop,105crate::filesystem::ErrorCode::TooManyLinks => Self::TooManyLinks,106crate::filesystem::ErrorCode::NameTooLong => Self::NameTooLong,107crate::filesystem::ErrorCode::NoEntry => Self::NoEntry,108crate::filesystem::ErrorCode::InsufficientMemory => Self::InsufficientMemory,109crate::filesystem::ErrorCode::InsufficientSpace => Self::InsufficientSpace,110crate::filesystem::ErrorCode::NotDirectory => Self::NotDirectory,111crate::filesystem::ErrorCode::NotEmpty => Self::NotEmpty,112crate::filesystem::ErrorCode::Unsupported => Self::Unsupported,113crate::filesystem::ErrorCode::Overflow => Self::Overflow,114crate::filesystem::ErrorCode::NotPermitted => Self::NotPermitted,115crate::filesystem::ErrorCode::Pipe => Self::Pipe,116crate::filesystem::ErrorCode::InvalidSeek => Self::InvalidSeek,117}118}119}120121impl From<crate::filesystem::ErrorCode> for FilesystemError {122fn from(error: crate::filesystem::ErrorCode) -> Self {123types::ErrorCode::from(error).into()124}125}126127impl From<wasmtime::component::ResourceTableError> for FilesystemError {128fn from(error: wasmtime::component::ResourceTableError) -> Self {129Self::trap(error)130}131}132133impl From<types::Advice> for system_interface::fs::Advice {134fn from(advice: types::Advice) -> Self {135match advice {136types::Advice::Normal => Self::Normal,137types::Advice::Sequential => Self::Sequential,138types::Advice::Random => Self::Random,139types::Advice::WillNeed => Self::WillNeed,140types::Advice::DontNeed => Self::DontNeed,141types::Advice::NoReuse => Self::NoReuse,142}143}144}145146impl From<types::OpenFlags> for crate::filesystem::OpenFlags {147fn from(flags: types::OpenFlags) -> Self {148let mut out = Self::empty();149if flags.contains(types::OpenFlags::CREATE) {150out |= Self::CREATE;151}152if flags.contains(types::OpenFlags::DIRECTORY) {153out |= Self::DIRECTORY;154}155if flags.contains(types::OpenFlags::EXCLUSIVE) {156out |= Self::EXCLUSIVE;157}158if flags.contains(types::OpenFlags::TRUNCATE) {159out |= Self::TRUNCATE;160}161out162}163}164165impl From<types::PathFlags> for crate::filesystem::PathFlags {166fn from(flags: types::PathFlags) -> Self {167let mut out = Self::empty();168if flags.contains(types::PathFlags::SYMLINK_FOLLOW) {169out |= Self::SYMLINK_FOLLOW;170}171out172}173}174175impl From<crate::filesystem::DescriptorFlags> for types::DescriptorFlags {176fn from(flags: crate::filesystem::DescriptorFlags) -> Self {177let mut out = Self::empty();178if flags.contains(crate::filesystem::DescriptorFlags::READ) {179out |= Self::READ;180}181if flags.contains(crate::filesystem::DescriptorFlags::WRITE) {182out |= Self::WRITE;183}184if flags.contains(crate::filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) {185out |= Self::FILE_INTEGRITY_SYNC;186}187if flags.contains(crate::filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) {188out |= Self::DATA_INTEGRITY_SYNC;189}190if flags.contains(crate::filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) {191out |= Self::REQUESTED_WRITE_SYNC;192}193if flags.contains(crate::filesystem::DescriptorFlags::MUTATE_DIRECTORY) {194out |= Self::MUTATE_DIRECTORY;195}196out197}198}199200impl From<types::DescriptorFlags> for crate::filesystem::DescriptorFlags {201fn from(flags: types::DescriptorFlags) -> Self {202let mut out = Self::empty();203if flags.contains(types::DescriptorFlags::READ) {204out |= Self::READ;205}206if flags.contains(types::DescriptorFlags::WRITE) {207out |= Self::WRITE;208}209if flags.contains(types::DescriptorFlags::FILE_INTEGRITY_SYNC) {210out |= Self::FILE_INTEGRITY_SYNC;211}212if flags.contains(types::DescriptorFlags::DATA_INTEGRITY_SYNC) {213out |= Self::DATA_INTEGRITY_SYNC;214}215if flags.contains(types::DescriptorFlags::REQUESTED_WRITE_SYNC) {216out |= Self::REQUESTED_WRITE_SYNC;217}218if flags.contains(types::DescriptorFlags::MUTATE_DIRECTORY) {219out |= Self::MUTATE_DIRECTORY;220}221out222}223}224225impl From<crate::filesystem::MetadataHashValue> for types::MetadataHashValue {226fn from(227crate::filesystem::MetadataHashValue { lower, upper }: crate::filesystem::MetadataHashValue,228) -> Self {229Self { lower, upper }230}231}232233impl From<crate::filesystem::DescriptorStat> for types::DescriptorStat {234fn from(235crate::filesystem::DescriptorStat {236type_,237link_count,238size,239data_access_timestamp,240data_modification_timestamp,241status_change_timestamp,242}: crate::filesystem::DescriptorStat,243) -> Self {244Self {245type_: type_.into(),246link_count,247size,248data_access_timestamp: data_access_timestamp.map(Into::into),249data_modification_timestamp: data_modification_timestamp.map(Into::into),250status_change_timestamp: status_change_timestamp.map(Into::into),251}252}253}254255impl From<crate::filesystem::DescriptorType> for types::DescriptorType {256fn from(ty: crate::filesystem::DescriptorType) -> Self {257match ty {258crate::filesystem::DescriptorType::Unknown => Self::Unknown,259crate::filesystem::DescriptorType::BlockDevice => Self::BlockDevice,260crate::filesystem::DescriptorType::CharacterDevice => Self::CharacterDevice,261crate::filesystem::DescriptorType::Directory => Self::Directory,262crate::filesystem::DescriptorType::SymbolicLink => Self::SymbolicLink,263crate::filesystem::DescriptorType::RegularFile => Self::RegularFile,264}265}266}267268impl From<cap_std::fs::FileType> for types::DescriptorType {269fn from(ft: cap_std::fs::FileType) -> Self {270use cap_fs_ext::FileTypeExt as _;271if ft.is_dir() {272Self::Directory273} else if ft.is_symlink() {274Self::SymbolicLink275} else if ft.is_block_device() {276Self::BlockDevice277} else if ft.is_char_device() {278Self::CharacterDevice279} else if ft.is_file() {280Self::RegularFile281} else {282Self::Unknown283}284}285}286287288