shitbox/utilbox/commands/swapoff/mod.rs

78 lines
2.7 KiB
Rust

use clap::{Arg, ArgAction, Command};
use mount::MntEntries;
use shitbox::{args, Cmd};
use std::{
fs::File,
io::{self, BufRead, BufReader},
};
#[derive(Debug, Default)]
pub struct Swapoff;
impl Cmd for Swapoff {
fn cli(&self) -> clap::Command {
Command::new("swapoff")
.about("disable devices and files for paging and swapping")
.author("Nathan Fisher")
.version(env!("CARGO_PKG_VERSION"))
.args([
Arg::new("all")
.help("Disable swapping on all known swap devices and files as found in /etc/fstab.")
.short('a')
.long("all")
.action(ArgAction::SetTrue),
args::verbose(),
Arg::new("device")
.num_args(1..)
.conflicts_with("all")
.required_unless_present("all"),
])
}
fn run(&self, matches: &clap::ArgMatches) -> Result<(), Box<dyn std::error::Error>> {
if matches.get_flag("all") {
if let Ok(entries) = MntEntries::new("/etc/fstab") {
for e in entries.filter(|x| &x.fstype == "swap") {
if e.is_swapped() {
let dev = e
.device()?
.to_str()
.ok_or(io::Error::new(io::ErrorKind::Other, "utf8 error"))?
.to_string();
mount::swapoff(&dev)?;
if matches.get_flag("verbose") {
println!("swapoff {dev}");
}
}
}
}
} else if let Some(devices) = matches.get_many::<String>("device") {
'devloop: for d in devices {
let fd = File::open("/proc/swaps")?;
let reader = BufReader::new(fd);
for line in reader.lines() {
let line = line?;
let swap = line.split_whitespace().next().ok_or(io::Error::new(
io::ErrorKind::Other,
"Error reading /proc/swaps",
))?;
if swap == d {
mount::swapoff(d)?;
if matches.get_flag("verbose") {
println!("swapoff {d}");
}
continue 'devloop;
}
}
let msg = format!("{d} is not swapped");
return Err(Box::new(io::Error::new(io::ErrorKind::Other, msg)));
}
}
Ok(())
}
fn path(&self) -> Option<shitbox::Path> {
Some(shitbox::Path::Sbin)
}
}