2023-02-08 16:20:25 -05:00
|
|
|
use clap::{Arg, ArgAction, Command};
|
|
|
|
use mount::MntEntries;
|
|
|
|
use shitbox::{args, Cmd};
|
|
|
|
use std::{
|
|
|
|
fs::File,
|
|
|
|
io::{self, BufRead, BufReader},
|
|
|
|
};
|
2023-02-07 10:34:09 -05:00
|
|
|
|
2023-02-08 16:20:25 -05:00
|
|
|
#[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") {
|
2023-02-20 23:00:35 -05:00
|
|
|
'devloop: for d in devices {
|
2023-02-08 16:20:25 -05:00
|
|
|
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}");
|
|
|
|
}
|
2023-02-20 23:00:35 -05:00
|
|
|
continue 'devloop;
|
2023-02-08 16:20:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|