]> git.sesse.net Git - bcachefs-tools-debian/blob - rust-src/src/cmd_list.rs
rust: Filesystem options now supported
[bcachefs-tools-debian] / rust-src / src / cmd_list.rs
1 use atty::Stream;
2 use bch_bindgen::error;
3 use bch_bindgen::bcachefs;
4 use bch_bindgen::opt_set;
5 use bch_bindgen::fs::Fs;
6 use bch_bindgen::btree::BtreeTrans;
7 use bch_bindgen::btree::BtreeIter;
8 use bch_bindgen::btree::BtreeIterFlags;
9 use clap::Parser;
10 use colored::Colorize;
11 use std::ffi::{CStr, OsStr, c_int, c_char};
12 use std::os::unix::ffi::OsStrExt;
13
14 fn list_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
15     let trans = BtreeTrans::new(fs);
16     let mut iter = BtreeIter::new(&trans, opt.btree, opt.start,
17         BtreeIterFlags::ALL_SNAPSHOTS|
18         BtreeIterFlags::PREFETCH);
19
20     while let Some(k) = iter.peek_and_restart()? {
21         if k.k.p > opt.end {
22             break;
23         }
24
25         println!("{}", k.to_text(fs));
26         iter.advance();
27     }
28
29     Ok(())
30 }
31
32 fn list_btree_formats(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
33     let trans = BtreeTrans::new(fs);
34
35     Ok(())
36 }
37
38 fn list_btree_nodes(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
39     let trans = BtreeTrans::new(fs);
40
41     Ok(())
42 }
43
44 fn list_nodes_ondisk(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
45     let trans = BtreeTrans::new(fs);
46
47     Ok(())
48 }
49
50 fn list_nodes_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
51     let trans = BtreeTrans::new(fs);
52
53     Ok(())
54 }
55
56 #[derive(Clone, clap::ValueEnum)]
57 enum Mode {
58     Keys,
59     Formats,
60     Nodes,
61     NodesOndisk,
62     NodesKeys,
63 }
64
65 #[derive(Parser)]
66 struct Cli {
67     /// Btree to list from
68     #[arg(short, long, default_value_t=bcachefs::btree_id::BTREE_ID_extents)]
69     btree:      bcachefs::btree_id,
70
71     /// Btree depth to descend to (0 == leaves)
72     #[arg(short, long, default_value_t=0)]
73     level:      u8,
74
75     /// Start position to list from
76     #[arg(short, long, default_value="POS_MIN")]
77     start:      bcachefs::bpos,
78
79     /// End position
80     #[arg(short, long, default_value="SPOS_MAX")]
81     end:        bcachefs::bpos,
82
83     #[arg(short, long, default_value="keys")]
84     mode:       Mode,
85
86     /// Check (fsck) the filesystem first
87     #[arg(short, long, default_value_t=false)]
88     fsck:       bool,
89
90     /// Force color on/off. Default: autodetect tty
91     #[arg(short, long, action = clap::ArgAction::Set, default_value_t=atty::is(Stream::Stdout))]
92     colorize:   bool,
93    
94     /// Verbose mode
95     #[arg(short, long)]
96     verbose:    bool,
97
98     #[arg(required(true))]
99     devices:    Vec<std::path::PathBuf>,
100 }
101
102 fn cmd_list_inner(opt: Cli) -> anyhow::Result<()> {
103     let mut fs_opts: bcachefs::bch_opts = Default::default();
104
105     opt_set!(fs_opts, nochanges,        1);
106     opt_set!(fs_opts, norecovery,       1);
107     opt_set!(fs_opts, degraded,         1);
108     opt_set!(fs_opts, errors,           bcachefs::bch_error_actions::BCH_ON_ERROR_continue as u8);
109
110     if opt.fsck {
111         opt_set!(fs_opts, fix_errors,   bcachefs::fsck_err_opts::FSCK_OPT_YES as u8);
112         opt_set!(fs_opts, norecovery,   0);
113     }
114
115     if opt.verbose {
116         opt_set!(fs_opts, verbose,      1);
117     }
118
119     let fs = Fs::open(&opt.devices, fs_opts)?;
120
121     match opt.mode {
122         Mode::Keys          => list_keys(&fs, opt),
123         Mode::Formats       => list_btree_formats(&fs, opt),
124         Mode::Nodes         => list_btree_nodes(&fs, opt),
125         Mode::NodesOndisk   => list_nodes_ondisk(&fs, opt),
126         Mode::NodesKeys     => list_nodes_keys(&fs, opt),
127     }
128 }
129
130 #[no_mangle]
131 pub extern "C" fn cmd_rust_list(argc: c_int, argv: *const *const c_char) {
132     let argv: Vec<_> = (0..argc)
133         .map(|i| unsafe { CStr::from_ptr(*argv.add(i as usize)) })
134         .map(|i| OsStr::from_bytes(i.to_bytes()))
135         .collect();
136
137     let opt = Cli::parse_from(argv);
138     colored::control::set_override(opt.colorize);
139     if let Err(e) = cmd_list_inner(opt) {
140         error!("Fatal error: {}", e);
141     }
142 }