wasmtime_wasi/p3/filesystem/
mod.rs1mod host;
2
3use crate::TrappableError;
4use crate::filesystem::{WasiFilesystem, WasiFilesystemView};
5use crate::p3::bindings::filesystem::{preopens, types};
6use wasmtime::component::Linker;
7
8pub type FilesystemResult<T> = Result<T, FilesystemError>;
9pub type FilesystemError = TrappableError<types::ErrorCode>;
10
11pub fn add_to_linker<T>(linker: &mut Linker<T>) -> wasmtime::Result<()>
63where
64 T: WasiFilesystemView + 'static,
65{
66 types::add_to_linker::<_, WasiFilesystem>(linker, T::filesystem)?;
67 preopens::add_to_linker::<_, WasiFilesystem>(linker, T::filesystem)?;
68 Ok(())
69}
70
71impl<'a> From<&'a std::io::Error> for types::ErrorCode {
72 fn from(err: &'a std::io::Error) -> Self {
73 crate::filesystem::ErrorCode::from(err).into()
74 }
75}
76
77impl From<std::io::Error> for types::ErrorCode {
78 fn from(err: std::io::Error) -> Self {
79 Self::from(&err)
80 }
81}
82
83impl From<std::io::Error> for FilesystemError {
84 fn from(error: std::io::Error) -> Self {
85 types::ErrorCode::from(error).into()
86 }
87}
88
89impl From<crate::filesystem::ErrorCode> for types::ErrorCode {
90 fn from(error: crate::filesystem::ErrorCode) -> Self {
91 match error {
92 crate::filesystem::ErrorCode::Access => Self::Access,
93 crate::filesystem::ErrorCode::Already => Self::Already,
94 crate::filesystem::ErrorCode::BadDescriptor => Self::BadDescriptor,
95 crate::filesystem::ErrorCode::Busy => Self::Busy,
96 crate::filesystem::ErrorCode::Exist => Self::Exist,
97 crate::filesystem::ErrorCode::FileTooLarge => Self::FileTooLarge,
98 crate::filesystem::ErrorCode::IllegalByteSequence => Self::IllegalByteSequence,
99 crate::filesystem::ErrorCode::InProgress => Self::InProgress,
100 crate::filesystem::ErrorCode::Interrupted => Self::Interrupted,
101 crate::filesystem::ErrorCode::Invalid => Self::Invalid,
102 crate::filesystem::ErrorCode::Io => Self::Io,
103 crate::filesystem::ErrorCode::IsDirectory => Self::IsDirectory,
104 crate::filesystem::ErrorCode::Loop => Self::Loop,
105 crate::filesystem::ErrorCode::TooManyLinks => Self::TooManyLinks,
106 crate::filesystem::ErrorCode::NameTooLong => Self::NameTooLong,
107 crate::filesystem::ErrorCode::NoEntry => Self::NoEntry,
108 crate::filesystem::ErrorCode::InsufficientMemory => Self::InsufficientMemory,
109 crate::filesystem::ErrorCode::InsufficientSpace => Self::InsufficientSpace,
110 crate::filesystem::ErrorCode::NotDirectory => Self::NotDirectory,
111 crate::filesystem::ErrorCode::NotEmpty => Self::NotEmpty,
112 crate::filesystem::ErrorCode::Unsupported => Self::Unsupported,
113 crate::filesystem::ErrorCode::Overflow => Self::Overflow,
114 crate::filesystem::ErrorCode::NotPermitted => Self::NotPermitted,
115 crate::filesystem::ErrorCode::Pipe => Self::Pipe,
116 crate::filesystem::ErrorCode::InvalidSeek => Self::InvalidSeek,
117 }
118 }
119}
120
121impl From<crate::filesystem::ErrorCode> for FilesystemError {
122 fn from(error: crate::filesystem::ErrorCode) -> Self {
123 types::ErrorCode::from(error).into()
124 }
125}
126
127impl From<wasmtime::component::ResourceTableError> for FilesystemError {
128 fn from(error: wasmtime::component::ResourceTableError) -> Self {
129 Self::trap(error)
130 }
131}
132
133impl From<types::Advice> for system_interface::fs::Advice {
134 fn from(advice: types::Advice) -> Self {
135 match advice {
136 types::Advice::Normal => Self::Normal,
137 types::Advice::Sequential => Self::Sequential,
138 types::Advice::Random => Self::Random,
139 types::Advice::WillNeed => Self::WillNeed,
140 types::Advice::DontNeed => Self::DontNeed,
141 types::Advice::NoReuse => Self::NoReuse,
142 }
143 }
144}
145
146impl From<types::OpenFlags> for crate::filesystem::OpenFlags {
147 fn from(flags: types::OpenFlags) -> Self {
148 let mut out = Self::empty();
149 if flags.contains(types::OpenFlags::CREATE) {
150 out |= Self::CREATE;
151 }
152 if flags.contains(types::OpenFlags::DIRECTORY) {
153 out |= Self::DIRECTORY;
154 }
155 if flags.contains(types::OpenFlags::EXCLUSIVE) {
156 out |= Self::EXCLUSIVE;
157 }
158 if flags.contains(types::OpenFlags::TRUNCATE) {
159 out |= Self::TRUNCATE;
160 }
161 out
162 }
163}
164
165impl From<types::PathFlags> for crate::filesystem::PathFlags {
166 fn from(flags: types::PathFlags) -> Self {
167 let mut out = Self::empty();
168 if flags.contains(types::PathFlags::SYMLINK_FOLLOW) {
169 out |= Self::SYMLINK_FOLLOW;
170 }
171 out
172 }
173}
174
175impl From<crate::filesystem::DescriptorFlags> for types::DescriptorFlags {
176 fn from(flags: crate::filesystem::DescriptorFlags) -> Self {
177 let mut out = Self::empty();
178 if flags.contains(crate::filesystem::DescriptorFlags::READ) {
179 out |= Self::READ;
180 }
181 if flags.contains(crate::filesystem::DescriptorFlags::WRITE) {
182 out |= Self::WRITE;
183 }
184 if flags.contains(crate::filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) {
185 out |= Self::FILE_INTEGRITY_SYNC;
186 }
187 if flags.contains(crate::filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) {
188 out |= Self::DATA_INTEGRITY_SYNC;
189 }
190 if flags.contains(crate::filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) {
191 out |= Self::REQUESTED_WRITE_SYNC;
192 }
193 if flags.contains(crate::filesystem::DescriptorFlags::MUTATE_DIRECTORY) {
194 out |= Self::MUTATE_DIRECTORY;
195 }
196 out
197 }
198}
199
200impl From<types::DescriptorFlags> for crate::filesystem::DescriptorFlags {
201 fn from(flags: types::DescriptorFlags) -> Self {
202 let mut out = Self::empty();
203 if flags.contains(types::DescriptorFlags::READ) {
204 out |= Self::READ;
205 }
206 if flags.contains(types::DescriptorFlags::WRITE) {
207 out |= Self::WRITE;
208 }
209 if flags.contains(types::DescriptorFlags::FILE_INTEGRITY_SYNC) {
210 out |= Self::FILE_INTEGRITY_SYNC;
211 }
212 if flags.contains(types::DescriptorFlags::DATA_INTEGRITY_SYNC) {
213 out |= Self::DATA_INTEGRITY_SYNC;
214 }
215 if flags.contains(types::DescriptorFlags::REQUESTED_WRITE_SYNC) {
216 out |= Self::REQUESTED_WRITE_SYNC;
217 }
218 if flags.contains(types::DescriptorFlags::MUTATE_DIRECTORY) {
219 out |= Self::MUTATE_DIRECTORY;
220 }
221 out
222 }
223}
224
225impl From<crate::filesystem::MetadataHashValue> for types::MetadataHashValue {
226 fn from(
227 crate::filesystem::MetadataHashValue { lower, upper }: crate::filesystem::MetadataHashValue,
228 ) -> Self {
229 Self { lower, upper }
230 }
231}
232
233impl From<crate::filesystem::DescriptorStat> for types::DescriptorStat {
234 fn from(
235 crate::filesystem::DescriptorStat {
236 type_,
237 link_count,
238 size,
239 data_access_timestamp,
240 data_modification_timestamp,
241 status_change_timestamp,
242 }: crate::filesystem::DescriptorStat,
243 ) -> Self {
244 Self {
245 type_: type_.into(),
246 link_count,
247 size,
248 data_access_timestamp: data_access_timestamp.map(Into::into),
249 data_modification_timestamp: data_modification_timestamp.map(Into::into),
250 status_change_timestamp: status_change_timestamp.map(Into::into),
251 }
252 }
253}
254
255impl From<crate::filesystem::DescriptorType> for types::DescriptorType {
256 fn from(ty: crate::filesystem::DescriptorType) -> Self {
257 match ty {
258 crate::filesystem::DescriptorType::Unknown => Self::Unknown,
259 crate::filesystem::DescriptorType::BlockDevice => Self::BlockDevice,
260 crate::filesystem::DescriptorType::CharacterDevice => Self::CharacterDevice,
261 crate::filesystem::DescriptorType::Directory => Self::Directory,
262 crate::filesystem::DescriptorType::SymbolicLink => Self::SymbolicLink,
263 crate::filesystem::DescriptorType::RegularFile => Self::RegularFile,
264 }
265 }
266}
267
268impl From<cap_std::fs::FileType> for types::DescriptorType {
269 fn from(ft: cap_std::fs::FileType) -> Self {
270 use cap_fs_ext::FileTypeExt as _;
271 if ft.is_dir() {
272 Self::Directory
273 } else if ft.is_symlink() {
274 Self::SymbolicLink
275 } else if ft.is_block_device() {
276 Self::BlockDevice
277 } else if ft.is_char_device() {
278 Self::CharacterDevice
279 } else if ft.is_file() {
280 Self::RegularFile
281 } else {
282 Self::Unknown
283 }
284 }
285}