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(long, conflicts_with_all = ["mirror", "all"])]
33 bytenr: Option<u64>,
34
35 #[clap(short = 'F', long)]
37 force: bool,
38}
39
40impl Runnable for DumpSuperCommand {
41 fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
42 let mut file = File::open(&self.path).with_context(|| {
43 format!("failed to open '{}'", self.path.display())
44 })?;
45
46 let offsets: Vec<(u64, String)> = if let Some(bytenr) = self.bytenr {
48 vec![(bytenr, format!("bytenr={bytenr}"))]
49 } else if self.all {
50 (0..SUPER_MIRROR_MAX)
51 .map(|m| {
52 let off = superblock::super_mirror_offset(m);
53 (off, format!("bytenr={off}"))
54 })
55 .collect()
56 } else {
57 let m = self.mirror.unwrap_or(0);
58 let off = superblock::super_mirror_offset(m);
59 vec![(off, format!("bytenr={off}"))]
60 };
61
62 for (i, (offset, label)) in offsets.iter().enumerate() {
63 if i > 0 {
64 println!();
65 }
66
67 println!("superblock: {label}, device={}", self.path.display());
68
69 let sb = match superblock::read_superblock_at(&mut file, *offset) {
70 Ok(sb) => sb,
71 Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
72 println!(
73 "superblock at {label} beyond end of device, skipping"
74 );
75 continue;
76 }
77 Err(e) => {
78 return Err(e).with_context(|| {
79 format!(
80 "failed to read superblock at {label} from '{}'",
81 self.path.display()
82 )
83 });
84 }
85 };
86
87 if !sb.magic_is_valid() && !self.force {
88 if self.all {
89 println!(
90 "superblock at {label} has bad magic, skipping (use -F to force)"
91 );
92 continue;
93 }
94 bail!(
95 "bad magic on superblock at {label} of '{}' (use -F to force)",
96 self.path.display()
97 );
98 }
99
100 println!(
101 "---------------------------------------------------------"
102 );
103 print_super::print_superblock(&sb, self.full);
104 }
105
106 Ok(())
107 }
108}