Skip to main content

linuxutils_system/
fsfreeze.rs

1use linuxutils_common::man::ManContent;
2
3pub const MAN: ManContent = ManContent::empty();
4
5use clap::Parser;
6use std::{fs::File, io, os::unix::io::AsRawFd, process::ExitCode};
7
8const FIFREEZE: libc::c_ulong = 0xc0045877;
9const FITHAW: libc::c_ulong = 0xc0045878;
10
11#[derive(Parser)]
12#[command(
13    name = "fsfreeze",
14    about = "Suspend or resume access to a filesystem"
15)]
16pub struct Args {
17    /// Freeze the filesystem
18    #[arg(short = 'f', long, conflicts_with = "unfreeze")]
19    freeze: bool,
20
21    /// Unfreeze the filesystem
22    #[arg(short = 'u', long, conflicts_with = "freeze")]
23    unfreeze: bool,
24
25    /// Mountpoint of the filesystem
26    mountpoint: String,
27}
28
29fn fsfreeze_ioctl(path: &str, ioctl_nr: libc::c_ulong) -> io::Result<()> {
30    let f = File::open(path)?;
31    let arg: libc::c_int = 0;
32    let ret = unsafe { libc::ioctl(f.as_raw_fd(), ioctl_nr, &arg) };
33    if ret < 0 {
34        Err(io::Error::last_os_error())
35    } else {
36        Ok(())
37    }
38}
39
40pub fn run(args: Args) -> ExitCode {
41    if !args.freeze && !args.unfreeze {
42        eprintln!("fsfreeze: one of --freeze or --unfreeze must be specified");
43        return ExitCode::FAILURE;
44    }
45
46    let (ioctl_nr, action) = if args.freeze {
47        (FIFREEZE, "freeze")
48    } else {
49        (FITHAW, "unfreeze")
50    };
51
52    if let Err(e) = fsfreeze_ioctl(&args.mountpoint, ioctl_nr) {
53        eprintln!("fsfreeze: failed to {action} {}: {e}", args.mountpoint);
54        return ExitCode::FAILURE;
55    }
56
57    ExitCode::SUCCESS
58}