From c1bd6716bd53cb4270eeb032f150ac2c7c1a8f96 Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Wed, 5 Jan 2022 07:00:49 -0600 Subject: Implement Mkdir --- examples/passthrough.rs | 12 ++++++++++++ src/ops/entry.rs | 37 +++++++++++++++++++++++++++++++++++-- src/ops/mod.rs | 2 +- src/ops/traits.rs | 13 ++++++++++++- src/session.rs | 3 +++ 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, @@ -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 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), -- cgit v1.2.3