summaryrefslogtreecommitdiffstats
path: root/third_party/rust/nix/src/mount/linux.rs
blob: aa166bc9d35a79018921f96b8cfc5496c426cba7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use crate::errno::Errno;
use crate::{NixPath, Result};
use libc::{self, c_int, c_ulong};

libc_bitflags!(
    /// Used with [`mount`].
    pub struct MsFlags: c_ulong {
        /// Mount read-only
        MS_RDONLY;
        /// Ignore suid and sgid bits
        MS_NOSUID;
        /// Disallow access to device special files
        MS_NODEV;
        /// Disallow program execution
        MS_NOEXEC;
        /// Writes are synced at once
        MS_SYNCHRONOUS;
        /// Alter flags of a mounted FS
        MS_REMOUNT;
        /// Allow mandatory locks on a FS
        MS_MANDLOCK;
        /// Directory modifications are synchronous
        MS_DIRSYNC;
        /// Do not update access times
        MS_NOATIME;
        /// Do not update directory access times
        MS_NODIRATIME;
        /// Linux 2.4.0 - Bind directory at different place
        MS_BIND;
        /// Move an existing mount to a new location
        MS_MOVE;
        /// Used to create a recursive bind mount.
        MS_REC;
        /// Suppress the display of certain kernel warning messages.
        MS_SILENT;
        /// VFS does not apply the umask
        MS_POSIXACL;
        /// The resulting mount cannot subsequently be bind mounted.
        MS_UNBINDABLE;
        /// Make this mount point private.
        MS_PRIVATE;
        /// If this is a shared mount point that is a member of a peer group
        /// that  contains  other  members, convert it to a slave mount.
        MS_SLAVE;
        /// Make  this mount point shared.
        MS_SHARED;
        /// When a file on this filesystem is accessed,  update  the  file's
        /// last  access  time (atime) only if the current value of atime is
        /// less than or equal to the file's last modification time  (mtime) or
        /// last  status change time (ctime).
        MS_RELATIME;
        /// Mount request came from within the kernel
        #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
        MS_KERNMOUNT;
        /// Update inode I_version field
        MS_I_VERSION;
        /// Always  update  the  last access time (atime) when files on this
        /// filesystem are accessed.
        MS_STRICTATIME;
        /// Reduce on-disk updates of inode timestamps (atime, mtime, ctime) by
        /// maintaining these changes only in memory.
        MS_LAZYTIME;
        #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
        #[allow(missing_docs)]  // Not documented in Linux
        MS_ACTIVE;
        #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
        #[allow(missing_docs)]  // Not documented in Linux
        MS_NOUSER;
        #[allow(missing_docs)]  // Not documented in Linux; possibly kernel-only
        MS_RMT_MASK;
        #[allow(missing_docs)]  // Not documented in Linux; possibly kernel-only
        MS_MGC_VAL;
        #[allow(missing_docs)]  // Not documented in Linux; possibly kernel-only
        MS_MGC_MSK;
    }
);

libc_bitflags!(
    /// Used with [`umount2].
    pub struct MntFlags: c_int {
        /// Attempt to unmount even if still in use, aborting pending requests.
        MNT_FORCE;
        /// Lazy unmount.  Disconnect the file system immediately, but don't
        /// actually unmount it until it ceases to be busy.
        MNT_DETACH;
        /// Mark the mount point as expired.
        MNT_EXPIRE;
        /// Don't dereference `target` if it is a symlink.
        UMOUNT_NOFOLLOW;
    }
);

/// Mount a file system.
///
/// # Arguments
/// - `source`  -   Specifies the file system.  e.g. `/dev/sd0`.
/// - `target` -    Specifies the destination.  e.g. `/mnt`.
/// - `fstype` -    The file system type, e.g. `ext4`.
/// - `flags` -     Optional flags controlling the mount.
/// - `data` -      Optional file system specific data.
///
/// # See Also
/// [`mount`](https://man7.org/linux/man-pages/man2/mount.2.html)
pub fn mount<
    P1: ?Sized + NixPath,
    P2: ?Sized + NixPath,
    P3: ?Sized + NixPath,
    P4: ?Sized + NixPath,
>(
    source: Option<&P1>,
    target: &P2,
    fstype: Option<&P3>,
    flags: MsFlags,
    data: Option<&P4>,
) -> Result<()> {
    fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
    where
        P: ?Sized + NixPath,
        F: FnOnce(*const libc::c_char) -> T,
    {
        match p {
            Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
            None => Ok(f(std::ptr::null())),
        }
    }

    let res = with_opt_nix_path(source, |s| {
        target.with_nix_path(|t| {
            with_opt_nix_path(fstype, |ty| {
                with_opt_nix_path(data, |d| unsafe {
                    libc::mount(
                        s,
                        t.as_ptr(),
                        ty,
                        flags.bits(),
                        d as *const libc::c_void,
                    )
                })
            })
        })
    })????;

    Errno::result(res).map(drop)
}

/// Unmount the file system mounted at `target`.
pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
    let res =
        target.with_nix_path(|cstr| unsafe { libc::umount(cstr.as_ptr()) })?;

    Errno::result(res).map(drop)
}

/// Unmount the file system mounted at `target`.
///
/// See also [`umount`](https://man7.org/linux/man-pages/man2/umount.2.html)
pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
    let res = target.with_nix_path(|cstr| unsafe {
        libc::umount2(cstr.as_ptr(), flags.bits())
    })?;

    Errno::result(res).map(drop)
}