summaryrefslogtreecommitdiff
path: root/src/commands/cmd_subvolume.rs
blob: c77eaacda57ca4916aa8b333bcd00730fd5e03b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use std::path::PathBuf;

use bch_bindgen::c::BCH_SUBVOL_SNAPSHOT_RO;
use clap::{Parser, Subcommand};

use crate::wrappers::handle::BcachefsHandle;

#[derive(Parser, Debug)]
pub struct Cli {
    #[command(subcommand)]
    subcommands: Subcommands,
}

/// Subvolumes-related commands
#[derive(Subcommand, Debug)]
enum Subcommands {
    #[command(visible_aliases = ["new"])]
    Create {
        /// Paths
        targets: Vec<PathBuf>
    },

    #[command(visible_aliases = ["del"])]
    Delete {
        /// Path
        target: PathBuf
    },

    #[command(allow_missing_positional = true, visible_aliases = ["snap"])]
    Snapshot {
        /// Make snapshot read only
        #[arg(long, short)]
        read_only: bool,
        source: Option<PathBuf>,
        dest: PathBuf
    }
}

pub fn cmd_subvolumes(argv: Vec<String>) -> i32 {
    let args = Cli::parse_from(argv);

    match args.subcommands {
        Subcommands::Create { targets } => {
            for target in targets {
                if let Some(dirname) = target.parent() {
                    let fs = unsafe { BcachefsHandle::open(dirname) };
                    fs.create_subvolume(target).expect("Failed to create the subvolume");
                }
            }
        }
        ,
        Subcommands::Delete { target } => {
            if let Some(dirname) = target.parent() {
                let fs = unsafe { BcachefsHandle::open(dirname) };
                fs.delete_subvolume(target).expect("Failed to delete the subvolume");
            }
        },
        Subcommands::Snapshot { read_only, source, dest } => {
            if let Some(dirname) = dest.parent() {
                let dot = PathBuf::from(".");
                let dir = if dirname.as_os_str().is_empty() { &dot } else { dirname };
                let fs = unsafe { BcachefsHandle::open(dir) };

                fs.snapshot_subvolume(if read_only { BCH_SUBVOL_SNAPSHOT_RO } else { 0x0 }, source, dest).expect("Failed to snapshot the subvolume");
            }
        }
    }

    0
}