diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-01-04 06:49:48 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-01-04 06:49:52 -0600 |
| commit | 70baa472b2bee69f205cc1aada304d597b858005 (patch) | |
| tree | 7a0b1a0381b68fe0e091b87d00634ff13568bf6d /src/ops/xattr.rs | |
| parent | 1955ec118a32d3fa174496abe5442c82c609273a (diff) | |
Move crate::fuse::* to the top-level
Diffstat (limited to 'src/ops/xattr.rs')
| -rw-r--r-- | src/ops/xattr.rs | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/ops/xattr.rs b/src/ops/xattr.rs new file mode 100644 index 0000000..886b290 --- /dev/null +++ b/src/ops/xattr.rs @@ -0,0 +1,141 @@ +use crate::{ + private_trait::Sealed, proto, util::OutputChain, Done, Errno, Operation, Reply, Request, +}; + +use super::c_to_os; +use std::ffi::{CStr, OsStr}; + +pub enum Setxattr {} +pub enum Getxattr {} +pub enum Listxattr {} +pub enum Removexattr {} + +pub struct XattrReadState { + size: u32, +} + +impl Sealed for Setxattr {} +impl Sealed for Getxattr {} +impl Sealed for Listxattr {} +impl Sealed for Removexattr {} + +impl<'o> Operation<'o> for Setxattr { + // header, name, value + type RequestBody = (&'o proto::SetxattrIn, &'o CStr, &'o [u8]); + type ReplyTail = (); +} + +impl<'o> Operation<'o> for Getxattr { + type RequestBody = (&'o proto::GetxattrIn, &'o CStr); + type ReplyTail = XattrReadState; +} + +impl<'o> Operation<'o> for Listxattr { + type RequestBody = &'o proto::ListxattrIn; + type ReplyTail = XattrReadState; +} + +impl<'o> Operation<'o> for Removexattr { + type RequestBody = &'o CStr; + type ReplyTail = (); +} + +//TODO: flags +impl<'o> Request<'o, Setxattr> { + 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<'o> Reply<'o, Setxattr> { + pub fn ok(self) -> Done<'o> { + self.empty() + } + + pub fn not_found(self) -> Done<'o> { + self.fail(Errno::ENODATA) + } +} + +impl<'o> Request<'o, Getxattr> { + pub fn size(&self) -> u32 { + self.body.0.size + } + + pub fn name(&self) -> &OsStr { + c_to_os(self.body.1) + } +} + +impl<'o> Reply<'o, Getxattr> { + 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) + } +} + +impl<'o> Request<'o, Listxattr> { + pub fn size(&self) -> u32 { + self.body.getxattr_in.size + } +} + +impl<'o> Reply<'o, Listxattr> { + //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) + } +} + +impl<'o> Request<'o, Removexattr> { + pub fn name(&self) -> &OsStr { + c_to_os(self.body) + } +} + +impl<'o> Reply<'o, Removexattr> { + pub fn ok(self) -> Done<'o> { + self.empty() + } +} |
