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}
30
31pub struct OpFdPathLike<Flags> {
32 pub fd: usize,
33 pub fcntl_flags: u32,
34 inner: OpPathLike<Flags>,
35}
36
37impl<F> OpFdPathLike<F> {
38 pub fn path(&self) -> &str {
39 self.inner.path()
40 }
41}
42
43impl<Flags: Debug> Debug for OpFdPathLike<Flags> {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.debug_struct("OpFdPathLike")
46 .field("fd", &self.fd)
47 .field("path", &self.path())
48 .field("flags", &self.inner.flags)
49 .field("fcntl_flags", &self.fcntl_flags)
50 .finish()
51 }
52}
53
54pub struct OpCall {
55 req: Tag,
56 pub fd: usize,
57 payload: *mut [u8], metadata: *const [u64], }
60impl OpCall {
61 pub fn payload_and_metadata(&mut self) -> (&mut [u8], &[u64]) {
62 unsafe { (&mut *self.payload, &*self.metadata) }
64 }
65 pub fn payload(&mut self) -> &mut [u8] {
66 self.payload_and_metadata().0
67 }
68 pub fn metadata(&self) -> &[u64] {
69 unsafe { &*self.metadata }
71 }
72}
73impl Debug for OpCall {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 f.debug_struct("OpCall")
76 .field("fd", &self.fd)
77 .field("payload", &self.payload)
79 .field("metadata", &self.metadata())
80 .finish()
81 }
82}
83#[derive(Debug)]
84pub struct OpQueryRead<T: ?Sized> {
85 pub fd: usize,
86 req: Tag,
87 buf: *mut T,
88}
89impl<T: ?Sized> OpQueryRead<T> {
90 pub fn buf(&mut self) -> &mut T {
91 unsafe { &mut *self.buf }
93 }
94}
95#[derive(Debug)]
96pub struct OpQueryWrite<T: ?Sized> {
97 pub fd: usize,
98 req: Tag,
99 buf: *const T,
100}
101impl<T: ?Sized> OpQueryWrite<T> {
102 pub fn buf(&self) -> &T {
103 unsafe { &*self.buf }
105 }
106}
107#[derive(Debug)]
108pub struct OpGetdents {
109 req: Tag,
110 pub fd: usize,
111 buf: *mut [u8],
112 pub header_size: u16,
113 pub opaque_offset: u64,
114}
115impl OpGetdents {
116 pub fn raw_buf(&mut self) -> &mut [u8] {
117 unsafe { &mut *self.buf }
119 }
120 pub fn buf(&mut self) -> Option<DirentBuf<&mut [u8]>> {
121 let sz = self.header_size;
122 DirentBuf::new(self.raw_buf(), sz)
123 }
124}
125#[derive(Debug)]
126pub struct OpRead {
127 req: Tag,
128 pub fd: usize,
129 pub offset: u64,
130 pub flags: u32,
131 buf: *mut [u8],
132}
133impl OpRead {
134 pub fn buf(&mut self) -> &mut [u8] {
135 unsafe { &mut *self.buf }
137 }
138}
139#[derive(Debug)]
140pub struct OpWrite {
141 req: Tag,
142 pub fd: usize,
143 pub offset: u64,
144 pub flags: u32,
145 buf: *const [u8],
146}
147impl OpWrite {
148 pub fn buf(&self) -> &[u8] {
149 unsafe { &*self.buf }
151 }
152}
153
154#[non_exhaustive]
155#[derive(Debug)]
156pub enum Op {
157 Open(OpPathLike<usize>),
158 OpenAt(OpFdPathLike<usize>),
159 Rmdir(OpPathLike<()>),
160 Unlink(OpPathLike<()>),
161 Dup(OpQueryWrite<[u8]>),
162 Read(OpRead),
163 Write(OpWrite),
164 Fsize {
165 req: Tag,
166 fd: usize,
167 },
168 Fchmod {
169 req: Tag,
170 fd: usize,
171 new_mode: u16,
172 },
173 Fchown {
174 req: Tag,
175 fd: usize,
176 new_uid: u32,
177 new_gid: u32,
178 },
179 Fcntl {
180 req: Tag,
181 fd: usize,
182 cmd: usize,
183 arg: usize,
184 },
185 Fevent {
186 req: Tag,
187 fd: usize,
188 req_flags: EventFlags,
189 },
190 Fpath(OpQueryRead<[u8]>),
191 Frename(OpQueryWrite<str>),
192 Fstat(OpQueryRead<Stat>),
193 FstatVfs(OpQueryRead<StatVfs>),
194 Fsync {
195 req: Tag,
196 fd: usize,
197 },
198 Ftruncate {
199 req: Tag,
200 fd: usize,
201 new_sz: u64,
202 },
203 Futimens(OpQueryWrite<[TimeSpec]>),
204
205 MmapPrep {
206 req: Tag,
207 fd: usize,
208 offset: u64,
209 len: usize,
210 flags: MapFlags,
211 },
212 Munmap {
213 req: Tag,
214 fd: usize,
215 offset: u64,
216 len: usize,
217 flags: MunmapFlags,
218 },
219
220 Call(OpCall),
221
222 Getdents(OpGetdents),
223}
224
225impl Op {
226 pub unsafe fn from_sqe_unchecked(sqe: &Sqe) -> Option<Op> {
233 let req = Tag(Id(sqe.tag));
234 let opcode = Opcode::try_from_raw(sqe.opcode)?;
235 let args = sqe.args;
236
237 let [a, b, c, d, e, _f] = args.map(|a| a as usize);
238 use core::{slice, str};
239
240 Some(match opcode {
241 Opcode::Open => Op::Open(OpPathLike {
242 req,
243 path: str::from_utf8_unchecked(slice::from_raw_parts(a as *const u8, b)),
244 flags: c,
245 }),
246 Opcode::OpenAt => Op::OpenAt(OpFdPathLike {
247 fd: a,
248 fcntl_flags: e as u32,
249 inner: OpPathLike {
250 req,
251 path: str::from_utf8_unchecked(slice::from_raw_parts(b as *const u8, c)),
252 flags: d,
253 },
254 }),
255 Opcode::Rmdir => Op::Rmdir(OpPathLike {
256 req,
257 path: str::from_utf8_unchecked(slice::from_raw_parts(a as *const u8, b)),
258 flags: (),
259 }),
260 Opcode::Unlink => Op::Unlink(OpPathLike {
261 req,
262 path: str::from_utf8_unchecked(slice::from_raw_parts(a as *const u8, b)),
263 flags: (),
264 }),
265 Opcode::Dup => Op::Dup(OpQueryWrite {
266 req,
267 fd: a,
268 buf: slice::from_raw_parts(b as *const u8, c),
269 }),
270 Opcode::Read => Op::Read(OpRead {
271 req,
272 fd: a,
273 buf: slice::from_raw_parts_mut(b as *mut u8, c),
274 offset: args[3],
275 flags: args[4] as u32,
276 }),
277 Opcode::Write => Op::Write(OpWrite {
278 req,
279 fd: a,
280 buf: slice::from_raw_parts(b as *const u8, c),
281 offset: args[3],
282 flags: args[4] as u32,
283 }),
284
285 Opcode::Fsize => Op::Fsize { req, fd: a },
287 Opcode::Fchmod => Op::Fchmod {
288 req,
289 fd: a,
290 new_mode: b as u16,
291 },
292 Opcode::Fchown => Op::Fchown {
293 req,
294 fd: a,
295 new_uid: b as u32,
296 new_gid: c as u32,
297 },
298 Opcode::Fcntl => Op::Fcntl {
299 req,
300 fd: a,
301 cmd: b,
302 arg: c,
303 },
304 Opcode::Fevent => Op::Fevent {
305 req,
306 fd: a,
307 req_flags: EventFlags::from_bits_retain(b),
308 },
309 Opcode::Fpath => Op::Fpath(OpQueryRead {
310 req,
311 fd: a,
312 buf: slice::from_raw_parts_mut(b as *mut u8, c),
313 }),
314 Opcode::Frename => Op::Frename(OpQueryWrite {
315 req,
316 fd: a,
317 buf: str::from_utf8_unchecked(slice::from_raw_parts(b as *const u8, c)),
318 }),
319 Opcode::Fstat => {
320 assert!(c >= size_of::<Stat>());
321 Op::Fstat(OpQueryRead {
322 req,
323 fd: a,
324 buf: &mut *(b as *mut Stat),
325 })
326 }
327 Opcode::Fstatvfs => {
328 assert!(c >= size_of::<StatVfs>());
329 Op::FstatVfs(OpQueryRead {
330 req,
331 fd: a,
332 buf: &mut *(b as *mut StatVfs),
333 })
334 }
335 Opcode::Fsync => Op::Fsync { req, fd: a },
336 Opcode::Ftruncate => Op::Ftruncate {
337 req,
338 fd: a,
339 new_sz: args[1],
340 },
341 Opcode::Futimens => {
342 assert!(c <= 2 * size_of::<TimeSpec>());
343 Op::Futimens(OpQueryWrite {
344 req,
345 fd: a,
346 buf: slice::from_raw_parts(b as *const TimeSpec, c / size_of::<TimeSpec>()),
347 })
348 }
349
350 Opcode::Call => Op::Call(OpCall {
351 req,
352 fd: a,
353 payload: slice::from_raw_parts_mut(b as *mut u8, c),
354 metadata: &sqe.args[3..],
355 }),
356 Opcode::Getdents => Op::Getdents(OpGetdents {
357 req,
358 fd: a,
359 buf: slice::from_raw_parts_mut(b as *mut u8, c),
360 header_size: sqe.args[3] as u16,
361 opaque_offset: sqe.args[4],
362 }),
363
364 Opcode::MmapPrep => Op::MmapPrep {
365 req,
366 fd: a,
367 offset: args[3],
368 len: b,
369 flags: MapFlags::from_bits_retain(c),
370 },
371 Opcode::Munmap => Op::Munmap {
372 req,
373 fd: a,
374 offset: args[3],
375 len: b,
376 flags: MunmapFlags::from_bits_retain(c),
377 },
378
379 _ => return None,
380 })
381 }
382 pub fn is_explicitly_nonblock(&self) -> bool {
383 let flags = match self {
384 Self::Read(r) => r.flags,
385 Self::Write(w) => w.flags,
386 Self::OpenAt(o) => o.fcntl_flags,
387 _ => 0,
388 };
389 flags as usize & O_NONBLOCK != 0
390 }
391 pub fn file_id(&self) -> Option<usize> {
392 Some(match self {
393 Op::Open(_) | Op::Rmdir(_) | Op::Unlink(_) => return None,
394 Op::OpenAt(op) => op.fd,
395 Op::Dup(op) => op.fd,
396 Op::Read(op) => op.fd,
397 Op::Write(op) => op.fd,
398 Op::Fsize { fd, .. }
399 | Op::Fchmod { fd, .. }
400 | Op::Fchown { fd, .. }
401 | Op::Fcntl { fd, .. }
402 | Op::Fevent { fd, .. }
403 | Op::Fsync { fd, .. }
404 | Op::Ftruncate { fd, .. }
405 | Op::MmapPrep { fd, .. }
406 | Op::Munmap { fd, .. } => *fd,
407 Op::Fpath(op) => op.fd,
408 Op::Frename(op) => op.fd,
409 Op::Fstat(op) => op.fd,
410 Op::FstatVfs(op) => op.fd,
411 Op::Futimens(op) => op.fd,
412 Op::Call(op) => op.fd,
413 Op::Getdents(op) => op.fd,
414 })
415 }
416}
417impl CallRequest {
418 pub fn caller(&self) -> CallerCtx {
419 let sqe = &self.inner.sqe;
420
421 CallerCtx {
422 pid: sqe.caller as usize,
423 uid: sqe.args[5] as u32,
424 gid: (sqe.args[5] >> 32) as u32,
425 id: Id(sqe.tag),
426 }
427 }
428 pub fn op(self) -> Result<Op, Self> {
429 match unsafe { Op::from_sqe_unchecked(&self.inner.sqe) } {
430 Some(op) => Ok(op),
431 None => Err(self),
432 }
433 }
434 pub async fn handle_async(self, s: &mut impl SchemeAsync) -> Response {
435 let caller = self.caller();
436
437 let op = match self.op() {
438 Ok(op) => op,
439 Err(this) => return Response::new(Err(Error::new(ENOSYS)), this),
440 };
441
442 op.handle_async(caller, s).await
443 }
444 pub fn handle_sync(self, s: &mut impl SchemeSync) -> Response {
445 let caller = self.caller();
446
447 let op = match self.op() {
448 Ok(op) => op,
449 Err(this) => return Response::new(Err(Error::new(ENOSYS)), this),
450 };
451 op.handle_sync(caller, s)
452 }
453}
454pub enum SchemeResponse {
455 Regular(Result<usize>),
456 Opened(Result<OpenResult>),
457}
458impl From<Result<usize>> for SchemeResponse {
459 fn from(value: Result<usize>) -> Self {
460 Self::Regular(value)
461 }
462}
463impl Op {
464 pub fn handle_sync(mut self, caller: CallerCtx, s: &mut impl SchemeSync) -> Response {
465 match self.handle_sync_dont_consume(&caller, s) {
466 SchemeResponse::Opened(open) => Response::open_dup_like(open, self),
467 SchemeResponse::Regular(reg) => Response::new(reg, self),
468 }
469 }
470 pub fn handle_sync_dont_consume(
471 &mut self,
472 caller: &CallerCtx,
473 s: &mut impl SchemeSync,
474 ) -> SchemeResponse {
475 match *self {
476 Op::Open(ref req) => {
477 let res = s.open(req.path(), req.flags, &caller);
478 return SchemeResponse::Opened(res);
479 }
480 Op::OpenAt(ref req) => {
481 let res = s.openat(
482 req.fd,
483 req.path(),
484 req.inner.flags,
485 req.fcntl_flags,
486 &caller,
487 );
488 return SchemeResponse::Opened(res);
489 }
490 Op::Rmdir(ref req) => s.rmdir(req.path(), &caller).map(|()| 0).into(),
491 Op::Unlink(ref req) => s.unlink(req.path(), &caller).map(|()| 0).into(),
492
493 Op::Dup(ref req) => {
494 let res = s.dup(req.fd, req.buf(), &caller);
495 return SchemeResponse::Opened(res);
496 }
497 Op::Read(ref mut req) => {
498 let OpRead {
499 fd, offset, flags, ..
500 } = *req;
501 s.read(fd, req.buf(), offset, flags, &caller).into()
502 }
503 Op::Write(ref req) => s
504 .write(req.fd, req.buf(), req.offset, req.flags, &caller)
505 .into(),
506
507 Op::Fsize { fd, .. } => s.fsize(fd, &caller).map(|l| l as usize).into(),
509
510 Op::Fchmod { fd, new_mode, .. } => s.fchmod(fd, new_mode, &caller).map(|()| 0).into(),
511 Op::Fchown {
512 fd,
513 new_uid,
514 new_gid,
515 ..
516 } => s.fchown(fd, new_uid, new_gid, &caller).map(|()| 0).into(),
517 Op::Fcntl { fd, cmd, arg, .. } => s.fcntl(fd, cmd, arg, &caller).into(),
518 Op::Fevent { fd, req_flags, .. } => {
519 s.fevent(fd, req_flags, &caller).map(|f| f.bits()).into()
520 }
521 Op::Fpath(ref mut req) => s.fpath(req.fd, req.buf(), &caller).into(),
522 Op::Frename(ref req) => s.frename(req.fd, req.buf(), &caller).into(),
523 Op::Fstat(ref mut req) => s.fstat(req.fd, req.buf(), &caller).map(|()| 0).into(),
524 Op::FstatVfs(ref mut req) => s.fstatvfs(req.fd, req.buf(), &caller).map(|()| 0).into(),
525 Op::Fsync { fd, .. } => s.fsync(fd, &caller).map(|()| 0).into(),
526 Op::Ftruncate { fd, new_sz, .. } => s.ftruncate(fd, new_sz, &caller).map(|()| 0).into(),
527 Op::Futimens(ref req) => s.futimens(req.fd, req.buf(), &caller).map(|()| 0).into(),
528
529 Op::MmapPrep {
530 fd,
531 offset,
532 len,
533 flags,
534 ..
535 } => s.mmap_prep(fd, offset, len, flags, &caller).into(),
536 Op::Munmap {
537 fd,
538 offset,
539 len,
540 flags,
541 ..
542 } => s.munmap(fd, offset, len, flags, &caller).map(|()| 0).into(),
543
544 Op::Call(ref mut req) => {
545 let fd = req.fd;
546 let (payload, metadata) = req.payload_and_metadata();
547 s.call(fd, payload, metadata).into()
548 }
549
550 Op::Getdents(ref mut req) => {
551 let OpGetdents {
552 fd, opaque_offset, ..
553 } = *req;
554 let Some(buf) = req.buf() else {
555 return Err(Error::new(EINVAL)).into();
556 };
557 let buf_res = s.getdents(fd, buf, opaque_offset);
558 buf_res.map(|b| b.finalize()).into()
559 }
560 }
561 }
562 pub async fn handle_async(self, caller: CallerCtx, s: &mut impl SchemeAsync) -> Response {
566 let (res, tag) = match self {
567 Op::Open(req) => {
568 let res = s.open(req.path(), req.flags, &caller).await;
569 return Response::open_dup_like(res, req);
570 }
571 Op::OpenAt(req) => {
572 let res = s
573 .openat(
574 req.fd,
575 req.path(),
576 req.inner.flags,
577 req.fcntl_flags,
578 &caller,
579 )
580 .await;
581 return Response::open_dup_like(res, req);
582 }
583 Op::Rmdir(req) => (
584 s.rmdir(req.path(), &caller).await.map(|()| 0),
585 req.into_tag(),
586 ),
587 Op::Unlink(req) => (
588 s.unlink(req.path(), &caller).await.map(|()| 0),
589 req.into_tag(),
590 ),
591
592 Op::Dup(req) => {
593 let res = s.dup(req.fd, req.buf(), &caller).await;
594 return Response::open_dup_like(res, req);
595 }
596 Op::Read(mut req) => {
597 let OpRead {
598 fd, offset, flags, ..
599 } = req;
600 (
601 s.read(fd, req.buf(), offset, flags, &caller).await,
602 req.into_tag(),
603 )
604 }
605 Op::Write(req) => (
606 s.write(req.fd, req.buf(), req.offset, req.flags, &caller)
607 .await,
608 req.into_tag(),
609 ),
610
611 Op::Fsize { req, fd } => (s.fsize(fd, &caller).await.map(|l| l as usize), req),
613
614 Op::Fchmod { req, fd, new_mode } => {
615 (s.fchmod(fd, new_mode, &caller).await.map(|()| 0), req)
616 }
617 Op::Fchown {
618 req,
619 fd,
620 new_uid,
621 new_gid,
622 } => (
623 s.fchown(fd, new_uid, new_gid, &caller).await.map(|()| 0),
624 req,
625 ),
626 Op::Fcntl { req, fd, cmd, arg } => (s.fcntl(fd, cmd, arg, &caller).await, req),
627 Op::Fevent { req, fd, req_flags } => (
628 s.fevent(fd, req_flags, &caller).await.map(|f| f.bits()),
629 req,
630 ),
631 Op::Fpath(mut req) => (s.fpath(req.fd, req.buf(), &caller).await, req.into_tag()),
632 Op::Frename(req) => (s.frename(req.fd, req.buf(), &caller).await, req.into_tag()),
633 Op::Fstat(mut req) => (
634 s.fstat(req.fd, req.buf(), &caller).await.map(|()| 0),
635 req.into_tag(),
636 ),
637 Op::FstatVfs(mut req) => (
638 s.fstatvfs(req.fd, req.buf(), &caller).await.map(|()| 0),
639 req.into_tag(),
640 ),
641 Op::Fsync { req, fd } => (s.fsync(fd, &caller).await.map(|()| 0), req),
642 Op::Ftruncate { req, fd, new_sz } => {
643 (s.ftruncate(fd, new_sz, &caller).await.map(|()| 0), req)
644 }
645 Op::Futimens(req) => (
646 s.futimens(req.fd, req.buf(), &caller).await.map(|()| 0),
647 req.into_tag(),
648 ),
649
650 Op::MmapPrep {
651 req,
652 fd,
653 offset,
654 len,
655 flags,
656 } => (s.mmap_prep(fd, offset, len, flags, &caller).await, req),
657 Op::Munmap {
658 req,
659 fd,
660 offset,
661 len,
662 flags,
663 } => (
664 s.munmap(fd, offset, len, flags, &caller).await.map(|()| 0),
665 req,
666 ),
667
668 Op::Call(mut req) => {
669 let fd = req.fd;
670 let (payload, metadata) = req.payload_and_metadata();
671 (s.call(fd, payload, metadata).await, req.into_tag())
672 }
673
674 Op::Getdents(mut req) => {
675 let OpGetdents {
676 fd, opaque_offset, ..
677 } = req;
678 let Some(buf) = req.buf() else {
679 return Response::err(EINVAL, req);
680 };
681 let buf_res = s.getdents(fd, buf, opaque_offset).await;
682 (buf_res.map(|b| b.finalize()), req.into_tag())
683 }
684 };
685 Response::new(res, tag)
686 }
687}
688
689#[allow(unused_variables)]
690pub trait SchemeAsync {
691 async fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
693 Err(Error::new(ENOENT))
694 }
695
696 async fn openat(
697 &mut self,
698 fd: usize,
699 path: &str,
700 flags: usize,
701 fcntl_flags: u32,
702 ctx: &CallerCtx,
703 ) -> Result<OpenResult> {
704 Err(Error::new(EOPNOTSUPP))
705 }
706
707 async fn rmdir(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
708 Err(Error::new(ENOENT))
709 }
710
711 async fn unlink(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
712 Err(Error::new(ENOENT))
713 }
714
715 async fn dup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
717 Err(Error::new(EOPNOTSUPP))
718 }
719
720 async fn read(
721 &mut self,
722 id: usize,
723 buf: &mut [u8],
724 offset: u64,
725 fcntl_flags: u32,
726 ctx: &CallerCtx,
727 ) -> Result<usize> {
728 Err(Error::new(EBADF))
729 }
730
731 async fn write(
732 &mut self,
733 id: usize,
734 buf: &[u8],
735 offset: u64,
736 fcntl_flags: u32,
737 ctx: &CallerCtx,
738 ) -> Result<usize> {
739 Err(Error::new(EBADF))
740 }
741
742 async fn fsize(&mut self, id: usize, ctx: &CallerCtx) -> Result<u64> {
743 Err(Error::new(ESPIPE))
744 }
745
746 async fn fchmod(&mut self, id: usize, new_mode: u16, ctx: &CallerCtx) -> Result<()> {
747 Err(Error::new(EOPNOTSUPP))
748 }
749
750 async fn fchown(
751 &mut self,
752 id: usize,
753 new_uid: u32,
754 new_gid: u32,
755 ctx: &CallerCtx,
756 ) -> Result<()> {
757 Err(Error::new(EOPNOTSUPP))
758 }
759
760 async fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, ctx: &CallerCtx) -> Result<usize> {
761 Err(Error::new(EOPNOTSUPP))
762 }
763
764 async fn fevent(
765 &mut self,
766 id: usize,
767 flags: EventFlags,
768 ctx: &CallerCtx,
769 ) -> Result<EventFlags> {
770 Ok(EventFlags::empty())
771 }
772
773 async fn fpath(&mut self, id: usize, buf: &mut [u8], ctx: &CallerCtx) -> Result<usize> {
774 Err(Error::new(EOPNOTSUPP))
775 }
776
777 async fn frename(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
778 Err(Error::new(EOPNOTSUPP))
779 }
780
781 async fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
782 Err(Error::new(EOPNOTSUPP))
783 }
784
785 async fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, ctx: &CallerCtx) -> Result<()> {
786 Err(Error::new(EOPNOTSUPP))
787 }
788
789 async fn fsync(&mut self, id: usize, ctx: &CallerCtx) -> Result<()> {
790 Ok(())
791 }
792
793 async fn ftruncate(&mut self, id: usize, len: u64, ctx: &CallerCtx) -> Result<()> {
794 Err(Error::new(EBADF))
795 }
796
797 async fn futimens(&mut self, id: usize, times: &[TimeSpec], ctx: &CallerCtx) -> Result<()> {
798 Err(Error::new(EBADF))
799 }
800
801 async fn call(&mut self, id: usize, payload: &mut [u8], metadata: &[u64]) -> Result<usize> {
802 Err(Error::new(EOPNOTSUPP))
803 }
804
805 async fn getdents<'buf>(
806 &mut self,
807 id: usize,
808 buf: DirentBuf<&'buf mut [u8]>,
809 opaque_offset: u64,
810 ) -> Result<DirentBuf<&'buf mut [u8]>> {
811 Err(Error::new(ENOTDIR))
812 }
813
814 async fn mmap_prep(
815 &mut self,
816 id: usize,
817 offset: u64,
818 size: usize,
819 flags: MapFlags,
820 ctx: &CallerCtx,
821 ) -> Result<usize> {
822 Err(Error::new(EOPNOTSUPP))
823 }
824
825 async fn munmap(
826 &mut self,
827 id: usize,
828 offset: u64,
829 size: usize,
830 flags: MunmapFlags,
831 ctx: &CallerCtx,
832 ) -> Result<()> {
833 Err(Error::new(EOPNOTSUPP))
834 }
835}
836#[allow(unused_variables)]
837pub trait SchemeSync {
838 fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
840 Err(Error::new(ENOENT))
841 }
842
843 fn openat(
844 &mut self,
845 fd: usize,
846 path: &str,
847 flags: usize,
848 fcntl_flags: u32,
849 ctx: &CallerCtx,
850 ) -> Result<OpenResult> {
851 Err(Error::new(EOPNOTSUPP))
852 }
853
854 fn rmdir(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
855 Err(Error::new(ENOENT))
856 }
857
858 fn unlink(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
859 Err(Error::new(ENOENT))
860 }
861
862 fn dup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
864 Err(Error::new(EOPNOTSUPP))
865 }
866
867 fn read(
868 &mut self,
869 id: usize,
870 buf: &mut [u8],
871 offset: u64,
872 fcntl_flags: u32,
873 ctx: &CallerCtx,
874 ) -> Result<usize> {
875 Err(Error::new(EBADF))
876 }
877
878 fn write(
879 &mut self,
880 id: usize,
881 buf: &[u8],
882 offset: u64,
883 fcntl_flags: u32,
884 ctx: &CallerCtx,
885 ) -> Result<usize> {
886 Err(Error::new(EBADF))
887 }
888
889 fn fsize(&mut self, id: usize, ctx: &CallerCtx) -> Result<u64> {
890 Err(Error::new(ESPIPE))
891 }
892
893 fn fchmod(&mut self, id: usize, new_mode: u16, ctx: &CallerCtx) -> Result<()> {
894 Err(Error::new(EOPNOTSUPP))
895 }
896
897 fn fchown(&mut self, id: usize, new_uid: u32, new_gid: u32, ctx: &CallerCtx) -> Result<()> {
898 Err(Error::new(EOPNOTSUPP))
899 }
900
901 fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, ctx: &CallerCtx) -> Result<usize> {
902 Err(Error::new(EOPNOTSUPP))
903 }
904
905 fn fevent(&mut self, id: usize, flags: EventFlags, ctx: &CallerCtx) -> Result<EventFlags> {
906 Ok(EventFlags::empty())
907 }
908
909 fn fpath(&mut self, id: usize, buf: &mut [u8], ctx: &CallerCtx) -> Result<usize> {
910 Err(Error::new(EOPNOTSUPP))
911 }
912
913 fn frename(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
914 Err(Error::new(EOPNOTSUPP))
915 }
916
917 fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
918 Err(Error::new(EOPNOTSUPP))
919 }
920
921 fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, ctx: &CallerCtx) -> Result<()> {
922 Err(Error::new(EOPNOTSUPP))
923 }
924
925 fn fsync(&mut self, id: usize, ctx: &CallerCtx) -> Result<()> {
926 Ok(())
927 }
928
929 fn ftruncate(&mut self, id: usize, len: u64, ctx: &CallerCtx) -> Result<()> {
930 Err(Error::new(EBADF))
931 }
932
933 fn futimens(&mut self, id: usize, times: &[TimeSpec], ctx: &CallerCtx) -> Result<()> {
934 Err(Error::new(EBADF))
935 }
936
937 fn call(&mut self, id: usize, payload: &mut [u8], metadata: &[u64]) -> Result<usize> {
938 Err(Error::new(EOPNOTSUPP))
939 }
940
941 fn getdents<'buf>(
942 &mut self,
943 id: usize,
944 buf: DirentBuf<&'buf mut [u8]>,
945 opaque_offset: u64,
946 ) -> Result<DirentBuf<&'buf mut [u8]>> {
947 Err(Error::new(ENOTDIR))
948 }
949
950 fn mmap_prep(
951 &mut self,
952 id: usize,
953 offset: u64,
954 size: usize,
955 flags: MapFlags,
956 ctx: &CallerCtx,
957 ) -> Result<usize> {
958 Err(Error::new(EOPNOTSUPP))
959 }
960
961 fn munmap(
962 &mut self,
963 id: usize,
964 offset: u64,
965 size: usize,
966 flags: MunmapFlags,
967 ctx: &CallerCtx,
968 ) -> Result<()> {
969 Err(Error::new(EOPNOTSUPP))
970 }
971
972 fn on_close(&mut self, id: usize) {}
973}
974pub trait IntoTag {
975 fn into_tag(self) -> Tag;
976 fn req_id(&self) -> Id;
977}
978impl IntoTag for Tag {
979 fn into_tag(self) -> Tag {
980 self
981 }
982 fn req_id(&self) -> Id {
983 self.0
984 }
985}
986impl IntoTag for CallRequest {
987 fn into_tag(self) -> Tag {
988 Tag(self.request_id())
989 }
990 fn req_id(&self) -> Id {
991 self.request_id()
992 }
993}
994impl IntoTag for SendFdRequest {
995 fn into_tag(self) -> Tag {
996 Tag(self.request_id())
997 }
998 fn req_id(&self) -> Id {
999 self.request_id()
1000 }
1001}
1002macro_rules! trivial_into {
1003 [$($name:ident,)*] => {
1004 $(
1005 impl IntoTag for $name {
1006 #[inline]
1007 fn into_tag(self) -> Tag {
1008 self.req
1009 }
1010 #[inline]
1011 fn req_id(&self) -> Id {
1012 self.req.req_id()
1013 }
1014 }
1015 )*
1016 }
1017}
1018trivial_into![OpCall, OpRead, OpWrite, OpGetdents,];
1019impl<T: ?Sized> IntoTag for OpQueryWrite<T> {
1020 fn into_tag(self) -> Tag {
1021 self.req
1022 }
1023 fn req_id(&self) -> Id {
1024 self.req.0
1025 }
1026}
1027impl<T: ?Sized> IntoTag for OpQueryRead<T> {
1028 fn into_tag(self) -> Tag {
1029 self.req
1030 }
1031 fn req_id(&self) -> Id {
1032 self.req.0
1033 }
1034}
1035impl<F> IntoTag for OpPathLike<F> {
1036 fn into_tag(self) -> Tag {
1037 self.req
1038 }
1039 fn req_id(&self) -> Id {
1040 self.req.0
1041 }
1042}
1043impl<F> IntoTag for OpFdPathLike<F> {
1044 fn into_tag(self) -> Tag {
1045 self.inner.req
1046 }
1047 fn req_id(&self) -> Id {
1048 self.inner.req.0
1049 }
1050}
1051impl IntoTag for Op {
1052 fn into_tag(self) -> Tag {
1053 use Op::*;
1054 match self {
1055 Open(op) => op.into_tag(),
1056 OpenAt(op) => op.into_tag(),
1057 Rmdir(op) | Self::Unlink(op) => op.into_tag(),
1058 Dup(op) => op.into_tag(),
1059 Read(op) => op.into_tag(),
1060 Write(op) => op.into_tag(),
1061 Fsize { req, .. }
1062 | Fchmod { req, .. }
1063 | Fchown { req, .. }
1064 | Fcntl { req, .. }
1065 | Fevent { req, .. }
1066 | Fsync { req, .. }
1067 | Ftruncate { req, .. }
1068 | MmapPrep { req, .. }
1069 | Munmap { req, .. } => req,
1070 Fpath(op) => op.into_tag(),
1071 Frename(op) => op.into_tag(),
1072 Fstat(op) => op.into_tag(),
1073 FstatVfs(op) => op.into_tag(),
1074 Futimens(op) => op.into_tag(),
1075 Call(op) => op.into_tag(),
1076 Getdents(op) => op.into_tag(),
1077 }
1078 }
1079 fn req_id(&self) -> Id {
1080 use Op::*;
1081 match self {
1082 Open(op) => op.req_id(),
1083 OpenAt(op) => op.req_id(),
1084 Rmdir(op) | Self::Unlink(op) => op.req_id(),
1085 Dup(op) => op.req_id(),
1086 Read(op) => op.req_id(),
1087 Write(op) => op.req_id(),
1088 Fsize { req, .. }
1089 | Fchmod { req, .. }
1090 | Fchown { req, .. }
1091 | Fcntl { req, .. }
1092 | Fevent { req, .. }
1093 | Fsync { req, .. }
1094 | Ftruncate { req, .. }
1095 | MmapPrep { req, .. }
1096 | Munmap { req, .. } => req.req_id(),
1097 Fpath(op) => op.req_id(),
1098 Frename(op) => op.req_id(),
1099 Fstat(op) => op.req_id(),
1100 FstatVfs(op) => op.req_id(),
1101 Futimens(op) => op.req_id(),
1102 Call(op) => op.req_id(),
1103 Getdents(op) => op.req_id(),
1104 }
1105 }
1106}