summaryrefslogtreecommitdiff
path: root/src/ops
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ops/entry.rs5
-rw-r--r--src/ops/mod.rs2
-rw-r--r--src/ops/open.rs88
-rw-r--r--src/ops/traits.rs17
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>,