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