From a65325e15844f880132a69b447e4aec983cb30ab Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Thu, 6 Jan 2022 03:42:56 -0600 Subject: Implement Symlink --- examples/passthrough.rs | 11 +++++++++++ src/ops/entry.rs | 27 +++++++++++++++++++++++++++ src/ops/mod.rs | 2 +- src/ops/traits.rs | 9 ++++++++- src/session.rs | 3 +++ 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/examples/passthrough.rs b/examples/passthrough.rs index 32f50ca..7115fb1 100644 --- a/examples/passthrough.rs +++ b/examples/passthrough.rs @@ -161,6 +161,16 @@ impl Passthrough { reply.ok() } + async fn symlink<'o>(&mut self, (request, reply): Op<'o, ops::Symlink>) -> Done<'o> { + let (reply, inode) = reply.and_then(self.known(request.ino()))?; + let path = inode.path.join(request.name()); + + let (reply, ()) = reply.and_then(fs::symlink(request.target(), &path).await)?; + 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 = { @@ -368,6 +378,7 @@ async fn main_loop(session: Start, mut fs: Passthrough) -> FuseResult<()> { Mkdir(mkdir) => fs.mkdir(mkdir.op()?).await, Unlink(unlink) => fs.unlink(unlink.op()?).await, Rmdir(rmdir) => fs.rmdir(rmdir.op()?).await, + Symlink(symlink) => fs.symlink(symlink.op()?).await, //TODO: Link Open(open) => fs.open(open.op()?).await, Read(read) => fs.read(read.op()?).await, diff --git a/src/ops/entry.rs b/src/ops/entry.rs index 74072ef..435188a 100644 --- a/src/ops/entry.rs +++ b/src/ops/entry.rs @@ -16,12 +16,17 @@ pub enum Getattr {} pub enum Mkdir {} pub enum Unlink {} pub enum Rmdir {} +pub enum Symlink {} pub enum Link {} pub trait RequestForget<'o>: Operation<'o> { fn forget_list<'a>(request: &'a Request<'o, Self>) -> ForgetList<'a>; } +pub trait RequestTarget<'o>: Operation<'o> { + fn target<'a>(request: &'a Request<'o, Self>) -> &'a OsStr; +} + pub trait RequestLink<'o>: Operation<'o> { fn source_ino(request: &Request<'o, Self>) -> Ino; } @@ -40,6 +45,7 @@ impl Sealed for Getattr {} impl Sealed for Mkdir {} impl Sealed for Unlink {} impl Sealed for Rmdir {} +impl Sealed for Symlink {} impl Sealed for Link {} impl<'o> Operation<'o> for Forget { @@ -72,6 +78,11 @@ impl<'o> Operation<'o> for Rmdir { type ReplyState = (); } +impl<'o> Operation<'o> for Symlink { + type RequestBody = (&'o CStr, &'o CStr); // name(), target() + type ReplyState = (); +} + impl<'o> Operation<'o> for Link { type RequestBody = (&'o proto::LinkIn, &'o CStr); type ReplyState = (); @@ -161,6 +172,22 @@ impl<'o> RequestName<'o> for Rmdir { impl<'o> ReplyOk<'o> for Rmdir {} +impl<'o> RequestName<'o> for Symlink { + fn name<'a>(request: &'a Request<'o, Self>) -> &'a OsStr { + let (name, _target) = request.body; + c_to_os(name) + } +} + +impl<'o> RequestTarget<'o> for Symlink { + fn target<'a>(request: &'a Request<'o, Self>) -> &'a OsStr { + let (_name, target) = request.body; + c_to_os(target) + } +} + +impl<'o> ReplyKnown<'o> for Symlink {} + impl<'o> RequestName<'o> for Link { fn name<'a>(request: &'a Request<'o, Self>) -> &'a OsStr { let (_header, name) = request.body; diff --git a/src/ops/mod.rs b/src/ops/mod.rs index 2970ef8..bc486b1 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, Link, Mkdir, Rmdir, Unlink}; +pub use entry::{Forget, Getattr, Link, Mkdir, Rmdir, Symlink, Unlink}; 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 6a4b1ce..52aaed3 100644 --- a/src/ops/traits.rs +++ b/src/ops/traits.rs @@ -5,7 +5,7 @@ use crate::{ pub use super::{ dir::{ReplyEntries, ReplyFound}, - entry::{ReplyStat, RequestForget, RequestLink}, + entry::{ReplyStat, RequestForget, RequestLink, RequestTarget}, global::ReplyFsInfo, open::{ReplyOpen, ReplyPermissionDenied}, rw::ReplyAll, @@ -146,6 +146,13 @@ impl<'o, O: Operation<'o>> Request<'o, O> { O::forget_list(self) } + pub fn target(&self) -> &OsStr + where + O: RequestTarget<'o>, + { + O::target(self) + } + pub fn source_ino(&self) -> Ino where O: RequestLink<'o>, diff --git a/src/session.rs b/src/session.rs index 5f6336f..696d97a 100644 --- a/src/session.rs +++ b/src/session.rs @@ -62,6 +62,7 @@ pub enum Dispatch<'o> { Mkdir(Incoming<'o, ops::Mkdir>), Unlink(Incoming<'o, ops::Unlink>), Rmdir(Incoming<'o, ops::Rmdir>), + Symlink(Incoming<'o, ops::Symlink>), Link(Incoming<'o, ops::Link>), Open(Incoming<'o, ops::Open>), Read(Incoming<'o, ops::Read>), @@ -259,6 +260,7 @@ impl<'o> Dispatch<'o> { Mkdir(incoming) => incoming.common, Unlink(incoming) => incoming.common, Rmdir(incoming) => incoming.common, + Symlink(incoming) => incoming.common, Link(incoming) => incoming.common, Open(incoming) => incoming.common, Read(incoming) => incoming.common, @@ -343,6 +345,7 @@ impl Endpoint<'_> { Mkdir => dispatch!(Mkdir), Unlink => dispatch!(Unlink), Rmdir => dispatch!(Rmdir), + Symlink => dispatch!(Symlink), Link => dispatch!(Link), Open => dispatch!(Open), Read => dispatch!(Read), -- cgit v1.2.3