1use crate::{
2 io::{Entry, FsInfo, Ino, Interruptible, Known, Mode, Stat, Ttl},
3 Done, Operation, Reply, Request,
4};
5
6use super::make_entry;
7use bytes::BufMut;
8use std::{ffi::OsStr, os::unix::ffi::OsStrExt};
9
10pub use super::{
11 dir::{ReplyEntries, ReplyFound},
12 entry::{RequestDevice, RequestLink, RequestTarget},
13 global::ReplyFsInfo,
14 inode::{ReplyBlock, ReplyStat, RequestBlock, RequestForget},
15 open::{ReplyOpen, ReplyPermissionDenied},
16 rw::ReplyAll,
17 xattr::ReplyXattrRead,
18};
19
20pub trait RequestName<'o>: Operation<'o> {
21 fn name<'a>(request: &'a Request<'o, Self>) -> &'a OsStr;
22}
23
24pub trait RequestSize<'o>: Operation<'o> {
25 fn size(request: &Request<'o, Self>) -> u32;
26}
27
28pub trait RequestOffset<'o>: Operation<'o> {
29 fn offset(request: &Request<'o, Self>) -> u64;
30}
31
32pub trait RequestHandle<'o>: Operation<'o> {
33 fn handle(request: &Request<'o, Self>) -> u64;
34}
35
36pub trait RequestData<'o>: Operation<'o> {
37 fn data<'a>(request: &'a Request<'o, Self>) -> &'a [u8];
38}
39
40pub trait RequestFlags<'o>: Operation<'o> {
41 type Flags: Copy;
42 fn flags(request: &Request<'o, Self>) -> Self::Flags;
43}
44
45pub trait RequestMode<'o>: Operation<'o> {
46 fn mode(request: &Request<'o, Self>) -> Mode;
47 fn umask(request: &Request<'o, Self>) -> Mode;
48}
49
50pub trait ReplyOk<'o>: Operation<'o> {
51 fn ok(reply: Reply<'o, Self>) -> Done<'o> {
52 reply.empty()
53 }
54}
55
56pub trait ReplyKnown<'o>: Operation<'o> {
57 fn known(reply: Reply<'o, Self>, entry: impl Known, ttl: Ttl) -> Done<'o> {
58 let (attrs, attrs_ttl) = entry.inode().attrs();
59 let attrs = attrs.finish(entry.inode());
60
61 let done = reply.single(&make_entry((entry.inode().ino(), ttl), (attrs, attrs_ttl)));
62 entry.unveil();
63
64 done
65 }
66}
67
68pub trait ReplyNotFound<'o>: Operation<'o> {
69 fn not_found(reply: Reply<'o, Self>) -> Done<'o>;
70}
71
72pub trait ReplyBuffered<'o, B>: Operation<'o>
73where
74 B: BufMut + AsRef<[u8]>,
75{
76 type Buffered: Operation<'o>;
77 fn buffered(reply: Reply<'o, Self>, buffer: B) -> Reply<'o, Self::Buffered>;
78}
79
80pub trait ReplyGather<'o>: Operation<'o> {
81 fn blob(reply: Reply<'o, Self>, blob: impl AsRef<OsStr>) -> Done<'o> {
82 Self::slice(reply, blob.as_ref().as_bytes())
83 }
84
85 fn slice(reply: Reply<'o, Self>, slice: impl AsRef<[u8]>) -> Done<'o> {
86 Self::gather(reply, &[slice.as_ref()])
87 }
88
89 fn gather(reply: Reply<'o, Self>, fragments: &[&[u8]]) -> Done<'o> {
90 reply.chain(crate::util::OutputChain::tail(fragments))
91 }
92}
93
94impl<'o, O: Operation<'o>> Request<'o, O> {
95 pub fn name(&self) -> &OsStr
96 where
97 O: RequestName<'o>,
98 {
99 O::name(self)
100 }
101
102 pub fn size(&self) -> u32
103 where
104 O: RequestSize<'o>,
105 {
106 O::size(self)
107 }
108
109 pub fn offset(&self) -> u64
110 where
111 O: RequestOffset<'o>,
112 {
113 O::offset(self)
114 }
115
116 pub fn handle(&self) -> u64
117 where
118 O: RequestHandle<'o>,
119 {
120 O::handle(self)
121 }
122
123 pub fn data(&self) -> &[u8]
124 where
125 O: RequestData<'o>,
126 {
127 O::data(self)
128 }
129
130 pub fn flags(&self) -> O::Flags
131 where
132 O: RequestFlags<'o>,
133 {
134 O::flags(self)
135 }
136
137 pub fn mode(&self) -> Mode
138 where
139 O: RequestMode<'o>,
140 {
141 O::mode(self)
142 }
143
144 pub fn umask(&self) -> Mode
145 where
146 O: RequestMode<'o>,
147 {
148 O::umask(self)
149 }
150
151 pub fn forget_list(&self) -> impl '_ + Iterator<Item = (Ino, u64)>
152 where
153 O: RequestForget<'o>,
154 {
155 O::forget_list(self)
156 }
157
158 pub fn device(&self) -> u32
159 where
160 O: RequestDevice<'o>,
161 {
162 O::device(self)
163 }
164
165 pub fn target(&self) -> &OsStr
166 where
167 O: RequestTarget<'o>,
168 {
169 O::target(self)
170 }
171
172 pub fn source_ino(&self) -> Ino
173 where
174 O: RequestLink<'o>,
175 {
176 O::source_ino(self)
177 }
178
179 pub fn block(&self) -> u64
180 where
181 O: RequestBlock<'o>,
182 {
183 O::block(self)
184 }
185
186 pub fn block_size(&self) -> u32
187 where
188 O: RequestBlock<'o>,
189 {
190 O::block_size(self)
191 }
192}
193
194impl<'o, O: Operation<'o>> Reply<'o, O> {
195 pub fn ok(self) -> Done<'o>
196 where
197 O: ReplyOk<'o>,
198 {
199 O::ok(self)
200 }
201
202 pub fn known(self, entry: impl Known, ttl: Ttl) -> Done<'o>
203 where
204 O: ReplyKnown<'o>,
205 {
206 O::known(self, entry, ttl)
207 }
208
209 pub fn not_found(self) -> Done<'o>
210 where
211 O: ReplyNotFound<'o>,
212 {
213 O::not_found(self)
214 }
215
216 pub fn permission_denied(self) -> Done<'o>
217 where
218 O: ReplyPermissionDenied<'o>,
219 {
220 O::permission_denied(self)
221 }
222
223 pub fn stat(self, inode: &impl Stat) -> Done<'o>
224 where
225 O: ReplyStat<'o>,
226 {
227 O::stat(self, inode)
228 }
229
230 pub fn ok_with_handle(self, handle: u64) -> Done<'o>
231 where
232 O: ReplyOpen<'o> + ReplyOk<'o>,
233 {
234 O::ok_with_handle(self, handle)
235 }
236
237 pub fn known_with_handle(self, known: impl Known, ttl: Ttl, handle: u64) -> Done<'o>
238 where
239 O: ReplyOpen<'o> + ReplyKnown<'o>,
240 {
241 O::known_with_handle(self, known, ttl, handle)
242 }
243
244 pub fn force_direct_io(&mut self)
245 where
246 O: ReplyOpen<'o>,
247 {
248 O::force_direct_io(self)
249 }
250
251 pub fn non_seekable(&mut self)
252 where
253 O: ReplyOpen<'o>,
254 {
255 O::non_seekable(self)
256 }
257
258 pub fn is_stream(&mut self)
259 where
260 O: ReplyOpen<'o>,
261 {
262 O::is_stream(self)
263 }
264
265 pub fn not_found_for(self, ttl: Ttl) -> Done<'o>
266 where
267 O: ReplyFound<'o>,
268 {
269 O::not_found_for(self, ttl)
270 }
271
272 pub fn entry(self, entry: Entry<impl Known>) -> Interruptible<'o, O, ()>
273 where
274 O: ReplyEntries<'o>,
275 {
276 O::entry(self, entry)
277 }
278
279 pub fn end(self) -> Done<'o>
280 where
281 O: ReplyEntries<'o>,
282 {
283 O::end(self)
284 }
285
286 pub fn all(self) -> Done<'o>
287 where
288 O: ReplyAll<'o>,
289 {
290 O::all(self)
291 }
292
293 pub fn buffered<B>(self, buffer: B) -> Reply<'o, O::Buffered>
294 where
295 O: ReplyBuffered<'o, B>,
296 B: BufMut + AsRef<[u8]>,
297 {
298 O::buffered(self, buffer)
299 }
300
301 pub fn blob(self, blob: impl AsRef<OsStr>) -> Done<'o>
302 where
303 O: ReplyGather<'o>,
304 {
305 O::blob(self, blob)
306 }
307
308 pub fn slice(self, slice: impl AsRef<[u8]>) -> Done<'o>
309 where
310 O: ReplyGather<'o>,
311 {
312 O::slice(self, slice)
313 }
314
315 pub fn gather(self, fragments: &[&[u8]]) -> Done<'o>
316 where
317 O: ReplyGather<'o>,
318 {
319 O::gather(self, fragments)
320 }
321
322 pub fn info(self, info: &FsInfo) -> Done<'o>
323 where
324 O: ReplyFsInfo<'o>,
325 {
326 O::info(self, info)
327 }
328
329 pub fn requires_size(self, size: u32) -> Done<'o>
330 where
331 O: ReplyXattrRead<'o>,
332 {
333 O::requires_size(self, size)
334 }
335
336 pub fn buffer_too_small(self) -> Done<'o>
337 where
338 O: ReplyXattrRead<'o>,
339 {
340 O::buffer_too_small(self)
341 }
342
343 pub fn block(self, block: u64) -> Done<'o>
344 where
345 O: ReplyBlock<'o>,
346 {
347 O::block(self, block)
348 }
349}