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