fuser_ng/types.rs
1// Public types exported by FuserNG.
2//
3// Copyright (c) 2016-2022 by William R. Fraser, 2026 by François NT
4//
5
6use crate::KernelConfig;
7use std::ffi::{OsStr, OsString};
8use std::ops::Deref;
9use std::path::{Path, PathBuf};
10use std::sync::Arc;
11use std::time::{Duration, SystemTime};
12
13/// Inode number used by the public path-oriented API.
14pub type Inode = u64;
15
16/// Info about a request.
17#[derive(Clone, Copy, Debug)]
18pub struct RequestInfo {
19 /// The unique ID assigned to this request by FUSE.
20 pub unique: u64,
21 /// The user ID of the process making the request.
22 pub uid: u32,
23 /// The group ID of the process making the request.
24 pub gid: u32,
25 /// The process ID of the process making the request.
26 pub pid: u32,
27}
28
29/// A directory entry together with its attributes.
30#[derive(Clone, Debug)]
31pub struct DirectoryEntry {
32 /// Name of the entry.
33 pub name: OsString,
34 /// Cache time-to-live for the entry and its attributes.
35 pub ttl: Duration,
36 /// Attributes of the entry.
37 pub attr: FileAttr,
38}
39
40/// A directory entry without attributes for the legacy FUSE readdir operation.
41#[cfg(feature = "legacy_readdir")]
42#[derive(Clone, Debug)]
43pub struct LegacyDirectoryEntry {
44 /// Name of the entry.
45 pub name: OsString,
46 /// Kind of file (directory, file, pipe, etc.).
47 pub kind: crate::FileType,
48}
49
50/// Filesystem statistics.
51#[derive(Clone, Copy, Debug)]
52pub struct Statfs {
53 /// Total data blocks in the filesystem
54 pub blocks: u64,
55 /// Free blocks in filesystem
56 pub bfree: u64,
57 /// Free blocks available to unprivileged user
58 pub bavail: u64,
59 /// Total file nodes in filesystem
60 pub files: u64,
61 /// Free file nodes in filesystem
62 pub ffree: u64,
63 /// Optimal transfer block size
64 pub bsize: u32,
65 /// Maximum length of filenames
66 pub namelen: u32,
67 /// Fragment size
68 pub frsize: u32,
69}
70
71/// File attributes.
72#[derive(Clone, Copy, Debug)]
73pub struct FileAttr {
74 /// Size in bytes
75 pub size: u64,
76 /// Size in blocks
77 pub blocks: u64,
78 /// Time of last access
79 pub atime: SystemTime,
80 /// Time of last modification
81 pub mtime: SystemTime,
82 /// Time of last metadata change
83 pub ctime: SystemTime,
84 /// Time of creation (macOS only)
85 pub crtime: SystemTime,
86 /// Kind of file (directory, file, pipe, etc.)
87 pub kind: crate::FileType,
88 /// Permissions
89 pub perm: u16,
90 /// Number of hard links
91 pub nlink: u32,
92 /// User ID
93 pub uid: u32,
94 /// Group ID
95 pub gid: u32,
96 /// Device ID (if special file)
97 pub rdev: u32,
98 /// block size
99 pub blksize: u32,
100 /// Flags (macOS only; see chflags(2))
101 pub flags: u32,
102}
103
104/// The return value for `create`: contains info on the newly-created file, as well as a handle to
105/// the opened file.
106#[derive(Clone, Debug)]
107pub struct CreatedEntry {
108 /// Entry cache time-to-live.
109 pub ttl: Duration,
110 /// Attributes returned for the created file.
111 pub attr: FileAttr,
112 /// File handle returned for the opened file.
113 pub fh: u64,
114 /// Open response flags returned to fuser.
115 pub flags: u32,
116}
117
118/// Represents the return value from the `listxattr` and `getxattr` calls, which can be either a
119/// size or contain data, depending on how they are called.
120#[derive(Clone, Debug)]
121pub enum Xattr {
122 /// Size needed to read the attribute value or name list.
123 Size(u32),
124 /// Attribute data or null-terminated attribute name list.
125 Data(Vec<u8>),
126}
127
128#[cfg(target_os = "macos")]
129/// Extended timestamps available on macOS.
130#[derive(Clone, Debug)]
131pub struct XTimes {
132 /// Time of the last backup.
133 pub bkuptime: SystemTime,
134 /// Time of creation.
135 pub crtime: SystemTime,
136}
137
138/// Result for operations that return no data.
139pub type ResultEmpty = std::io::Result<()>;
140/// Result containing the cache duration and attributes of an entry.
141pub type ResultEntry = std::io::Result<(Duration, FileAttr)>;
142/// Result containing a file handle and FUSE open response flags.
143pub type ResultOpen = std::io::Result<(u64, u32)>;
144/// Result containing an owned byte buffer.
145pub type ResultData = std::io::Result<Vec<u8>>;
146/// Result containing one batch of directory entries and their attributes.
147pub type ResultReaddirBatch = std::io::Result<Vec<DirectoryEntry>>;
148#[cfg(feature = "legacy_readdir")]
149/// Result containing one batch of legacy directory entries without attributes.
150pub type ResultLegacyReaddirBatch = std::io::Result<Vec<LegacyDirectoryEntry>>;
151/// Result containing a borrowed byte slice.
152pub type ResultSlice<'a> = std::io::Result<&'a [u8]>;
153/// Result containing the number of bytes written.
154pub type ResultWrite = std::io::Result<u32>;
155/// Result containing filesystem statistics.
156pub type ResultStatfs = std::io::Result<Statfs>;
157/// Result containing a newly created and opened entry.
158pub type ResultCreate = std::io::Result<CreatedEntry>;
159/// Result containing extended attribute data or its required size.
160pub type ResultXattr = std::io::Result<Xattr>;
161
162#[cfg(target_os = "macos")]
163/// Result containing extended macOS timestamps.
164pub type ResultXTimes = std::io::Result<XTimes>;
165
166/// Dummy struct returned by the callback in the `read()` method. Cannot be constructed outside
167/// this crate, `read()` requires you to return it, thus ensuring that you don't forget to call the
168/// callback.
169pub struct CallbackResult {
170 pub(crate) _private: std::marker::PhantomData<()>,
171}
172
173/// Path resolved from an inode with the current inode number attached.
174#[derive(Debug, Clone)]
175pub struct ResolvedPath {
176 parent: Arc<PathBuf>,
177 name: Arc<OsStr>,
178 ino: Inode,
179}
180
181impl ResolvedPath {
182 /// Returns the full path by joining the parent path and entry name.
183 pub fn full_path(&self) -> PathBuf {
184 self.parent.join(self.name.as_ref())
185 }
186 /// Returns the final path component.
187 pub fn name(&self) -> &OsStr {
188 &self.name
189 }
190 /// Returns the inode associated with this resolved path.
191 pub fn ino(&self) -> Inode {
192 self.ino
193 }
194 /// Returns the parent directory path.
195 pub fn parent_path(&self) -> Arc<PathBuf> {
196 self.parent.clone()
197 }
198}
199
200/// Entry name resolved relative to a parent directory path.
201#[derive(Debug, Clone)]
202pub struct EntryName {
203 parent: Arc<PathBuf>,
204 //parent_ino: Inode,
205 name: Arc<OsStr>,
206}
207
208impl EntryName {
209 /// Attaches an inode to this entry name.
210 pub(crate) fn with(self, ino: Inode) -> ResolvedPath {
211 ResolvedPath {
212 parent: self.parent,
213 name: self.name,
214 ino,
215 }
216 }
217 /// Creates an entry name from a parent folder path and child name.
218 pub(crate) fn new(parent: FolderPath, name: Arc<OsStr>) -> Self {
219 Self {
220 parent: parent.0,
221 name,
222 }
223 }
224 /// Returns the full path by joining the parent path and entry name.
225 pub fn full_path(&self) -> PathBuf {
226 self.parent.join(self.name.as_ref())
227 }
228 /// Returns the final path component.
229 pub fn name(&self) -> &OsStr {
230 &self.name
231 }
232
233 /// Returns the parent directory path.
234 pub fn parent_path(&self) -> Arc<PathBuf> {
235 self.parent.clone()
236 }
237}
238
239/// Entry path passed to callbacks that may run before or after inode resolution.
240///
241/// Lookup is used while resolving a parent/name pair before an inode is attached.
242/// Resolved is used when the inode table already has an inode for the entry.
243#[derive(Debug, Clone)]
244pub enum EntryRef {
245 /// Entry identified by a parent path and name before inode resolution.
246 Lookup(EntryName),
247 /// Entry whose inode has already been resolved.
248 Resolved(ResolvedPath),
249}
250
251impl EntryRef {
252 /// Returns the full path by joining the parent path and entry name.
253 pub fn full_path(&self) -> PathBuf {
254 match self {
255 EntryRef::Lookup(this) => this.full_path(),
256 EntryRef::Resolved(this) => this.full_path(),
257 }
258 }
259 /// Returns the final path component.
260 pub fn name(&self) -> &OsStr {
261 match self {
262 EntryRef::Lookup(this) => this.name(),
263 EntryRef::Resolved(this) => this.name(),
264 }
265 }
266 /// Returns the parent directory path.
267 pub fn parent_path(&self) -> Arc<PathBuf> {
268 match self {
269 EntryRef::Lookup(this) => this.parent_path(),
270 EntryRef::Resolved(this) => this.parent_path(),
271 }
272 }
273}
274
275/// Shared path for a directory entry in the inode table.
276#[repr(transparent)]
277#[derive(Debug)]
278pub(crate) struct FolderPath(Arc<PathBuf>);
279
280impl From<Arc<PathBuf>> for FolderPath {
281 fn from(value: Arc<PathBuf>) -> Self {
282 Self(value)
283 }
284}
285
286impl From<&OsStr> for FolderPath {
287 fn from(value: &OsStr) -> Self {
288 Self(Arc::new(value.into()))
289 }
290}
291
292impl Deref for FolderPath {
293 type Target = Arc<PathBuf>;
294 fn deref(&self) -> &Self::Target {
295 &self.0
296 }
297}
298
299fn enosys_error<T>() -> std::io::Result<T> {
300 Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
301}
302
303/// This trait must be implemented to implement a filesystem with FuserNG.
304///
305/// Methods have default ENOSYS implementations, so a filesystem can implement only the operations
306/// it supports.
307///
308/// ```no_run
309/// use std::io;
310/// use std::time::{Duration, SystemTime};
311///
312/// use fuser_ng::{EntryRef, FileAttr, FileType, Filesystem, RequestInfo, ResultEntry};
313///
314/// struct RootOnly;
315///
316/// impl Filesystem for RootOnly {
317/// fn getattr(&self, _req: RequestInfo, path: &EntryRef, _fh: Option<u64>) -> ResultEntry {
318/// if path.full_path() != std::path::Path::new("/") {
319/// return Err(io::Error::from_raw_os_error(libc::ENOENT));
320/// }
321///
322/// let now = SystemTime::now();
323///
324/// Ok((
325/// Duration::from_secs(1),
326/// FileAttr {
327/// size: 0,
328/// blocks: 0,
329/// atime: now,
330/// mtime: now,
331/// ctime: now,
332/// crtime: now,
333/// kind: FileType::Directory,
334/// perm: 0o755,
335/// nlink: 2,
336/// uid: 0,
337/// gid: 0,
338/// rdev: 0,
339/// blksize: 512,
340/// flags: 0,
341/// },
342/// ))
343/// }
344/// }
345/// ```
346#[allow(unused_variables)]
347pub trait Filesystem {
348 /// Called on mount, before any other function.
349 fn init(&self, req: RequestInfo, config: &mut KernelConfig) -> ResultEmpty {
350 Ok(())
351 }
352
353 /// Called on filesystem unmount.
354 fn destroy(&self) {
355 // Nothing.
356 }
357
358 /// Get the attributes of a filesystem entry.
359 ///
360 /// * `fh`: a file handle if this is called on an open file.
361 fn getattr(&self, req: RequestInfo, path: &EntryRef, fh: Option<u64>) -> ResultEntry {
362 enosys_error()
363 }
364
365 // The following operations in the FUSE C API are all one kernel call: setattr
366 // We split them out to match the C API's behavior.
367
368 /// Change the mode of a filesystem entry.
369 ///
370 /// * `fh`: a file handle if this is called on an open file.
371 /// * `mode`: the mode to change the file to.
372 fn chmod(
373 &self,
374 req: RequestInfo,
375 path: &ResolvedPath,
376 fh: Option<u64>,
377 mode: u32,
378 ) -> ResultEmpty {
379 enosys_error()
380 }
381
382 /// Change the owner UID and/or group GID of a filesystem entry.
383 ///
384 /// * `fh`: a file handle if this is called on an open file.
385 /// * `uid`: user ID to change the file's owner to. If `None`, leave the UID unchanged.
386 /// * `gid`: group ID to change the file's group to. If `None`, leave the GID unchanged.
387 fn chown(
388 &self,
389 req: RequestInfo,
390 path: &ResolvedPath,
391 fh: Option<u64>,
392 uid: Option<u32>,
393 gid: Option<u32>,
394 ) -> ResultEmpty {
395 enosys_error()
396 }
397
398 /// Set the length of a file.
399 ///
400 /// * `fh`: a file handle if this is called on an open file.
401 /// * `size`: size in bytes to set as the file's length.
402 fn truncate(
403 &self,
404 req: RequestInfo,
405 path: &ResolvedPath,
406 fh: Option<u64>,
407 size: u64,
408 ) -> ResultEmpty {
409 enosys_error()
410 }
411
412 /// Set timestamps of a filesystem entry.
413 ///
414 /// * `fh`: a file handle if this is called on an open file.
415 /// * `atime`: the time of last access.
416 /// * `mtime`: the time of last modification.
417 fn utimens(
418 &self,
419 req: RequestInfo,
420 path: &ResolvedPath,
421 fh: Option<u64>,
422 atime: Option<SystemTime>,
423 mtime: Option<SystemTime>,
424 ) -> ResultEmpty {
425 enosys_error()
426 }
427
428 /// Set timestamps of a filesystem entry (with extra options only used on MacOS).
429 #[allow(clippy::too_many_arguments)]
430 fn utimens_macos(
431 &self,
432 req: RequestInfo,
433 path: &ResolvedPath,
434 fh: Option<u64>,
435 crtime: Option<SystemTime>,
436 chgtime: Option<SystemTime>,
437 bkuptime: Option<SystemTime>,
438 flags: Option<u32>,
439 ) -> ResultEmpty {
440 enosys_error()
441 }
442
443 // END OF SETATTR FUNCTIONS
444
445 /// Read a symbolic link.
446 fn readlink(&self, req: RequestInfo, path: &ResolvedPath) -> ResultData {
447 enosys_error()
448 }
449
450 /// Create a special file.
451 ///
452 /// * `parent`: path to the directory to make the entry under.
453 /// * `name`: name of the entry.
454 /// * `mode`: mode for the new entry.
455 /// * `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.
456 fn mknod(&self, req: RequestInfo, entry: &EntryName, mode: u32, rdev: u32) -> ResultEntry {
457 enosys_error()
458 }
459
460 /// Create a directory.
461 ///
462 /// * `parent`: path to the directory to make the directory under.
463 /// * `name`: name of the directory.
464 /// * `mode`: permissions for the new directory.
465 fn mkdir(&self, req: RequestInfo, entry: &EntryName, mode: u32) -> ResultEntry {
466 enosys_error()
467 }
468
469 /// Remove a file.
470 ///
471 /// * `parent`: path to the directory containing the file to delete.
472 /// * `name`: name of the file to delete.
473 fn unlink(&self, req: RequestInfo, entry: &EntryName) -> ResultEmpty {
474 enosys_error()
475 }
476
477 /// Remove a directory.
478 ///
479 /// * `parent`: path to the directory containing the directory to delete.
480 /// * `name`: name of the directory to delete.
481 fn rmdir(&self, req: RequestInfo, entry: &EntryName) -> ResultEmpty {
482 enosys_error()
483 }
484
485 /// Create a symbolic link.
486 ///
487 /// * `parent`: path to the directory to make the link in.
488 /// * `name`: name of the symbolic link.
489 /// * `target`: path (may be relative or absolute) to the target of the link.
490 fn symlink(&self, req: RequestInfo, entry: &EntryName, target: &Path) -> ResultEntry {
491 enosys_error()
492 }
493
494 /// Rename a filesystem entry.
495 ///
496 /// * `parent`: path to the directory containing the existing entry.
497 /// * `name`: name of the existing entry.
498 /// * `newparent`: path to the directory it should be renamed into (may be the same as `parent`).
499 /// * `newname`: name of the new entry.
500 fn rename(&self, req: RequestInfo, entry: &EntryName, new_entry: &EntryName) -> ResultEmpty {
501 enosys_error()
502 }
503
504 /// Create a hard link.
505 ///
506 /// * `path`: path to an existing file.
507 /// * `newparent`: path to the directory for the new link.
508 /// * `newname`: name for the new link.
509 fn link(&self, req: RequestInfo, path: &ResolvedPath, new_entry: &EntryName) -> ResultEntry {
510 enosys_error()
511 }
512
513 /// Open a file.
514 ///
515 /// * `path`: path to the file.
516 /// * `flags`: one of `O_RDONLY`, `O_WRONLY`, or `O_RDWR`, plus maybe additional flags.
517 ///
518 /// Return a tuple of (file handle, flags). The file handle will be passed to any subsequent
519 /// calls that operate on the file, and can be any value you choose, though it should allow
520 /// your filesystem to identify the file opened even without any path info.
521 fn open(&self, req: RequestInfo, path: &ResolvedPath, flags: u32) -> ResultOpen {
522 enosys_error()
523 }
524
525 /// Read from a file.
526 ///
527 /// Note that it is not an error for this call to request to read past the end of the file, and
528 /// you should only return data up to the end of the file (i.e. the number of bytes returned
529 /// will be fewer than requested; possibly even zero). Do not extend the file in this case.
530 ///
531 /// * `path`: path to the file.
532 /// * `fh`: file handle returned from the `open` call.
533 /// * `offset`: offset into the file to start reading.
534 /// * `size`: number of bytes to read.
535 /// * `callback`: a callback that must be invoked to return the result of the operation: either
536 /// the result data as a slice, or an error code.
537 ///
538 /// Return the return value from the `callback` function.
539 fn read(
540 &self,
541 req: RequestInfo,
542 path: &ResolvedPath,
543 fh: u64,
544 offset: u64,
545 size: u32,
546 callback: impl FnOnce(ResultSlice<'_>) -> CallbackResult,
547 ) -> CallbackResult {
548 callback(enosys_error())
549 }
550
551 /// Write to a file.
552 ///
553 /// * `path`: path to the file.
554 /// * `fh`: file handle returned from the `open` call.
555 /// * `offset`: offset into the file to start writing.
556 /// * `data`: the data to write
557 /// * `flags`:
558 ///
559 /// Return the number of bytes written.
560 fn write(
561 &self,
562 req: RequestInfo,
563 path: &ResolvedPath,
564 fh: u64,
565 offset: u64,
566 data: Vec<u8>,
567 flags: u32,
568 ) -> ResultWrite {
569 enosys_error()
570 }
571
572 /// Called each time a program calls `close` on an open file.
573 ///
574 /// Note that because file descriptors can be duplicated (by `dup`, `dup2`, `fork`) this may be
575 /// called multiple times for a given file handle. The main use of this function is if the
576 /// filesystem would like to return an error to the `close` call. Note that most programs
577 /// ignore the return value of `close`, though.
578 ///
579 /// * `path`: path to the file.
580 /// * `fh`: file handle returned from the `open` call.
581 /// * `lock_owner`: if the filesystem supports locking (`setlk`, `getlk`), remove all locks
582 /// belonging to this lock owner.
583 fn flush(
584 &self,
585 req: RequestInfo,
586 path: &ResolvedPath,
587 fh: u64,
588 lock_owner: u64,
589 ) -> ResultEmpty {
590 enosys_error()
591 }
592
593 /// Called when an open file is closed.
594 ///
595 /// There will be one of these for each `open` call. After `release`, no more calls will be
596 /// made with the given file handle.
597 ///
598 /// * `path`: path to the file.
599 /// * `fh`: file handle returned from the `open` call.
600 /// * `flags`: the flags passed when the file was opened.
601 /// * `lock_owner`: if the filesystem supports locking (`setlk`, `getlk`), remove all locks
602 /// belonging to this lock owner.
603 /// * `flush`: whether pending data must be flushed or not.
604 fn release(
605 &self,
606 req: RequestInfo,
607 path: &ResolvedPath,
608 fh: u64,
609 flags: u32,
610 lock_owner: u64,
611 flush: bool,
612 ) -> ResultEmpty {
613 enosys_error()
614 }
615
616 /// Write out any pending changes of a file.
617 ///
618 /// When this returns, data should be written to persistent storage.
619 ///
620 /// * `path`: path to the file.
621 /// * `fh`: file handle returned from the `open` call.
622 /// * `datasync`: if `false`, also write metadata, otherwise just write file data.
623 fn fsync(&self, req: RequestInfo, path: &ResolvedPath, fh: u64, datasync: bool) -> ResultEmpty {
624 enosys_error()
625 }
626
627 /// Open a directory.
628 ///
629 /// Analogous to the `opend` call.
630 ///
631 /// * `path`: path to the directory.
632 /// * `flags`: file access flags. Will contain `O_DIRECTORY` at least.
633 ///
634 /// Return a tuple of (file handle, flags). The file handle will be passed to any subsequent
635 /// calls that operate on the directory, and can be any value you choose, though it should
636 /// allow your filesystem to identify the directory opened even without any path info.
637 fn opendir(&self, req: RequestInfo, path: &ResolvedPath, flags: u32) -> ResultOpen {
638 enosys_error()
639 }
640
641 /// Gets directory entries together with their attributes.
642 ///
643 /// * `path`: path to the directory.
644 /// * `fh`: file handle returned from the `opendir` call.
645 ///
646 /// Results are produced in batches and retained by FuserNG until releasedir, allowing
647 /// offsets previously returned to FUSE to be revisited.
648 fn readdir(
649 &self,
650 req: RequestInfo,
651 path: &ResolvedPath,
652 fh: u64,
653 ) -> impl Iterator<Item = ResultReaddirBatch> + Send + 'static {
654 std::iter::once(enosys_error())
655 }
656
657 /// Gets directory entries without attributes for the legacy FUSE readdir operation.
658 ///
659 /// Results are produced in batches and retained by FuserNG until releasedir, allowing
660 /// offsets previously returned to FUSE to be revisited.
661 #[cfg(feature = "legacy_readdir")]
662 fn legacy_readdir(
663 &self,
664 req: RequestInfo,
665 path: &ResolvedPath,
666 fh: u64,
667 ) -> impl Iterator<Item = ResultLegacyReaddirBatch> + Send + 'static {
668 std::iter::once(enosys_error())
669 }
670
671 /// Close an open directory.
672 ///
673 /// This will be called exactly once for each `opendir` call.
674 ///
675 /// * `path`: path to the directory.
676 /// * `fh`: file handle returned from the `opendir` call.
677 /// * `flags`: the file access flags passed to the `opendir` call.
678 fn releasedir(
679 &self,
680 req: RequestInfo,
681 path: &ResolvedPath,
682 fh: u64,
683 flags: u32,
684 ) -> ResultEmpty {
685 enosys_error()
686 }
687
688 /// Write out any pending changes to a directory.
689 ///
690 /// Analogous to the `fsync` call.
691 fn fsyncdir(
692 &self,
693 req: RequestInfo,
694 path: &ResolvedPath,
695 fh: u64,
696 datasync: bool,
697 ) -> ResultEmpty {
698 enosys_error()
699 }
700
701 /// Get filesystem statistics.
702 ///
703 /// * `path`: path to some folder in the filesystem.
704 ///
705 /// See the `Statfs` struct for more details.
706 fn statfs(&self, req: RequestInfo, path: &ResolvedPath) -> ResultStatfs {
707 enosys_error()
708 }
709
710 /// Set a file extended attribute.
711 ///
712 /// * `path`: path to the file.
713 /// * `name`: attribute name.
714 /// * `value`: the data to set the value to.
715 /// * `flags`: can be either `XATTR_CREATE` or `XATTR_REPLACE`.
716 /// * `position`: offset into the attribute value to write data.
717 fn setxattr(
718 &self,
719 req: RequestInfo,
720 path: &ResolvedPath,
721 name: &OsStr,
722 value: &[u8],
723 flags: u32,
724 position: u32,
725 ) -> ResultEmpty {
726 enosys_error()
727 }
728
729 /// Get a file extended attribute.
730 ///
731 /// * `path`: path to the file
732 /// * `name`: attribute name.
733 /// * `size`: the maximum number of bytes to read.
734 ///
735 /// If `size` is 0, return `Xattr::Size(n)` where `n` is the size of the attribute data.
736 /// Otherwise, return `Xattr::Data(data)` with the requested data.
737 fn getxattr(
738 &self,
739 req: RequestInfo,
740 path: &ResolvedPath,
741 name: &OsStr,
742 size: u32,
743 ) -> ResultXattr {
744 enosys_error()
745 }
746
747 /// List extended attributes for a file.
748 ///
749 /// * `path`: path to the file.
750 /// * `size`: maximum number of bytes to return.
751 ///
752 /// If `size` is 0, return `Xattr::Size(n)` where `n` is the size required for the list of
753 /// attribute names.
754 /// Otherwise, return `Xattr::Data(data)` where `data` is all the null-terminated attribute
755 /// names.
756 fn listxattr(&self, req: RequestInfo, path: &ResolvedPath, size: u32) -> ResultXattr {
757 enosys_error()
758 }
759
760 /// Remove an extended attribute for a file.
761 ///
762 /// * `path`: path to the file.
763 /// * `name`: name of the attribute to remove.
764 fn removexattr(&self, req: RequestInfo, path: &ResolvedPath, name: &OsStr) -> ResultEmpty {
765 enosys_error()
766 }
767
768 /// Check for access to a file.
769 ///
770 /// * `path`: path to the file.
771 /// * `mask`: mode bits to check for access to.
772 ///
773 /// Return `Ok(())` if all requested permissions are allowed, otherwise return `Err(EACCES)`
774 /// or other error code as appropriate (e.g. `ENOENT` if the file doesn't exist).
775 fn access(&self, req: RequestInfo, path: &ResolvedPath, mask: u32) -> ResultEmpty {
776 enosys_error()
777 }
778
779 /// Create and open a new file.
780 ///
781 /// * `parent`: path to the directory to create the file in.
782 /// * `name`: name of the file to be created.
783 /// * `mode`: the mode to set on the new file.
784 /// * `flags`: flags like would be passed to `open`.
785 ///
786 /// Return a `CreatedEntry` (which contains the new file's attributes as well as a file handle
787 /// -- see documentation on `open` for more info on that).
788 fn create(&self, req: RequestInfo, path: &ResolvedPath, mode: u32, flags: u32) -> ResultCreate {
789 enosys_error()
790 }
791
792 // getlk
793
794 // setlk
795
796 // bmap
797
798 /// macOS only: Rename the volume.
799 ///
800 /// * `name`: new name for the volume
801 #[cfg(target_os = "macos")]
802 fn setvolname(&self, req: RequestInfo, name: &OsStr) -> ResultEmpty {
803 enosys_error()
804 }
805
806 // exchange (macOS only, undocumented)
807
808 /// macOS only: Query extended times (bkuptime and crtime).
809 ///
810 /// * `path`: path to the file to get the times for.
811 ///
812 /// Return an `XTimes` struct with the times, or other error code as appropriate.
813 #[cfg(target_os = "macos")]
814 fn getxtimes(&self, req: RequestInfo, path: &ResolvedPath) -> ResultXTimes {
815 Err(libc::ENOSYS)
816 }
817}