utilbox/umount - add lazy
flag, iter through mnt entries in one pass
to filter chosen entries when using `all` options
This commit is contained in:
parent
a468b09816
commit
29af667a0f
@ -1,7 +1,7 @@
|
||||
use std::io;
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command, ValueHint};
|
||||
use mount::MntEntries;
|
||||
use shitbox::{args, Cmd};
|
||||
use std::io;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Umount;
|
||||
@ -12,12 +12,16 @@ impl Cmd for Umount {
|
||||
.about("unmount filesystems")
|
||||
.author("Nathan Fisher")
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.before_long_help(
|
||||
"umount detaches the target filesystem(s). A file system is specified \
|
||||
by giving the directory where it has been mounted. Giving the special \
|
||||
device on which the file system lives may also work, but is obsolete.",
|
||||
)
|
||||
.args([
|
||||
Arg::new("all")
|
||||
.help(
|
||||
"All of the filesystems described in /proc/self/mountinfo \
|
||||
are unmounted, except the proc, devfs, devpts, sysfs, rpc_pipefs \
|
||||
and nfsd filesystems.",
|
||||
"All of the file systems described in /proc/mounts are \
|
||||
unmounted. The proc filesystem is not unmounted.",
|
||||
)
|
||||
.short('a')
|
||||
.long("all")
|
||||
@ -27,6 +31,22 @@ impl Cmd for Umount {
|
||||
.short('f')
|
||||
.long("force")
|
||||
.action(ArgAction::SetTrue),
|
||||
Arg::new("lazy")
|
||||
.help(
|
||||
"Lazy unmount. Detach the filesystem from the fs hierarchy \
|
||||
now, and cleanup all references to the filesystem as soon \
|
||||
as it is not busy anymore.",
|
||||
)
|
||||
.short('l')
|
||||
.long("lazy")
|
||||
.action(ArgAction::SetTrue),
|
||||
Arg::new("nomtab")
|
||||
.help(
|
||||
"Unmount without writing in /etc/mtab. This is the default action. \
|
||||
This flag exists only for historical compatability.",
|
||||
)
|
||||
.short('n')
|
||||
.action(ArgAction::SetTrue),
|
||||
Arg::new("types")
|
||||
.help(
|
||||
"Indicate that the actions should only be taken on filesystems \
|
||||
@ -55,50 +75,55 @@ impl Cmd for Umount {
|
||||
}
|
||||
|
||||
fn run(&self, matches: &ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let flags = if matches.get_flag("force") {
|
||||
let mut flags = if matches.get_flag("force") {
|
||||
libc::MNT_FORCE
|
||||
} else {
|
||||
0
|
||||
};
|
||||
if matches.get_flag("lazy") {
|
||||
flags |= libc::MNT_DETACH;
|
||||
}
|
||||
if matches.get_flag("all") {
|
||||
let mut mntpts: Vec<mount::MntEntry> = MntEntries::new("/proc/mounts")?
|
||||
.filter(|x| {
|
||||
x.fstype != "proc"
|
||||
&& x.fstype != "sysfs"
|
||||
&& x.fstype != "devfs"
|
||||
&& x.fstype != "devpts"
|
||||
&& x.fstype != "rpc_pipefs"
|
||||
&& x.fstype != "nfsd"
|
||||
&& x.fstype != "swap"
|
||||
})
|
||||
.collect();
|
||||
if let Some(types) = matches.get_many::<String>("types") {
|
||||
for t in types {
|
||||
if t.starts_with("no") {
|
||||
let t = t.strip_prefix("no").unwrap();
|
||||
mntpts.retain(|x| x.fstype != t);
|
||||
} else {
|
||||
mntpts.retain(|x| &x.fstype == t);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(spec) = matches.get_many::<String>("spec") {
|
||||
for s in spec {
|
||||
for p in &mntpts {
|
||||
if &p.dir == s {
|
||||
mount::umount(s, flags as u32)?;
|
||||
if matches.get_flag("verbose") {
|
||||
println!("umount: {s} unmounted");
|
||||
let mntpts = MntEntries::new("/proc/mounts")?.filter(|x| {
|
||||
let mut ret = x.fstype != "proc"
|
||||
&& x.fstype != "sysfs"
|
||||
&& x.fstype != "devfs"
|
||||
&& x.fstype != "devpts"
|
||||
&& x.fstype != "rpc_pipefs"
|
||||
&& x.fstype != "nfsd"
|
||||
&& x.fstype != "swap"
|
||||
&& x.fsname != "/";
|
||||
if let Some(types) = matches.get_many::<String>("types") {
|
||||
for t in types {
|
||||
if t.starts_with("no") {
|
||||
let t = t.strip_prefix("no").unwrap();
|
||||
if x.fstype == t {
|
||||
ret = false;
|
||||
}
|
||||
} else {
|
||||
if &x.fstype != t {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for p in &mntpts {
|
||||
mount::umount(&p.dir, flags as u32)?;
|
||||
if matches.get_flag("verbose") {
|
||||
println!("umount: {} unmounted", &p.dir);
|
||||
if let Some(spec) = matches.get_many::<String>("spec") {
|
||||
let mut r2 = false;
|
||||
for s in spec {
|
||||
if &x.dir == s || &x.fsname == s {
|
||||
r2 = true;
|
||||
}
|
||||
}
|
||||
if !r2 {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
ret
|
||||
});
|
||||
for p in mntpts {
|
||||
mount::umount(&p.dir, flags as u32)?;
|
||||
if matches.get_flag("verbose") {
|
||||
println!("umount: {} unmounted", &p.dir);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user