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