1 use crate::errno::Errno;
2 use crate::{NixPath, Result};
3 use libc::{self, c_int, c_ulong};
4 
5 libc_bitflags!(
6     /// Used with [`mount`].
7     pub struct MsFlags: c_ulong {
8         /// Mount read-only
9         MS_RDONLY;
10         /// Ignore suid and sgid bits
11         MS_NOSUID;
12         /// Disallow access to device special files
13         MS_NODEV;
14         /// Disallow program execution
15         MS_NOEXEC;
16         /// Writes are synced at once
17         MS_SYNCHRONOUS;
18         /// Alter flags of a mounted FS
19         MS_REMOUNT;
20         /// Allow mandatory locks on a FS
21         MS_MANDLOCK;
22         /// Directory modifications are synchronous
23         MS_DIRSYNC;
24         /// Do not update access times
25         MS_NOATIME;
26         /// Do not update directory access times
27         MS_NODIRATIME;
28         /// Linux 2.4.0 - Bind directory at different place
29         MS_BIND;
30         /// Move an existing mount to a new location
31         MS_MOVE;
32         /// Used to create a recursive bind mount.
33         MS_REC;
34         /// Suppress the display of certain kernel warning messages.
35         MS_SILENT;
36         /// VFS does not apply the umask
37         MS_POSIXACL;
38         /// The resulting mount cannot subsequently be bind mounted.
39         MS_UNBINDABLE;
40         /// Make this mount point private.
41         MS_PRIVATE;
42         /// If this is a shared mount point that is a member of a peer group
43         /// that  contains  other  members, convert it to a slave mount.
44         MS_SLAVE;
45         /// Make  this mount point shared.
46         MS_SHARED;
47         /// When a file on this filesystem is accessed,  update  the  file's
48         /// last  access  time (atime) only if the current value of atime is
49         /// less than or equal to the file's last modification time  (mtime) or
50         /// last  status change time (ctime).
51         MS_RELATIME;
52         /// Mount request came from within the kernel
53         #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
54         MS_KERNMOUNT;
55         /// Update inode I_version field
56         MS_I_VERSION;
57         /// Always  update  the  last access time (atime) when files on this
58         /// filesystem are accessed.
59         MS_STRICTATIME;
60         /// Reduce on-disk updates of inode timestamps (atime, mtime, ctime) by
61         /// maintaining these changes only in memory.
62         MS_LAZYTIME;
63         #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
64         #[allow(missing_docs)]  // Not documented in Linux
65         MS_ACTIVE;
66         #[deprecated(since = "0.27.0", note = "Should only be used in-kernel")]
67         #[allow(missing_docs)]  // Not documented in Linux
68         MS_NOUSER;
69         #[allow(missing_docs)]  // Not documented in Linux; possibly kernel-only
70         MS_RMT_MASK;
71         #[allow(missing_docs)]  // Not documented in Linux; possibly kernel-only
72         MS_MGC_VAL;
73         #[allow(missing_docs)]  // Not documented in Linux; possibly kernel-only
74         MS_MGC_MSK;
75     }
76 );
77 
78 libc_bitflags!(
79     /// Used with [`umount2].
80     pub struct MntFlags: c_int {
81         /// Attempt to unmount even if still in use, aborting pending requests.
82         MNT_FORCE;
83         /// Lazy unmount.  Disconnect the file system immediately, but don't
84         /// actually unmount it until it ceases to be busy.
85         MNT_DETACH;
86         /// Mark the mount point as expired.
87         MNT_EXPIRE;
88         /// Don't dereference `target` if it is a symlink.
89         UMOUNT_NOFOLLOW;
90     }
91 );
92 
93 /// Mount a file system.
94 ///
95 /// # Arguments
96 /// - `source`  -   Specifies the file system.  e.g. `/dev/sd0`.
97 /// - `target` -    Specifies the destination.  e.g. `/mnt`.
98 /// - `fstype` -    The file system type, e.g. `ext4`.
99 /// - `flags` -     Optional flags controlling the mount.
100 /// - `data` -      Optional file system specific data.
101 ///
102 /// # See Also
103 /// [`mount`](https://man7.org/linux/man-pages/man2/mount.2.html)
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<()>104 pub fn mount<
105     P1: ?Sized + NixPath,
106     P2: ?Sized + NixPath,
107     P3: ?Sized + NixPath,
108     P4: ?Sized + NixPath,
109 >(
110     source: Option<&P1>,
111     target: &P2,
112     fstype: Option<&P3>,
113     flags: MsFlags,
114     data: Option<&P4>,
115 ) -> Result<()> {
116     fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
117     where
118         P: ?Sized + NixPath,
119         F: FnOnce(*const libc::c_char) -> T,
120     {
121         match p {
122             Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
123             None => Ok(f(std::ptr::null())),
124         }
125     }
126 
127     let res = with_opt_nix_path(source, |s| {
128         target.with_nix_path(|t| {
129             with_opt_nix_path(fstype, |ty| {
130                 with_opt_nix_path(data, |d| unsafe {
131                     libc::mount(
132                         s,
133                         t.as_ptr(),
134                         ty,
135                         flags.bits(),
136                         d as *const libc::c_void,
137                     )
138                 })
139             })
140         })
141     })????;
142 
143     Errno::result(res).map(drop)
144 }
145 
146 /// Unmount the file system mounted at `target`.
umount<P: ?Sized + NixPath>(target: &P) -> Result<()>147 pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
148     let res =
149         target.with_nix_path(|cstr| unsafe { libc::umount(cstr.as_ptr()) })?;
150 
151     Errno::result(res).map(drop)
152 }
153 
154 /// Unmount the file system mounted at `target`.
155 ///
156 /// See also [`umount`](https://man7.org/linux/man-pages/man2/umount.2.html)
umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()>157 pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
158     let res = target.with_nix_path(|cstr| unsafe {
159         libc::umount2(cstr.as_ptr(), flags.bits())
160     })?;
161 
162     Errno::result(res).map(drop)
163 }
164