damascus/os/linux/fuseoverlay/
opt.rs

1// Copyright 2025 Yato202010
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
8use std::{fmt::Display, str::FromStr};
9
10use crate::common::fs::MountOption;
11
12#[non_exhaustive]
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
14pub enum FuseOverlayFsOption {
15    /// Use separate fuse device fd for each thread
16    CloneFd,
17    /// The maximum number of idle worker threads allowed (default: -1)
18    MaxIdleThread(isize),
19    /// The maximum number of worker threads allowed (default: 10)
20    MaxThread(usize),
21    /// Allow access by all users
22    AllowOther,
23    /// Allow access by root
24    AllowRoot,
25    /// Every file and directory is owned by the root user (0:0).
26    SquashToRoot,
27    /// Every file and directory is owned by the specified uid.
28    /// It has higher precedence over squash_to_root.
29    SquashToUid(usize),
30    /// Every file and directory is owned by the specified gid.
31    /// It has higher precedence over squash_to_root.
32    SquashToGid(usize),
33    /// Set st_nlink to static value 1 for all directories
34    StaticNLink,
35    /// Disable ACL support in the FUSE file system
36    NoAcl,
37    // TODO : look into uidmapping and gidmapping
38}
39
40impl MountOption for FuseOverlayFsOption {
41    fn defaults() -> Vec<String> {
42        vec!["auto_unmount".to_string()]
43    }
44}
45
46impl From<FuseOverlayFsOption> for String {
47    fn from(val: FuseOverlayFsOption) -> Self {
48        val.to_string()
49    }
50}
51
52impl FromStr for FuseOverlayFsOption {
53    type Err = std::io::Error;
54
55    fn from_str(s: &str) -> Result<Self, Self::Err> {
56        if let Some((op, va)) = s.split_once('=') {
57            match op {
58                "max_idle_threads" => {
59                    if let Ok(u) = va.parse() {
60                        return Ok(Self::MaxIdleThread(u));
61                    }
62                }
63                "max_threads" => {
64                    if let Ok(u) = va.parse() {
65                        return Ok(Self::MaxThread(u));
66                    }
67                }
68                "squash_to_uid" => {
69                    if let Ok(u) = va.parse() {
70                        return Ok(Self::SquashToUid(u));
71                    }
72                }
73                "squash_to_gid" => {
74                    if let Ok(u) = va.parse() {
75                        return Ok(Self::SquashToGid(u));
76                    }
77                }
78                _ => {}
79            };
80        }
81
82        Ok(match s {
83            "allow_other" => Self::AllowOther,
84            "allow_root" => Self::AllowRoot,
85            "squash_to_root" => Self::SquashToRoot,
86            "static_nlink" => Self::StaticNLink,
87            "noacl" => Self::NoAcl,
88            "clone_fd" => Self::CloneFd,
89            _ => {
90                return Err(std::io::Error::new(
91                    std::io::ErrorKind::Unsupported,
92                    "Unsupported mount option",
93                ));
94            }
95        })
96    }
97}
98impl Display for FuseOverlayFsOption {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        write!(
101            f,
102            "{}",
103            match self {
104                FuseOverlayFsOption::CloneFd => "clone_fd".to_owned(),
105                FuseOverlayFsOption::MaxIdleThread(x) => format!("max_idle_threads={}", x),
106                FuseOverlayFsOption::MaxThread(x) => format!("max_threads={}", x),
107                FuseOverlayFsOption::AllowOther => "allow_other".to_owned(),
108                FuseOverlayFsOption::AllowRoot => "allow_root".to_owned(),
109                FuseOverlayFsOption::SquashToRoot => "squash_to_root".to_owned(),
110                FuseOverlayFsOption::SquashToUid(uid) => format!("squash_to_uid={}", uid),
111                FuseOverlayFsOption::SquashToGid(gid) => format!("squash_to_gid={}", gid),
112                FuseOverlayFsOption::StaticNLink => "static_nlink".to_owned(),
113                FuseOverlayFsOption::NoAcl => "noacl".to_owned(),
114            }
115        )
116    }
117}