use linuxutils_common::man::ManContent;
pub const MAN: ManContent = ManContent::empty();
use clap::Parser;
use std::{
ffi::CString,
fs::File,
io::{self, BufRead},
process::ExitCode,
};
#[derive(Parser)]
#[command(
name = "swapoff",
about = "Disable devices and files for paging and swapping"
)]
pub struct Args {
#[arg(short = 'a', long)]
all: bool,
#[arg(short = 'v', long)]
verbose: bool,
devices: Vec<String>,
}
fn read_active_swaps() -> Vec<String> {
let Ok(file) = File::open("/proc/swaps") else {
return Vec::new();
};
io::BufReader::new(file)
.lines()
.map_while(Result::ok)
.skip(1)
.filter_map(|line| {
line.split_whitespace().next().map(|s| s.to_string())
})
.collect()
}
fn do_swapoff(path: &str) -> io::Result<()> {
let cpath =
CString::new(path).map_err(|e| io::Error::other(e.to_string()))?;
if unsafe { libc::swapoff(cpath.as_ptr()) } < 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}
pub fn run(args: Args) -> ExitCode {
let devices = if args.all {
read_active_swaps()
} else if args.devices.is_empty() {
eprintln!("swapoff: no device specified. Try 'swapoff --help'");
return ExitCode::from(16);
} else {
args.devices.clone()
};
let mut successes = 0;
let mut failures = 0;
for device in &devices {
if args.verbose {
eprintln!("swapoff: disabling {device}");
}
if let Err(e) = do_swapoff(device) {
eprintln!("swapoff: {device}: {e}");
failures += 1;
} else {
successes += 1;
}
}
if failures == 0 {
ExitCode::SUCCESS
} else if args.all && successes == 0 {
ExitCode::from(32)
} else if args.all {
ExitCode::from(64)
} else {
ExitCode::from(4)
}
}