3 use bch_bindgen::bcachefs;
4 use bch_bindgen::opt_set;
5 use bch_bindgen::fs::Fs;
6 use bch_bindgen::bkey::BkeySC;
7 use bch_bindgen::btree::BtreeTrans;
8 use bch_bindgen::btree::BtreeIter;
9 use bch_bindgen::btree::BtreeNodeIter;
10 use bch_bindgen::btree::BtreeIterFlags;
12 use std::ffi::{c_int, c_char};
13 use crate::transform_c_args;
15 fn list_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
16 let trans = BtreeTrans::new(fs);
17 let mut iter = BtreeIter::new(&trans, opt.btree, opt.start,
18 BtreeIterFlags::ALL_SNAPSHOTS|
19 BtreeIterFlags::PREFETCH);
21 while let Some(k) = iter.peek_and_restart()? {
26 println!("{}", k.to_text(fs));
33 fn list_btree_formats(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
34 let trans = BtreeTrans::new(fs);
35 let mut iter = BtreeNodeIter::new(&trans, opt.btree, opt.start,
37 BtreeIterFlags::PREFETCH);
39 while let Some(b) = iter.peek_and_restart()? {
40 if b.key.k.p > opt.end {
44 println!("{}", b.to_text(fs));
51 fn list_btree_nodes(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
52 let trans = BtreeTrans::new(fs);
53 let mut iter = BtreeNodeIter::new(&trans, opt.btree, opt.start,
55 BtreeIterFlags::PREFETCH);
57 while let Some(b) = iter.peek_and_restart()? {
58 if b.key.k.p > opt.end {
62 println!("{}", BkeySC::from(&b.key).to_text(fs));
69 fn list_nodes_ondisk(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
70 let trans = BtreeTrans::new(fs);
71 let mut iter = BtreeNodeIter::new(&trans, opt.btree, opt.start,
73 BtreeIterFlags::PREFETCH);
75 while let Some(b) = iter.peek_and_restart()? {
76 if b.key.k.p > opt.end {
80 println!("{}", b.ondisk_to_text(fs));
87 #[derive(Clone, clap::ValueEnum, Debug)]
95 /// List filesystem metadata in textual form
96 #[derive(Parser, Debug)]
98 /// Btree to list from
99 #[arg(short, long, default_value_t=bcachefs::btree_id::BTREE_ID_extents)]
100 btree: bcachefs::btree_id,
102 /// Btree depth to descend to (0 == leaves)
103 #[arg(short, long, default_value_t=0)]
106 /// Start position to list from
107 #[arg(short, long, default_value="POS_MIN")]
108 start: bcachefs::bpos,
111 #[arg(short, long, default_value="SPOS_MAX")]
114 #[arg(short, long, default_value="keys")]
117 /// Check (fsck) the filesystem first
118 #[arg(short, long, default_value_t=false)]
121 /// Force color on/off. Default: autodetect tty
122 #[arg(short, long, action = clap::ArgAction::Set, default_value_t=atty::is(Stream::Stdout))]
129 #[arg(required(true))]
130 devices: Vec<std::path::PathBuf>,
133 fn cmd_list_inner(opt: Cli) -> anyhow::Result<()> {
134 let mut fs_opts: bcachefs::bch_opts = Default::default();
136 opt_set!(fs_opts, nochanges, 1);
137 opt_set!(fs_opts, read_only, 1);
138 opt_set!(fs_opts, norecovery, 1);
139 opt_set!(fs_opts, degraded, 1);
140 opt_set!(fs_opts, errors, bcachefs::bch_error_actions::BCH_ON_ERROR_continue as u8);
143 opt_set!(fs_opts, fix_errors, bcachefs::fsck_err_opts::FSCK_FIX_yes as u8);
144 opt_set!(fs_opts, norecovery, 0);
148 opt_set!(fs_opts, verbose, 1);
151 let fs = Fs::open(&opt.devices, fs_opts)?;
154 Mode::Keys => list_keys(&fs, opt),
155 Mode::Formats => list_btree_formats(&fs, opt),
156 Mode::Nodes => list_btree_nodes(&fs, opt),
157 Mode::NodesOndisk => list_nodes_ondisk(&fs, opt),
162 #[allow(clippy::not_unsafe_ptr_arg_deref)]
163 pub extern "C" fn cmd_list(argc: c_int, argv: *const *const c_char) {
164 transform_c_args!(argv, argc, argv);
165 let opt = Cli::parse_from(argv);
166 colored::control::set_override(opt.colorize);
167 if let Err(e) = cmd_list_inner(opt) {
168 error!("Fatal error: {}", e);