summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--examples/passthrough.rs12
-rw-r--r--src/ops/entry.rs37
-rw-r--r--src/ops/mod.rs2
-rw-r--r--src/ops/traits.rs13
-rw-r--r--src/session.rs3
5 files changed, 63 insertions, 4 deletions
diff --git a/examples/passthrough.rs b/examples/passthrough.rs
index 1607f10..e8c51ca 100644
--- a/examples/passthrough.rs
+++ b/examples/passthrough.rs
@@ -26,6 +26,7 @@ use tokio::{
};
use clap::{App, Arg};
+use nix::unistd::mkdir;
struct Passthrough {
known: HashMap<Ino, Inode>,
@@ -134,6 +135,16 @@ impl Passthrough {
reply.blob(&target)
}
+ async fn mkdir<'o>(&mut self, (request, reply): Op<'o, ops::Mkdir>) -> Done<'o> {
+ let (reply, inode) = reply.and_then(self.known(request.ino()))?;
+ let path = inode.path.join(request.name());
+
+ let (reply, ()) = reply.and_then(mkdir(&path, request.mode()))?;
+ let (reply, metadata) = reply.and_then(fs::symlink_metadata(&path).await)?;
+
+ reply.known(New(&mut self.known, Inode::new(path, metadata)), Ttl::MAX)
+ }
+
async fn open<'o>(&mut self, (request, reply): Op<'o, ops::Open>) -> Done<'o> {
let (reply, inode) = reply.and_then(self.known(request.ino()))?;
let options = {
@@ -338,6 +349,7 @@ async fn main_loop(session: Start, mut fs: Passthrough) -> FuseResult<()> {
Forget(forget) => fs.forget(forget.op()?),
Getattr(getattr) => fs.getattr(getattr.op()?),
Readlink(readlink) => fs.readlink(readlink.op()?).await,
+ Mkdir(mkdir) => fs.mkdir(mkdir.op()?).await,
Open(open) => fs.open(open.op()?).await,
Read(read) => fs.read(read.op()?).await,
Write(write) => fs.write(write.op()?).await,
diff --git a/src/ops/entry.rs b/src/ops/entry.rs
index 139a506..a65be29 100644
--- a/src/ops/entry.rs
+++ b/src/ops/entry.rs
@@ -1,8 +1,19 @@
-use super::traits::{ReplyOk, RequestHandle};
-use crate::{io::Stat, private_trait::Sealed, proto, Done, Ino, Operation, Reply, Request};
+use crate::{
+ io::{Mode, Stat},
+ private_trait::Sealed,
+ proto, Done, Ino, Operation, Reply, Request,
+};
+
+use super::{
+ c_to_os,
+ traits::{ReplyKnown, ReplyOk, RequestHandle, RequestMode, RequestName},
+};
+
+use std::ffi::{CStr, OsStr};
pub enum Forget {}
pub enum Getattr {}
+pub enum Mkdir {}
pub trait RequestForget<'o>: Operation<'o> {
fn forget_list<'a>(request: &'a Request<'o, Self>) -> ForgetList<'a>;
@@ -19,6 +30,7 @@ pub enum ForgetList<'a> {
impl Sealed for Forget {}
impl Sealed for Getattr {}
+impl Sealed for Mkdir {}
impl<'o> Operation<'o> for Forget {
type RequestBody = proto::OpcodeSelect<
@@ -35,6 +47,11 @@ impl<'o> Operation<'o> for Getattr {
type ReplyTail = ();
}
+impl<'o> Operation<'o> for Mkdir {
+ type RequestBody = (&'o proto::MkdirIn, &'o CStr);
+ type ReplyTail = ();
+}
+
impl<'o> RequestForget<'o> for Forget {
fn forget_list<'a>(request: &'a Request<'o, Self>) -> ForgetList<'a> {
use {proto::OpcodeSelect::*, ForgetList::*};
@@ -86,3 +103,19 @@ impl<'o> ReplyStat<'o> for Getattr {
})
}
}
+
+impl<'o> RequestName<'o> for Mkdir {
+ fn name<'a>(request: &'a Request<'o, Self>) -> &'a OsStr {
+ let (_header, name) = request.body;
+ c_to_os(name)
+ }
+}
+
+impl<'o> RequestMode<'o> for Mkdir {
+ fn mode(request: &Request<'o, Self>) -> Mode {
+ let (header, _name) = request.body;
+ Mode::from_bits_truncate(header.mode)
+ }
+}
+
+impl<'o> ReplyKnown<'o> for Mkdir {}
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index 3e64b97..ad019e3 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -12,7 +12,7 @@ use bytemuck::{bytes_of, Pod};
pub mod traits;
pub use dir::{BufferedReaddir, Lookup, Readdir};
-pub use entry::{Forget, Getattr};
+pub use entry::{Forget, Getattr, Mkdir};
pub use global::{Init, Statfs};
pub use open::{Access, Open, Opendir, Release, Releasedir};
pub use rw::{Flush, Read, Readlink, Write};
diff --git a/src/ops/traits.rs b/src/ops/traits.rs
index 70e529a..9808358 100644
--- a/src/ops/traits.rs
+++ b/src/ops/traits.rs
@@ -1,5 +1,5 @@
use crate::{
- io::{Entry, FsInfo, Interruptible, Known, Stat},
+ io::{Entry, FsInfo, Interruptible, Known, Mode, Stat},
Done, Ino, Operation, Reply, Request, Ttl,
};
@@ -41,6 +41,10 @@ pub trait RequestFlags<'o>: Operation<'o> {
fn flags(request: &Request<'o, Self>) -> Self::Flags;
}
+pub trait RequestMode<'o>: Operation<'o> {
+ fn mode(request: &Request<'o, Self>) -> Mode;
+}
+
pub trait ReplyOk<'o>: Operation<'o> {
fn ok(reply: Reply<'o, Self>) -> Done<'o> {
reply.empty()
@@ -128,6 +132,13 @@ impl<'o, O: Operation<'o>> Request<'o, O> {
O::flags(self)
}
+ pub fn mode(&self) -> Mode
+ where
+ O: RequestMode<'o>,
+ {
+ O::mode(self)
+ }
+
pub fn forget_list(&self) -> impl '_ + Iterator<Item = (Ino, u64)>
where
O: RequestForget<'o>,
diff --git a/src/session.rs b/src/session.rs
index 0c768b3..d1722a3 100644
--- a/src/session.rs
+++ b/src/session.rs
@@ -59,6 +59,7 @@ pub enum Dispatch<'o> {
Forget(Incoming<'o, ops::Forget>),
Getattr(Incoming<'o, ops::Getattr>),
Readlink(Incoming<'o, ops::Readlink>),
+ Mkdir(Incoming<'o, ops::Mkdir>),
Open(Incoming<'o, ops::Open>),
Read(Incoming<'o, ops::Read>),
Write(Incoming<'o, ops::Write>),
@@ -252,6 +253,7 @@ impl<'o> Dispatch<'o> {
Forget(incoming) => incoming.common,
Getattr(incoming) => incoming.common,
Readlink(incoming) => incoming.common,
+ Mkdir(incoming) => incoming.common,
Open(incoming) => incoming.common,
Read(incoming) => incoming.common,
Write(incoming) => incoming.common,
@@ -332,6 +334,7 @@ impl Endpoint<'_> {
Forget => dispatch!(Forget),
Getattr => dispatch!(Getattr),
Readlink => dispatch!(Readlink),
+ Mkdir => dispatch!(Mkdir),
Open => dispatch!(Open),
Read => dispatch!(Read),
Write => dispatch!(Write),