wasmer_wasix/fs/
relative_path_hack.rs1use std::{path::Path, sync::Arc};
2
3use futures::future::BoxFuture;
4use virtual_fs::{FileSystem, FsError, OpenOptions, OpenOptionsConfig};
5
6#[derive(Debug)]
7pub struct RelativeOrAbsolutePathHack<F>(pub F);
8
9impl<F: FileSystem> RelativeOrAbsolutePathHack<F> {
10 fn execute<Func, Ret>(&self, path: &Path, operation: Func) -> Result<Ret, FsError>
11 where
12 Func: Fn(&F, &Path) -> Result<Ret, FsError>,
13 {
14 let result = operation(&self.0, path);
16
17 if result.is_err() && !path.is_absolute() {
18 let path = Path::new("/").join(path);
21 operation(&self.0, &path)
22 } else {
23 result
24 }
25 }
26}
27
28impl<F: FileSystem> virtual_fs::FileSystem for RelativeOrAbsolutePathHack<F> {
29 fn readlink(&self, path: &Path) -> virtual_fs::Result<std::path::PathBuf> {
30 self.execute(path, |fs, p| fs.readlink(p))
31 }
32
33 fn read_dir(&self, path: &Path) -> virtual_fs::Result<virtual_fs::ReadDir> {
34 self.execute(path, |fs, p| fs.read_dir(p))
35 }
36
37 fn create_dir(&self, path: &Path) -> virtual_fs::Result<()> {
38 self.execute(path, |fs, p| fs.create_dir(p))
39 }
40
41 fn remove_dir(&self, path: &Path) -> virtual_fs::Result<()> {
42 self.execute(path, |fs, p| fs.remove_dir(p))
43 }
44
45 fn rename<'a>(&'a self, from: &Path, to: &Path) -> BoxFuture<'a, virtual_fs::Result<()>> {
46 let from = from.to_owned();
47 let to = to.to_owned();
48 Box::pin(async move { self.0.rename(&from, &to).await })
49 }
50
51 fn metadata(&self, path: &Path) -> virtual_fs::Result<virtual_fs::Metadata> {
52 self.execute(path, |fs, p| fs.metadata(p))
53 }
54
55 fn symlink_metadata(&self, path: &Path) -> virtual_fs::Result<virtual_fs::Metadata> {
56 self.execute(path, |fs, p| fs.symlink_metadata(p))
57 }
58
59 fn remove_file(&self, path: &Path) -> virtual_fs::Result<()> {
60 self.execute(path, |fs, p| fs.remove_file(p))
61 }
62
63 fn new_open_options(&self) -> OpenOptions<'_> {
64 virtual_fs::OpenOptions::new(self)
65 }
66
67 fn mount(
68 &self,
69 name: String,
70 path: &Path,
71 fs: Box<dyn FileSystem + Send + Sync>,
72 ) -> virtual_fs::Result<()> {
73 let name_ref = &name;
74 let f_ref = &Arc::new(fs);
75 self.execute(path, move |f, p| {
76 f.mount(name_ref.clone(), p, Box::new(f_ref.clone()))
77 })
78 }
79}
80
81impl<F: FileSystem> virtual_fs::FileOpener for RelativeOrAbsolutePathHack<F> {
82 fn open(
83 &self,
84 path: &Path,
85 conf: &OpenOptionsConfig,
86 ) -> virtual_fs::Result<Box<dyn virtual_fs::VirtualFile + Send + Sync + 'static>> {
87 self.execute(path, |fs, p| {
88 fs.new_open_options().options(conf.clone()).open(p)
89 })
90 }
91}