1use crate::time_compat::SystemTime;
8use async_trait::async_trait;
9use std::io::{Error as IoError, ErrorKind};
10use std::path::{Path, PathBuf};
11use std::sync::Arc;
12
13use super::limits::{FsLimits, FsUsage};
14use super::traits::{DirEntry, FileSystem, FileSystemExt, Metadata};
15use crate::error::Result;
16
17pub struct ReadOnlyFs {
19 inner: Arc<dyn FileSystem>,
20}
21
22impl ReadOnlyFs {
23 pub fn new(inner: Arc<dyn FileSystem>) -> Self {
24 Self { inner }
25 }
26
27 fn readonly_error() -> crate::Error {
28 IoError::new(ErrorKind::PermissionDenied, "filesystem is read-only").into()
29 }
30}
31
32#[async_trait]
33impl FileSystem for ReadOnlyFs {
34 async fn read_file(&self, path: &Path) -> Result<Vec<u8>> {
35 self.inner.read_file(path).await
36 }
37
38 async fn write_file(&self, _path: &Path, _content: &[u8]) -> Result<()> {
39 Err(Self::readonly_error())
40 }
41
42 async fn append_file(&self, _path: &Path, _content: &[u8]) -> Result<()> {
43 Err(Self::readonly_error())
44 }
45
46 async fn mkdir(&self, _path: &Path, _recursive: bool) -> Result<()> {
47 Err(Self::readonly_error())
48 }
49
50 async fn remove(&self, _path: &Path, _recursive: bool) -> Result<()> {
51 Err(Self::readonly_error())
52 }
53
54 async fn stat(&self, path: &Path) -> Result<Metadata> {
55 self.inner.stat(path).await
56 }
57
58 async fn read_dir(&self, path: &Path) -> Result<Vec<DirEntry>> {
59 self.inner.read_dir(path).await
60 }
61
62 async fn exists(&self, path: &Path) -> Result<bool> {
63 self.inner.exists(path).await
64 }
65
66 async fn rename(&self, _from: &Path, _to: &Path) -> Result<()> {
67 Err(Self::readonly_error())
68 }
69
70 async fn copy(&self, _from: &Path, _to: &Path) -> Result<()> {
71 Err(Self::readonly_error())
72 }
73
74 async fn symlink(&self, _target: &Path, _link: &Path) -> Result<()> {
75 Err(Self::readonly_error())
76 }
77
78 async fn read_link(&self, path: &Path) -> Result<PathBuf> {
79 self.inner.read_link(path).await
80 }
81
82 async fn chmod(&self, _path: &Path, _mode: u32) -> Result<()> {
83 Err(Self::readonly_error())
84 }
85
86 async fn set_modified_time(&self, _path: &Path, _time: SystemTime) -> Result<()> {
87 Err(Self::readonly_error())
88 }
89
90 fn as_search_capable(&self) -> Option<&dyn super::SearchCapable> {
91 self.inner.as_search_capable()
92 }
93}
94
95#[async_trait]
96impl FileSystemExt for ReadOnlyFs {
97 fn usage(&self) -> FsUsage {
98 self.inner.usage()
99 }
100
101 fn limits(&self) -> FsLimits {
102 self.inner.limits()
103 }
104
105 async fn mkfifo(&self, _path: &Path, _mode: u32) -> Result<()> {
106 Err(Self::readonly_error())
107 }
108
109 fn vfs_snapshot(&self) -> Option<super::VfsSnapshot> {
110 self.inner.vfs_snapshot()
111 }
112
113 fn vfs_restore(&self, _snapshot: &super::VfsSnapshot) -> Result<()> {
114 Err(Self::readonly_error())
115 }
116}