diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-01-04 06:23:02 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-01-04 06:23:04 -0600 |
| commit | c3c7a5b25a47e54df5d6b887d19f23c6fb20be8b (patch) | |
| tree | 7edf6f3a6c4ae2fd0fb6f8cb4139c80f0a365e01 /src/fuse/ops/rw.rs | |
| parent | 47cda6cd90d40a1b550d55f7181b34c21508c2fb (diff) | |
Split crate::fuse::ops into submodules
Diffstat (limited to 'src/fuse/ops/rw.rs')
| -rw-r--r-- | src/fuse/ops/rw.rs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/fuse/ops/rw.rs b/src/fuse/ops/rw.rs new file mode 100644 index 0000000..726143b --- /dev/null +++ b/src/fuse/ops/rw.rs @@ -0,0 +1,123 @@ +use std::{ffi::OsStr, os::unix::ffi::OsStrExt}; +use crate::{proto, util::OutputChain}; +use crate::fuse::{private_trait::Sealed, Done, Operation, Reply, Request}; +use super::FromRequest; + +pub enum Readlink {} +pub enum Read {} +pub enum Write {} +pub enum Flush {} + +pub struct WriteState { + size: u32, +} + +impl Sealed for Readlink {} +impl Sealed for Read {} +impl Sealed for Write {} +impl Sealed for Flush {} + +impl<'o> Operation<'o> for Readlink { + type RequestBody = (); + type ReplyTail = (); +} + +impl<'o> Operation<'o> for Read { + type RequestBody = &'o proto::ReadIn; + type ReplyTail = (); +} + +impl<'o> Operation<'o> for Write { + type RequestBody = (&'o proto::WriteIn, &'o [u8]); + type ReplyTail = WriteState; +} + +impl<'o> Operation<'o> for Flush { + type RequestBody = &'o proto::FlushIn; + type ReplyTail = (); +} + +impl<'o> Reply<'o, Readlink> { + /// This inode corresponds to a symbolic link pointing to the given target path. + pub fn target<T: AsRef<OsStr>>(self, target: T) -> Done<'o> { + self.chain(OutputChain::tail(&[target.as_ref().as_bytes()])) + } + + /// Same as [`Reply::target()`], except that the target path is taken from disjoint + /// slices. This involves no additional allocation. + pub fn gather_target(self, target: &[&[u8]]) -> Done<'o> { + self.chain(OutputChain::tail(target)) + } +} + +impl<'o> Request<'o, Read> { + pub fn handle(&self) -> u64 { + self.body.fh + } + + pub fn offset(&self) -> u64 { + self.body.offset + } + + pub fn size(&self) -> u32 { + self.body.size + } +} + +impl<'o> Reply<'o, Read> { + pub fn slice(self, data: &[u8]) -> Done<'o> { + self.chain(OutputChain::tail(&[data])) + } +} + +impl<'o> Request<'o, Write> { + pub fn handle(&self) -> u64 { + self.body.0.fh + } + + pub fn offset(&self) -> u64 { + self.body.0.offset + } + + pub fn data(&self) -> &[u8] { + self.body.1 + } +} + +impl<'o> Reply<'o, Write> { + pub fn all(self) -> Done<'o> { + let size = self.tail.size; + self.single(&proto::WriteOut { + size, + padding: Default::default(), + }) + } +} + +impl<'o> Request<'o, Flush> { + pub fn handle(&self) -> u64 { + self.body.fh + } +} + +impl<'o> Reply<'o, Flush> { + pub fn ok(self) -> Done<'o> { + self.empty() + } +} + +impl<'o> FromRequest<'o, Write> for WriteState { + fn from_request(request: &Request<'o, Write>) -> Self { + let (body, data) = request.body; + + if body.size as usize != data.len() { + log::warn!( + "Write size={} differs from data.len={}", + body.size, + data.len() + ); + } + + WriteState { size: body.size } + } +} |
