diff options
Diffstat (limited to '')
| -rw-r--r-- | src/ops/open.rs | 88 |
1 files changed, 83 insertions, 5 deletions
diff --git a/src/ops/open.rs b/src/ops/open.rs index cb4b30a..40a07a9 100644 --- a/src/ops/open.rs +++ b/src/ops/open.rs @@ -1,22 +1,32 @@ use crate::{ - io::{AccessFlags, OpenFlags}, + io::{AccessFlags, Known, Mode, OpenFlags, Stat}, private_trait::Sealed, - proto, Done, Errno, Operation, Reply, Request, + proto, + util::OutputChain, + Done, Errno, Operation, Reply, Request, Ttl, }; use super::{ - traits::{ReplyOk, RequestFlags, RequestHandle}, + c_to_os, make_entry, + traits::{ReplyKnown, ReplyOk, RequestFlags, RequestHandle, RequestMode, RequestName}, FromRequest, }; +use bytemuck::bytes_of; +use std::ffi::{CStr, OsStr}; + pub enum Open {} pub enum Release {} pub enum Opendir {} pub enum Releasedir {} pub enum Access {} +pub enum Create {} -pub trait ReplyOpen<'o>: ReplyOk<'o, ReplyState = proto::OpenOutFlags> { - fn ok_with_handle(reply: Reply<'o, Self>, handle: u64) -> Done<'o> { +pub trait ReplyOpen<'o>: Operation<'o, ReplyState = proto::OpenOutFlags> { + fn ok_with_handle(reply: Reply<'o, Self>, handle: u64) -> Done<'o> + where + Self: ReplyOk<'o>, + { let open_flags = reply.state.bits(); reply.single(&proto::OpenOut { @@ -26,6 +36,31 @@ pub trait ReplyOpen<'o>: ReplyOk<'o, ReplyState = proto::OpenOutFlags> { }) } + fn known_with_handle( + reply: Reply<'o, Self>, + known: impl Known, + ttl: Ttl, + handle: u64, + ) -> Done<'o> + where + Self: ReplyKnown<'o>, + { + let (attrs, attrs_ttl) = known.inode().attrs(); + let attrs = attrs.finish(known.inode()); + + let entry = make_entry((known.inode().ino(), ttl), (attrs, attrs_ttl)); + let open = proto::OpenOut { + fh: handle, + open_flags: reply.state.bits(), + padding: Default::default(), + }; + + let done = reply.chain(OutputChain::tail(&[bytes_of(&entry), bytes_of(&open)])); + known.unveil(); + + done + } + fn force_direct_io(reply: &mut Reply<'o, Self>) { reply.state |= proto::OpenOutFlags::DIRECT_IO; } @@ -42,6 +77,7 @@ impl Sealed for Release {} impl Sealed for Opendir {} impl Sealed for Releasedir {} impl Sealed for Access {} +impl Sealed for Create {} impl<'o> Operation<'o> for Open { type RequestBody = &'o proto::OpenIn; @@ -68,6 +104,11 @@ impl<'o> Operation<'o> for Access { type ReplyState = (); } +impl<'o> Operation<'o> for Create { + type RequestBody = (&'o proto::CreateIn, &'o CStr); + type ReplyState = proto::OpenOutFlags; +} + impl<'o> RequestFlags<'o> for Open { type Flags = OpenFlags; @@ -127,3 +168,40 @@ impl<'o, O: ReplyOpen<'o>> FromRequest<'o, O> for proto::OpenOutFlags { proto::OpenOutFlags::empty() } } + +impl<'o> RequestName<'o> for Create { + fn name<'a>(request: &'a Request<'o, Self>) -> &'a OsStr { + let (_header, name) = request.body; + c_to_os(name) + } +} + +impl<'o> RequestMode<'o> for Create { + fn mode(request: &Request<'o, Self>) -> Mode { + let (header, _name) = request.body; + Mode::from_bits_truncate(header.mode) + } + + fn umask(request: &Request<'o, Self>) -> Mode { + let (header, _name) = request.body; + Mode::from_bits_truncate(header.umask) + } +} + +impl<'o> RequestFlags<'o> for Create { + type Flags = OpenFlags; + + fn flags(request: &Request<'o, Self>) -> Self::Flags { + let (header, _name) = request.body; + OpenFlags::from_bits_truncate(header.flags as _) + } +} + +impl<'o> ReplyKnown<'o> for Create { + fn known(reply: Reply<'o, Self>, entry: impl Known, ttl: Ttl) -> Done<'o> { + reply.known_with_handle(entry, ttl, 0) + } +} + +impl<'o> ReplyOpen<'o> for Create {} +impl<'o> ReplyPermissionDenied<'o> for Create {} |
