fuse/
filesystem.rs

1// Copyright 2019 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Data structures and traits for the fuse filesystem.
6
7#![deny(missing_docs)]
8
9use std::convert::TryInto;
10use std::ffi::CStr;
11use std::fs::File;
12use std::io;
13use std::mem;
14use std::mem::MaybeUninit;
15use std::time::Duration;
16
17use crate::server::Mapper;
18use crate::sys;
19pub use crate::sys::FsOptions;
20pub use crate::sys::IoctlFlags;
21pub use crate::sys::IoctlIovec;
22pub use crate::sys::OpenOptions;
23pub use crate::sys::RemoveMappingOne;
24pub use crate::sys::SetattrValid;
25pub use crate::sys::ROOT_ID;
26
27const MAX_BUFFER_SIZE: u32 = 1 << 20;
28
29/// Information about a path in the filesystem.
30#[derive(Debug)]
31pub struct Entry {
32    /// An `Inode` that uniquely identifies this path. During `lookup`, setting this to `0` means a
33    /// negative entry. Returning `ENOENT` also means a negative entry but setting this to `0`
34    /// allows the kernel to cache the negative result for `entry_timeout`. The value should be
35    /// produced by converting a `FileSystem::Inode` into a `u64`.
36    pub inode: u64,
37
38    /// The generation number for this `Entry`. Typically used for network file systems. An `inode`
39    /// / `generation` pair must be unique over the lifetime of the file system (rather than just
40    /// the lifetime of the mount). In other words, if a `FileSystem` implementation re-uses an
41    /// `Inode` after it has been deleted then it must assign a new, previously unused generation
42    /// number to the `Inode` at the same time.
43    pub generation: u64,
44
45    /// Inode attributes. Even if `attr_timeout` is zero, `attr` must be correct. For example, for
46    /// `open()`, FUSE uses `attr.st_size` from `lookup()` to determine how many bytes to request.
47    /// If this value is not correct, incorrect data will be returned.
48    pub attr: libc::stat64,
49
50    /// How long the values in `attr` should be considered valid. If the attributes of the `Entry`
51    /// are only modified by the FUSE client, then this should be set to a very large value.
52    pub attr_timeout: Duration,
53
54    /// How long the name associated with this `Entry` should be considered valid. If directory
55    /// entries are only changed or deleted by the FUSE client, then this should be set to a very
56    /// large value.
57    pub entry_timeout: Duration,
58}
59
60impl From<Entry> for sys::EntryOut {
61    fn from(entry: Entry) -> sys::EntryOut {
62        sys::EntryOut {
63            nodeid: entry.inode,
64            generation: entry.generation,
65            entry_valid: entry.entry_timeout.as_secs(),
66            attr_valid: entry.attr_timeout.as_secs(),
67            entry_valid_nsec: entry.entry_timeout.subsec_nanos(),
68            attr_valid_nsec: entry.attr_timeout.subsec_nanos(),
69            attr: entry.attr.into(),
70        }
71    }
72}
73
74impl Entry {
75    /// Creates a new negative cache entry. A negative d_entry has an inode number of 0, and is
76    /// valid for the duration of `negative_timeout`.
77    ///
78    /// # Arguments
79    ///
80    /// * `negative_timeout` - The duration for which this negative d_entry should be considered
81    ///   valid. After the timeout expires, the d_entry will be invalidated.
82    ///
83    /// # Returns
84    ///
85    /// A new negative entry with provided entry timeout and 0 attr timeout.
86    pub fn new_negative(negative_timeout: Duration) -> Entry {
87        let attr = MaybeUninit::<libc::stat64>::zeroed();
88        Entry {
89            inode: 0, // Using 0 for negative entry
90            entry_timeout: negative_timeout,
91            // Zero-fill other fields that won't be used.
92            attr_timeout: Duration::from_secs(0),
93            generation: 0,
94            // SAFETY: zero-initialized `stat64` is a valid value.
95            attr: unsafe { attr.assume_init() },
96        }
97    }
98}
99
100/// Represents information about an entry in a directory.
101pub struct DirEntry<'a> {
102    /// The inode number for this entry. This does NOT have to be the same as the `Inode` for this
103    /// directory entry. However, it must be the same as the `attr.st_ino` field of the `Entry`
104    /// that would be returned by a `lookup` request in the parent directory for `name`.
105    pub ino: libc::ino64_t,
106
107    /// Any non-zero value that the kernel can use to identify the current point in the directory
108    /// entry stream. It does not need to be the actual physical position. A value of `0` is
109    /// reserved to mean "from the beginning" and should never be used. The `offset` value of the
110    /// first entry in a stream should point to the beginning of the second entry and so on.
111    pub offset: u64,
112
113    /// The type of this directory entry. Valid values are any of the `libc::DT_*` constants.
114    pub type_: u32,
115
116    /// The name of this directory entry. There are no requirements for the contents of this field
117    /// and any sequence of bytes is considered valid.
118    pub name: &'a CStr,
119}
120
121/// A reply to a `getxattr` method call.
122#[derive(Debug)]
123pub enum GetxattrReply {
124    /// The value of the requested extended attribute. This can be arbitrary textual or binary data
125    /// and does not need to be nul-terminated.
126    Value(Vec<u8>),
127
128    /// The size of the buffer needed to hold the value of the requested extended attribute. Should
129    /// be returned when the `size` parameter is 0. Callers should note that it is still possible
130    /// for the size of the value to change in between `getxattr` calls and should not assume that
131    /// a subsequent call to `getxattr` with the returned count will always succeed.
132    Count(u32),
133}
134
135/// A reply to a `listxattr` method call.
136pub enum ListxattrReply {
137    /// A buffer containing a nul-separated list of the names of all the extended attributes
138    /// associated with this `Inode`. This list of names may be unordered and includes a namespace
139    /// prefix. There may be several disjoint namespaces associated with a single `Inode`.
140    Names(Vec<u8>),
141
142    /// This size of the buffer needed to hold the full list of extended attribute names associated
143    /// with this `Inode`. Should be returned when the `size` parameter is 0. Callers should note
144    /// that it is still possible for the set of extended attributes to change between `listxattr`
145    /// calls and so should not assume that a subsequent call to `listxattr` with the returned
146    /// count will always succeed.
147    Count(u32),
148}
149
150/// A reply to an `ioctl` method call.
151#[derive(Debug)]
152pub enum IoctlReply {
153    /// Indicates that the ioctl should be retried. This is only a valid reply when the `flags`
154    /// field of the ioctl request contains `IoctlFlags::UNRESTRICTED`. The kernel will read in
155    /// data and prepare output buffers as specified in the `input` and `output` fields before
156    /// re-sending the ioctl message.
157    Retry {
158        /// Data that should be read by the kernel module and sent to the server when the ioctl is
159        /// retried.
160        input: Vec<IoctlIovec>,
161
162        /// Buffer space that should be prepared so that the server can send back the response to
163        /// the ioctl.
164        output: Vec<IoctlIovec>,
165    },
166
167    /// Indicates that the ioctl was processed.
168    Done(io::Result<Vec<u8>>),
169}
170
171/// A trait for directly copying data from the fuse transport into a `File` without first storing it
172/// in an intermediate buffer.
173pub trait ZeroCopyReader {
174    /// Copies at most `count` bytes from `self` directly into `f` at offset `off` without storing
175    /// it in any intermediate buffers. If the return value is `Ok(n)` then it must be guaranteed
176    /// that `0 <= n <= count`. If `n` is `0`, then it can indicate one of 3 possibilities:
177    ///
178    /// 1. There is no more data left in `self`.
179    /// 2. There is no more space in `f`.
180    /// 3. `count` was `0`.
181    ///
182    /// # Errors
183    ///
184    /// If any error is returned then the implementation must guarantee that no bytes were copied
185    /// from `self`. If the underlying write to `f` returns `0` then the implementation must return
186    /// an error of the kind `io::ErrorKind::WriteZero`.
187    fn read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>;
188
189    /// Copies exactly `count` bytes of data from `self` into `f` at offset `off`. `off + count`
190    /// must be less than `u64::MAX`.
191    ///
192    /// # Errors
193    ///
194    /// If an error is returned then the number of bytes copied from `self` is unspecified but it
195    /// will never be more than `count`.
196    fn read_exact_to(&mut self, f: &mut File, mut count: usize, mut off: u64) -> io::Result<()> {
197        let c = count
198            .try_into()
199            .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
200        if off.checked_add(c).is_none() {
201            return Err(io::Error::new(
202                io::ErrorKind::InvalidInput,
203                "`off` + `count` must be less than u64::MAX",
204            ));
205        }
206
207        while count > 0 {
208            match self.read_to(f, count, off) {
209                Ok(0) => {
210                    return Err(io::Error::new(
211                        io::ErrorKind::WriteZero,
212                        "failed to fill whole buffer",
213                    ))
214                }
215                Ok(n) => {
216                    count -= n;
217                    off += n as u64;
218                }
219                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
220                Err(e) => return Err(e),
221            }
222        }
223
224        Ok(())
225    }
226
227    /// Copies all remaining bytes from `self` into `f` at offset `off`. Equivalent to repeatedly
228    /// calling `read_to` until it returns either `Ok(0)` or a non-`ErrorKind::Interrupted` error.
229    ///
230    /// # Errors
231    ///
232    /// If an error is returned then the number of bytes copied from `self` is unspecified.
233    fn copy_to_end(&mut self, f: &mut File, mut off: u64) -> io::Result<usize> {
234        let mut out = 0;
235        loop {
236            match self.read_to(f, usize::MAX, off) {
237                Ok(0) => return Ok(out),
238                Ok(n) => {
239                    off = off.saturating_add(n as u64);
240                    out += n;
241                }
242                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
243                Err(e) => return Err(e),
244            }
245        }
246    }
247}
248
249impl<R: ZeroCopyReader> ZeroCopyReader for &mut R {
250    fn read_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize> {
251        (**self).read_to(f, count, off)
252    }
253    fn read_exact_to(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<()> {
254        (**self).read_exact_to(f, count, off)
255    }
256    fn copy_to_end(&mut self, f: &mut File, off: u64) -> io::Result<usize> {
257        (**self).copy_to_end(f, off)
258    }
259}
260
261/// A trait for directly copying data from a `File` into the fuse transport without first storing
262/// it in an intermediate buffer.
263pub trait ZeroCopyWriter {
264    /// Copies at most `count` bytes from `f` at offset `off` directly into `self` without storing
265    /// it in any intermediate buffers. If the return value is `Ok(n)` then it must be guaranteed
266    /// that `0 <= n <= count`. If `n` is `0`, then it can indicate one of 3 possibilities:
267    ///
268    /// 1. There is no more data left in `f`.
269    /// 2. There is no more space in `self`.
270    /// 3. `count` was `0`.
271    ///
272    /// # Errors
273    ///
274    /// If any error is returned then the implementation must guarantee that no bytes were copied
275    /// from `f`. If the underlying read from `f` returns `0` then the implementation must return an
276    /// error of the kind `io::ErrorKind::UnexpectedEof`.
277    fn write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize>;
278
279    /// Copies exactly `count` bytes of data from `f` at offset `off` into `self`. `off + count`
280    /// must be less than `u64::MAX`.
281    ///
282    /// # Errors
283    ///
284    /// If an error is returned then the number of bytes copied from `self` is unspecified but it
285    /// well never be more than `count`.
286    fn write_all_from(&mut self, f: &mut File, mut count: usize, mut off: u64) -> io::Result<()> {
287        let c = count
288            .try_into()
289            .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
290        if off.checked_add(c).is_none() {
291            return Err(io::Error::new(
292                io::ErrorKind::InvalidInput,
293                "`off` + `count` must be less than u64::MAX",
294            ));
295        }
296
297        while count > 0 {
298            match self.write_from(f, count, off) {
299                Ok(0) => {
300                    return Err(io::Error::new(
301                        io::ErrorKind::UnexpectedEof,
302                        "failed to write whole buffer",
303                    ))
304                }
305                Ok(n) => {
306                    // No need for checked math here because we verified that `off + count` will not
307                    // overflow and `n` must be <= `count`.
308                    count -= n;
309                    off += n as u64;
310                }
311                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
312                Err(e) => return Err(e),
313            }
314        }
315
316        Ok(())
317    }
318
319    /// Copies all remaining bytes from `f` at offset `off` into `self`. Equivalent to repeatedly
320    /// calling `write_from` until it returns either `Ok(0)` or a non-`ErrorKind::Interrupted`
321    /// error.
322    ///
323    /// # Errors
324    ///
325    /// If an error is returned then the number of bytes copied from `f` is unspecified.
326    fn copy_to_end(&mut self, f: &mut File, mut off: u64) -> io::Result<usize> {
327        let mut out = 0;
328        loop {
329            match self.write_from(f, usize::MAX, off) {
330                Ok(0) => return Ok(out),
331                Ok(n) => {
332                    off = off.saturating_add(n as u64);
333                    out += n;
334                }
335                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
336                Err(e) => return Err(e),
337            }
338        }
339    }
340}
341
342impl<W: ZeroCopyWriter> ZeroCopyWriter for &mut W {
343    fn write_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<usize> {
344        (**self).write_from(f, count, off)
345    }
346    fn write_all_from(&mut self, f: &mut File, count: usize, off: u64) -> io::Result<()> {
347        (**self).write_all_from(f, count, off)
348    }
349    fn copy_to_end(&mut self, f: &mut File, off: u64) -> io::Result<usize> {
350        (**self).copy_to_end(f, off)
351    }
352}
353
354/// Additional context associated with requests.
355#[derive(Clone, Copy, Debug)]
356pub struct Context {
357    /// The user ID of the calling process.
358    pub uid: libc::uid_t,
359
360    /// The group ID of the calling process.
361    pub gid: libc::gid_t,
362
363    /// The thread group ID of the calling process.
364    pub pid: libc::pid_t,
365}
366
367impl From<sys::InHeader> for Context {
368    fn from(source: sys::InHeader) -> Self {
369        Context {
370            uid: source.uid,
371            gid: source.gid,
372            pid: source.pid as i32,
373        }
374    }
375}
376
377/// A trait for iterating over the contents of a directory. This trait is needed because rust
378/// doesn't support generic associated types, which means that it's not possible to implement a
379/// regular iterator that yields a `DirEntry` due to its generic lifetime parameter.
380pub trait DirectoryIterator {
381    /// Returns the next entry in the directory or `None` if there are no more.
382    fn next(&mut self) -> Option<DirEntry>;
383}
384
385/// The main trait that connects a file system with a transport.
386#[allow(unused_variables)]
387pub trait FileSystem {
388    /// Represents a location in the filesystem tree and can be used to perform operations that act
389    /// on the metadata of a file/directory (e.g., `getattr` and `setattr`). Can also be used as the
390    /// starting point for looking up paths in the filesystem tree. An `Inode` may support operating
391    /// directly on the content of the path that to which it points. `FileSystem` implementations
392    /// that support this should set the `FsOptions::ZERO_MESSAGE_OPEN` option in the return value
393    /// of the `init` function. On linux based systems, an `Inode` is equivalent to opening a file
394    /// or directory with the `libc::O_PATH` flag.
395    ///
396    /// # Lookup Count
397    ///
398    /// The `FileSystem` implementation is required to keep a "lookup count" for every `Inode`.
399    /// Every time an `Entry` is returned by a `FileSystem` trait method, this lookup count should
400    /// increase by 1. The lookup count for an `Inode` decreases when the kernel sends a `forget`
401    /// request. `Inode`s with a non-zero lookup count may receive requests from the kernel even
402    /// after calls to `unlink`, `rmdir` or (when overwriting an existing file) `rename`.
403    /// `FileSystem` implementations must handle such requests properly and it is recommended to
404    /// defer removal of the `Inode` until the lookup count reaches zero. Calls to `unlink`, `rmdir`
405    /// or `rename` will be followed closely by `forget` unless the file or directory is open, in
406    /// which case the kernel issues `forget` only after the `release` or `releasedir` calls.
407    ///
408    /// Note that if a file system will be exported over NFS the `Inode`'s lifetime must extend even
409    /// beyond `forget`. See the `generation` field in `Entry`.
410    type Inode: From<u64> + Into<u64>;
411
412    /// Represents a file or directory that is open for reading/writing.
413    type Handle: From<u64> + Into<u64>;
414
415    /// An iterator over the entries of a directory. See the documentation for `readdir` for more
416    /// details.
417    type DirIter: DirectoryIterator;
418
419    /// Maximum size of the buffer that the filesystem can generate data to, including the header.
420    /// This corresponds to max_write in the initialization.
421    fn max_buffer_size(&self) -> u32 {
422        MAX_BUFFER_SIZE
423    }
424
425    /// Initialize the file system.
426    ///
427    /// This method is called when a connection to the FUSE kernel module is first established. The
428    /// `capable` parameter indicates the features that are supported by the kernel module. The
429    /// implementation should return the options that it supports. Any options set in the returned
430    /// `FsOptions` that are not also set in `capable` are silently dropped.
431    fn init(&self, capable: FsOptions) -> io::Result<FsOptions> {
432        Ok(FsOptions::empty())
433    }
434
435    /// Clean up the file system.
436    ///
437    /// Called when the filesystem exits. All open `Handle`s should be closed and the lookup count
438    /// for all open `Inode`s implicitly goes to zero. At this point the connection to the FUSE
439    /// kernel module may already be gone so implementations should not rely on being able to
440    /// communicate with the kernel.
441    fn destroy(&self) {}
442
443    /// Look up a directory entry by name and get its attributes.
444    ///
445    /// If this call is successful then the lookup count of the `Inode` associated with the returned
446    /// `Entry` must be increased by 1.
447    fn lookup(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<Entry> {
448        Err(io::Error::from_raw_os_error(libc::ENOSYS))
449    }
450
451    /// Forget about an inode.
452    ///
453    /// Called when the kernel removes an inode from its internal caches. `count` indicates the
454    /// amount by which the lookup count for the inode should be decreased. If reducing the lookup
455    /// count by `count` causes it to go to zero, then the implementation may delete the `Inode`.
456    fn forget(&self, ctx: Context, inode: Self::Inode, count: u64) {}
457
458    /// Forget about multiple inodes.
459    ///
460    /// `requests` is a vector of `(inode, count)` pairs. See the documentation for `forget` for
461    /// more information.
462    fn batch_forget(&self, ctx: Context, requests: Vec<(Self::Inode, u64)>) {
463        for (inode, count) in requests {
464            self.forget(ctx, inode, count)
465        }
466    }
467
468    /// Get attributes for a file / directory.
469    ///
470    /// If `handle` is not `None`, then it contains the handle previously returned by the
471    /// implementation after a call to `open` or `opendir`. However, implementations should still
472    /// take care to verify the handle if they do not trust the client (e.g., virtio-fs).
473    ///
474    /// If writeback caching is enabled (`FsOptions::WRITEBACK_CACHE`), then the kernel module
475    /// likely has a better idea of the length of the file than the file system (for
476    /// example, if there was a write that extended the size of the file but has not yet been
477    /// flushed). In this case, the `st_size` field of the returned struct is ignored.
478    ///
479    /// The returned `Duration` indicates how long the returned attributes should be considered
480    /// valid by the client. If the attributes are only changed via the FUSE kernel module (i.e.,
481    /// the kernel module has exclusive access), then this should be a very large value.
482    fn getattr(
483        &self,
484        ctx: Context,
485        inode: Self::Inode,
486        handle: Option<Self::Handle>,
487    ) -> io::Result<(libc::stat64, Duration)> {
488        Err(io::Error::from_raw_os_error(libc::ENOSYS))
489    }
490
491    /// Set attributes for a file / directory.
492    ///
493    /// If `handle` is not `None`, then it contains the handle previously returned by the
494    /// implementation after a call to `open` or `opendir`. However, implementations should still
495    /// take care to verify the handle if they do not trust the client (e.g., virtio-fs).
496    ///
497    /// The `valid` parameter indicates the fields of `attr` that may be considered valid and should
498    /// be set by the file system. The content of all other fields in `attr` is undefined.
499    ///
500    /// If the `FsOptions::HANDLE_KILLPRIV` was set during `init`, then the implementation is
501    /// expected to reset the setuid and setgid bits if the file size or owner is being changed.
502    ///
503    /// This method returns the new attributes after making the modifications requested by the
504    /// client. The returned `Duration` indicates how long the returned attributes should be
505    /// considered valid by the client. If the attributes are only changed via the FUSE kernel
506    /// module (i.e., the kernel module has exclusive access), then this should be a very large
507    /// value.
508    fn setattr(
509        &self,
510        ctx: Context,
511        inode: Self::Inode,
512        attr: libc::stat64,
513        handle: Option<Self::Handle>,
514        valid: SetattrValid,
515    ) -> io::Result<(libc::stat64, Duration)> {
516        Err(io::Error::from_raw_os_error(libc::ENOSYS))
517    }
518
519    /// Read a symbolic link.
520    fn readlink(&self, ctx: Context, inode: Self::Inode) -> io::Result<Vec<u8>> {
521        Err(io::Error::from_raw_os_error(libc::ENOSYS))
522    }
523
524    /// Create a symbolic link.
525    ///
526    /// The file system must create a symbolic link named `name` in the directory represented by
527    /// `parent`, which contains the string `linkname`. Returns an `Entry` for the newly created
528    /// symlink.
529    ///
530    /// If this call is successful then the lookup count of the `Inode` associated with the returned
531    /// `Entry` must be increased by 1.
532    fn symlink(
533        &self,
534        ctx: Context,
535        linkname: &CStr,
536        parent: Self::Inode,
537        name: &CStr,
538        security_ctx: Option<&CStr>,
539    ) -> io::Result<Entry> {
540        Err(io::Error::from_raw_os_error(libc::ENOSYS))
541    }
542
543    /// Create a file node.
544    ///
545    /// Create a regular file, character device, block device, fifo, or socket node named `name` in
546    /// the directory represented by `inode`. Valid values for `mode` and `rdev` are the same as
547    /// those accepted by the `mknod(2)` system call. Returns an `Entry` for the newly created node.
548    ///
549    /// When the `FsOptions::DONT_MASK` feature is set, the file system is responsible for setting
550    /// the permissions of the created node to `mode & !umask`.
551    ///
552    /// If this call is successful then the lookup count of the `Inode` associated with the returned
553    /// `Entry` must be increased by 1.
554    fn mknod(
555        &self,
556        ctx: Context,
557        inode: Self::Inode,
558        name: &CStr,
559        mode: u32,
560        rdev: u32,
561        umask: u32,
562        security_ctx: Option<&CStr>,
563    ) -> io::Result<Entry> {
564        Err(io::Error::from_raw_os_error(libc::ENOSYS))
565    }
566
567    /// Create a directory.
568    ///
569    /// When the `FsOptions::DONT_MASK` feature is set, the file system is responsible for setting
570    /// the permissions of the created directory to `mode & !umask`. Returns an `Entry` for the
571    /// newly created directory.
572    ///
573    /// If this call is successful then the lookup count of the `Inode` associated with the returned
574    /// `Entry` must be increased by 1.
575    fn mkdir(
576        &self,
577        ctx: Context,
578        parent: Self::Inode,
579        name: &CStr,
580        mode: u32,
581        umask: u32,
582        security_ctx: Option<&CStr>,
583    ) -> io::Result<Entry> {
584        Err(io::Error::from_raw_os_error(libc::ENOSYS))
585    }
586
587    /// Create an unnamed temporary file.
588    fn chromeos_tmpfile(
589        &self,
590        ctx: Context,
591        parent: Self::Inode,
592        mode: u32,
593        umask: u32,
594        security_ctx: Option<&CStr>,
595    ) -> io::Result<Entry> {
596        Err(io::Error::from_raw_os_error(libc::ENOSYS))
597    }
598
599    /// Remove a file.
600    ///
601    /// If the file's inode lookup count is non-zero, then the file system is expected to delay
602    /// removal of the inode until the lookup count goes to zero. See the documentation of the
603    /// `forget` function for more information.
604    fn unlink(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()> {
605        Err(io::Error::from_raw_os_error(libc::ENOSYS))
606    }
607
608    /// Remove a directory.
609    ///
610    /// If the directory's inode lookup count is non-zero, then the file system is expected to delay
611    /// removal of the inode until the lookup count goes to zero. See the documentation of the
612    /// `forget` function for more information.
613    fn rmdir(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()> {
614        Err(io::Error::from_raw_os_error(libc::ENOSYS))
615    }
616
617    /// Rename a file / directory.
618    ///
619    /// If the destination exists, it should be atomically replaced. If the destination's inode
620    /// lookup count is non-zero, then the file system is expected to delay removal of the inode
621    /// until the lookup count goes to zero. See the documentation of the `forget` function for more
622    /// information.
623    ///
624    /// `flags` may be `libc::RENAME_EXCHANGE` or `libc::RENAME_NOREPLACE`. If
625    /// `libc::RENAME_NOREPLACE` is specified, the implementation must not overwrite `newname` if it
626    /// exists and must return an error instead. If `libc::RENAME_EXCHANGE` is specified, the
627    /// implementation must atomically exchange the two files, i.e., both must exist and neither may
628    /// be deleted.
629    fn rename(
630        &self,
631        ctx: Context,
632        olddir: Self::Inode,
633        oldname: &CStr,
634        newdir: Self::Inode,
635        newname: &CStr,
636        flags: u32,
637    ) -> io::Result<()> {
638        Err(io::Error::from_raw_os_error(libc::ENOSYS))
639    }
640
641    /// Create a hard link.
642    ///
643    /// Create a hard link from `inode` to `newname` in the directory represented by `newparent`.
644    ///
645    /// If this call is successful then the lookup count of the `Inode` associated with the returned
646    /// `Entry` must be increased by 1.
647    fn link(
648        &self,
649        ctx: Context,
650        inode: Self::Inode,
651        newparent: Self::Inode,
652        newname: &CStr,
653    ) -> io::Result<Entry> {
654        Err(io::Error::from_raw_os_error(libc::ENOSYS))
655    }
656
657    /// Open a file.
658    ///
659    /// Open the file associated with `inode` for reading / writing. All values accepted by the
660    /// `open(2)` system call are valid values for `flags` and must be handled by the file system.
661    /// However, there are some additional rules:
662    ///
663    /// * Creation flags (`libc::O_CREAT`, `libc::O_EXCL`, `libc::O_NOCTTY`) will be filtered out
664    ///   and handled by the kernel.
665    ///
666    /// * The file system should check the access modes (`libc::O_RDONLY`, `libc::O_WRONLY`,
667    ///   `libc::O_RDWR`) to determine if the operation is permitted. If the file system was mounted
668    ///   with the `-o default_permissions` mount option, then this check will also be carried out
669    ///   by the kernel before sending the open request.
670    ///
671    /// * When writeback caching is enabled (`FsOptions::WRITEBACK_CACHE`) the kernel may send read
672    ///   requests even for files opened with `libc::O_WRONLY`. The file system should be prepared
673    ///   to handle this.
674    ///
675    /// * When writeback caching is enabled, the kernel will handle the `libc::O_APPEND` flag.
676    ///   However, this will not work reliably unless the kernel has exclusive access to the file.
677    ///   In this case the file system may either ignore the `libc::O_APPEND` flag or return an
678    ///   error to indicate that reliable `libc::O_APPEND` handling is not available.
679    ///
680    /// * When writeback caching is disabled, the file system is expected to properly handle
681    ///   `libc::O_APPEND` and ensure that each write is appended to the end of the file.
682    ///
683    /// The file system may choose to return a `Handle` to refer to the newly opened file. The
684    /// kernel will then use this `Handle` for all operations on the content of the file (`read`,
685    /// `write`, `flush`, `release`, `fsync`). If the file system does not return a
686    /// `Handle` then the kernel will use the `Inode` for the file to operate on its contents. In
687    /// this case the file system may wish to enable the `FsOptions::ZERO_MESSAGE_OPEN` feature if
688    /// it is supported by the kernel (see below).
689    ///
690    /// The returned `OpenOptions` allow the file system to change the way the opened file is
691    /// handled by the kernel. See the documentation of `OpenOptions` for more information.
692    ///
693    /// If the `FsOptions::ZERO_MESSAGE_OPEN` feature is enabled by both the file system
694    /// implementation and the kernel, then the file system may return an error of `ENOSYS`. This
695    /// will be interpreted by the kernel as success and future calls to `open` and `release` will
696    /// be handled by the kernel without being passed on to the file system.
697    fn open(
698        &self,
699        ctx: Context,
700        inode: Self::Inode,
701        flags: u32,
702    ) -> io::Result<(Option<Self::Handle>, OpenOptions)> {
703        // Matches the behavior of libfuse.
704        Ok((None, OpenOptions::empty()))
705    }
706
707    /// Create and open a file.
708    ///
709    /// If the file does not already exist, the file system should create it with the specified
710    /// `mode`. When the `FsOptions::DONT_MASK` feature is set, the file system is responsible for
711    /// setting the permissions of the created file to `mode & !umask`.
712    ///
713    /// If the file system returns an `ENOSYS` error, then the kernel will treat this method as
714    /// unimplemented and all future calls to `create` will be handled by calling the `mknod` and
715    /// `open` methods instead.
716    ///
717    /// See the documentation for the `open` method for more information about opening the file. In
718    /// addition to the optional `Handle` and the `OpenOptions`, the file system must also return an
719    /// `Entry` for the file. This increases the lookup count for the `Inode` associated with the
720    /// file by 1.
721    fn create(
722        &self,
723        ctx: Context,
724        parent: Self::Inode,
725        name: &CStr,
726        mode: u32,
727        flags: u32,
728        umask: u32,
729        security_ctx: Option<&CStr>,
730    ) -> io::Result<(Entry, Option<Self::Handle>, OpenOptions)> {
731        Err(io::Error::from_raw_os_error(libc::ENOSYS))
732    }
733
734    /// Read data from a file.
735    ///
736    /// Returns `size` bytes of data starting from offset `off` from the file associated with
737    /// `inode` or `handle`.
738    ///
739    /// `flags` contains the flags used to open the file. Similarly, `handle` is the `Handle`
740    /// returned by the file system from the `open` method, if any. If the file system
741    /// implementation did not return a `Handle` from `open` then the contents of `handle` are
742    /// undefined.
743    ///
744    /// This method should return exactly the number of bytes requested by the kernel, except in the
745    /// case of error or EOF. Otherwise, the kernel will substitute the rest of the data with
746    /// zeroes. An exception to this rule is if the file was opened with the "direct I/O" option
747    /// (`libc::O_DIRECT`), in which case the kernel will forward the return code from this method
748    /// to the userspace application that made the system call.
749    fn read<W: io::Write + ZeroCopyWriter>(
750        &self,
751        ctx: Context,
752        inode: Self::Inode,
753        handle: Self::Handle,
754        w: W,
755        size: u32,
756        offset: u64,
757        lock_owner: Option<u64>,
758        flags: u32,
759    ) -> io::Result<usize> {
760        Err(io::Error::from_raw_os_error(libc::ENOSYS))
761    }
762
763    /// Write data to a file.
764    ///
765    /// Writes `size` bytes of data starting from offset `off` to the file associated with `inode`
766    /// or `handle`.
767    ///
768    /// `flags` contains the flags used to open the file. Similarly, `handle` is the `Handle`
769    /// returned by the file system from the `open` method, if any. If the file system
770    /// implementation did not return a `Handle` from `open` then the contents of `handle` are
771    /// undefined.
772    ///
773    /// If the `FsOptions::HANDLE_KILLPRIV` feature is not enabled then then the file system is
774    /// expected to clear the setuid and setgid bits.
775    ///
776    /// If `delayed_write` is true then it indicates that this is a write for buffered data.
777    ///
778    /// This method should return exactly the number of bytes requested by the kernel, except in the
779    /// case of error. An exception to this rule is if the file was opened with the "direct I/O"
780    /// option (`libc::O_DIRECT`), in which case the kernel will forward the return code from this
781    /// method to the userspace application that made the system call.
782    fn write<R: io::Read + ZeroCopyReader>(
783        &self,
784        ctx: Context,
785        inode: Self::Inode,
786        handle: Self::Handle,
787        r: R,
788        size: u32,
789        offset: u64,
790        lock_owner: Option<u64>,
791        delayed_write: bool,
792        flags: u32,
793    ) -> io::Result<usize> {
794        Err(io::Error::from_raw_os_error(libc::ENOSYS))
795    }
796
797    /// Flush the contents of a file.
798    ///
799    /// This method is called on every `close()` of a file descriptor. Since it is possible to
800    /// duplicate file descriptors there may be many `flush` calls for one call to `open`.
801    ///
802    /// File systems should not make any assumptions about when `flush` will be
803    /// called or even if it will be called at all.
804    ///
805    /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the
806    /// file system did not return a `Handle` from `open` then the contents of `handle` are
807    /// undefined.
808    ///
809    /// Unlike `fsync`, the file system is not required to flush pending writes. One reason to flush
810    /// data is if the file system wants to return write errors during close. However, this is not
811    /// portable because POSIX does not require `close` to wait for delayed I/O to complete.
812    ///
813    /// If the `FsOptions::POSIX_LOCKS` feature is enabled, then the file system must remove all
814    /// locks belonging to `lock_owner`.
815    ///
816    /// If this method returns an `ENOSYS` error then the kernel will treat it as success and all
817    /// subsequent calls to `flush` will be handled by the kernel without being forwarded to the
818    /// file system.
819    fn flush(
820        &self,
821        ctx: Context,
822        inode: Self::Inode,
823        handle: Self::Handle,
824        lock_owner: u64,
825    ) -> io::Result<()> {
826        Err(io::Error::from_raw_os_error(libc::ENOSYS))
827    }
828
829    /// Synchronize file contents.
830    ///
831    /// File systems must ensure that the file contents have been flushed to disk before returning
832    /// from this method. If `datasync` is true then only the file data (but not the metadata) needs
833    /// to be flushed.
834    ///
835    /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the
836    /// file system did not return a `Handle` from `open` then the contents of
837    /// `handle` are undefined.
838    ///
839    /// If this method returns an `ENOSYS` error then the kernel will treat it as success and all
840    /// subsequent calls to `fsync` will be handled by the kernel without being forwarded to the
841    /// file system.
842    fn fsync(
843        &self,
844        ctx: Context,
845        inode: Self::Inode,
846        datasync: bool,
847        handle: Self::Handle,
848    ) -> io::Result<()> {
849        Err(io::Error::from_raw_os_error(libc::ENOSYS))
850    }
851
852    /// Allocate requested space for file data.
853    ///
854    /// If this function returns success, then the file sytem must guarantee that it is possible to
855    /// write up to `length` bytes of data starting at `offset` without failing due to a lack of
856    /// free space on the disk.
857    ///
858    /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the
859    /// file system did not return a `Handle` from `open` then the contents of `handle` are
860    /// undefined.
861    ///
862    /// If this method returns an `ENOSYS` error then the kernel will treat that as a permanent
863    /// failure: all future calls to `fallocate` will fail with `EOPNOTSUPP` without being forwarded
864    /// to the file system.
865    fn fallocate(
866        &self,
867        ctx: Context,
868        inode: Self::Inode,
869        handle: Self::Handle,
870        mode: u32,
871        offset: u64,
872        length: u64,
873    ) -> io::Result<()> {
874        Err(io::Error::from_raw_os_error(libc::ENOSYS))
875    }
876
877    /// Release an open file.
878    ///
879    /// This method is called when there are no more references to an open file: all file
880    /// descriptors are closed and all memory mappings are unmapped.
881    ///
882    /// For every `open` call there will be exactly one `release` call (unless the file system is
883    /// force-unmounted).
884    ///
885    /// The file system may reply with an error, but error values are not returned to the `close()`
886    /// or `munmap()` which triggered the release.
887    ///
888    /// `handle` is the `Handle` returned by the file system from the `open` method, if any. If the
889    /// file system did not return a `Handle` from `open` then the contents of
890    /// `handle` are undefined.
891    ///
892    /// If `flush` is `true` then the contents of the file should also be flushed to disk.
893    fn release(
894        &self,
895        ctx: Context,
896        inode: Self::Inode,
897        flags: u32,
898        handle: Self::Handle,
899        flush: bool,
900        flock_release: bool,
901        lock_owner: Option<u64>,
902    ) -> io::Result<()> {
903        Err(io::Error::from_raw_os_error(libc::ENOSYS))
904    }
905
906    /// Get information about the file system.
907    fn statfs(&self, ctx: Context, inode: Self::Inode) -> io::Result<libc::statvfs64> {
908        // SAFETY: zero-initializing a struct with only POD fields.
909        let mut st: libc::statvfs64 = unsafe { mem::zeroed() };
910
911        // This matches the behavior of libfuse as it returns these values if the
912        // filesystem doesn't implement this method.
913        st.f_namemax = 255;
914        st.f_bsize = 512;
915
916        Ok(st)
917    }
918
919    /// Set an extended attribute.
920    ///
921    /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent
922    /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `setxattr` without
923    /// forwarding them to the file system.
924    ///
925    /// Valid values for flags are the same as those accepted by the `setxattr(2)` system call and
926    /// have the same behavior.
927    fn setxattr(
928        &self,
929        ctx: Context,
930        inode: Self::Inode,
931        name: &CStr,
932        value: &[u8],
933        flags: u32,
934    ) -> io::Result<()> {
935        Err(io::Error::from_raw_os_error(libc::ENOSYS))
936    }
937
938    /// Get an extended attribute.
939    ///
940    /// If `size` is 0, then the file system should respond with `GetxattrReply::Count` and the
941    /// number of bytes needed to hold the value. If `size` is large enough to hold the value, then
942    /// the file system should reply with `GetxattrReply::Value` and the value of the extended
943    /// attribute. If `size` is not 0 but is also not large enough to hold the value, then the file
944    /// system should reply with an `ERANGE` error.
945    ///
946    /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent
947    /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `getxattr` without
948    /// forwarding them to the file system.
949    fn getxattr(
950        &self,
951        ctx: Context,
952        inode: Self::Inode,
953        name: &CStr,
954        size: u32,
955    ) -> io::Result<GetxattrReply> {
956        Err(io::Error::from_raw_os_error(libc::ENOSYS))
957    }
958
959    /// List extended attribute names.
960    ///
961    /// If `size` is 0, then the file system should respond with `ListxattrReply::Count` and the
962    /// number of bytes needed to hold a `\0` byte separated list of the names of all the extended
963    /// attributes. If `size` is large enough to hold the `\0` byte separated list of the attribute
964    /// names, then the file system should reply with `ListxattrReply::Names` and the list. If
965    /// `size` is not 0 but is also not large enough to hold the list, then the file system should
966    /// reply with an `ERANGE` error.
967    ///
968    /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent
969    /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `listxattr` without
970    /// forwarding them to the file system.
971    fn listxattr(&self, ctx: Context, inode: Self::Inode, size: u32) -> io::Result<ListxattrReply> {
972        Err(io::Error::from_raw_os_error(libc::ENOSYS))
973    }
974
975    /// Remove an extended attribute.
976    ///
977    /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent
978    /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `removexattr` without
979    /// forwarding them to the file system.
980    fn removexattr(&self, ctx: Context, inode: Self::Inode, name: &CStr) -> io::Result<()> {
981        Err(io::Error::from_raw_os_error(libc::ENOSYS))
982    }
983
984    /// Open a directory for reading.
985    ///
986    /// The file system may choose to return a `Handle` to refer to the newly opened directory. The
987    /// kernel will then use this `Handle` for all operations on the content of the directory
988    /// (`readdir`, `readdirplus`, `fsyncdir`, `releasedir`). If the file system does not return a
989    /// `Handle` then the kernel will use the `Inode` for the directory to operate on its contents.
990    /// In this case the file system may wish to enable the `FsOptions::ZERO_MESSAGE_OPENDIR`
991    /// feature if it is supported by the kernel (see below).
992    ///
993    /// The returned `OpenOptions` allow the file system to change the way the opened directory is
994    /// handled by the kernel. See the documentation of `OpenOptions` for more information.
995    ///
996    /// If the `FsOptions::ZERO_MESSAGE_OPENDIR` feature is enabled by both the file system
997    /// implementation and the kernel, then the file system may return an error of `ENOSYS`. This
998    /// will be interpreted by the kernel as success and future calls to `opendir` and `releasedir`
999    /// will be handled by the kernel without being passed on to the file system.
1000    fn opendir(
1001        &self,
1002        ctx: Context,
1003        inode: Self::Inode,
1004        flags: u32,
1005    ) -> io::Result<(Option<Self::Handle>, OpenOptions)> {
1006        // Matches the behavior of libfuse.
1007        Ok((None, OpenOptions::empty()))
1008    }
1009
1010    /// Read a directory.
1011    ///
1012    /// `handle` is the `Handle` returned by the file system from the `opendir` method, if any. If
1013    /// the file system did not return a `Handle` from `opendir` then the contents of `handle` are
1014    /// undefined.
1015    ///
1016    /// `size` indicates the maximum number of bytes that should be returned by this method.
1017    ///
1018    /// If `offset` is non-zero then it corresponds to one of the `offset` values from a `DirEntry`
1019    /// that was previously returned by a call to `readdir` for the same handle. In this case the
1020    /// file system should skip over the entries before the position defined by the `offset` value.
1021    /// If entries were added or removed while the `Handle` is open then the file system may still
1022    /// include removed entries or skip newly created entries. However, adding or removing entries
1023    /// should never cause the file system to skip over unrelated entries or include an entry more
1024    /// than once. This means that `offset` cannot be a simple index and must include sufficient
1025    /// information to uniquely determine the next entry in the list even when the set of entries is
1026    /// being changed.
1027    ///
1028    /// The file system may return entries for the current directory (".") and parent directory
1029    /// ("..") but is not required to do so. If the file system does not return these entries, then
1030    /// they are implicitly added by the kernel.
1031    ///
1032    /// The lookup count for `Inode`s associated with the returned directory entries is **NOT**
1033    /// affected by this method.
1034    fn readdir(
1035        &self,
1036        ctx: Context,
1037        inode: Self::Inode,
1038        handle: Self::Handle,
1039        size: u32,
1040        offset: u64,
1041    ) -> io::Result<Self::DirIter> {
1042        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1043    }
1044
1045    /// Synchronize the contents of a directory.
1046    ///
1047    /// File systems must ensure that the directory contents have been flushed to disk before
1048    /// returning from this method. If `datasync` is true then only the directory data (but not the
1049    /// metadata) needs to be flushed.
1050    ///
1051    /// `handle` is the `Handle` returned by the file system from the `opendir` method, if any. If
1052    /// the file system did not return a `Handle` from `opendir` then the contents of
1053    /// `handle` are undefined.
1054    ///
1055    /// If this method returns an `ENOSYS` error then the kernel will treat it as success and all
1056    /// subsequent calls to `fsyncdir` will be handled by the kernel without being forwarded to the
1057    /// file system.
1058    fn fsyncdir(
1059        &self,
1060        ctx: Context,
1061        inode: Self::Inode,
1062        datasync: bool,
1063        handle: Self::Handle,
1064    ) -> io::Result<()> {
1065        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1066    }
1067
1068    /// Release an open directory.
1069    ///
1070    /// For every `opendir` call there will be exactly one `releasedir` call (unless the file system
1071    /// is force-unmounted).
1072    ///
1073    /// `handle` is the `Handle` returned by the file system from the `opendir` method, if any. If
1074    /// the file system did not return a `Handle` from `opendir` then the contents of `handle` are
1075    /// undefined.
1076    ///
1077    /// `flags` contains used the flags used to open the directory in `opendir`.
1078    fn releasedir(
1079        &self,
1080        ctx: Context,
1081        inode: Self::Inode,
1082        flags: u32,
1083        handle: Self::Handle,
1084    ) -> io::Result<()> {
1085        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1086    }
1087
1088    /// Check file access permissions.
1089    ///
1090    /// This method is called when a userspace process in the client makes an `access()` or
1091    /// `chdir()` system call. If the file system was mounted with the `-o default_permissions`
1092    /// mount option, then the kernel will perform these checks itself and this method will not be
1093    /// called.
1094    ///
1095    /// If this method returns an `ENOSYS` error, then the kernel will treat it as a permanent
1096    /// success: all future calls to `access` will return success without being forwarded to the
1097    /// file system.
1098    fn access(&self, ctx: Context, inode: Self::Inode, mask: u32) -> io::Result<()> {
1099        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1100    }
1101
1102    /// Perform an ioctl on a file or directory.
1103    ///
1104    /// `handle` is the `Handle` returned by the file system from the `open` or `opendir` methods,
1105    /// if any. If the file system did not return a `Handle` from then the contents of `handle` are
1106    /// undefined.
1107    ///
1108    /// If `flags` contains `IoctlFlags::UNRESTRICTED` then the file system may retry the ioctl
1109    /// after informing the kernel about the input and output areas. If `flags` does not contain
1110    /// `IoctlFlags::UNRESTRICTED` then the kernel will prepare the input and output areas according
1111    /// to the encoding in the ioctl command. In that case the ioctl cannot be retried.
1112    ///
1113    /// `cmd` is the ioctl request made by the calling process, truncated to 32 bits.
1114    ///
1115    /// `arg` is the argument provided by the calling process.
1116    ///
1117    /// `in_size` is the length of the additional data that accompanies the request. The file system
1118    /// may fetch this data from `reader`.
1119    ///
1120    /// `out_size` is the length of the output area prepared by the kernel to hold the response to
1121    /// the ioctl.
1122    fn ioctl<R: io::Read>(
1123        &self,
1124        ctx: Context,
1125        inode: Self::Inode,
1126        handle: Self::Handle,
1127        flags: IoctlFlags,
1128        cmd: u32,
1129        arg: u64,
1130        in_size: u32,
1131        out_size: u32,
1132        reader: R,
1133    ) -> io::Result<IoctlReply> {
1134        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1135    }
1136
1137    /// TODO: support this
1138    fn getlk(&self) -> io::Result<()> {
1139        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1140    }
1141
1142    /// TODO: support this
1143    fn setlk(&self) -> io::Result<()> {
1144        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1145    }
1146
1147    /// TODO: support this
1148    fn setlkw(&self) -> io::Result<()> {
1149        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1150    }
1151
1152    /// TODO: support this
1153    fn bmap(&self) -> io::Result<()> {
1154        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1155    }
1156
1157    /// TODO: support this
1158    fn poll(&self) -> io::Result<()> {
1159        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1160    }
1161
1162    /// TODO: support this
1163    fn notify_reply(&self) -> io::Result<()> {
1164        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1165    }
1166
1167    /// TODO: support this
1168    fn lseek(&self) -> io::Result<()> {
1169        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1170    }
1171
1172    /// Copy a range of data from one file to another
1173    ///
1174    /// Performs an optimized copy between two file descriptors without the additional cost of
1175    /// transferring data through the kernel module to user space (glibc) and then back into
1176    /// the file system again.
1177    ///
1178    /// In case this method is not implemented, glibc falls back to reading data from the source and
1179    /// writing to the destination.
1180    ///
1181    /// If this method fails with an `ENOSYS` error, then the kernel will treat that as a permanent
1182    /// failure. The kernel will return `EOPNOTSUPP` for all future calls to `copy_file_range`
1183    /// without forwarding them to the file system.
1184    ///
1185    /// All values accepted by the `copy_file_range(2)` system call are valid values for `flags` and
1186    /// must be handled by the file system.
1187    fn copy_file_range(
1188        &self,
1189        ctx: Context,
1190        inode_src: Self::Inode,
1191        handle_src: Self::Handle,
1192        offset_src: u64,
1193        inode_dst: Self::Inode,
1194        handle_dst: Self::Handle,
1195        offset_dst: u64,
1196        length: u64,
1197        flags: u64,
1198    ) -> io::Result<usize> {
1199        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1200    }
1201
1202    /// Set up memory mappings.
1203    ///
1204    /// Used to set up file mappings in DAX window.
1205    ///
1206    /// # Arguments
1207    ///
1208    /// * `file_offset` - Offset into the file to start the mapping.
1209    /// * `mem_offset` - Offset in Memory Window.
1210    /// * `size` - Length of mapping required.
1211    /// * `flags` - Bit field of `FUSE_SETUPMAPPING_FLAGS_*`.
1212    /// * `mapper` - Mapper object which performs the mapping.
1213    fn set_up_mapping<M: Mapper>(
1214        &self,
1215        ctx: Context,
1216        inode: Self::Inode,
1217        handle: Self::Handle,
1218        file_offset: u64,
1219        mem_offset: u64,
1220        size: usize,
1221        flags: u32,
1222        mapper: M,
1223    ) -> io::Result<()> {
1224        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1225    }
1226
1227    /// Remove memory mappings.
1228    ///
1229    /// Used to tear down file mappings in DAX window. This method must be supported when
1230    /// `set_up_mapping` is supported.
1231    fn remove_mapping<M: Mapper>(&self, msgs: &[RemoveMappingOne], mapper: M) -> io::Result<()> {
1232        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1233    }
1234
1235    /// Lookup and open/create the file
1236    ///
1237    /// In this call, program first do a lookup on the file. Then depending upon
1238    /// flags combination, either do create + open, open only or return error.
1239    /// In all successful cases, it will return the dentry. For return value's
1240    /// handle and open options atomic_open should apply same rules to handle
1241    /// flags and configuration in open/create system call.
1242    ///
1243    /// This function is called when the client supports FUSE_OPEN_ATOMIC.
1244    /// Implementing atomic_open is optional. When the it's not implemented,
1245    /// the client fall back to send lookup and open requests separately.
1246    ///
1247    ///  # Specification
1248    ///
1249    /// If file was indeed newly created (as a result of O_CREAT), then set
1250    /// `FOPEN_FILE_CREATED` bit in `struct OpenOptions open`. This bit is used by
1251    ///  crosvm to inform the fuse client to set `FILE_CREATED` bit in `struct
1252    /// fuse_file_info'.
1253    ///
1254    /// All flags applied to open/create should be handled samely in atomic open,
1255    /// only the following are exceptions:
1256    /// * The O_NOCTTY is filtered out by fuse client.
1257    /// * O_TRUNC is filtered out by VFS for O_CREAT, O_EXCL combination.
1258    ///
1259    /// # Implementation
1260    ///
1261    /// To implement this API, you need to handle the following cases:
1262    ///
1263    /// a) File does not exist
1264    ///  - O_CREAT:
1265    ///    - Create file with specified mode
1266    ///    - Set `FOPEN_FILE_CREATED` bit in `struct OpenOptions open`
1267    ///    - Open the file
1268    ///    - Return d_entry and file handler
1269    ///  - ~O_CREAT:
1270    ///    - ENOENT
1271    ///
1272    /// b) File exist already (exception is O_EXCL)
1273    ///    - O_CREAT:
1274    ///      - Open the file
1275    ///      - Return d_entry and file handler
1276    ///    - O_EXCL:
1277    ///      - EEXIST
1278    ///
1279    /// c) File is symbol link
1280    ///    - Return dentry and file handler
1281    fn atomic_open(
1282        &self,
1283        ctx: Context,
1284        parent: Self::Inode,
1285        name: &CStr,
1286        mode: u32,
1287        flags: u32,
1288        umask: u32,
1289        security_ctx: Option<&CStr>,
1290    ) -> io::Result<(Entry, Option<Self::Handle>, OpenOptions)> {
1291        Err(io::Error::from_raw_os_error(libc::ENOSYS))
1292    }
1293}