xref: /aosp_15_r20/external/crosvm/fuse/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! FUSE (Filesystem in Userspace) server and filesystem mounting support.
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker #![cfg(any(target_os = "android", target_os = "linux"))]
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::FromBytesWithNulError;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
12*bb4ee6a4SAndroid Build Coastguard Worker 
13*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
14*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
15*bb4ee6a4SAndroid Build Coastguard Worker 
16*bb4ee6a4SAndroid Build Coastguard Worker pub mod filesystem;
17*bb4ee6a4SAndroid Build Coastguard Worker pub mod fuzzing;
18*bb4ee6a4SAndroid Build Coastguard Worker pub mod mount;
19*bb4ee6a4SAndroid Build Coastguard Worker mod server;
20*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
21*bb4ee6a4SAndroid Build Coastguard Worker pub mod sys;
22*bb4ee6a4SAndroid Build Coastguard Worker pub mod worker;
23*bb4ee6a4SAndroid Build Coastguard Worker 
24*bb4ee6a4SAndroid Build Coastguard Worker use filesystem::FileSystem;
25*bb4ee6a4SAndroid Build Coastguard Worker pub use mount::mount;
26*bb4ee6a4SAndroid Build Coastguard Worker pub use server::Mapper;
27*bb4ee6a4SAndroid Build Coastguard Worker pub use server::Reader;
28*bb4ee6a4SAndroid Build Coastguard Worker pub use server::Server;
29*bb4ee6a4SAndroid Build Coastguard Worker pub use server::Writer;
30*bb4ee6a4SAndroid Build Coastguard Worker 
31*bb4ee6a4SAndroid Build Coastguard Worker /// Errors that may occur during the creation or operation of an Fs device.
32*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
33*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug)]
34*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
35*bb4ee6a4SAndroid Build Coastguard Worker     /// A request is missing readable descriptors.
36*bb4ee6a4SAndroid Build Coastguard Worker     /// Failed to decode protocol messages.
37*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to decode fuse message: {0}")]
38*bb4ee6a4SAndroid Build Coastguard Worker     DecodeMessage(io::Error),
39*bb4ee6a4SAndroid Build Coastguard Worker     /// Failed to encode protocol messages.
40*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to encode fuse message: {0}")]
41*bb4ee6a4SAndroid Build Coastguard Worker     EncodeMessage(io::Error),
42*bb4ee6a4SAndroid Build Coastguard Worker     /// Failed to set up FUSE endpoint to talk with.
43*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to set up FUSE endpoint to talk with: {0}")]
44*bb4ee6a4SAndroid Build Coastguard Worker     EndpointSetup(io::Error),
45*bb4ee6a4SAndroid Build Coastguard Worker     /// Failed to flush protocol messages.
46*bb4ee6a4SAndroid Build Coastguard Worker     #[error("failed to flush fuse message: {0}")]
47*bb4ee6a4SAndroid Build Coastguard Worker     FlushMessage(io::Error),
48*bb4ee6a4SAndroid Build Coastguard Worker     /// A C string parameter is invalid.
49*bb4ee6a4SAndroid Build Coastguard Worker     #[error("a c string parameter is invalid: {0}")]
50*bb4ee6a4SAndroid Build Coastguard Worker     InvalidCString(FromBytesWithNulError),
51*bb4ee6a4SAndroid Build Coastguard Worker     /// The `len` field of the header is too small.
52*bb4ee6a4SAndroid Build Coastguard Worker     #[error("the `len` field of the header is too small")]
53*bb4ee6a4SAndroid Build Coastguard Worker     InvalidHeaderLength,
54*bb4ee6a4SAndroid Build Coastguard Worker     /// The `size` field of the `SetxattrIn` message does not match the length
55*bb4ee6a4SAndroid Build Coastguard Worker     /// of the decoded value.
56*bb4ee6a4SAndroid Build Coastguard Worker     #[error(
57*bb4ee6a4SAndroid Build Coastguard Worker         "The `size` field of the `SetxattrIn` message does not match the\
58*bb4ee6a4SAndroid Build Coastguard Worker              length of the decoded value: size = {0}, value.len() = {1}"
59*bb4ee6a4SAndroid Build Coastguard Worker     )]
60*bb4ee6a4SAndroid Build Coastguard Worker     InvalidXattrSize(u32, usize),
61*bb4ee6a4SAndroid Build Coastguard Worker     /// One or more parameters are missing.
62*bb4ee6a4SAndroid Build Coastguard Worker     #[error("one or more parameters are missing")]
63*bb4ee6a4SAndroid Build Coastguard Worker     MissingParameter,
64*bb4ee6a4SAndroid Build Coastguard Worker     /// Thread exited
65*bb4ee6a4SAndroid Build Coastguard Worker     #[error("Thread exited")]
66*bb4ee6a4SAndroid Build Coastguard Worker     ThreadExited,
67*bb4ee6a4SAndroid Build Coastguard Worker     /// Requested too many `iovec`s for an `ioctl` retry.
68*bb4ee6a4SAndroid Build Coastguard Worker     #[error(
69*bb4ee6a4SAndroid Build Coastguard Worker         "requested too many `iovec`s for an `ioctl` retry reply: requested\
70*bb4ee6a4SAndroid Build Coastguard Worker             {0}, max: {1}"
71*bb4ee6a4SAndroid Build Coastguard Worker     )]
72*bb4ee6a4SAndroid Build Coastguard Worker     TooManyIovecs(usize, usize),
73*bb4ee6a4SAndroid Build Coastguard Worker }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = ::std::result::Result<T, Error>;
76*bb4ee6a4SAndroid Build Coastguard Worker 
77*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)]
78*bb4ee6a4SAndroid Build Coastguard Worker pub struct FuseConfig {
79*bb4ee6a4SAndroid Build Coastguard Worker     dev_fuse_file: Option<File>,
80*bb4ee6a4SAndroid Build Coastguard Worker     max_write_bytes: Option<u32>,
81*bb4ee6a4SAndroid Build Coastguard Worker     max_read_bytes: Option<u32>,
82*bb4ee6a4SAndroid Build Coastguard Worker     num_of_threads: Option<usize>,
83*bb4ee6a4SAndroid Build Coastguard Worker }
84*bb4ee6a4SAndroid Build Coastguard Worker 
85*bb4ee6a4SAndroid Build Coastguard Worker impl FuseConfig {
new() -> Self86*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Self {
87*bb4ee6a4SAndroid Build Coastguard Worker         FuseConfig {
88*bb4ee6a4SAndroid Build Coastguard Worker             ..Default::default()
89*bb4ee6a4SAndroid Build Coastguard Worker         }
90*bb4ee6a4SAndroid Build Coastguard Worker     }
91*bb4ee6a4SAndroid Build Coastguard Worker 
92*bb4ee6a4SAndroid Build Coastguard Worker     /// Set the FUSE device.
dev_fuse(&mut self, file: File) -> &mut Self93*bb4ee6a4SAndroid Build Coastguard Worker     pub fn dev_fuse(&mut self, file: File) -> &mut Self {
94*bb4ee6a4SAndroid Build Coastguard Worker         self.dev_fuse_file = Some(file);
95*bb4ee6a4SAndroid Build Coastguard Worker         self
96*bb4ee6a4SAndroid Build Coastguard Worker     }
97*bb4ee6a4SAndroid Build Coastguard Worker 
98*bb4ee6a4SAndroid Build Coastguard Worker     /// Set the maximum data in a read request. Must be large enough (usually equal) to `n` in
99*bb4ee6a4SAndroid Build Coastguard Worker     /// `MountOption::MaxRead(n)`.
max_read(&mut self, bytes: u32) -> &mut Self100*bb4ee6a4SAndroid Build Coastguard Worker     pub fn max_read(&mut self, bytes: u32) -> &mut Self {
101*bb4ee6a4SAndroid Build Coastguard Worker         self.max_read_bytes = Some(bytes);
102*bb4ee6a4SAndroid Build Coastguard Worker         self
103*bb4ee6a4SAndroid Build Coastguard Worker     }
104*bb4ee6a4SAndroid Build Coastguard Worker 
105*bb4ee6a4SAndroid Build Coastguard Worker     /// Set the maximum data in a write request.
max_write(&mut self, bytes: u32) -> &mut Self106*bb4ee6a4SAndroid Build Coastguard Worker     pub fn max_write(&mut self, bytes: u32) -> &mut Self {
107*bb4ee6a4SAndroid Build Coastguard Worker         self.max_write_bytes = Some(bytes);
108*bb4ee6a4SAndroid Build Coastguard Worker         self
109*bb4ee6a4SAndroid Build Coastguard Worker     }
110*bb4ee6a4SAndroid Build Coastguard Worker 
111*bb4ee6a4SAndroid Build Coastguard Worker     /// Set the number of threads to run the `FileSystem`.
num_threads(&mut self, num: usize) -> &mut Self112*bb4ee6a4SAndroid Build Coastguard Worker     pub fn num_threads(&mut self, num: usize) -> &mut Self {
113*bb4ee6a4SAndroid Build Coastguard Worker         self.num_of_threads = Some(num);
114*bb4ee6a4SAndroid Build Coastguard Worker         self
115*bb4ee6a4SAndroid Build Coastguard Worker     }
116*bb4ee6a4SAndroid Build Coastguard Worker 
enter_message_loop<F: FileSystem + Sync + Send>(self, fs: F) -> Result<()>117*bb4ee6a4SAndroid Build Coastguard Worker     pub fn enter_message_loop<F: FileSystem + Sync + Send>(self, fs: F) -> Result<()> {
118*bb4ee6a4SAndroid Build Coastguard Worker         let FuseConfig {
119*bb4ee6a4SAndroid Build Coastguard Worker             dev_fuse_file,
120*bb4ee6a4SAndroid Build Coastguard Worker             max_write_bytes,
121*bb4ee6a4SAndroid Build Coastguard Worker             max_read_bytes,
122*bb4ee6a4SAndroid Build Coastguard Worker             num_of_threads,
123*bb4ee6a4SAndroid Build Coastguard Worker         } = self;
124*bb4ee6a4SAndroid Build Coastguard Worker         let num = num_of_threads.unwrap_or(1);
125*bb4ee6a4SAndroid Build Coastguard Worker         if num == 1 {
126*bb4ee6a4SAndroid Build Coastguard Worker             worker::start_message_loop(
127*bb4ee6a4SAndroid Build Coastguard Worker                 dev_fuse_file.ok_or(Error::MissingParameter)?,
128*bb4ee6a4SAndroid Build Coastguard Worker                 max_read_bytes.ok_or(Error::MissingParameter)?,
129*bb4ee6a4SAndroid Build Coastguard Worker                 max_write_bytes.ok_or(Error::MissingParameter)?,
130*bb4ee6a4SAndroid Build Coastguard Worker                 fs,
131*bb4ee6a4SAndroid Build Coastguard Worker             )
132*bb4ee6a4SAndroid Build Coastguard Worker         } else {
133*bb4ee6a4SAndroid Build Coastguard Worker             worker::internal::start_message_loop_mt(
134*bb4ee6a4SAndroid Build Coastguard Worker                 dev_fuse_file.ok_or(Error::MissingParameter)?,
135*bb4ee6a4SAndroid Build Coastguard Worker                 max_read_bytes.ok_or(Error::MissingParameter)?,
136*bb4ee6a4SAndroid Build Coastguard Worker                 max_write_bytes.ok_or(Error::MissingParameter)?,
137*bb4ee6a4SAndroid Build Coastguard Worker                 num,
138*bb4ee6a4SAndroid Build Coastguard Worker                 fs,
139*bb4ee6a4SAndroid Build Coastguard Worker             )
140*bb4ee6a4SAndroid Build Coastguard Worker         }
141*bb4ee6a4SAndroid Build Coastguard Worker     }
142*bb4ee6a4SAndroid Build Coastguard Worker }
143