btrfs_cli/inspect/
dump_super.rs1use super::print_super;
2use crate::{Format, Runnable};
3use anyhow::{Context, Result, bail};
4use btrfs_disk::superblock::{self, SUPER_MIRROR_MAX};
5use clap::Parser;
6use std::{fs::File, path::PathBuf};
7
8#[derive(Parser, Debug)]
15pub struct DumpSuperCommand {
16 path: PathBuf,
18
19 #[clap(short = 'f', long)]
21 full: bool,
22
23 #[clap(short = 'a', long)]
25 all: bool,
26
27 #[clap(short = 's', long = "super", value_parser = clap::value_parser!(u32).range(..SUPER_MIRROR_MAX as i64))]
29 mirror: Option<u32>,
30
31 #[clap(short = 'F', long)]
33 force: bool,
34}
35
36impl Runnable for DumpSuperCommand {
37 fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
38 let mut file = File::open(&self.path).with_context(|| {
39 format!("failed to open '{}'", self.path.display())
40 })?;
41
42 let mirrors: Vec<u32> = if self.all {
43 (0..SUPER_MIRROR_MAX).collect()
44 } else if let Some(m) = self.mirror {
45 vec![m]
46 } else {
47 vec![0]
48 };
49
50 for (i, &mirror) in mirrors.iter().enumerate() {
51 if i > 0 {
52 println!();
53 }
54
55 let offset = superblock::super_mirror_offset(mirror);
56 println!(
57 "superblock: bytenr={offset}, device={}",
58 self.path.display()
59 );
60
61 let sb = match superblock::read_superblock(&mut file, mirror) {
62 Ok(sb) => sb,
63 Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
64 println!(
65 "superblock mirror {mirror} beyond end of device, skipping"
66 );
67 continue;
68 }
69 Err(e) => {
70 return Err(e).with_context(|| {
71 format!(
72 "failed to read superblock mirror {mirror} from '{}'",
73 self.path.display()
74 )
75 });
76 }
77 };
78
79 if !sb.magic_is_valid() && !self.force {
80 if self.all {
81 println!(
82 "superblock mirror {mirror} has bad magic, skipping (use -F to force)"
83 );
84 continue;
85 }
86 bail!(
87 "bad magic on superblock mirror {mirror} of '{}' (use -F to force)",
88 self.path.display()
89 );
90 }
91
92 println!(
93 "---------------------------------------------------------"
94 );
95 print_super::print_superblock(&sb, self.full);
96 }
97
98 Ok(())
99 }
100}