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