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: [u64; 3],
59}
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 &self.metadata
70 }
71}
72impl Debug for OpCall {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 f.debug_struct("OpCall")
75 .field("fd", &self.fd)
76 .field("payload", &self.payload)
78 .field("metadata", &self.metadata())
79 .finish()
80 }
81}
82#[derive(Debug)]
83pub struct OpQueryRead<T: ?Sized> {
84 pub fd: usize,
85 req: Tag,
86 buf: *mut T,
87}
88impl<T: ?Sized> OpQueryRead<T> {
89 pub fn buf(&mut self) -> &mut T {
90 unsafe { &mut *self.buf }
92 }
93}
94#[derive(Debug)]
95pub struct OpQueryWrite<T: ?Sized> {
96 pub fd: usize,
97 req: Tag,
98 buf: *const T,
99}
100impl<T: ?Sized> OpQueryWrite<T> {
101 pub fn buf(&self) -> &T {
102 unsafe { &*self.buf }
104 }
105}
106#[derive(Debug)]
107pub struct OpGetdents {
108 req: Tag,
109 pub fd: usize,
110 buf: *mut [u8],
111 pub header_size: u16,
112 pub opaque_offset: u64,
113}
114impl OpGetdents {
115 pub fn raw_buf(&mut self) -> &mut [u8] {
116 unsafe { &mut *self.buf }
118 }
119 pub fn buf(&mut self) -> Option<DirentBuf<&mut [u8]>> {
120 let sz = self.header_size;
121 DirentBuf::new(self.raw_buf(), sz)
122 }
123}
124#[derive(Debug)]
125pub struct OpRead {
126 req: Tag,
127 pub fd: usize,
128 pub offset: u64,
129 pub flags: u32,
130 buf: *mut [u8],
131}
132impl OpRead {
133 pub fn buf(&mut self) -> &mut [u8] {
134 unsafe { &mut *self.buf }
136 }
137}
138#[derive(Debug)]
139pub struct OpWrite {
140 req: Tag,
141 pub fd: usize,
142 pub offset: u64,
143 pub flags: u32,
144 buf: *const [u8],
145}
146impl OpWrite {
147 pub fn buf(&self) -> &[u8] {
148 unsafe { &*self.buf }
150 }
151}
152
153#[non_exhaustive]
154#[derive(Debug)]
155pub enum Op {
156 Open(OpPathLike<usize>),
157 OpenAt(OpFdPathLike<usize>),
158 Rmdir(OpPathLike<()>),
159 Unlink(OpPathLike<()>),
160 Dup(OpQueryWrite<[u8]>),
161 Read(OpRead),
162 Write(OpWrite),
163 Fsize {
164 req: Tag,
165 fd: usize,
166 },
167 Fchmod {
168 req: Tag,
169 fd: usize,
170 new_mode: u16,
171 },
172 Fchown {
173 req: Tag,
174 fd: usize,
175 new_uid: u32,
176 new_gid: u32,
177 },
178 Fcntl {
179 req: Tag,
180 fd: usize,
181 cmd: usize,
182 arg: usize,
183 },
184 Fevent {
185 req: Tag,
186 fd: usize,
187 req_flags: EventFlags,
188 },
189 Flink(OpQueryWrite<str>),
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::Flink => Op::Flink(OpQueryWrite {
310 req,
311 fd: a,
312 buf: str::from_utf8_unchecked(slice::from_raw_parts(b as *const u8, c)),
313 }),
314 Opcode::Fpath => Op::Fpath(OpQueryRead {
315 req,
316 fd: a,
317 buf: slice::from_raw_parts_mut(b as *mut u8, c),
318 }),
319 Opcode::Frename => Op::Frename(OpQueryWrite {
320 req,
321 fd: a,
322 buf: str::from_utf8_unchecked(slice::from_raw_parts(b as *const u8, c)),
323 }),
324 Opcode::Fstat => {
325 assert!(c >= size_of::<Stat>());
326 Op::Fstat(OpQueryRead {
327 req,
328 fd: a,
329 buf: &mut *(b as *mut Stat),
330 })
331 }
332 Opcode::Fstatvfs => {
333 assert!(c >= size_of::<StatVfs>());
334 Op::FstatVfs(OpQueryRead {
335 req,
336 fd: a,
337 buf: &mut *(b as *mut StatVfs),
338 })
339 }
340 Opcode::Fsync => Op::Fsync { req, fd: a },
341 Opcode::Ftruncate => Op::Ftruncate {
342 req,
343 fd: a,
344 new_sz: args[1],
345 },
346 Opcode::Futimens => {
347 assert!(c <= 2 * size_of::<TimeSpec>());
348 Op::Futimens(OpQueryWrite {
349 req,
350 fd: a,
351 buf: slice::from_raw_parts(b as *const TimeSpec, c / size_of::<TimeSpec>()),
352 })
353 }
354
355 Opcode::Call => Op::Call(OpCall {
356 req,
357 fd: a,
358 payload: slice::from_raw_parts_mut(b as *mut u8, c),
359 metadata: [sqe.args[3], sqe.args[4], sqe.args[5]],
360 }),
361 Opcode::Getdents => Op::Getdents(OpGetdents {
362 req,
363 fd: a,
364 buf: slice::from_raw_parts_mut(b as *mut u8, c),
365 header_size: sqe.args[3] as u16,
366 opaque_offset: sqe.args[4],
367 }),
368
369 Opcode::MmapPrep => Op::MmapPrep {
370 req,
371 fd: a,
372 offset: args[3],
373 len: b,
374 flags: MapFlags::from_bits_retain(c),
375 },
376 Opcode::Munmap => Op::Munmap {
377 req,
378 fd: a,
379 offset: args[3],
380 len: b,
381 flags: MunmapFlags::from_bits_retain(c),
382 },
383
384 _ => return None,
385 })
386 }
387 pub fn is_explicitly_nonblock(&self) -> bool {
388 let flags = match self {
389 Self::Read(r) => r.flags,
390 Self::Write(w) => w.flags,
391 Self::OpenAt(o) => o.fcntl_flags,
392 Self::Open(o) => o.flags as u32,
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}
461
462impl SendFdRequest {
463 pub fn caller(&self) -> CallerCtx {
464 let sqe = &self.inner.sqe;
465
466 CallerCtx {
467 pid: sqe.caller as usize,
468 uid: sqe.args[5] as u32,
469 gid: (sqe.args[5] >> 32) as u32,
470 id: self.request_id(),
471 }
472 }
473}
474
475pub enum SchemeResponse {
476 Regular(Result<usize>),
477 Opened(Result<OpenResult>),
478}
479impl From<Result<usize>> for SchemeResponse {
480 fn from(value: Result<usize>) -> Self {
481 Self::Regular(value)
482 }
483}
484impl Op {
485 pub fn handle_sync(mut self, caller: CallerCtx, s: &mut impl SchemeSync) -> Response {
486 match self.handle_sync_dont_consume(&caller, s) {
487 SchemeResponse::Opened(open) => Response::open_dup_like(open, self),
488 SchemeResponse::Regular(reg) => Response::new(reg, self),
489 }
490 }
491 pub fn handle_sync_dont_consume(
492 &mut self,
493 caller: &CallerCtx,
494 s: &mut impl SchemeSync,
495 ) -> SchemeResponse {
496 match *self {
497 Op::Open(ref req) => {
498 let res = s.open(req.path(), req.flags, &caller);
499 return SchemeResponse::Opened(res);
500 }
501 Op::OpenAt(ref req) => {
502 let res = s.openat(
503 req.fd,
504 req.path(),
505 req.inner.flags,
506 req.fcntl_flags,
507 &caller,
508 );
509 return SchemeResponse::Opened(res);
510 }
511 Op::Rmdir(ref req) => s.rmdir(req.path(), &caller).map(|()| 0).into(),
512 Op::Unlink(ref req) => s.unlink(req.path(), &caller).map(|()| 0).into(),
513
514 Op::Dup(ref req) => {
515 let res = s.dup(req.fd, req.buf(), &caller);
516 return SchemeResponse::Opened(res);
517 }
518 Op::Read(ref mut req) => {
519 let OpRead {
520 fd, offset, flags, ..
521 } = *req;
522 s.read(fd, req.buf(), offset, flags, &caller).into()
523 }
524 Op::Write(ref req) => s
525 .write(req.fd, req.buf(), req.offset, req.flags, &caller)
526 .into(),
527
528 Op::Fsize { fd, .. } => s.fsize(fd, &caller).map(|l| l as usize).into(),
530
531 Op::Fchmod { fd, new_mode, .. } => s.fchmod(fd, new_mode, &caller).map(|()| 0).into(),
532 Op::Fchown {
533 fd,
534 new_uid,
535 new_gid,
536 ..
537 } => s.fchown(fd, new_uid, new_gid, &caller).map(|()| 0).into(),
538 Op::Fcntl { fd, cmd, arg, .. } => s.fcntl(fd, cmd, arg, &caller).into(),
539 Op::Fevent { fd, req_flags, .. } => {
540 s.fevent(fd, req_flags, &caller).map(|f| f.bits()).into()
541 }
542 Op::Flink(ref req) => s.flink(req.fd, req.buf(), &caller).into(),
543 Op::Fpath(ref mut req) => s.fpath(req.fd, req.buf(), &caller).into(),
544 Op::Frename(ref req) => s.frename(req.fd, req.buf(), &caller).into(),
545 Op::Fstat(ref mut req) => s.fstat(req.fd, req.buf(), &caller).map(|()| 0).into(),
546 Op::FstatVfs(ref mut req) => s.fstatvfs(req.fd, req.buf(), &caller).map(|()| 0).into(),
547 Op::Fsync { fd, .. } => s.fsync(fd, &caller).map(|()| 0).into(),
548 Op::Ftruncate { fd, new_sz, .. } => s.ftruncate(fd, new_sz, &caller).map(|()| 0).into(),
549 Op::Futimens(ref req) => s.futimens(req.fd, req.buf(), &caller).map(|()| 0).into(),
550
551 Op::MmapPrep {
552 fd,
553 offset,
554 len,
555 flags,
556 ..
557 } => s.mmap_prep(fd, offset, len, flags, &caller).into(),
558 Op::Munmap {
559 fd,
560 offset,
561 len,
562 flags,
563 ..
564 } => s.munmap(fd, offset, len, flags, &caller).map(|()| 0).into(),
565
566 Op::Call(ref mut req) => {
567 let fd = req.fd;
568 let (payload, metadata) = req.payload_and_metadata();
569 s.call(fd, payload, metadata, &caller).into()
570 }
571
572 Op::Getdents(ref mut req) => {
573 let OpGetdents {
574 fd, opaque_offset, ..
575 } = *req;
576 let Some(buf) = req.buf() else {
577 return Err(Error::new(EINVAL)).into();
578 };
579 let buf_res = s.getdents(fd, buf, opaque_offset);
580 buf_res.map(|b| b.finalize()).into()
581 }
582 }
583 }
584 pub async fn handle_async(self, caller: CallerCtx, s: &mut impl SchemeAsync) -> Response {
588 let (res, tag) = match self {
589 Op::Open(req) => {
590 let res = s.open(req.path(), req.flags, &caller).await;
591 return Response::open_dup_like(res, req);
592 }
593 Op::OpenAt(req) => {
594 let res = s
595 .openat(
596 req.fd,
597 req.path(),
598 req.inner.flags,
599 req.fcntl_flags,
600 &caller,
601 )
602 .await;
603 return Response::open_dup_like(res, req);
604 }
605 Op::Rmdir(req) => (
606 s.rmdir(req.path(), &caller).await.map(|()| 0),
607 req.into_tag(),
608 ),
609 Op::Unlink(req) => (
610 s.unlink(req.path(), &caller).await.map(|()| 0),
611 req.into_tag(),
612 ),
613
614 Op::Dup(req) => {
615 let res = s.dup(req.fd, req.buf(), &caller).await;
616 return Response::open_dup_like(res, req);
617 }
618 Op::Read(mut req) => {
619 let OpRead {
620 fd, offset, flags, ..
621 } = req;
622 (
623 s.read(fd, req.buf(), offset, flags, &caller).await,
624 req.into_tag(),
625 )
626 }
627 Op::Write(req) => (
628 s.write(req.fd, req.buf(), req.offset, req.flags, &caller)
629 .await,
630 req.into_tag(),
631 ),
632
633 Op::Fsize { req, fd } => (s.fsize(fd, &caller).await.map(|l| l as usize), req),
635
636 Op::Fchmod { req, fd, new_mode } => {
637 (s.fchmod(fd, new_mode, &caller).await.map(|()| 0), req)
638 }
639 Op::Fchown {
640 req,
641 fd,
642 new_uid,
643 new_gid,
644 } => (
645 s.fchown(fd, new_uid, new_gid, &caller).await.map(|()| 0),
646 req,
647 ),
648 Op::Fcntl { req, fd, cmd, arg } => (s.fcntl(fd, cmd, arg, &caller).await, req),
649 Op::Fevent { req, fd, req_flags } => (
650 s.fevent(fd, req_flags, &caller).await.map(|f| f.bits()),
651 req,
652 ),
653 Op::Flink(req) => (s.flink(req.fd, req.buf(), &caller).await, req.into_tag()),
654 Op::Fpath(mut req) => (s.fpath(req.fd, req.buf(), &caller).await, req.into_tag()),
655 Op::Frename(req) => (s.frename(req.fd, req.buf(), &caller).await, req.into_tag()),
656 Op::Fstat(mut req) => (
657 s.fstat(req.fd, req.buf(), &caller).await.map(|()| 0),
658 req.into_tag(),
659 ),
660 Op::FstatVfs(mut req) => (
661 s.fstatvfs(req.fd, req.buf(), &caller).await.map(|()| 0),
662 req.into_tag(),
663 ),
664 Op::Fsync { req, fd } => (s.fsync(fd, &caller).await.map(|()| 0), req),
665 Op::Ftruncate { req, fd, new_sz } => {
666 (s.ftruncate(fd, new_sz, &caller).await.map(|()| 0), req)
667 }
668 Op::Futimens(req) => (
669 s.futimens(req.fd, req.buf(), &caller).await.map(|()| 0),
670 req.into_tag(),
671 ),
672
673 Op::MmapPrep {
674 req,
675 fd,
676 offset,
677 len,
678 flags,
679 } => (s.mmap_prep(fd, offset, len, flags, &caller).await, req),
680 Op::Munmap {
681 req,
682 fd,
683 offset,
684 len,
685 flags,
686 } => (
687 s.munmap(fd, offset, len, flags, &caller).await.map(|()| 0),
688 req,
689 ),
690
691 Op::Call(mut req) => {
692 let fd = req.fd;
693 let (payload, metadata) = req.payload_and_metadata();
694 (s.call(fd, payload, metadata, &caller).await, req.into_tag())
695 }
696
697 Op::Getdents(mut req) => {
698 let OpGetdents {
699 fd, opaque_offset, ..
700 } = req;
701 let Some(buf) = req.buf() else {
702 return Response::err(EINVAL, req);
703 };
704 let buf_res = s.getdents(fd, buf, opaque_offset).await;
705 (buf_res.map(|b| b.finalize()), req.into_tag())
706 }
707 };
708 Response::new(res, tag)
709 }
710}
711
712#[allow(unused_variables)]
713pub trait SchemeAsync {
714 async fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
716 Err(Error::new(ENOENT))
717 }
718
719 async fn openat(
720 &mut self,
721 fd: usize,
722 path: &str,
723 flags: usize,
724 fcntl_flags: u32,
725 ctx: &CallerCtx,
726 ) -> Result<OpenResult> {
727 Err(Error::new(EOPNOTSUPP))
728 }
729
730 async fn rmdir(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
731 Err(Error::new(ENOENT))
732 }
733
734 async fn unlink(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
735 Err(Error::new(ENOENT))
736 }
737
738 async fn dup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
740 Err(Error::new(EOPNOTSUPP))
741 }
742
743 async fn read(
744 &mut self,
745 id: usize,
746 buf: &mut [u8],
747 offset: u64,
748 fcntl_flags: u32,
749 ctx: &CallerCtx,
750 ) -> Result<usize> {
751 Err(Error::new(EBADF))
752 }
753
754 async fn write(
755 &mut self,
756 id: usize,
757 buf: &[u8],
758 offset: u64,
759 fcntl_flags: u32,
760 ctx: &CallerCtx,
761 ) -> Result<usize> {
762 Err(Error::new(EBADF))
763 }
764
765 async fn fsize(&mut self, id: usize, ctx: &CallerCtx) -> Result<u64> {
766 Err(Error::new(ESPIPE))
767 }
768
769 async fn fchmod(&mut self, id: usize, new_mode: u16, ctx: &CallerCtx) -> Result<()> {
770 Err(Error::new(EOPNOTSUPP))
771 }
772
773 async fn fchown(
774 &mut self,
775 id: usize,
776 new_uid: u32,
777 new_gid: u32,
778 ctx: &CallerCtx,
779 ) -> Result<()> {
780 Err(Error::new(EOPNOTSUPP))
781 }
782
783 async fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, ctx: &CallerCtx) -> Result<usize> {
784 Err(Error::new(EOPNOTSUPP))
785 }
786
787 async fn fevent(
788 &mut self,
789 id: usize,
790 flags: EventFlags,
791 ctx: &CallerCtx,
792 ) -> Result<EventFlags> {
793 Ok(EventFlags::empty())
794 }
795
796 async fn flink(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
797 Err(Error::new(EOPNOTSUPP))
798 }
799
800 async fn fpath(&mut self, id: usize, buf: &mut [u8], ctx: &CallerCtx) -> Result<usize> {
801 Err(Error::new(EOPNOTSUPP))
802 }
803
804 async fn frename(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
805 Err(Error::new(EOPNOTSUPP))
806 }
807
808 async fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
809 Err(Error::new(EOPNOTSUPP))
810 }
811
812 async fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, ctx: &CallerCtx) -> Result<()> {
813 Err(Error::new(EOPNOTSUPP))
814 }
815
816 async fn fsync(&mut self, id: usize, ctx: &CallerCtx) -> Result<()> {
817 Ok(())
818 }
819
820 async fn ftruncate(&mut self, id: usize, len: u64, ctx: &CallerCtx) -> Result<()> {
821 Err(Error::new(EBADF))
822 }
823
824 async fn futimens(&mut self, id: usize, times: &[TimeSpec], ctx: &CallerCtx) -> Result<()> {
825 Err(Error::new(EBADF))
826 }
827
828 async fn call(
829 &mut self,
830 id: usize,
831 payload: &mut [u8],
832 metadata: &[u64],
833 ctx: &CallerCtx, ) -> Result<usize> {
835 Err(Error::new(EOPNOTSUPP))
836 }
837
838 async fn getdents<'buf>(
839 &mut self,
840 id: usize,
841 buf: DirentBuf<&'buf mut [u8]>,
842 opaque_offset: u64,
843 ) -> Result<DirentBuf<&'buf mut [u8]>> {
844 Err(Error::new(ENOTDIR))
845 }
846
847 async fn mmap_prep(
848 &mut self,
849 id: usize,
850 offset: u64,
851 size: usize,
852 flags: MapFlags,
853 ctx: &CallerCtx,
854 ) -> Result<usize> {
855 Err(Error::new(EOPNOTSUPP))
856 }
857
858 async fn munmap(
859 &mut self,
860 id: usize,
861 offset: u64,
862 size: usize,
863 flags: MunmapFlags,
864 ctx: &CallerCtx,
865 ) -> Result<()> {
866 Err(Error::new(EOPNOTSUPP))
867 }
868}
869#[allow(unused_variables)]
870pub trait SchemeSync {
871 fn open(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
873 Err(Error::new(ENOENT))
874 }
875
876 fn openat(
877 &mut self,
878 fd: usize,
879 path: &str,
880 flags: usize,
881 fcntl_flags: u32,
882 ctx: &CallerCtx,
883 ) -> Result<OpenResult> {
884 Err(Error::new(EOPNOTSUPP))
885 }
886
887 fn rmdir(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
888 Err(Error::new(ENOENT))
889 }
890
891 fn unlink(&mut self, path: &str, ctx: &CallerCtx) -> Result<()> {
892 Err(Error::new(ENOENT))
893 }
894
895 fn dup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
897 Err(Error::new(EOPNOTSUPP))
898 }
899
900 fn read(
901 &mut self,
902 id: usize,
903 buf: &mut [u8],
904 offset: u64,
905 fcntl_flags: u32,
906 ctx: &CallerCtx,
907 ) -> Result<usize> {
908 Err(Error::new(EBADF))
909 }
910
911 fn write(
912 &mut self,
913 id: usize,
914 buf: &[u8],
915 offset: u64,
916 fcntl_flags: u32,
917 ctx: &CallerCtx,
918 ) -> Result<usize> {
919 Err(Error::new(EBADF))
920 }
921
922 fn fsize(&mut self, id: usize, ctx: &CallerCtx) -> Result<u64> {
923 Err(Error::new(ESPIPE))
924 }
925
926 fn fchmod(&mut self, id: usize, new_mode: u16, ctx: &CallerCtx) -> Result<()> {
927 Err(Error::new(EOPNOTSUPP))
928 }
929
930 fn fchown(&mut self, id: usize, new_uid: u32, new_gid: u32, ctx: &CallerCtx) -> Result<()> {
931 Err(Error::new(EOPNOTSUPP))
932 }
933
934 fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, ctx: &CallerCtx) -> Result<usize> {
935 Err(Error::new(EOPNOTSUPP))
936 }
937
938 fn fevent(&mut self, id: usize, flags: EventFlags, ctx: &CallerCtx) -> Result<EventFlags> {
939 Ok(EventFlags::empty())
940 }
941
942 fn flink(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
943 Err(Error::new(EOPNOTSUPP))
944 }
945
946 fn fpath(&mut self, id: usize, buf: &mut [u8], ctx: &CallerCtx) -> Result<usize> {
947 Err(Error::new(EOPNOTSUPP))
948 }
949
950 fn frename(&mut self, id: usize, path: &str, ctx: &CallerCtx) -> Result<usize> {
951 Err(Error::new(EOPNOTSUPP))
952 }
953
954 fn fstat(&mut self, id: usize, stat: &mut Stat, ctx: &CallerCtx) -> Result<()> {
955 Err(Error::new(EOPNOTSUPP))
956 }
957
958 fn fstatvfs(&mut self, id: usize, stat: &mut StatVfs, ctx: &CallerCtx) -> Result<()> {
959 Err(Error::new(EOPNOTSUPP))
960 }
961
962 fn fsync(&mut self, id: usize, ctx: &CallerCtx) -> Result<()> {
963 Ok(())
964 }
965
966 fn ftruncate(&mut self, id: usize, len: u64, ctx: &CallerCtx) -> Result<()> {
967 Err(Error::new(EBADF))
968 }
969
970 fn futimens(&mut self, id: usize, times: &[TimeSpec], ctx: &CallerCtx) -> Result<()> {
971 Err(Error::new(EBADF))
972 }
973
974 fn call(
975 &mut self,
976 id: usize,
977 payload: &mut [u8],
978 metadata: &[u64],
979 ctx: &CallerCtx, ) -> Result<usize> {
981 Err(Error::new(EOPNOTSUPP))
982 }
983
984 fn getdents<'buf>(
985 &mut self,
986 id: usize,
987 buf: DirentBuf<&'buf mut [u8]>,
988 opaque_offset: u64,
989 ) -> Result<DirentBuf<&'buf mut [u8]>> {
990 Err(Error::new(ENOTDIR))
991 }
992
993 fn mmap_prep(
994 &mut self,
995 id: usize,
996 offset: u64,
997 size: usize,
998 flags: MapFlags,
999 ctx: &CallerCtx,
1000 ) -> Result<usize> {
1001 Err(Error::new(EOPNOTSUPP))
1002 }
1003
1004 fn munmap(
1005 &mut self,
1006 id: usize,
1007 offset: u64,
1008 size: usize,
1009 flags: MunmapFlags,
1010 ctx: &CallerCtx,
1011 ) -> Result<()> {
1012 Err(Error::new(EOPNOTSUPP))
1013 }
1014
1015 fn on_close(&mut self, id: usize) {}
1016
1017 fn on_sendfd(&mut self, sendfd_request: &SendFdRequest) -> Result<usize> {
1018 Err(Error::new(EOPNOTSUPP))
1019 }
1020}
1021pub trait IntoTag {
1022 fn into_tag(self) -> Tag;
1023 fn req_id(&self) -> Id;
1024}
1025impl IntoTag for Tag {
1026 fn into_tag(self) -> Tag {
1027 self
1028 }
1029 fn req_id(&self) -> Id {
1030 self.0
1031 }
1032}
1033impl IntoTag for CallRequest {
1034 fn into_tag(self) -> Tag {
1035 Tag(self.request_id())
1036 }
1037 fn req_id(&self) -> Id {
1038 self.request_id()
1039 }
1040}
1041impl IntoTag for SendFdRequest {
1042 fn into_tag(self) -> Tag {
1043 Tag(self.request_id())
1044 }
1045 fn req_id(&self) -> Id {
1046 self.request_id()
1047 }
1048}
1049macro_rules! trivial_into {
1050 [$($name:ident,)*] => {
1051 $(
1052 impl IntoTag for $name {
1053 #[inline]
1054 fn into_tag(self) -> Tag {
1055 self.req
1056 }
1057 #[inline]
1058 fn req_id(&self) -> Id {
1059 self.req.req_id()
1060 }
1061 }
1062 )*
1063 }
1064}
1065trivial_into![OpCall, OpRead, OpWrite, OpGetdents,];
1066impl<T: ?Sized> IntoTag for OpQueryWrite<T> {
1067 fn into_tag(self) -> Tag {
1068 self.req
1069 }
1070 fn req_id(&self) -> Id {
1071 self.req.0
1072 }
1073}
1074impl<T: ?Sized> IntoTag for OpQueryRead<T> {
1075 fn into_tag(self) -> Tag {
1076 self.req
1077 }
1078 fn req_id(&self) -> Id {
1079 self.req.0
1080 }
1081}
1082impl<F> IntoTag for OpPathLike<F> {
1083 fn into_tag(self) -> Tag {
1084 self.req
1085 }
1086 fn req_id(&self) -> Id {
1087 self.req.0
1088 }
1089}
1090impl<F> IntoTag for OpFdPathLike<F> {
1091 fn into_tag(self) -> Tag {
1092 self.inner.req
1093 }
1094 fn req_id(&self) -> Id {
1095 self.inner.req.0
1096 }
1097}
1098impl IntoTag for Op {
1099 fn into_tag(self) -> Tag {
1100 use Op::*;
1101 match self {
1102 Open(op) => op.into_tag(),
1103 OpenAt(op) => op.into_tag(),
1104 Rmdir(op) | Self::Unlink(op) => op.into_tag(),
1105 Dup(op) => op.into_tag(),
1106 Read(op) => op.into_tag(),
1107 Write(op) => op.into_tag(),
1108 Fsize { req, .. }
1109 | Fchmod { req, .. }
1110 | Fchown { req, .. }
1111 | Fcntl { req, .. }
1112 | Fevent { req, .. }
1113 | Fsync { req, .. }
1114 | Ftruncate { req, .. }
1115 | MmapPrep { req, .. }
1116 | Munmap { req, .. } => req,
1117 Flink(op) => op.into_tag(),
1118 Fpath(op) => op.into_tag(),
1119 Frename(op) => op.into_tag(),
1120 Fstat(op) => op.into_tag(),
1121 FstatVfs(op) => op.into_tag(),
1122 Futimens(op) => op.into_tag(),
1123 Call(op) => op.into_tag(),
1124 Getdents(op) => op.into_tag(),
1125 }
1126 }
1127 fn req_id(&self) -> Id {
1128 use Op::*;
1129 match self {
1130 Open(op) => op.req_id(),
1131 OpenAt(op) => op.req_id(),
1132 Rmdir(op) | Self::Unlink(op) => op.req_id(),
1133 Dup(op) => op.req_id(),
1134 Read(op) => op.req_id(),
1135 Write(op) => op.req_id(),
1136 Fsize { req, .. }
1137 | Fchmod { req, .. }
1138 | Fchown { req, .. }
1139 | Fcntl { req, .. }
1140 | Fevent { req, .. }
1141 | Fsync { req, .. }
1142 | Ftruncate { req, .. }
1143 | MmapPrep { req, .. }
1144 | Munmap { req, .. } => req.req_id(),
1145 Flink(op) => op.req_id(),
1146 Fpath(op) => op.req_id(),
1147 Frename(op) => op.req_id(),
1148 Fstat(op) => op.req_id(),
1149 FstatVfs(op) => op.req_id(),
1150 Futimens(op) => op.req_id(),
1151 Call(op) => op.req_id(),
1152 Getdents(op) => op.req_id(),
1153 }
1154 }
1155}