Skip to main content

starnix_uapi/
mount_flags.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::uapi;
6use atomic_bitflags::atomic_bitflags;
7
8atomic_bitflags! {
9    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
10    pub struct MountFlags: u32 {
11        // per-mountpoint flags
12        const RDONLY = uapi::MS_RDONLY;
13        const NOEXEC = uapi::MS_NOEXEC;
14        const NOSUID = uapi::MS_NOSUID;
15        const NODEV = uapi::MS_NODEV;
16        const NOATIME = uapi::MS_NOATIME;
17        const NODIRATIME = uapi::MS_NODIRATIME;
18        const RELATIME = uapi::MS_RELATIME;
19        const STRICTATIME = uapi::MS_STRICTATIME;
20
21        // per-superblock flags
22        const SILENT = uapi::MS_SILENT;
23        const LAZYTIME = uapi::MS_LAZYTIME;
24        const SYNCHRONOUS = uapi::MS_SYNCHRONOUS;
25        const DIRSYNC = uapi::MS_DIRSYNC;
26        const MANDLOCK = uapi::MS_MANDLOCK;
27
28        // mount() control flags
29        const REMOUNT = uapi::MS_REMOUNT;
30        const BIND = uapi::MS_BIND;
31        const REC = uapi::MS_REC;
32        const DOWNSTREAM = uapi::MS_SLAVE;
33        const SHARED = uapi::MS_SHARED;
34        const PRIVATE = uapi::MS_PRIVATE;
35
36        /// Flags that change be changed with REMOUNT.
37        ///
38        /// MS_DIRSYNC and MS_SILENT cannot be changed with REMOUNT.
39        const CHANGEABLE_WITH_REMOUNT = MountpointFlags::all().bits() |
40            Self::MANDLOCK.bits() | Self::LAZYTIME.bits() | Self::SYNCHRONOUS.bits();
41    }
42}
43
44atomic_bitflags! {
45    /// Subset of `MountFlags` that allow the behaviours of different mountpoints to the same
46    /// underlying `FileSystem` to be independently configured.
47    /// Note that
48    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
49    pub struct MountpointFlags: u32 {
50        // Flags stored for each mountpoint to configure its behaviour.
51        const RDONLY = MountFlags::RDONLY.bits();
52        const NOEXEC = MountFlags::NOEXEC.bits();
53        const NOSUID = MountFlags::NOSUID.bits();
54        const NODEV = MountFlags::NODEV.bits();
55        const NOATIME = MountFlags::NOATIME.bits();
56        const NODIRATIME = MountFlags::NODIRATIME.bits();
57        const RELATIME = MountFlags::RELATIME.bits();
58
59        const STORED_ON_MOUNT = Self::RDONLY.bits() | Self::NOEXEC.bits() | Self::NOSUID.bits() |
60            Self::NODEV.bits() | Self::NOATIME.bits() | Self::NODIRATIME.bits() | Self::RELATIME.bits();
61
62        // Flags affecting the behaviour of a single operation on a mountpoint.
63        const STRICTATIME = MountFlags::STRICTATIME.bits();
64        const REC = MountFlags::REC.bits();
65    }
66}
67
68impl From<MountpointFlags> for MountFlags {
69    fn from(flags: MountpointFlags) -> Self {
70        // MountpointFlags is defined using only bits that are valid for MountFlags.
71        Self::from_bits_retain(flags.bits())
72    }
73}
74
75atomic_bitflags! {
76    /// Subset of `MountFlags` that affect `FileSystem` behaviour.
77    #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
78    pub struct FileSystemFlags: u32 {
79        const RDONLY = MountFlags::RDONLY.bits();
80        const DIRSYNC = MountFlags::DIRSYNC.bits();
81        const LAZYTIME = MountFlags::LAZYTIME.bits();
82        const MANDLOCK = MountFlags::MANDLOCK.bits();
83        const SILENT = MountFlags::SILENT.bits();
84        const SYNCHRONOUS = MountFlags::SYNCHRONOUS.bits();
85    }
86}
87
88impl From<FileSystemFlags> for MountFlags {
89    fn from(flags: FileSystemFlags) -> Self {
90        // FileSystemFlags is defined using only bits that are valid for MountFlags.
91        Self::from_bits_retain(flags.bits())
92    }
93}
94
95impl MountFlags {
96    pub fn mountpoint_flags(&self) -> MountpointFlags {
97        MountpointFlags::from_bits_truncate(self.bits())
98    }
99
100    pub fn file_system_flags(&self) -> FileSystemFlags {
101        FileSystemFlags::from_bits_truncate(self.bits())
102    }
103}
104
105impl std::fmt::Display for MountpointFlags {
106    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107        MountFlags::from(*self).fmt(f)
108    }
109}
110
111impl std::fmt::Display for FileSystemFlags {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        MountFlags::from(*self).fmt(f)
114    }
115}
116
117impl std::fmt::Display for MountFlags {
118    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119        write!(f, "{}", if self.contains(Self::RDONLY) { "ro" } else { "rw" })?;
120        if self.contains(Self::NOEXEC) {
121            write!(f, ",noexec")?;
122        }
123        if self.contains(Self::NOSUID) {
124            write!(f, ",nosuid")?;
125        }
126        if self.contains(Self::NODEV) {
127            write!(f, ",nodev")?
128        }
129        if self.contains(Self::NOATIME) {
130            write!(f, ",noatime")?;
131        }
132        if self.contains(Self::SILENT) {
133            write!(f, ",silent")?;
134        }
135        if self.contains(Self::BIND) {
136            write!(f, ",bind")?;
137        }
138        if self.contains(Self::LAZYTIME) {
139            write!(f, ",lazytime")?;
140        }
141        Ok(())
142    }
143}