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