summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-01-06 11:04:26 -0600
committerAlejandro Soto <alejandro@34project.org>2022-01-06 11:04:26 -0600
commitf0e7c0997553ab356d5aa683d5322ab2de575188 (patch)
tree825a83b83668539fe110b6ad25ed714e1e73edc9
parentb9a99211a54d62f556fdf71d5eb91107f11398cf (diff)
Implement Create
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
-rw-r--r--src/session.rs3
5 files changed, 108 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>,
diff --git a/src/session.rs b/src/session.rs
index 7c4172b..7fb1d16 100644
--- a/src/session.rs
+++ b/src/session.rs
@@ -80,6 +80,7 @@ pub enum Dispatch<'o> {
Releasedir(Incoming<'o, ops::Releasedir>),
Fsyncdir(Incoming<'o, ops::Fsyncdir>),
Access(Incoming<'o, ops::Access>),
+ Create(Incoming<'o, ops::Create>),
}
pub struct Incoming<'o, O: Operation<'o>> {
@@ -280,6 +281,7 @@ impl<'o> Dispatch<'o> {
Releasedir(incoming) => incoming.common,
Fsyncdir(incoming) => incoming.common,
Access(incoming) => incoming.common,
+ Create(incoming) => incoming.common,
};
common.into_generic_op()
@@ -367,6 +369,7 @@ impl Endpoint<'_> {
Releasedir => dispatch!(Releasedir),
Fsyncdir => dispatch!(Fsyncdir),
Access => dispatch!(Access),
+ Create => dispatch!(Create),
BatchForget => dispatch!(Forget),
ReaddirPlus => dispatch!(Readdir),