blown_fuse/ops/
traits.rs

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}