From d6dead36761f4731951026f48bc3a8d83260b9e5 Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Thu, 30 Dec 2021 21:12:29 -0600 Subject: Add xattr filesystem calls --- src/fuse/ops.rs | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/fuse/session.rs | 12 +++++ 2 files changed, 154 insertions(+), 5 deletions(-) (limited to 'src/fuse') diff --git a/src/fuse/ops.rs b/src/fuse/ops.rs index e6de185..e55511a 100644 --- a/src/fuse/ops.rs +++ b/src/fuse/ops.rs @@ -63,7 +63,7 @@ op! { impl Request { /// Returns the name of the entry being looked up in this directory. pub fn name(&self) -> &OsStr { - OsStr::from_bytes(self.body.to_bytes()) + c_to_os(self.body) } } @@ -360,6 +360,135 @@ op! { } } +op! { + Setxattr { + // header, name, value + type RequestBody = (&'o proto::SetxattrIn, &'o CStr, &'o [u8]); + type ReplyTail = (); + } + + //TODO: flags + impl Request { + pub fn name(&self) -> &OsStr { + let (_header, name, _value) = self.body; + c_to_os(name) + } + + pub fn value(&self) -> &[u8] { + let (_header, _name, value) = self.body; + value + } + } + + impl Reply { + pub fn ok(self) -> Done<'o> { + self.empty() + } + + pub fn not_found(self) -> Done<'o> { + self.fail(Errno::ENODATA) + } + } +} + +op! { + Getxattr { + type RequestBody = (&'o proto::GetxattrIn, &'o CStr); + type ReplyTail = state::ReadXattr; + } + + impl Request { + pub fn size(&self) -> u32 { + self.body.0.size + } + + pub fn name(&self) -> &OsStr { + c_to_os(self.body.1) + } + } + + impl Reply { + pub fn slice(self, value: &[u8]) -> Done<'o> { + let size = value.len().try_into().expect("Extremely large xattr"); + if self.tail.size == 0 { + return self.value_size(size); + } else if self.tail.size < size { + return self.buffer_too_small(); + } + + self.chain(OutputChain::tail(&[value])) + } + + pub fn value_size(self, size: u32) -> Done<'o> { + assert_eq!(self.tail.size, 0); + + self.single(&proto::GetxattrOut { + size, + padding: Default::default(), + }) + } + + pub fn buffer_too_small(self) -> Done<'o> { + self.fail(Errno::ERANGE) + } + + pub fn not_found(self) -> Done<'o> { + self.fail(Errno::ENODATA) + } + } +} + +op! { + Listxattr { + type RequestBody = &'o proto::ListxattrIn; + type ReplyTail = state::ReadXattr; + } + + impl Request { + pub fn size(&self) -> u32 { + self.body.getxattr_in.size + } + } + + impl Reply { + //TODO: buffered(), gather() + + pub fn value_size(self, size: u32) -> Done<'o> { + assert_eq!(self.tail.size, 0); + + self.single(&proto::ListxattrOut { + getxattr_out: proto::GetxattrOut { + size, + padding: Default::default(), + }, + }) + } + + pub fn buffer_too_small(self) -> Done<'o> { + self.fail(Errno::ERANGE) + } + } +} + +op! { + Removexattr { + type RequestBody = &'o CStr; + type ReplyTail = (); + } + + impl Request { + pub fn name(&self) -> &OsStr { + c_to_os(self.body) + } + } + + impl Reply { + pub fn ok(self) -> Done<'o> { + self.empty() + } + } +} + op! { Opendir { type RequestBody = &'o proto::OpendirIn; @@ -578,13 +707,17 @@ pub(crate) mod state { } pub struct Readdir { - pub max_read: usize, - pub is_plus: bool, - pub buffer: B, + pub(super) max_read: usize, + pub(super) is_plus: bool, + pub(super) buffer: B, } pub struct Write { - pub size: u32, + pub(super) size: u32, + } + + pub struct ReadXattr { + pub(super) size: u32, } } @@ -667,3 +800,7 @@ fn dirent_pad_bytes(entry_len: usize) -> usize { const ALIGN_MASK: usize = (1 << proto::DIRENT_ALIGNMENT_BITS) - 1; ((entry_len + ALIGN_MASK) & !ALIGN_MASK) - entry_len } + +fn c_to_os(c_str: &CStr) -> &OsStr { + OsStr::from_bytes(c_str.to_bytes()) +} diff --git a/src/fuse/session.rs b/src/fuse/session.rs index 8b31706..1fbcb68 100644 --- a/src/fuse/session.rs +++ b/src/fuse/session.rs @@ -62,6 +62,10 @@ pub enum Dispatch<'o> { Write(Incoming<'o, ops::Write>), Statfs(Incoming<'o, ops::Statfs>), Release(Incoming<'o, ops::Release>), + Setxattr(Incoming<'o, ops::Setxattr>), + Getxattr(Incoming<'o, ops::Getxattr>), + Listxattr(Incoming<'o, ops::Listxattr>), + Removexattr(Incoming<'o, ops::Removexattr>), Opendir(Incoming<'o, ops::Opendir>), Readdir(Incoming<'o, ops::Readdir>), Releasedir(Incoming<'o, ops::Releasedir>), @@ -229,6 +233,10 @@ impl<'o> Dispatch<'o> { Write(incoming) => incoming.common, Statfs(incoming) => incoming.common, Release(incoming) => incoming.common, + Setxattr(incoming) => incoming.common, + Getxattr(incoming) => incoming.common, + Listxattr(incoming) => incoming.common, + Removexattr(incoming) => incoming.common, Opendir(incoming) => incoming.common, Readdir(incoming) => incoming.common, Releasedir(incoming) => incoming.common, @@ -299,6 +307,10 @@ impl Endpoint<'_> { Write => dispatch!(Write), Statfs => dispatch!(Statfs), Release => dispatch!(Release), + Setxattr => dispatch!(Setxattr), + Getxattr => dispatch!(Getxattr), + Listxattr => dispatch!(Listxattr), + Removexattr => dispatch!(Removexattr), Opendir => dispatch!(Opendir), Readdir => dispatch!(Readdir), Releasedir => dispatch!(Releasedir), -- cgit v1.2.3