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, pub flags: Flags,
15}
16impl<F> OpPathLike<F> {
17 pub fn path(&self) -> &str {
18 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], metadata: *const [u64], }
36impl OpCall {
37 pub fn payload_and_metadata(&mut self) -> (&mut [u8], &[u64]) {
38 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 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 .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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}