use {
crate::*,
lazy_regex::*,
std::path::PathBuf,
};
#[cfg(unix)]
static REMOTE_ONLY_FS_TYPES: &[&str] = &[
"afs",
"coda",
"auristorfs",
"fhgfs",
"gpfs",
"ibrix",
"ocfs2",
"vxfs",
];
static OPTIONS_NOT_IN_OPTIONS_STRING: &[&str] = &[
"removable", ];
pub type MountId = u32;
#[derive(Debug, Clone)]
pub struct MountInfo {
pub id: Option<MountId>,
pub parent: Option<MountId>,
pub dev: DeviceId,
pub root: PathBuf,
pub mount_point: PathBuf,
pub options: Vec<MountOption>,
pub fs: String, pub fs_type: String,
pub bound: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub struct MountOption {
pub name: String,
pub value: Option<String>,
}
impl MountOption {
pub fn new<S: Into<String>>(
name: S,
value: Option<S>,
) -> Self {
MountOption {
name: name.into(),
value: value.map(|s| s.into()),
}
}
}
impl MountInfo {
pub fn dm_name(&self) -> Option<&str> {
regex_captures!(r#"^/dev/mapper/([^/]+)$"#, &self.fs).map(|(_, dm_name)| dm_name)
}
pub fn fs_name(&self) -> Option<&str> {
regex_find!(r#"[^\\/]+$"#, &self.fs)
}
#[cfg(unix)]
pub fn is_remote(&self) -> bool {
self.fs.contains(':')
|| (self.fs.starts_with("//")
&& ["cifs", "smb3", "smbfs"].contains(&self.fs_type.as_ref()))
|| REMOTE_ONLY_FS_TYPES.contains(&self.fs_type.as_ref())
|| self.fs == "-hosts"
}
pub fn options_string(&self) -> String {
let mut s = String::new();
let mut first = true;
for option in &self.options {
if OPTIONS_NOT_IN_OPTIONS_STRING
.iter()
.any(|s| s == &option.name)
{
continue;
}
if !first {
s.push(',');
}
s.push_str(&option.name);
if let Some(value) = &option.value {
s.push('=');
s.push_str(value);
}
first = false;
}
s
}
pub fn has_option(
&self,
name: &str,
) -> bool {
for option in &self.options {
if option.name == name {
return true;
}
}
false
}
pub fn option_value(
&self,
name: &str,
) -> Option<&str> {
for option in &self.options {
if option.name == name {
return option.value.as_deref();
}
}
None
}
}