1#![cfg(any(target_os = "android", target_os = "linux"))]
8
9use std::ffi::FromBytesWithNulError;
10use std::fs::File;
11use std::io;
12
13use remain::sorted;
14use thiserror::Error as ThisError;
15
16pub mod filesystem;
17pub mod fuzzing;
18pub mod mount;
19mod server;
20#[allow(dead_code)]
21pub mod sys;
22pub mod worker;
23
24use filesystem::FileSystem;
25pub use mount::mount;
26pub use server::Mapper;
27pub use server::Reader;
28pub use server::Server;
29pub use server::Writer;
30
31#[sorted]
33#[derive(ThisError, Debug)]
34pub enum Error {
35 #[error("failed to decode fuse message: {0}")]
38 DecodeMessage(io::Error),
39 #[error("failed to encode fuse message: {0}")]
41 EncodeMessage(io::Error),
42 #[error("failed to set up FUSE endpoint to talk with: {0}")]
44 EndpointSetup(io::Error),
45 #[error("failed to flush fuse message: {0}")]
47 FlushMessage(io::Error),
48 #[error("a c string parameter is invalid: {0}")]
50 InvalidCString(FromBytesWithNulError),
51 #[error("the `len` field of the header is too small")]
53 InvalidHeaderLength,
54 #[error(
57 "The `size` field of the `SetxattrIn` message does not match the\
58 length of the decoded value: size = {0}, value.len() = {1}"
59 )]
60 InvalidXattrSize(u32, usize),
61 #[error("one or more parameters are missing")]
63 MissingParameter,
64 #[error("Thread exited")]
66 ThreadExited,
67 #[error(
69 "requested too many `iovec`s for an `ioctl` retry reply: requested\
70 {0}, max: {1}"
71 )]
72 TooManyIovecs(usize, usize),
73}
74
75pub type Result<T> = ::std::result::Result<T, Error>;
76
77#[derive(Default)]
78pub struct FuseConfig {
79 dev_fuse_file: Option<File>,
80 max_write_bytes: Option<u32>,
81 max_read_bytes: Option<u32>,
82 num_of_threads: Option<usize>,
83}
84
85impl FuseConfig {
86 pub fn new() -> Self {
87 FuseConfig {
88 ..Default::default()
89 }
90 }
91
92 pub fn dev_fuse(&mut self, file: File) -> &mut Self {
94 self.dev_fuse_file = Some(file);
95 self
96 }
97
98 pub fn max_read(&mut self, bytes: u32) -> &mut Self {
101 self.max_read_bytes = Some(bytes);
102 self
103 }
104
105 pub fn max_write(&mut self, bytes: u32) -> &mut Self {
107 self.max_write_bytes = Some(bytes);
108 self
109 }
110
111 pub fn num_threads(&mut self, num: usize) -> &mut Self {
113 self.num_of_threads = Some(num);
114 self
115 }
116
117 pub fn enter_message_loop<F: FileSystem + Sync + Send>(self, fs: F) -> Result<()> {
118 let FuseConfig {
119 dev_fuse_file,
120 max_write_bytes,
121 max_read_bytes,
122 num_of_threads,
123 } = self;
124 let num = num_of_threads.unwrap_or(1);
125 if num == 1 {
126 worker::start_message_loop(
127 dev_fuse_file.ok_or(Error::MissingParameter)?,
128 max_read_bytes.ok_or(Error::MissingParameter)?,
129 max_write_bytes.ok_or(Error::MissingParameter)?,
130 fs,
131 )
132 } else {
133 worker::internal::start_message_loop_mt(
134 dev_fuse_file.ok_or(Error::MissingParameter)?,
135 max_read_bytes.ok_or(Error::MissingParameter)?,
136 max_write_bytes.ok_or(Error::MissingParameter)?,
137 num,
138 fs,
139 )
140 }
141 }
142}