diff options
Diffstat (limited to '')
| -rw-r--r-- | src/ops/entry.rs | 5 | ||||
| -rw-r--r-- | src/ops/mod.rs | 2 | ||||
| -rw-r--r-- | src/ops/open.rs | 88 | ||||
| -rw-r--r-- | src/ops/traits.rs | 17 |
4 files changed, 105 insertions, 7 deletions
diff --git a/src/ops/entry.rs b/src/ops/entry.rs index c174bc7..bcbe6b8 100644 --- a/src/ops/entry.rs +++ b/src/ops/entry.rs @@ -63,6 +63,11 @@ impl<'o> RequestMode<'o> for Mkdir { 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> ReplyKnown<'o> for Mkdir {} diff --git a/src/ops/mod.rs b/src/ops/mod.rs index 4e5f052..010f488 100644 --- a/src/ops/mod.rs +++ b/src/ops/mod.rs @@ -15,7 +15,7 @@ pub use dir::{BufferedReaddir, Lookup, Readdir}; pub use entry::{Link, Mkdir, Rmdir, Symlink, Unlink}; pub use global::{Init, Statfs}; pub use inode::{Forget, Getattr}; -pub use open::{Access, Open, Opendir, Release, Releasedir}; +pub use open::{Access, Create, Open, Opendir, Release, Releasedir}; pub use rw::{Flush, Fsync, Fsyncdir, Read, Readlink, Write}; pub use xattr::{Getxattr, Listxattr, Removexattr, Setxattr}; 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 {} diff --git a/src/ops/traits.rs b/src/ops/traits.rs index 883f2f8..3a81e85 100644 --- a/src/ops/traits.rs +++ b/src/ops/traits.rs @@ -44,6 +44,7 @@ pub trait RequestFlags<'o>: Operation<'o> { pub trait RequestMode<'o>: Operation<'o> { fn mode(request: &Request<'o, Self>) -> Mode; + fn umask(request: &Request<'o, Self>) -> Mode; } pub trait ReplyOk<'o>: Operation<'o> { @@ -140,6 +141,13 @@ impl<'o, O: Operation<'o>> Request<'o, O> { O::mode(self) } + pub fn umask(&self) -> Mode + where + O: RequestMode<'o>, + { + O::umask(self) + } + pub fn forget_list(&self) -> impl '_ + Iterator<Item = (Ino, u64)> where O: RequestForget<'o>, @@ -200,11 +208,18 @@ impl<'o, O: Operation<'o>> Reply<'o, O> { pub fn ok_with_handle(self, handle: u64) -> Done<'o> where - O: ReplyOpen<'o>, + O: ReplyOpen<'o> + ReplyOk<'o>, { O::ok_with_handle(self, handle) } + pub fn known_with_handle(self, known: impl Known, ttl: Ttl, handle: u64) -> Done<'o> + where + O: ReplyOpen<'o> + ReplyKnown<'o>, + { + O::known_with_handle(self, known, ttl, handle) + } + pub fn force_direct_io(&mut self) where O: ReplyOpen<'o>, |
