Skip to main content

btrfs_cli/inspect/
logical_resolve.rs

1use crate::{Format, Runnable, util::open_path};
2use anyhow::{Context, Result};
3use clap::Parser;
4use std::{os::unix::io::AsFd, path::PathBuf};
5
6/// Get file system paths for the given logical address
7#[derive(Parser, Debug)]
8pub struct LogicalResolveCommand {
9    /// Logical address
10    logical: u64,
11
12    /// Path to a file or directory on the btrfs filesystem
13    path: PathBuf,
14
15    /// Skip the path resolving and print the inodes instead
16    #[clap(short = 'P', long)]
17    skip_paths: bool,
18
19    /// Ignore offsets when matching references
20    #[clap(short = 'o', long)]
21    ignore_offset: bool,
22
23    /// Set inode container's size
24    #[clap(short = 's', long)]
25    bufsize: Option<u64>,
26}
27
28impl Runnable for LogicalResolveCommand {
29    fn run(&self, _format: Format, _dry_run: bool) -> Result<()> {
30        let file = open_path(&self.path)?;
31        let fd = file.as_fd();
32
33        let results = btrfs_uapi::inode::logical_ino(
34            fd,
35            self.logical,
36            self.ignore_offset,
37            self.bufsize,
38        )
39        .context(
40            "failed to look up logical address (is this a btrfs filesystem?)",
41        )?;
42
43        if results.is_empty() {
44            eprintln!("no results found for logical address {}", self.logical);
45        } else if self.skip_paths {
46            // Just print inode, offset, root
47            for result in results {
48                println!(
49                    "inode {} offset {} root {}",
50                    result.inode, result.offset, result.root
51                );
52            }
53        } else {
54            // Resolve paths for each inode
55            for result in results {
56                match btrfs_uapi::inode::ino_paths(fd, result.inode) {
57                    Ok(paths) => {
58                        if paths.is_empty() {
59                            println!(
60                                "inode {} offset {} root {} <no path>",
61                                result.inode, result.offset, result.root
62                            );
63                        } else {
64                            for path in paths {
65                                println!("{}", path);
66                            }
67                        }
68                    }
69                    Err(_) => {
70                        println!(
71                            "inode {} offset {} root {} <error resolving path>",
72                            result.inode, result.offset, result.root
73                        );
74                    }
75                }
76            }
77        }
78
79        Ok(())
80    }
81}