blkar_lib/
cli_rescue.rs

1use rescue_core::Param;
2use rescue_core;
3use sbx_specs::SBX_FILE_UID_LEN;
4use std::str::FromStr;
5
6use sbx_block::BlockType;
7use json_printer::BracketType;
8
9use file_utils;
10
11use clap::*;
12use cli_utils::*;
13
14pub fn sub_command<'a, 'b>() -> App<'a, 'b> {
15    SubCommand::with_name("rescue")
16        .about("Rescue SBX blocks from file/block device, essentially ddrescue but for SBX blocks
17
18===== IMPORTANT =====
19Please note that this is the last version of this software to be released under the name rsbx,
20future releases will be published under the name blkar. See project repo for details.
21=====================")
22        .arg(in_file_arg()
23             .help("File/block device to rescue sbx data from"))
24        .arg(out_dir_arg()
25             .required(true)
26             .help("Directory to store rescued data"))
27        .arg(Arg::with_name("log_file")
28             .value_name("LOGFILE")
29             .index(3)
30             .help("Log file to keep track of the progress to survive interruptions.
31Note that you should use the same log file for the same file and
32range specified in the initial run."))
33        .arg(Arg::with_name("block_type")
34                         .value_name("TYPE")
35                         .long("only-pick-block")
36                         .takes_value(true)
37                         .help("Only pick BLOCK-TYPE of blocks, one of :
38    any
39    meta
40    data"))
41        .arg(Arg::with_name("uid")
42             .value_name("UID-HEX")
43             .long("only-pick-uid")
44             .takes_value(true)
45             .help("Only pick blocks with UID-HEX as uid. Uid must be exactly 6
46bytes (12 hex digits) in length."))
47        .arg(force_misalign_arg())
48        .arg(pr_verbosity_level_arg())
49        .arg(from_byte_arg()
50             .help("Start from byte FROM-BYTE. The position is automatically rounded
51down to the closest multiple of 128 bytes, after adding the bytes
52processed field from the log file (if specified). If this option is
53not specified, defaults to the start of file. Negative values are
54rejected. If FROM-BYTE exceeds the largest possible
55position (file size - 1), then it will be treated as (file size - 1).
56The rounding procedure is applied after all auto-adjustments."))
57        .arg(to_byte_arg())
58        .arg(json_arg())
59}
60
61pub fn rescue<'a>(matches : &ArgMatches<'a>) -> i32 {
62    let json_printer = get_json_printer!(matches);
63
64    json_printer.print_open_bracket(None, BracketType::Curly);
65
66    let mut temp_uid = [0; SBX_FILE_UID_LEN];
67    let uid : Option<&[u8; SBX_FILE_UID_LEN]> = {
68        match matches.value_of("uid") {
69            None    => None ,
70            Some(x) => { parse_uid!(temp_uid, x, json_printer);
71                         Some(&temp_uid) }
72        }
73    };
74
75    let block_type = match matches.value_of("block_type") {
76        None    => None,
77        Some(x) => {
78            match x {
79                "any"  => None,
80                "meta" => Some(BlockType::Meta),
81                "data" => Some(BlockType::Data),
82                _      => exit_with_msg!(usr json_printer => "Invalid block type")
83            }
84        }
85    };
86
87    let from_pos = get_from_pos!(matches, json_printer);
88    let to_pos   = get_to_pos!(matches, json_printer);
89
90    let pr_verbosity_level = get_pr_verbosity_level!(matches, json_printer);
91
92    let in_file  = matches.value_of("in_file").unwrap();
93    exit_if_file!(not_exists in_file
94                  => json_printer
95                  => "File \"{}\" does not exist", in_file);
96    let out_dir = matches.value_of("out_dir").unwrap();
97
98    if !file_utils::check_if_file_exists(out_dir) {
99        exit_with_msg!(usr json_printer => "Directory \"{}\" does not exist", out_dir);
100    }
101    if !file_utils::check_if_file_is_dir(out_dir) {
102        exit_with_msg!(usr json_printer => "\"{}\" is not a directory", out_dir);
103    }
104
105    let log_file = matches.value_of("log_file");
106
107    let param = Param::new(in_file,
108                           out_dir,
109                           log_file,
110                           from_pos,
111                           to_pos,
112                           matches.is_present("force_misalign"),
113                           &json_printer,
114                           block_type,
115                           uid,
116                           pr_verbosity_level);
117    match rescue_core::rescue_from_file(&param) {
118        Ok(s)  => exit_with_msg!(ok json_printer => "{}", s),
119        Err(e) => exit_with_msg!(op json_printer => "{}", e)
120    }
121}