1use crate::umount::{unmount_, Unmount, UnmountDrop};
5use crate::{MountBuilder, PropagationType, UnmountFlags};
6use std::ptr;
7use std::{
8 ffi::{CString, OsStr},
9 io,
10 os::unix::ffi::OsStrExt,
11 path::Path,
12};
13
14#[derive(Debug)]
16pub struct Mount {
17 pub(crate) target: CString,
18 pub(crate) fstype: String,
19 #[cfg(feature = "loop")]
20 pub(crate) loopback: Option<loopdev::LoopDevice>,
21 pub(crate) loop_path: Option<std::path::PathBuf>,
22}
23
24impl Unmount for Mount {
25 fn unmount(&self, flags: UnmountFlags) -> io::Result<()> {
26 unsafe {
27 unmount_(self.target.as_ptr(), flags)?;
28 }
29
30 #[cfg(feature = "loop")]
31 if let Some(ref loopback) = self.loopback {
32 loopback.detach()?;
33 }
34
35 Ok(())
36 }
37}
38
39impl Mount {
40 #[inline]
54 #[must_use]
55 pub fn builder<'a>() -> MountBuilder<'a> {
56 MountBuilder::default()
57 }
58
59 #[inline]
69 pub fn new(source: impl AsRef<Path>, target: impl AsRef<Path>) -> io::Result<Mount> {
70 let supported = crate::SupportedFilesystems::new()?;
71 MountBuilder::default()
72 .fstype(&supported)
73 .mount(source, target)
74 }
75
76 #[inline]
79 #[must_use]
80 pub fn backing_loop_device(&self) -> Option<&Path> {
81 self.loop_path.as_deref()
82 }
83
84 #[inline]
88 #[must_use]
89 pub fn get_fstype(&self) -> &str {
90 &self.fstype
91 }
92
93 #[inline]
95 #[must_use]
96 pub fn target_path(&self) -> &Path {
97 Path::new(OsStr::from_bytes(self.target.as_bytes()))
98 }
99
100 #[inline]
102 #[must_use]
103 pub fn set_propagation_type(&mut self, propagation_type: PropagationType) -> io::Result<()> {
104 let result = unsafe {
105 libc::mount(
106 ptr::null(),
107 self.target.as_ptr(),
108 ptr::null(),
109 propagation_type.bits(),
110 ptr::null(),
111 )
112 };
113
114 match result {
115 0 => Ok(()),
116 _err => Err(io::Error::last_os_error()),
117 }
118 }
119
120 #[inline]
121 pub(crate) fn from_target_and_fstype(target: CString, fstype: String) -> Self {
122 Mount {
123 target,
124 fstype,
125 #[cfg(feature = "loop")]
126 loopback: None,
127 loop_path: None,
128 }
129 }
130}
131
132pub struct Mounts(pub Vec<UnmountDrop<Mount>>);
134
135impl Mounts {
136 pub fn unmount(&mut self, lazy: bool) -> io::Result<()> {
142 let flags = if lazy {
143 UnmountFlags::DETACH
144 } else {
145 UnmountFlags::empty()
146 };
147 self.0
148 .iter_mut()
149 .rev()
150 .try_for_each(|mount| mount.unmount(flags))
151 }
152}
153
154impl Drop for Mounts {
155 fn drop(&mut self) {
156 for mount in self.0.drain(..).rev() {
157 drop(mount);
158 }
159 }
160}