Skip to main content

fuser_ng/
lib.rs

1#![doc = include_str!("../DOC.md")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4// FuserNG -- A higher-level FUSE (Filesystem in Userspace) interface and wrapper around the
5// low-level `fuser`` library that makes implementing a filesystem a bit easier.
6//
7// FuserNG translates inodes to paths and simplifies some details of filesystem implementation,
8// for example: splitting the `setattr` call
9// into multiple separate operations, and simplifying the `readdir` call so that filesystems don't
10// need to deal with pagination.
11//
12// To implement a filesystem, implement the `Filesystem` trait. Not all functions in it need to
13// be implemented -- the default behavior is to return `ENOSYS` ("Function not implemented"). For
14// example, a read-only filesystem can skip implementing the `write` call and many others.
15
16//
17// Copyright (c) 2016-2022 by William R. Fraser, 2026 by François NT
18//
19
20#[macro_use]
21extern crate log;
22#[cfg(feature = "async")]
23mod r#async;
24mod directory_cache;
25mod fuserng;
26mod inode_table;
27mod types;
28#[cfg(feature = "async")]
29pub use r#async::{AsyncFilesystem, AsyncFuserNG};
30#[cfg(feature = "async")]
31pub use futures_core::Stream;
32/// Asynchronous counterparts to the main filesystem trait and adapter.
33#[cfg(feature = "async")]
34pub mod asynchronous {
35    pub use crate::AsyncFilesystem as Filesystem;
36    pub use crate::AsyncFuserNG as FuserNG;
37}
38pub use crate::fuserng::*;
39pub use crate::types::*;
40pub use fuser::FileType;
41pub use fuser::InitFlags;
42pub use fuser::KernelConfig;
43pub use fuser::MountOption;
44// Forward to similarly-named fuser functions to work around deprecation for now.
45// When these are removed, we'll have to either reimplement or break reverse compat.
46// Keep the doc comments in sync with those in fuser.
47
48use std::io;
49use std::path::Path;
50
51/// Number of fuser event-loop threads used to serve a mount.
52/// This configures fuser session threading, not an internal worker pool.
53#[derive(Debug, Default)]
54pub enum ThreadCount {
55    /// Use the current machine parallelism as reported by the standard library.
56    #[default]
57    Default,
58    /// Use an explicit number of fuser event-loop threads.
59    NumThreads(usize),
60}
61
62impl ThreadCount {
63    fn value(&self) -> usize {
64        match self {
65            Self::Default => std::thread::available_parallelism().unwrap().into(),
66            Self::NumThreads(num_threads) => *num_threads,
67        }
68    }
69}
70
71impl From<usize> for ThreadCount {
72    fn from(value: usize) -> Self {
73        ThreadCount::NumThreads(value)
74    }
75}
76/// Mount the given filesystem to the given mountpoint. This function will not return until the
77/// filesystem is unmounted.
78#[inline(always)]
79pub fn mount<FS: fuser::Filesystem, P: AsRef<Path>>(
80    fs: FS,
81    mountpoint: P,
82    options: &[MountOption],
83    num_threads: ThreadCount,
84) -> io::Result<()> {
85    let mut config = fuser::Config::default();
86    config.mount_options = options.to_vec();
87    let num_threads = num_threads.value();
88    if num_threads > 0 {
89        config.n_threads = Some(num_threads);
90    }
91    fuser::mount(fs, mountpoint, &config)
92}
93
94/// Mount the given filesystem to the given mountpoint. This function spawns a background thread to
95/// handle filesystem operations while being mounted and therefore returns immediately. The
96/// returned handle should be stored to reference the mounted filesystem. If it's dropped, the
97/// filesystem will be unmounted.
98#[inline(always)]
99pub fn spawn_mount<FS: fuser::Filesystem + Send + 'static, P: AsRef<Path>>(
100    fs: FS,
101    mountpoint: P,
102    options: &[MountOption],
103    num_threads: ThreadCount,
104) -> io::Result<fuser::BackgroundSession> {
105    let mut config = fuser::Config::default();
106    config.mount_options = options.to_vec();
107    let num_threads = num_threads.value();
108    if num_threads > 0 {
109        config.n_threads = Some(num_threads);
110    }
111    fuser::spawn_mount(fs, mountpoint, &config)
112}