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