nfs3_server/vfs/adapters/
mod.rs1mod iterator;
4
5pub use iterator::ReadDirPlusToReadDir;
6use nfs3_types::nfs3::{fattr3, filename3, nfsstat3, sattr3};
7
8use super::{
9 DirEntryPlus, NextResult, NfsFileSystem, NfsReadFileSystem, ReadDirIterator,
10 ReadDirPlusIterator, VFSCapabilities,
11};
12use crate::vfs::FileHandle;
13
14pub struct ReadOnlyAdapter<T>(T);
21
22impl<T> ReadOnlyAdapter<T>
23where
24 T: NfsReadFileSystem,
25{
26 pub const fn new(inner: T) -> Self {
27 Self(inner)
28 }
29}
30
31impl<T> NfsReadFileSystem for ReadOnlyAdapter<T>
32where
33 T: NfsReadFileSystem,
34{
35 type Handle = T::Handle;
36
37 fn root_dir(&self) -> Self::Handle {
38 self.0.root_dir()
39 }
40
41 async fn lookup(
42 &self,
43 dirid: &Self::Handle,
44 filename: &filename3<'_>,
45 ) -> Result<Self::Handle, nfsstat3> {
46 self.0.lookup(dirid, filename).await
47 }
48
49 async fn getattr(&self, id: &Self::Handle) -> Result<fattr3, nfsstat3> {
50 let mut result = self.0.getattr(id).await;
51 if let Ok(attr) = &mut result {
52 remove_write_permissions(attr);
53 }
54 result
55 }
56
57 async fn read(
58 &self,
59 id: &Self::Handle,
60 offset: u64,
61 count: u32,
62 ) -> Result<(Vec<u8>, bool), nfsstat3> {
63 self.0.read(id, offset, count).await
64 }
65
66 async fn readdir(
67 &self,
68 dirid: &Self::Handle,
69 cookie3: u64,
70 ) -> Result<impl ReadDirIterator, nfsstat3> {
71 self.0.readdir(dirid, cookie3).await
72 }
73
74 async fn readdirplus(
75 &self,
76 dirid: &Self::Handle,
77 cookie3: u64,
78 ) -> Result<impl ReadDirPlusIterator<Self::Handle>, nfsstat3> {
79 self.0
80 .readdirplus(dirid, cookie3)
81 .await
82 .map(ReadOnlyIterator)
83 }
84
85 async fn readlink(
86 &self,
87 id: &Self::Handle,
88 ) -> Result<nfs3_types::nfs3::nfspath3<'_>, nfsstat3> {
89 self.0.readlink(id).await
90 }
91}
92
93impl<T> NfsFileSystem for ReadOnlyAdapter<T>
94where
95 T: NfsReadFileSystem,
96{
97 fn capabilities(&self) -> VFSCapabilities {
98 VFSCapabilities::ReadOnly
99 }
100
101 async fn setattr(&self, _id: &Self::Handle, _setattr: sattr3) -> Result<fattr3, nfsstat3> {
102 Err(nfsstat3::NFS3ERR_ROFS)
103 }
104
105 async fn write(
106 &self,
107 _id: &Self::Handle,
108 _offset: u64,
109 _data: &[u8],
110 _stable: nfs3_types::nfs3::stable_how,
111 ) -> Result<(fattr3, nfs3_types::nfs3::stable_how), nfsstat3> {
112 Err(nfsstat3::NFS3ERR_ROFS)
113 }
114
115 async fn create(
116 &self,
117 _dirid: &Self::Handle,
118 _filename: &filename3<'_>,
119 _attr: sattr3,
120 ) -> Result<(Self::Handle, fattr3), nfsstat3> {
121 Err(nfsstat3::NFS3ERR_ROFS)
122 }
123
124 async fn create_exclusive(
125 &self,
126 _dirid: &Self::Handle,
127 _filename: &filename3<'_>,
128 _createverf: nfs3_types::nfs3::createverf3,
129 ) -> Result<Self::Handle, nfsstat3> {
130 Err(nfsstat3::NFS3ERR_ROFS)
131 }
132
133 async fn mkdir(
134 &self,
135 _dirid: &Self::Handle,
136 _dirname: &filename3<'_>,
137 ) -> Result<(Self::Handle, fattr3), nfsstat3> {
138 Err(nfsstat3::NFS3ERR_ROFS)
139 }
140
141 async fn remove(
142 &self,
143 _dirid: &Self::Handle,
144 _filename: &filename3<'_>,
145 ) -> Result<(), nfsstat3> {
146 Err(nfsstat3::NFS3ERR_ROFS)
147 }
148
149 async fn rename<'a>(
150 &self,
151 _from_dirid: &Self::Handle,
152 _from_filename: &filename3<'a>,
153 _to_dirid: &Self::Handle,
154 _to_filename: &filename3<'a>,
155 ) -> Result<(), nfsstat3> {
156 Err(nfsstat3::NFS3ERR_ROFS)
157 }
158
159 async fn symlink<'a>(
160 &self,
161 _dirid: &Self::Handle,
162 _linkname: &filename3<'a>,
163 _symlink: &nfs3_types::nfs3::nfspath3<'a>,
164 _attr: &sattr3,
165 ) -> Result<(Self::Handle, fattr3), nfsstat3> {
166 Err(nfsstat3::NFS3ERR_ROFS)
167 }
168
169 async fn commit(&self, _id: &Self::Handle, _offset: u64, _count: u32) -> Result<(), nfsstat3> {
170 Err(nfsstat3::NFS3ERR_ROFS)
171 }
172}
173
174#[derive(Debug)]
175struct ReadOnlyIterator<T>(T);
176
177impl<H, T> ReadDirPlusIterator<H> for ReadOnlyIterator<T>
178where
179 H: FileHandle,
180 T: ReadDirPlusIterator<H>,
181{
182 async fn next(&mut self) -> NextResult<DirEntryPlus<H>> {
183 let mut result = self.0.next().await;
184 if let NextResult::Ok(entry) = &mut result {
185 if let Some(attr) = &mut entry.name_attributes {
186 remove_write_permissions(attr);
187 }
188 }
189 result
190 }
191}
192
193const fn remove_write_permissions(attr: &mut fattr3) {
194 attr.mode &= 0o555; }