simply_fuse/
lib.rs

1pub mod attrs;
2pub mod basic;
3pub mod error;
4mod runner;
5
6pub use crate::runner::Runner;
7
8use crate::attrs::*;
9use crate::error::{FSError, FSResult};
10
11use std::ffi::{OsStr, OsString};
12use std::io::BufRead;
13use std::time::Duration;
14
15use typed_builder::TypedBuilder;
16
17#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
18pub struct INode(u64);
19
20impl INode {
21    pub const fn to_u64(self) -> u64 {
22        self.0
23    }
24
25    const fn next_inode(self) -> INode {
26        INode(self.0 + 1)
27    }
28}
29
30impl From<u64> for INode {
31    fn from(i: u64) -> INode {
32        INode(i)
33    }
34}
35
36#[derive(Debug, TypedBuilder)]
37pub struct Lookup {
38    attributes: FileAttributes,
39    inode: INode,
40
41    #[builder(default = None)]
42    generation: Option<u64>,
43
44    #[builder(default = Some(Duration::from_secs(1)))]
45    attr_timeout: Option<Duration>,
46
47    #[builder(default = Some(Duration::from_secs(1)))]
48    entry_timeout: Option<Duration>,
49}
50
51#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
52pub struct Filehandle(u64);
53
54impl Filehandle {
55    pub const fn from_raw(old: u64) -> Self {
56        Self(old)
57    }
58
59    pub const fn to_raw(self) -> u64 {
60        self.0
61    }
62}
63
64#[derive(Debug, TypedBuilder)]
65pub struct OpenFile {
66    handle: Filehandle,
67
68    #[builder(default = true)]
69    direct_io: bool,
70
71    #[builder(default = false)]
72    keep_cache: bool,
73
74    #[builder(default = true)]
75    seekable: bool,
76}
77
78#[derive(Debug, TypedBuilder)]
79pub struct OpenDir {
80    handle: Filehandle,
81
82    #[builder(default = true)]
83    direct_io: bool,
84
85    #[builder(default = false)]
86    keep_cache: bool,
87
88    #[builder(default = true)]
89    seekable: bool,
90
91    #[builder(default = true)]
92    cache_dir: bool,
93}
94
95#[derive(Debug, Copy, Clone)]
96pub enum FileType {
97    FIFO,
98    Unknown,
99    Regular,
100    Directory,
101    Socket,
102    Char,
103    Block,
104    Link,
105}
106
107impl FileType {
108    pub const fn to_libc_type(self) -> u8 {
109        match self {
110            Self::FIFO => libc::DT_FIFO,
111            Self::Unknown => libc::DT_UNKNOWN,
112            Self::Regular => libc::DT_REG,
113            Self::Directory => libc::DT_DIR,
114            Self::Socket => libc::DT_SOCK,
115            Self::Char => libc::DT_CHR,
116            Self::Block => libc::DT_BLK,
117            Self::Link => libc::DT_LNK,
118        }
119    }
120}
121
122#[derive(Debug, TypedBuilder, Clone)]
123pub struct DirEntry {
124    name: OsString,
125    inode: INode,
126    typ: FileType,
127    offset: u64,
128}
129
130#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
131pub enum SetXAttrFlags {
132    Create,
133    Replace,
134}
135
136impl SetXAttrFlags {
137    pub const fn to_libc_type(self) -> i32 {
138        match self {
139            Self::Create => libc::XATTR_CREATE,
140            Self::Replace => libc::XATTR_REPLACE,
141        }
142    }
143
144    pub const fn from_libc_type(from: i32) -> Option<Self> {
145        let create = from & libc::XATTR_CREATE != 0;
146        let replace = from & libc::XATTR_REPLACE != 0;
147
148        if create && replace {
149            // (false && false) and (true && true)
150            None
151        } else if create {
152            Some(Self::Create)
153        } else if replace {
154            Some(Self::Replace)
155        } else {
156            // I don't think this case would ever actually be called
157            None
158        }
159    }
160}
161
162/// Acts as a reference to an xattr, containing a slice for the requested data along with the
163/// length of its data source.
164#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
165pub struct XAttrRef<'a> {
166    /// Represents the actual, full size of `data`. This is not the same as `data.len()`, but
167    /// rather then length of the origianl source of the slice.
168    full_len: usize,
169    data: &'a [u8],
170}
171
172impl<'a> XAttrRef<'a> {
173    pub fn new(data: &'a [u8], full_len: usize) -> XAttrRef<'a> {
174        XAttrRef { full_len, data }
175    }
176
177    pub fn full_len(&self) -> usize {
178        self.full_len
179    }
180
181    pub fn data(&self) -> &[u8] {
182        self.data
183    }
184}
185
186pub trait Filesystem {
187    fn open(&mut self, _ino: INode, _flags: u32) -> FSResult<OpenFile> {
188        Err(FSError::NotImplemented)
189    }
190
191    fn open_dir(&mut self, _ino: INode, _flags: u32) -> FSResult<OpenDir> {
192        Err(FSError::NotImplemented)
193    }
194
195    fn lookup(&mut self, _parent: INode, _name: &OsStr) -> FSResult<Lookup> {
196        Err(FSError::NotImplemented)
197    }
198
199    fn getattr(&mut self, _inode: INode) -> FSResult<FileAttributes> {
200        Err(FSError::NotImplemented)
201    }
202
203    fn setattr(&mut self, _inode: INode, _attr: SetFileAttributes) -> FSResult<FileAttributes> {
204        Err(FSError::NotImplemented)
205    }
206
207    fn setxattr(
208        &mut self,
209        _ino: INode,
210        _attr_name: &OsStr,
211        _attr_value: &[u8],
212        _flags: SetXAttrFlags,
213    ) -> FSResult<()> {
214        Err(FSError::NotImplemented)
215    }
216
217    /// When `max_len == 0`, this is functionally requesting only the length of the requested
218    /// attribute.
219    fn getxattr(
220        &mut self,
221        _ino: INode,
222        _attr_name: &OsStr,
223        _max_len: u32,
224    ) -> FSResult<XAttrRef<'_>> {
225        Err(FSError::NotImplemented)
226    }
227
228    /// When `max_len` is 0, the return value should be an empty string and the length of all the
229    /// attributes with an additional nul byte.
230    ///
231    /// When `max_len` is greater than 0, this function should return an `OsString` composed of all
232    /// the xattr names seperated by a nul (\0) byte. If the length of that string is greater than
233    /// `max_len`, however, the method should error and return `FSError::BufferWouldOverflow`.
234    fn listxattrs(&mut self, _ino: INode, _max_len: u32) -> FSResult<(OsString, u32)> {
235        Err(FSError::NotImplemented)
236    }
237
238    /// Reads a directory.
239    ///
240    /// # Warning
241    /// This method **must** include the "." and ".." directories, as well as properly accounting
242    /// for `offset`. If not, some operations may get stuck in an infinite loop while trying to
243    /// read a directory.
244    fn readdir(&mut self, _dir: INode, _offset: u64) -> FSResult<Vec<DirEntry>> {
245        Err(FSError::NotImplemented)
246    }
247
248    fn read(&mut self, _ino: INode, _offset: u64, _size: u32) -> FSResult<&[u8]> {
249        Err(FSError::NotImplemented)
250    }
251
252    /// Returns the amount of bytes written
253    fn write<T: BufRead>(
254        &mut self,
255        _ino: INode,
256        _offset: u64,
257        _size: u32,
258        _buf: T,
259    ) -> FSResult<u32> {
260        Err(FSError::NotImplemented)
261    }
262}