in reverie-process/src/mount.rs [400:488]
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut map: HashMap<&str, Option<&str>> = HashMap::new();
for item in s.split(',') {
let item = item.trim();
if item.is_empty() {
continue;
}
let (key, value) = match item.split_once('=') {
Some((key, value)) => (key, Some(value)),
None => (item, None),
};
map.insert(key, value);
}
// The mount target is always required.
let mut mount = match map
.remove("target")
.or_else(|| map.remove("destination"))
.or_else(|| map.remove("dest"))
.or_else(|| map.remove("dst"))
.flatten()
{
Some(target) => Mount::new(target),
None => {
return Err(MountParseError::MissingTarget);
}
};
if let Some(source) = map.remove("source").or_else(|| map.remove("src")).flatten() {
mount = mount.source(source);
}
let is_bind_mount = if let Some(fstype) = map.remove("type").flatten() {
if fstype == "bind" {
true
} else {
mount = mount.fstype(fstype);
false
}
} else {
true
};
if is_bind_mount {
mount = mount.flags(MountFlags::MS_BIND);
}
if let Some((key, value)) = map.remove_entry("readonly") {
if let Some(value) = value {
// No value should have been specified.
return Err(MountParseError::Invalid(key.into(), Some(value.to_owned())));
}
mount = mount.readonly();
}
if let Some(propagation) = map.remove("bind-propagation").flatten() {
let flags = match propagation {
"shared" => MountFlags::MS_SHARED,
"slave" => MountFlags::MS_SLAVE,
"private" => MountFlags::MS_PRIVATE,
"rshared" => MountFlags::MS_REC | MountFlags::MS_SHARED,
"rslave" => MountFlags::MS_REC | MountFlags::MS_SLAVE,
"rprivate" => MountFlags::MS_REC | MountFlags::MS_PRIVATE,
_ => {
return Err(MountParseError::Invalid(
"bind-propagation".into(),
Some(propagation.into()),
));
}
};
mount = mount.flags(flags);
} else {
// All mounts get these flags by default.
mount = mount.flags(MountFlags::MS_REC | MountFlags::MS_PRIVATE);
}
// Any left over keys are invalid.
if let Some((k, v)) = map.into_iter().next() {
return Err(MountParseError::Invalid(k.into(), v.map(ToOwned::to_owned)));
}
Ok(mount)
}