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}