Skip to main content

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}