summaryrefslogtreecommitdiff
path: root/src/ops/xattr.rs
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-01-05 02:52:04 -0600
committerAlejandro Soto <alejandro@34project.org>2022-01-05 02:52:04 -0600
commit75cced9d4c101ec2f9f04ed95621ff3a3f750eae (patch)
treea8ff3fa46a75b18ee3c1133aa6fc0857132d6115 /src/ops/xattr.rs
parentff17b04143dde5157808be5bcf1cbf8a942db4c4 (diff)
Refactor impls of Reply as individual traits
Diffstat (limited to 'src/ops/xattr.rs')
-rw-r--r--src/ops/xattr.rs88
1 files changed, 51 insertions, 37 deletions
diff --git a/src/ops/xattr.rs b/src/ops/xattr.rs
index 886b290..2de222b 100644
--- a/src/ops/xattr.rs
+++ b/src/ops/xattr.rs
@@ -2,7 +2,11 @@ use crate::{
private_trait::Sealed, proto, util::OutputChain, Done, Errno, Operation, Reply, Request,
};
-use super::c_to_os;
+use super::{
+ c_to_os,
+ traits::{ReplyGather, ReplyNotFound, ReplyOk},
+};
+
use std::ffi::{CStr, OsStr};
pub enum Setxattr {}
@@ -14,6 +18,14 @@ pub struct XattrReadState {
size: u32,
}
+pub trait ReplyXattrRead<'o>: Operation<'o> {
+ fn requires_size(reply: Reply<'o, Self>, size: u32) -> Done<'o>;
+
+ fn buffer_too_small(reply: Reply<'o, Self>) -> Done<'o> {
+ reply.fail(Errno::ERANGE)
+ }
+}
+
impl Sealed for Setxattr {}
impl Sealed for Getxattr {}
impl Sealed for Listxattr {}
@@ -53,13 +65,11 @@ impl<'o> Request<'o, Setxattr> {
}
}
-impl<'o> Reply<'o, Setxattr> {
- pub fn ok(self) -> Done<'o> {
- self.empty()
- }
+impl<'o> ReplyOk<'o> for Setxattr {}
- pub fn not_found(self) -> Done<'o> {
- self.fail(Errno::ENODATA)
+impl<'o> ReplyNotFound<'o> for Setxattr {
+ fn not_found(reply: Reply<'o, Self>) -> Done<'o> {
+ reply.fail(Errno::ENODATA)
}
}
@@ -73,34 +83,40 @@ impl<'o> Request<'o, Getxattr> {
}
}
-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();
+impl<'o> ReplyNotFound<'o> for Getxattr {
+ fn not_found(reply: Reply<'o, Self>) -> Done<'o> {
+ reply.fail(Errno::ENODATA)
+ }
+}
+
+impl<'o> ReplyGather<'o> for Getxattr {
+ fn gather(reply: Reply<'o, Self>, fragments: &[&[u8]]) -> Done<'o> {
+ let size = fragments
+ .iter()
+ .map(|fragment| fragment.len())
+ .sum::<usize>()
+ .try_into()
+ .expect("Extremely large xattr");
+
+ if reply.tail.size == 0 {
+ return reply.requires_size(size);
+ } else if reply.tail.size < size {
+ return reply.buffer_too_small();
}
- self.chain(OutputChain::tail(&[value]))
+ reply.chain(OutputChain::tail(fragments))
}
+}
- pub fn value_size(self, size: u32) -> Done<'o> {
- assert_eq!(self.tail.size, 0);
+impl<'o> ReplyXattrRead<'o> for Getxattr {
+ fn requires_size(reply: Reply<'o, Self>, size: u32) -> Done<'o> {
+ assert_eq!(reply.tail.size, 0);
- self.single(&proto::GetxattrOut {
+ reply.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> {
@@ -109,23 +125,19 @@ impl<'o> Request<'o, Listxattr> {
}
}
-impl<'o> Reply<'o, Listxattr> {
+impl<'o> ReplyXattrRead<'o> for Listxattr {
//TODO: buffered(), gather()
- pub fn value_size(self, size: u32) -> Done<'o> {
- assert_eq!(self.tail.size, 0);
+ fn requires_size(reply: Reply<'o, Self>, size: u32) -> Done<'o> {
+ assert_eq!(reply.tail.size, 0);
- self.single(&proto::ListxattrOut {
+ reply.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> {
@@ -134,8 +146,10 @@ impl<'o> Request<'o, Removexattr> {
}
}
-impl<'o> Reply<'o, Removexattr> {
- pub fn ok(self) -> Done<'o> {
- self.empty()
+impl<'o> ReplyOk<'o> for Removexattr {}
+
+impl<'o> ReplyNotFound<'o> for Removexattr {
+ fn not_found(reply: Reply<'o, Self>) -> Done<'o> {
+ reply.fail(Errno::ENODATA)
}
}