redox_scheme/
scheme.rs

1#![allow(async_fn_in_trait)]
2
3use core::fmt::{self, Debug};
4use core::mem::size_of;
5use syscall::dirent::DirentBuf;
6use syscall::schemev2::{Opcode, Sqe};
7use syscall::{error::*, flag::*, Stat, StatVfs, TimeSpec};
8
9use crate::{CallRequest, CallerCtx, Id, OpenResult, Response, SendFdRequest, Tag};
10
11pub struct OpPathLike<Flags> {
12    req: Tag,
13    path: *const str, // &req
14    pub flags: Flags,
15}
16impl<F> OpPathLike<F> {
17    pub fn path(&self) -> &str {
18        // SAFETY: borrowed from self.req
19        unsafe { &*self.path }
20    }
21}
22impl<Flags: Debug> Debug for OpPathLike<Flags> {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        f.debug_struct("OpPathLike")
25            .field("path", &self.path())
26            .field("flags", &self.flags)
27            .finish()
28    }
29}
30pub struct OpCall {
31    req: Tag,
32    pub fd: usize,
33    payload: *mut [u8],     // &req
34    metadata: *const [u64], // &req
35}
36impl OpCall {
37    pub fn payload_and_metadata(&mut self) -> (&mut [u8], &[u64]) {
38        // SAFETY: borrows &self.req
39        unsafe { (&mut *self.payload, &*self.metadata) }
40    }
41    pub fn payload(&mut self) -> &mut [u8] {
42        self.payload_and_metadata().0
43    }
44    pub fn metadata(&self) -> &[u64] {
45        // SAFETY: borrows &self.req
46        unsafe { &*self.metadata }
47    }
48}
49impl Debug for OpCall {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        f.debug_struct("OpCall")
52            .field("fd", &self.fd)
53            // TODO: debug first and last few bytes, collapse middle to ...
54            .field("payload", &self.payload)
55            .field("metadata", &self.metadata())
56            .finish()
57    }
58}
59#[derive(Debug)]
60pub struct OpQueryRead<T: ?Sized> {
61    pub fd: usize,
62    req: Tag,
63    buf: *mut T,
64}
65impl<T: ?Sized> OpQueryRead<T> {
66    pub fn buf(&mut self) -> &mut T {
67        // SAFETY: borrows &mut self.req
68        unsafe { &mut *self.buf }
69    }
70}
71#[derive(Debug)]
72pub struct OpQueryWrite<T: ?Sized> {
73    pub fd: usize,
74    req: Tag,
75    buf: *const T,
76}
77impl<T: ?Sized> OpQueryWrite<T> {
78    pub fn buf(&self) -> &T {
79        // SAFETY: borrows &self.req
80        unsafe { &*self.buf }
81    }
82}
83#[derive(Debug)]
84pub struct OpGetdents {
85    req: Tag,
86    pub fd: usize,
87    buf: *mut [u8],
88    pub header_size: u16,
89    pub opaque_offset: u64,
90}
91impl OpGetdents {
92    pub fn raw_buf(&mut self) -> &mut [u8] {
93        // SAFETY: borrows
94        unsafe { &mut *self.buf }
95    }
96    pub fn buf(&mut self) -> Option<DirentBuf<&mut [u8]>> {
97        let sz = self.header_size;
98        DirentBuf::new(self.raw_buf(), sz)
99    }
100}
101#[derive(Debug)]
102pub struct OpRead {
103    req: Tag,
104    pub fd: usize,
105    pub offset: u64,
106    pub flags: u32,
107    buf: *mut [u8],
108}
109impl OpRead {
110    pub fn buf(&mut self) -> &mut [u8] {
111        // SAFETY: Borrows &mut self.req
112        unsafe { &mut *self.buf }
113    }
114}
115#[derive(Debug)]
116pub struct OpWrite {
117    req: Tag,
118    pub fd: usize,
119    pub offset: u64,
120    pub flags: u32,
121    buf: *const [u8],
122}
123impl OpWrite {
124    pub fn buf(&self) -> &[u8] {
125        // SAFETY: Borrows &self.req
126        unsafe { &*self.buf }
127    }
128}
129
130#[non_exhaustive]
131#[derive(Debug)]
132pub enum Op {
133    Open(OpPathLike<usize>),
134    Rmdir(OpPathLike<()>),
135    Unlink(OpPathLike<()>),
136    Dup(OpQueryWrite<[u8]>),
137    Read(OpRead),
138    Write(OpWrite),
139    Fsize {
140        req: Tag,
141        fd: usize,
142    },
143    Fchmod {
144        req: Tag,
145        fd: usize,
146        new_mode: u16,
147    },
148    Fchown {
149        req: Tag,
150        fd: usize,
151        new_uid: u32,
152        new_gid: u32,
153    },
154    Fcntl {
155        req: Tag,
156        fd: usize,
157        cmd: usize,
158        arg: usize,
159    },
160    Fevent {
161        req: Tag,
162        fd: usize,
163        req_flags: EventFlags,
164    },
165    Fpath(OpQueryRead<[u8]>),
166    Frename(OpQueryWrite<str>),
167    Fstat(OpQueryRead<Stat>),
168    FstatVfs(OpQueryRead<StatVfs>),
169    Fsync {
170        req: Tag,
171        fd: usize,
172    },
173    Ftruncate {
174        req: Tag,
175        fd: usize,
176        new_sz: u64,
177    },
178    Futimens(OpQueryWrite<[TimeSpec]>),
179
180    MmapPrep {
181        req: Tag,
182        fd: usize,
183        offset: u64,
184        len: usize,
185        flags: MapFlags,
186    },
187    Munmap {
188        req: Tag,
189        fd: usize,
190        offset: u64,
191        len: usize,
192        flags: MunmapFlags,
193    },
194
195    Call(OpCall),
196
197    Getdents(OpGetdents),
198}
199
200impl Op {
201    /// Decode the raw SQE into an Op with borrowed buffers passed as slices.
202    ///
203    /// # Safety
204    ///
205    /// Any borrowed buffers will be unmapped whenever a response is sent, which unlike the
206    /// move-based CallRequest API, needs to be managed manually by the caller.
207    pub unsafe fn from_sqe_unchecked(sqe: &Sqe) -> Option<Op> {
208        let req = Tag(Id(sqe.tag));
209        let opcode = Opcode::try_from_raw(sqe.opcode)?;
210        let args = sqe.args;
211
212        let [a, b, c, _d, _e, _f] = args.map(|a| a as usize);
213        use core::{slice, str};
214
215        Some(match opcode {
216            Opcode::Open => Op::Open(OpPathLike {
217                req,
218                path: str::from_utf8_unchecked(slice::from_raw_parts(a as *const u8, b)),
219                flags: c,
220            }),
221            Opcode::Rmdir => Op::Rmdir(OpPathLike {
222                req,
223                path: str::from_utf8_unchecked(slice::from_raw_parts(a as *const u8, b)),
224                flags: (),
225            }),
226            Opcode::Unlink => Op::Unlink(OpPathLike {
227                req,
228                path: str::from_utf8_unchecked(slice::from_raw_parts(a as *const u8, b)),
229                flags: (),
230            }),
231            Opcode::Dup => Op::Dup(OpQueryWrite {
232                req,
233                fd: a,
234                buf: slice::from_raw_parts(b as *const u8, c),
235            }),
236            Opcode::Read => Op::Read(OpRead {
237                req,
238                fd: a,
239                buf: slice::from_raw_parts_mut(b as *mut u8, c),
240                offset: args[3],
241                flags: args[4] as u32,
242            }),
243            Opcode::Write => Op::Write(OpWrite {
244                req,
245                fd: a,
246                buf: slice::from_raw_parts(b as *const u8, c),
247                offset: args[3],
248                flags: args[4] as u32,
249            }),
250
251            // TODO: 64-bit offset on 32-bit platforms
252            Opcode::Fsize => Op::Fsize { req, fd: a },
253            Opcode::Fchmod => Op::Fchmod {
254                req,
255                fd: a,
256                new_mode: b as u16,
257            },
258            Opcode::Fchown => Op::Fchown {
259                req,
260                fd: a,
261                new_uid: b as u32,
262                new_gid: c as u32,
263            },
264            Opcode::Fcntl => Op::Fcntl {
265                req,
266                fd: a,
267                cmd: b,
268                arg: c,
269            },
270            Opcode::Fevent => Op::Fevent {
271                req,
272                fd: a,
273                req_flags: EventFlags::from_bits_retain(b),
274            },
275            Opcode::Fpath => Op::Fpath(OpQueryRead {
276                req,
277                fd: a,
278                buf: slice::from_raw_parts_mut(b as *mut u8, c),
279            }),
280            Opcode::Frename => Op::Frename(OpQueryWrite {
281                req,
282                fd: a,
283                buf: str::from_utf8_unchecked(slice::from_raw_parts(b as *const u8, c)),
284            }),
285            Opcode::Fstat => {
286                assert!(c >= size_of::<Stat>());
287                Op::Fstat(OpQueryRead {
288                    req,
289                    fd: a,
290                    buf: &mut *(b as *mut Stat),
291                })
292            }
293            Opcode::Fstatvfs => {
294                assert!(c >= size_of::<StatVfs>());
295                Op::FstatVfs(OpQueryRead {
296                    req,
297                    fd: a,
298                    buf: &mut *(b as *mut StatVfs),
299                })
300            }
301            Opcode::Fsync => Op::Fsync { req, fd: a },
302            Opcode::Ftruncate => Op::Ftruncate {
303                req,
304                fd: a,
305                new_sz: args[1],
306            },
307            Opcode::Futimens => {
308                assert!(c <= 2 * size_of::<TimeSpec>());
309                Op::Futimens(OpQueryWrite {
310                    req,
311                    fd: a,
312                    buf: slice::from_raw_parts(b as *const TimeSpec, c / size_of::<TimeSpec>()),
313                })
314            }
315
316            Opcode::Call => Op::Call(OpCall {
317                req,
318                fd: a,
319                payload: slice::from_raw_parts_mut(b as *mut u8, c),
320                metadata: &sqe.args[3..],
321            }),
322            Opcode::Getdents => Op::Getdents(OpGetdents {
323                req,
324                fd: a,
325                buf: slice::from_raw_parts_mut(b as *mut u8, c),
326                header_size: sqe.args[3] as u16,
327                opaque_offset: sqe.args[4],
328            }),
329
330            Opcode::MmapPrep => Op::MmapPrep {
331                req,
332                fd: a,
333                offset: args[3],
334                len: b,
335                flags: MapFlags::from_bits_retain(c),
336            },
337            Opcode::Munmap => Op::Munmap {
338                req,
339                fd: a,
340                offset: args[3],
341                len: b,
342                flags: MunmapFlags::from_bits_retain(c),
343            },
344
345            _ => return None,
346        })
347    }
348}
349impl CallRequest {
350    pub fn caller(&self) -> CallerCtx {
351        let sqe = &self.inner.sqe;
352
353        CallerCtx {
354            pid: sqe.caller as usize,
355            uid: sqe.args[5] as u32,
356            gid: (sqe.args[5] >> 32) as u32,
357        }
358    }
359    pub fn op(self) -> Result<Op, Self> {
360        match unsafe { Op::from_sqe_unchecked(&self.inner.sqe) } {
361            Some(op) => Ok(op),
362            None => Err(self),
363        }
364    }
365    pub async fn handle_async(self, s: &mut impl SchemeAsync) -> Response {
366        let caller = self.caller();
367
368        let op = match self.op() {
369            Ok(op) => op,
370            Err(this) => return Response::new(Err(Error::new(ENOSYS)), this),
371        };
372
373        let (res, tag) = match op {
374            Op::Open(req) => {
375                let res = s.open(req.path(), req.flags, &caller).await;
376                return Response::open_dup_like(res, req);
377            }
378            Op::Rmdir(req) => (
379                s.rmdir(req.path(), &caller).await.map(|()| 0),
380                req.into_tag(),
381            ),
382            Op::Unlink(req) => (
383                s.unlink(req.path(), &caller).await.map(|()| 0),
384                req.into_tag(),
385            ),
386
387            Op::Dup(req) => {
388                let res = s.dup(req.fd, req.buf(), &caller).await;
389                return Response::open_dup_like(res, req);
390            }
391            Op::Read(mut req) => {
392                let OpRead {
393                    fd, offset, flags, ..
394                } = req;
395                (
396                    s.read(fd, req.buf(), offset, flags, &caller).await,
397                    req.into_tag(),
398                )
399            }
400            Op::Write(req) => (
401                s.write(req.fd, req.buf(), req.offset, req.flags, &caller)
402                    .await,
403                req.into_tag(),
404            ),
405
406            // TODO: Don't convert to usize
407            Op::Fsize { req, fd } => (s.fsize(fd, &caller).await.map(|l| l as usize), req),
408
409            Op::Fchmod { req, fd, new_mode } => {
410                (s.fchmod(fd, new_mode, &caller).await.map(|()| 0), req)
411            }
412            Op::Fchown {
413                req,
414                fd,
415                new_uid,
416                new_gid,
417            } => (
418                s.fchown(fd, new_uid, new_gid, &caller).await.map(|()| 0),
419                req,
420            ),
421            Op::Fcntl { req, fd, cmd, arg } => (s.fcntl(fd, cmd, arg, &caller).await, req),
422            Op::Fevent { req, fd, req_flags } => (
423                s.fevent(fd, req_flags, &caller).await.map(|f| f.bits()),
424                req,
425            ),
426            Op::Fpath(mut req) => (s.fpath(req.fd, req.buf(), &caller).await, req.into_tag()),
427            Op::Frename(req) => (s.frename(req.fd, req.buf(), &caller).await, req.into_tag()),
428            Op::Fstat(mut req) => (
429                s.fstat(req.fd, req.buf(), &caller).await.map(|()| 0),
430                req.into_tag(),
431            ),
432            Op::FstatVfs(mut req) => (
433                s.fstatvfs(req.fd, req.buf(), &caller).await.map(|()| 0),
434                req.into_tag(),
435            ),
436            Op::Fsync { req, fd } => (s.fsync(fd, &caller).await.map(|()| 0), req),
437            Op::Ftruncate { req, fd, new_sz } => {
438                (s.ftruncate(fd, new_sz, &caller).await.map(|()| 0), req)
439            }
440            Op::Futimens(req) => (
441                s.futimens(req.fd, req.buf(), &caller).await.map(|()| 0),
442                req.into_tag(),
443            ),
444
445            Op::MmapPrep {
446                req,
447                fd,
448                offset,
449                len,
450                flags,
451            } => (s.mmap_prep(fd, offset, len, flags, &caller).await, req),
452            Op::Munmap {
453                req,
454                fd,
455                offset,
456                len,
457                flags,
458            } => (
459                s.munmap(fd, offset, len, flags, &caller).await.map(|()| 0),
460                req,
461            ),
462
463            Op::Call(mut req) => {
464                let fd = req.fd;
465                let (payload, metadata) = req.payload_and_metadata();
466                (s.call(fd, payload, metadata).await, req.into_tag())
467            }
468
469            Op::Getdents(mut req) => {
470                let OpGetdents {
471                    fd, opaque_offset, ..
472                } = req;
473                let Some(buf) = req.buf() else {
474                    return Response::err(EINVAL, req);
475                };
476                let buf_res = s.getdents(fd, buf, opaque_offset).await;
477                (buf_res.map(|b| b.finalize()), req.into_tag())
478            }
479        };
480        Response::new(res, tag)
481    }
482    // TODO: Fix function coloring, this is just s/.await//g
483    pub fn handle_sync(self, s: &mut impl SchemeSync) -> Response {
484        let caller = self.caller();
485
486        let op = match self.op() {
487            Ok(op) => op,
488            Err(this) => return Response::new(Err(Error::new(ENOSYS)), this),
489        };
490
491        let (res, tag) = match op {
492            Op::Open(req) => {
493                let res = s.open(req.path(), req.flags, &caller);
494                return Response::open_dup_like(res, req);
495            }
496            Op::Rmdir(req) => (s.rmdir(req.path(), &caller).map(|()| 0), req.into_tag()),
497            Op::Unlink(req) => (s.unlink(req.path(), &caller).map(|()| 0), req.into_tag()),
498
499            Op::Dup(req) => {
500                let res = s.dup(req.fd, req.buf(), &caller);
501                return Response::open_dup_like(res, req);
502            }
503            Op::Read(mut req) => {
504                let OpRead {
505                    fd, offset, flags, ..
506                } = req;
507                (
508                    s.read(fd, req.buf(), offset, flags, &caller),
509                    req.into_tag(),
510                )
511            }
512            Op::Write(req) => (
513                s.write(req.fd, req.buf(), req.offset, req.flags, &caller),
514                req.into_tag(),
515            ),
516
517            // TODO: Don't convert to usize
518            Op::Fsize { req, fd } => (s.fsize(fd, &caller).map(|l| l as usize), req),
519
520            Op::Fchmod { req, fd, new_mode } => (s.fchmod(fd, new_mode, &caller).map(|()| 0), req),
521            Op::Fchown {
522                req,
523                fd,
524                new_uid,
525                new_gid,
526            } => (s.fchown(fd, new_uid, new_gid, &caller).map(|()| 0), req),
527            Op::Fcntl { req, fd, cmd, arg } => (s.fcntl(fd, cmd, arg, &caller), req),
528            Op::Fevent { req, fd, req_flags } => {
529                (s.fevent(fd, req_flags, &caller).map(|f| f.bits()), req)
530            }
531            Op::Fpath(mut req) => (s.fpath(req.fd, req.buf(), &caller), req.into_tag()),
532            Op::Frename(req) => (s.frename(req.fd, req.buf(), &caller), req.into_tag()),
533            Op::Fstat(mut req) => (
534                s.fstat(req.fd, req.buf(), &caller).map(|()| 0),
535                req.into_tag(),
536            ),
537            Op::FstatVfs(mut req) => (
538                s.fstatvfs(req.fd, req.buf(), &caller).map(|()| 0),
539                req.into_tag(),
540            ),
541            Op::Fsync { req, fd } => (s.fsync(fd, &caller).map(|()| 0), req),
542            Op::Ftruncate { req, fd, new_sz } => {
543                (s.ftruncate(fd, new_sz, &caller).map(|()| 0), req)
544            }
545            Op::Futimens(req) => (
546                s.futimens(req.fd, req.buf(), &caller).map(|()| 0),
547                req.into_tag(),
548            ),
549
550            Op::MmapPrep {
551                req,
552                fd,
553                offset,
554                len,
555                flags,
556            } => (s.mmap_prep(fd, offset, len, flags, &caller), req),
557            Op::Munmap {
558                req,
559                fd,
560                offset,
561                len,
562                flags,
563            } => (s.munmap(fd, offset, len, flags, &caller).map(|()| 0), req),
564
565            Op::Call(mut req) => {
566                let fd = req.fd;
567                let (payload, metadata) = req.payload_and_metadata();
568                (s.call(fd, payload, metadata), req.into_tag())
569            }
570
571            Op::Getdents(mut req) => {
572                let OpGetdents {
573                    fd, opaque_offset, ..
574                } = req;
575                let Some(buf) = req.buf() else {
576                    return Response::err(EINVAL, req);
577                };
578                let buf_res = s.getdents(fd, buf, opaque_offset);
579                (buf_res.map(|b| b.finalize()), req.into_tag())
580            }
581        };
582        Response::new(res, tag)
583    }
584}
585
586#[allow(unused_variables)]
587pub trait SchemeAsync {
588    /* Scheme operations */
589    async fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
590        Err(Error::new(ENOENT))
591    }
592
593    async fn rmdir(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
594        Err(Error::new(ENOENT))
595    }
596
597    async fn unlink(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
598        Err(Error::new(ENOENT))
599    }
600
601    /* Resource operations */
602    async fn dup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
603        Err(Error::new(EOPNOTSUPP))
604    }
605
606    async fn read(
607        &mut self,
608        id: usize,
609        buf: &mut [u8],
610        offset: u64,
611        fcntl_flags: u32,
612        ctx: &CallerCtx,
613    ) -> Result<usize> {
614        Err(Error::new(EBADF))
615    }
616
617    async fn write(
618        &mut self,
619        id: usize,
620        buf: &[u8],
621        offset: u64,
622        fcntl_flags: u32,
623        ctx: &CallerCtx,
624    ) -> Result<usize> {
625        Err(Error::new(EBADF))
626    }
627
628    async fn fsize(&mut self, id: usize, ctx: &CallerCtx) -> Result<u64> {
629        Err(Error::new(ESPIPE))
630    }
631
632    async fn fchmod(&mut self, id: usize, new_mode: u16, ctx: &CallerCtx) -> Result<()> {
633        Err(Error::new(EOPNOTSUPP))
634    }
635
636    async fn fchown(
637        &mut self,
638        id: usize,
639        new_uid: u32,
640        new_gid: u32,
641        ctx: &CallerCtx,
642    ) -> Result<()> {
643        Err(Error::new(EOPNOTSUPP))
644    }
645
646    async fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, ctx: &CallerCtx) -> Result<usize> {
647        Err(Error::new(EOPNOTSUPP))
648    }
649
650    async fn fevent(
651        &mut self,
652        id: usize,
653        flags: EventFlags,
654        ctx: &CallerCtx,
655    ) -> Result<EventFlags> {
656        Ok(EventFlags::empty())
657    }
658
659    async fn fpath(&mut self, id: usize, buf: &mut [u8], ctx: &CallerCtx) -> Result<usize> {
660        Err(Error::new(EOPNOTSUPP))
661    }
662
663    async fn frename(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
664        Err(Error::new(EOPNOTSUPP))
665    }
666
667    async fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
668        Err(Error::new(EOPNOTSUPP))
669    }
670
671    async fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, ctx: &CallerCtx) -> Result<()> {
672        Err(Error::new(EOPNOTSUPP))
673    }
674
675    async fn fsync(&mut self, id: usize, ctx: &CallerCtx) -> Result<()> {
676        Ok(())
677    }
678
679    async fn ftruncate(&mut self, id: usize, len: u64, ctx: &CallerCtx) -> Result<()> {
680        Err(Error::new(EBADF))
681    }
682
683    async fn futimens(&mut self, id: usize, times: &[TimeSpec], ctx: &CallerCtx) -> Result<()> {
684        Err(Error::new(EBADF))
685    }
686
687    async fn call(&mut self, id: usize, payload: &mut [u8], metadata: &[u64]) -> Result<usize> {
688        Err(Error::new(EOPNOTSUPP))
689    }
690
691    async fn getdents<'buf>(
692        &mut self,
693        id: usize,
694        buf: DirentBuf<&'buf mut [u8]>,
695        opaque_offset: u64,
696    ) -> Result<DirentBuf<&'buf mut [u8]>> {
697        Err(Error::new(ENOTDIR))
698    }
699
700    async fn mmap_prep(
701        &mut self,
702        id: usize,
703        offset: u64,
704        size: usize,
705        flags: MapFlags,
706        ctx: &CallerCtx,
707    ) -> Result<usize> {
708        Err(Error::new(EOPNOTSUPP))
709    }
710
711    async fn munmap(
712        &mut self,
713        id: usize,
714        offset: u64,
715        size: usize,
716        flags: MunmapFlags,
717        ctx: &CallerCtx,
718    ) -> Result<()> {
719        Err(Error::new(EOPNOTSUPP))
720    }
721}
722#[allow(unused_variables)]
723pub trait SchemeSync {
724    /* Scheme operations */
725    fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
726        Err(Error::new(ENOENT))
727    }
728
729    fn rmdir(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
730        Err(Error::new(ENOENT))
731    }
732
733    fn unlink(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
734        Err(Error::new(ENOENT))
735    }
736
737    /* Resource operations */
738    fn dup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
739        Err(Error::new(EOPNOTSUPP))
740    }
741
742    fn read(
743        &mut self,
744        id: usize,
745        buf: &mut [u8],
746        offset: u64,
747        fcntl_flags: u32,
748        ctx: &CallerCtx,
749    ) -> Result<usize> {
750        Err(Error::new(EBADF))
751    }
752
753    fn write(
754        &mut self,
755        id: usize,
756        buf: &[u8],
757        offset: u64,
758        fcntl_flags: u32,
759        ctx: &CallerCtx,
760    ) -> Result<usize> {
761        Err(Error::new(EBADF))
762    }
763
764    fn fsize(&mut self, id: usize, ctx: &CallerCtx) -> Result<u64> {
765        Err(Error::new(ESPIPE))
766    }
767
768    fn fchmod(&mut self, id: usize, new_mode: u16, ctx: &CallerCtx) -> Result<()> {
769        Err(Error::new(EOPNOTSUPP))
770    }
771
772    fn fchown(
773        &mut self,
774        id: usize,
775        new_uid: u32,
776        new_gid: u32,
777        ctx: &CallerCtx,
778    ) -> Result<()> {
779        Err(Error::new(EOPNOTSUPP))
780    }
781
782    fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, ctx: &CallerCtx) -> Result<usize> {
783        Err(Error::new(EOPNOTSUPP))
784    }
785
786    fn fevent(
787        &mut self,
788        id: usize,
789        flags: EventFlags,
790        ctx: &CallerCtx,
791    ) -> Result<EventFlags> {
792        Ok(EventFlags::empty())
793    }
794
795    fn fpath(&mut self, id: usize, buf: &mut [u8], ctx: &CallerCtx) -> Result<usize> {
796        Err(Error::new(EOPNOTSUPP))
797    }
798
799    fn frename(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
800        Err(Error::new(EOPNOTSUPP))
801    }
802
803    fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
804        Err(Error::new(EOPNOTSUPP))
805    }
806
807    fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, ctx: &CallerCtx) -> Result<()> {
808        Err(Error::new(EOPNOTSUPP))
809    }
810
811    fn fsync(&mut self, id: usize, ctx: &CallerCtx) -> Result<()> {
812        Ok(())
813    }
814
815    fn ftruncate(&mut self, id: usize, len: u64, ctx: &CallerCtx) -> Result<()> {
816        Err(Error::new(EBADF))
817    }
818
819    fn futimens(&mut self, id: usize, times: &[TimeSpec], ctx: &CallerCtx) -> Result<()> {
820        Err(Error::new(EBADF))
821    }
822
823    fn call(&mut self, id: usize, payload: &mut [u8], metadata: &[u64]) -> Result<usize> {
824        Err(Error::new(EOPNOTSUPP))
825    }
826
827    fn getdents<'buf>(
828        &mut self,
829        id: usize,
830        buf: DirentBuf<&'buf mut [u8]>,
831        opaque_offset: u64,
832    ) -> Result<DirentBuf<&'buf mut [u8]>> {
833        Err(Error::new(ENOTDIR))
834    }
835
836    fn mmap_prep(
837        &mut self,
838        id: usize,
839        offset: u64,
840        size: usize,
841        flags: MapFlags,
842        ctx: &CallerCtx,
843    ) -> Result<usize> {
844        Err(Error::new(EOPNOTSUPP))
845    }
846
847    fn munmap(
848        &mut self,
849        id: usize,
850        offset: u64,
851        size: usize,
852        flags: MunmapFlags,
853        ctx: &CallerCtx,
854    ) -> Result<()> {
855        Err(Error::new(EOPNOTSUPP))
856    }
857}
858pub trait IntoTag {
859    fn into_tag(self) -> Tag;
860}
861impl IntoTag for Tag {
862    fn into_tag(self) -> Tag {
863        self
864    }
865}
866impl IntoTag for CallRequest {
867    fn into_tag(self) -> Tag {
868        Tag(self.request_id())
869    }
870}
871impl IntoTag for SendFdRequest {
872    fn into_tag(self) -> Tag {
873        Tag(self.request_id())
874    }
875}
876macro_rules! trivial_into {
877    [$($name:ident,)*] => {
878        $(
879        impl IntoTag for $name {
880            #[inline]
881            fn into_tag(self) -> Tag {
882                self.req
883            }
884        }
885        )*
886    }
887}
888trivial_into![OpCall, OpRead, OpWrite, OpGetdents,];
889impl<T: ?Sized> IntoTag for OpQueryWrite<T> {
890    fn into_tag(self) -> Tag {
891        self.req
892    }
893}
894impl<T: ?Sized> IntoTag for OpQueryRead<T> {
895    fn into_tag(self) -> Tag {
896        self.req
897    }
898}
899impl<F> IntoTag for OpPathLike<F> {
900    fn into_tag(self) -> Tag {
901        self.req
902    }
903}
904impl IntoTag for Op {
905    fn into_tag(self) -> Tag {
906        use Op::*;
907        match self {
908            Open(op) => op.into_tag(),
909            Rmdir(op) | Self::Unlink(op) => op.into_tag(),
910            Dup(op) => op.into_tag(),
911            Read(op) => op.into_tag(),
912            Write(op) => op.into_tag(),
913            Fsize { req, .. }
914            | Fchmod { req, .. }
915            | Fchown { req, .. }
916            | Fcntl { req, .. }
917            | Fevent { req, .. }
918            | Fsync { req, .. }
919            | Ftruncate { req, .. }
920            | MmapPrep { req, .. }
921            | Munmap { req, .. } => req,
922            Fpath(op) => op.into_tag(),
923            Frename(op) => op.into_tag(),
924            Fstat(op) => op.into_tag(),
925            FstatVfs(op) => op.into_tag(),
926            Futimens(op) => op.into_tag(),
927            Call(op) => op.into_tag(),
928            Getdents(op) => op.into_tag(),
929        }
930    }
931}