fuse_mt/
types.rs

1// Public types exported by FuseMT.
2//
3// Copyright (c) 2016-2022 by William R. Fraser
4//
5
6use std::ffi::{OsStr, OsString};
7use std::path::Path;
8use std::time::{Duration, SystemTime};
9
10/// Info about a request.
11#[derive(Clone, Copy, Debug)]
12pub struct RequestInfo {
13    /// The unique ID assigned to this request by FUSE.
14    pub unique: u64,
15    /// The user ID of the process making the request.
16    pub uid: u32,
17    /// The group ID of the process making the request.
18    pub gid: u32,
19    /// The process ID of the process making the request.
20    pub pid: u32,
21}
22
23/// A directory entry.
24#[derive(Clone, Debug)]
25pub struct DirectoryEntry {
26    /// Name of the entry
27    pub name: OsString,
28    /// Kind of file (directory, file, pipe, etc.)
29    pub kind: crate::FileType,
30}
31
32/// Filesystem statistics.
33#[derive(Clone, Copy, Debug)]
34pub struct Statfs {
35    /// Total data blocks in the filesystem
36    pub blocks: u64,
37    /// Free blocks in filesystem
38    pub bfree: u64,
39    /// Free blocks available to unprivileged user
40    pub bavail: u64,
41    /// Total file nodes in filesystem
42    pub files: u64,
43    /// Free file nodes in filesystem
44    pub ffree: u64,
45    /// Optimal transfer block size
46    pub bsize: u32,
47    /// Maximum length of filenames
48    pub namelen: u32,
49    /// Fragment size
50    pub frsize: u32,
51}
52
53/// File attributes.
54#[derive(Clone, Copy, Debug)]
55pub struct FileAttr {
56    /// Size in bytes
57    pub size: u64,
58    /// Size in blocks
59    pub blocks: u64,
60    /// Time of last access
61    pub atime: SystemTime,
62    /// Time of last modification
63    pub mtime: SystemTime,
64    /// Time of last metadata change
65    pub ctime: SystemTime,
66    /// Time of creation (macOS only)
67    pub crtime: SystemTime,
68    /// Kind of file (directory, file, pipe, etc.)
69    pub kind: crate::FileType,
70    /// Permissions
71    pub perm: u16,
72    /// Number of hard links
73    pub nlink: u32,
74    /// User ID
75    pub uid: u32,
76    /// Group ID
77    pub gid: u32,
78    /// Device ID (if special file)
79    pub rdev: u32,
80    /// Flags (macOS only; see chflags(2))
81    pub flags: u32,
82}
83
84/// The return value for `create`: contains info on the newly-created file, as well as a handle to
85/// the opened file.
86#[derive(Clone, Debug)]
87pub struct CreatedEntry {
88    pub ttl: Duration,
89    pub attr: FileAttr,
90    pub fh: u64,
91    pub flags: u32,
92}
93
94/// Represents the return value from the `listxattr` and `getxattr` calls, which can be either a
95/// size or contain data, depending on how they are called.
96#[derive(Clone, Debug)]
97pub enum Xattr {
98    Size(u32),
99    Data(Vec<u8>),
100}
101
102#[cfg(target_os = "macos")]
103#[derive(Clone, Debug)]
104pub struct XTimes {
105    pub bkuptime: SystemTime,
106    pub crtime: SystemTime,
107}
108
109pub type ResultEmpty = Result<(), libc::c_int>;
110pub type ResultEntry = Result<(Duration, FileAttr), libc::c_int>;
111pub type ResultOpen = Result<(u64, u32), libc::c_int>;
112pub type ResultReaddir = Result<Vec<DirectoryEntry>, libc::c_int>;
113pub type ResultData = Result<Vec<u8>, libc::c_int>;
114pub type ResultSlice<'a> = Result<&'a [u8], libc::c_int>;
115pub type ResultWrite = Result<u32, libc::c_int>;
116pub type ResultStatfs = Result<Statfs, libc::c_int>;
117pub type ResultCreate = Result<CreatedEntry, libc::c_int>;
118pub type ResultXattr = Result<Xattr, libc::c_int>;
119
120#[cfg(target_os = "macos")]
121pub type ResultXTimes = Result<XTimes, libc::c_int>;
122
123#[deprecated(since = "0.3.0", note = "use ResultEntry instead")]
124pub type ResultGetattr = ResultEntry;
125
126/// Dummy struct returned by the callback in the `read()` method. Cannot be constructed outside
127/// this crate, `read()` requires you to return it, thus ensuring that you don't forget to call the
128/// callback.
129pub struct CallbackResult {
130    pub(crate) _private: std::marker::PhantomData<()>,
131}
132
133/// This trait must be implemented to implement a filesystem with FuseMT.
134pub trait FilesystemMT {
135    /// Called on mount, before any other function.
136    fn init(&self, _req: RequestInfo) -> ResultEmpty {
137        Ok(())
138    }
139
140    /// Called on filesystem unmount.
141    fn destroy(&self) {
142        // Nothing.
143    }
144
145    /// Get the attributes of a filesystem entry.
146    ///
147    /// * `fh`: a file handle if this is called on an open file.
148    fn getattr(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>) -> ResultEntry {
149        Err(libc::ENOSYS)
150    }
151
152    // The following operations in the FUSE C API are all one kernel call: setattr
153    // We split them out to match the C API's behavior.
154
155    /// Change the mode of a filesystem entry.
156    ///
157    /// * `fh`: a file handle if this is called on an open file.
158    /// * `mode`: the mode to change the file to.
159    fn chmod(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _mode: u32) -> ResultEmpty {
160        Err(libc::ENOSYS)
161    }
162
163    /// Change the owner UID and/or group GID of a filesystem entry.
164    ///
165    /// * `fh`: a file handle if this is called on an open file.
166    /// * `uid`: user ID to change the file's owner to. If `None`, leave the UID unchanged.
167    /// * `gid`: group ID to change the file's group to. If `None`, leave the GID unchanged.
168    fn chown(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _uid: Option<u32>, _gid: Option<u32>) -> ResultEmpty {
169        Err(libc::ENOSYS)
170    }
171
172    /// Set the length of a file.
173    ///
174    /// * `fh`: a file handle if this is called on an open file.
175    /// * `size`: size in bytes to set as the file's length.
176    fn truncate(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _size: u64) -> ResultEmpty {
177        Err(libc::ENOSYS)
178    }
179
180    /// Set timestamps of a filesystem entry.
181    ///
182    /// * `fh`: a file handle if this is called on an open file.
183    /// * `atime`: the time of last access.
184    /// * `mtime`: the time of last modification.
185    fn utimens(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _atime: Option<SystemTime>, _mtime: Option<SystemTime>) -> ResultEmpty {
186        Err(libc::ENOSYS)
187    }
188
189    /// Set timestamps of a filesystem entry (with extra options only used on MacOS).
190    #[allow(clippy::too_many_arguments)]
191    fn utimens_macos(&self, _req: RequestInfo, _path: &Path, _fh: Option<u64>, _crtime: Option<SystemTime>, _chgtime: Option<SystemTime>, _bkuptime: Option<SystemTime>, _flags: Option<u32>) -> ResultEmpty {
192        Err(libc::ENOSYS)
193    }
194
195    // END OF SETATTR FUNCTIONS
196
197    /// Read a symbolic link.
198    fn readlink(&self, _req: RequestInfo, _path: &Path) -> ResultData {
199        Err(libc::ENOSYS)
200    }
201
202    /// Create a special file.
203    ///
204    /// * `parent`: path to the directory to make the entry under.
205    /// * `name`: name of the entry.
206    /// * `mode`: mode for the new entry.
207    /// * `rdev`: if mode has the bits `S_IFCHR` or `S_IFBLK` set, this is the major and minor numbers for the device file. Otherwise it should be ignored.
208    fn mknod(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _rdev: u32) -> ResultEntry {
209        Err(libc::ENOSYS)
210    }
211
212    /// Create a directory.
213    ///
214    /// * `parent`: path to the directory to make the directory under.
215    /// * `name`: name of the directory.
216    /// * `mode`: permissions for the new directory.
217    fn mkdir(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32) -> ResultEntry {
218        Err(libc::ENOSYS)
219    }
220
221    /// Remove a file.
222    ///
223    /// * `parent`: path to the directory containing the file to delete.
224    /// * `name`: name of the file to delete.
225    fn unlink(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr) -> ResultEmpty {
226        Err(libc::ENOSYS)
227    }
228
229    /// Remove a directory.
230    ///
231    /// * `parent`: path to the directory containing the directory to delete.
232    /// * `name`: name of the directory to delete.
233    fn rmdir(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr) -> ResultEmpty {
234        Err(libc::ENOSYS)
235    }
236
237    /// Create a symbolic link.
238    ///
239    /// * `parent`: path to the directory to make the link in.
240    /// * `name`: name of the symbolic link.
241    /// * `target`: path (may be relative or absolute) to the target of the link.
242    fn symlink(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _target: &Path) -> ResultEntry {
243        Err(libc::ENOSYS)
244    }
245
246    /// Rename a filesystem entry.
247    ///
248    /// * `parent`: path to the directory containing the existing entry.
249    /// * `name`: name of the existing entry.
250    /// * `newparent`: path to the directory it should be renamed into (may be the same as `parent`).
251    /// * `newname`: name of the new entry.
252    fn rename(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _newparent: &Path, _newname: &OsStr) -> ResultEmpty {
253        Err(libc::ENOSYS)
254    }
255
256    /// Create a hard link.
257    ///
258    /// * `path`: path to an existing file.
259    /// * `newparent`: path to the directory for the new link.
260    /// * `newname`: name for the new link.
261    fn link(&self, _req: RequestInfo, _path: &Path, _newparent: &Path, _newname: &OsStr) -> ResultEntry {
262        Err(libc::ENOSYS)
263    }
264
265    /// Open a file.
266    ///
267    /// * `path`: path to the file.
268    /// * `flags`: one of `O_RDONLY`, `O_WRONLY`, or `O_RDWR`, plus maybe additional flags.
269    ///
270    /// Return a tuple of (file handle, flags). The file handle will be passed to any subsequent
271    /// calls that operate on the file, and can be any value you choose, though it should allow
272    /// your filesystem to identify the file opened even without any path info.
273    fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpen {
274        Err(libc::ENOSYS)
275    }
276
277    /// Read from a file.
278    ///
279    /// Note that it is not an error for this call to request to read past the end of the file, and
280    /// you should only return data up to the end of the file (i.e. the number of bytes returned
281    /// will be fewer than requested; possibly even zero). Do not extend the file in this case.
282    ///
283    /// * `path`: path to the file.
284    /// * `fh`: file handle returned from the `open` call.
285    /// * `offset`: offset into the file to start reading.
286    /// * `size`: number of bytes to read.
287    /// * `callback`: a callback that must be invoked to return the result of the operation: either
288    ///   the result data as a slice, or an error code.
289    ///
290    /// Return the return value from the `callback` function.
291    fn read(&self, _req: RequestInfo, _path: &Path, _fh: u64, _offset: u64, _size: u32, callback: impl FnOnce(ResultSlice<'_>) -> CallbackResult) -> CallbackResult {
292        callback(Err(libc::ENOSYS))
293    }
294
295    /// Write to a file.
296    ///
297    /// * `path`: path to the file.
298    /// * `fh`: file handle returned from the `open` call.
299    /// * `offset`: offset into the file to start writing.
300    /// * `data`: the data to write
301    /// * `flags`:
302    ///
303    /// Return the number of bytes written.
304    fn write(&self, _req: RequestInfo, _path: &Path, _fh: u64, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
305        Err(libc::ENOSYS)
306    }
307
308    /// Called each time a program calls `close` on an open file.
309    ///
310    /// Note that because file descriptors can be duplicated (by `dup`, `dup2`, `fork`) this may be
311    /// called multiple times for a given file handle. The main use of this function is if the
312    /// filesystem would like to return an error to the `close` call. Note that most programs
313    /// ignore the return value of `close`, though.
314    ///
315    /// * `path`: path to the file.
316    /// * `fh`: file handle returned from the `open` call.
317    /// * `lock_owner`: if the filesystem supports locking (`setlk`, `getlk`), remove all locks
318    ///   belonging to this lock owner.
319    fn flush(&self, _req: RequestInfo, _path: &Path, _fh: u64, _lock_owner: u64) -> ResultEmpty {
320        Err(libc::ENOSYS)
321    }
322
323    /// Called when an open file is closed.
324    ///
325    /// There will be one of these for each `open` call. After `release`, no more calls will be
326    /// made with the given file handle.
327    ///
328    /// * `path`: path to the file.
329    /// * `fh`: file handle returned from the `open` call.
330    /// * `flags`: the flags passed when the file was opened.
331    /// * `lock_owner`: if the filesystem supports locking (`setlk`, `getlk`), remove all locks
332    ///   belonging to this lock owner.
333    /// * `flush`: whether pending data must be flushed or not.
334    fn release(&self, _req: RequestInfo, _path: &Path, _fh: u64, _flags: u32, _lock_owner: u64, _flush: bool) -> ResultEmpty {
335        Err(libc::ENOSYS)
336    }
337
338    /// Write out any pending changes of a file.
339    ///
340    /// When this returns, data should be written to persistent storage.
341    ///
342    /// * `path`: path to the file.
343    /// * `fh`: file handle returned from the `open` call.
344    /// * `datasync`: if `false`, also write metadata, otherwise just write file data.
345    fn fsync(&self, _req: RequestInfo, _path: &Path, _fh: u64, _datasync: bool) -> ResultEmpty {
346        Err(libc::ENOSYS)
347    }
348
349    /// Open a directory.
350    ///
351    /// Analogous to the `opend` call.
352    ///
353    /// * `path`: path to the directory.
354    /// * `flags`: file access flags. Will contain `O_DIRECTORY` at least.
355    ///
356    /// Return a tuple of (file handle, flags). The file handle will be passed to any subsequent
357    /// calls that operate on the directory, and can be any value you choose, though it should
358    /// allow your filesystem to identify the directory opened even without any path info.
359    fn opendir(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpen {
360        Err(libc::ENOSYS)
361    }
362
363    /// Get the entries of a directory.
364    ///
365    /// * `path`: path to the directory.
366    /// * `fh`: file handle returned from the `opendir` call.
367    ///
368    /// Return all the entries of the directory.
369    fn readdir(&self, _req: RequestInfo, _path: &Path, _fh: u64) -> ResultReaddir {
370        Err(libc::ENOSYS)
371    }
372
373    /// Close an open directory.
374    ///
375    /// This will be called exactly once for each `opendir` call.
376    ///
377    /// * `path`: path to the directory.
378    /// * `fh`: file handle returned from the `opendir` call.
379    /// * `flags`: the file access flags passed to the `opendir` call.
380    fn releasedir(&self, _req: RequestInfo, _path: &Path, _fh: u64, _flags: u32) -> ResultEmpty {
381        Err(libc::ENOSYS)
382    }
383
384    /// Write out any pending changes to a directory.
385    ///
386    /// Analogous to the `fsync` call.
387    fn fsyncdir(&self, _req: RequestInfo, _path: &Path, _fh: u64, _datasync: bool) -> ResultEmpty {
388        Err(libc::ENOSYS)
389    }
390
391    /// Get filesystem statistics.
392    ///
393    /// * `path`: path to some folder in the filesystem.
394    ///
395    /// See the `Statfs` struct for more details.
396    fn statfs(&self, _req: RequestInfo, _path: &Path) -> ResultStatfs {
397        Err(libc::ENOSYS)
398    }
399
400    /// Set a file extended attribute.
401    ///
402    /// * `path`: path to the file.
403    /// * `name`: attribute name.
404    /// * `value`: the data to set the value to.
405    /// * `flags`: can be either `XATTR_CREATE` or `XATTR_REPLACE`.
406    /// * `position`: offset into the attribute value to write data.
407    fn setxattr(&self, _req: RequestInfo, _path: &Path, _name: &OsStr, _value: &[u8], _flags: u32, _position: u32) -> ResultEmpty {
408        Err(libc::ENOSYS)
409    }
410
411    /// Get a file extended attribute.
412    ///
413    /// * `path`: path to the file
414    /// * `name`: attribute name.
415    /// * `size`: the maximum number of bytes to read.
416    ///
417    /// If `size` is 0, return `Xattr::Size(n)` where `n` is the size of the attribute data.
418    /// Otherwise, return `Xattr::Data(data)` with the requested data.
419    fn getxattr(&self, _req: RequestInfo, _path: &Path, _name: &OsStr, _size: u32) -> ResultXattr {
420        Err(libc::ENOSYS)
421    }
422
423    /// List extended attributes for a file.
424    ///
425    /// * `path`: path to the file.
426    /// * `size`: maximum number of bytes to return.
427    ///
428    /// If `size` is 0, return `Xattr::Size(n)` where `n` is the size required for the list of
429    /// attribute names.
430    /// Otherwise, return `Xattr::Data(data)` where `data` is all the null-terminated attribute
431    /// names.
432    fn listxattr(&self, _req: RequestInfo, _path: &Path, _size: u32) -> ResultXattr {
433        Err(libc::ENOSYS)
434    }
435
436    /// Remove an extended attribute for a file.
437    ///
438    /// * `path`: path to the file.
439    /// * `name`: name of the attribute to remove.
440    fn removexattr(&self, _req: RequestInfo, _path: &Path, _name: &OsStr) -> ResultEmpty {
441        Err(libc::ENOSYS)
442    }
443
444    /// Check for access to a file.
445    ///
446    /// * `path`: path to the file.
447    /// * `mask`: mode bits to check for access to.
448    ///
449    /// Return `Ok(())` if all requested permissions are allowed, otherwise return `Err(EACCES)`
450    /// or other error code as appropriate (e.g. `ENOENT` if the file doesn't exist).
451    fn access(&self, _req: RequestInfo, _path: &Path, _mask: u32) -> ResultEmpty {
452        Err(libc::ENOSYS)
453    }
454
455    /// Create and open a new file.
456    ///
457    /// * `parent`: path to the directory to create the file in.
458    /// * `name`: name of the file to be created.
459    /// * `mode`: the mode to set on the new file.
460    /// * `flags`: flags like would be passed to `open`.
461    ///
462    /// Return a `CreatedEntry` (which contains the new file's attributes as well as a file handle
463    /// -- see documentation on `open` for more info on that).
464    fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreate {
465        Err(libc::ENOSYS)
466    }
467
468    // getlk
469
470    // setlk
471
472    // bmap
473
474    /// macOS only: Rename the volume.
475    ///
476    /// * `name`: new name for the volume
477    #[cfg(target_os = "macos")]
478    fn setvolname(&self, _req: RequestInfo, _name: &OsStr) -> ResultEmpty {
479        Err(libc::ENOSYS)
480    }
481
482    // exchange (macOS only, undocumented)
483
484    /// macOS only: Query extended times (bkuptime and crtime).
485    ///
486    /// * `path`: path to the file to get the times for.
487    ///
488    /// Return an `XTimes` struct with the times, or other error code as appropriate.
489    #[cfg(target_os = "macos")]
490    fn getxtimes(&self, _req: RequestInfo, _path: &Path) -> ResultXTimes {
491        Err(libc::ENOSYS)
492    }
493}