From 83bdade363b222a1fe4d496b97cae603aaff4213 Mon Sep 17 00:00:00 2001 From: Florian Stecker Date: Thu, 25 Apr 2024 16:27:35 -0400 Subject: [PATCH] remove old code --- btrfs_explorer/src/btrfs_lookup.rs | 2 +- btrfs_explorer/src/http_chunk.rs | 9 +- btrfs_explorer/src/render_common.rs | 3 + btrfs_explorer_bin/src/main.rs | 239 +--------------------------- 4 files changed, 10 insertions(+), 243 deletions(-) diff --git a/btrfs_explorer/src/btrfs_lookup.rs b/btrfs_explorer/src/btrfs_lookup.rs index 03d732f..0c8b530 100644 --- a/btrfs_explorer/src/btrfs_lookup.rs +++ b/btrfs_explorer/src/btrfs_lookup.rs @@ -2,7 +2,7 @@ use std::convert::identity; use std::rc::Rc; use std::ops::{Deref, RangeBounds, Bound}; -use crate::btrfs_structs::{DirItem, InteriorNode, Item, ItemType, Key, Leaf, Node, ParseBin, ParseError, Superblock, Value, LAST_KEY, ZERO_KEY}; +use crate::btrfs_structs::{InteriorNode, Item, ItemType, Key, Leaf, Node, ParseBin, ParseError, Superblock, Value, LAST_KEY, ZERO_KEY}; use crate::nodereader::NodeReader; /// Represents a B-Tree inside a filesystem image. Can be used to look up keys, diff --git a/btrfs_explorer/src/http_chunk.rs b/btrfs_explorer/src/http_chunk.rs index d4a8936..0859f39 100644 --- a/btrfs_explorer/src/http_chunk.rs +++ b/btrfs_explorer/src/http_chunk.rs @@ -1,8 +1,7 @@ -use std::convert::identity; -use maud::{Markup, html, DOCTYPE, PreEscaped}; +use maud::{Markup, html}; use rouille::{Request, Response}; use crate::{ - btrfs_lookup::Tree, btrfs_structs::{self, BlockRef, ChunkItem, ItemType, Key, TreeID, Value}, key, main_error::MainError, render_common::{render_page, size_name} + btrfs_lookup::Tree, btrfs_structs::{self, BlockRef, ItemType, TreeID, Value}, key, main_error::MainError, render_common::{render_page, size_name} }; struct ChunkLineDisplay { @@ -129,13 +128,11 @@ pub fn http_chunk(image: &[u8], offset: &str, _req: &Request) -> Result Markup { let header = format!("Metadata nodes in chunk at address {:x}", data.offset); - let body = format!("{:?}", &data.refs); - let boxes: Vec> = data.refs .chunks(64) .map(|row|row.iter() diff --git a/btrfs_explorer/src/render_common.rs b/btrfs_explorer/src/render_common.rs index ff3eb52..53e60c4 100644 --- a/btrfs_explorer/src/render_common.rs +++ b/btrfs_explorer/src/render_common.rs @@ -44,6 +44,9 @@ pub fn render_page(title: &str, content: Markup) -> Markup { (DOCTYPE) head { link rel="stylesheet" href={(HTTP_PATH) "/style.css"}; + title { + (title) + } } body { (content) diff --git a/btrfs_explorer_bin/src/main.rs b/btrfs_explorer_bin/src/main.rs index f9eb27b..24df14a 100644 --- a/btrfs_explorer_bin/src/main.rs +++ b/btrfs_explorer_bin/src/main.rs @@ -1,16 +1,9 @@ use std::{ - collections::HashMap, env, fs::{File, OpenOptions}, iter, + env, fs::{File, OpenOptions}, }; use memmap2::MmapOptions; -use rouille::{Request, Response, router}; -use btrfs_explorer::{ - btrfs_structs::{TreeID, Value::Extent, Value::BlockGroup, NODE_SIZE, ItemType}, - btrfs_lookup::Tree, - addrmap::AddressMap, - main_error::MainError, -}; - -const COLORS: &[&str] = &["#e6194b", "#3cb44b", "#ffe119", "#4363d8", "#f58231", "#911eb4", "#46f0f0", "#f032e6", "#bcf60c", "#fabebe", "#008080", "#e6beff", "#9a6324", "#fffac8", "#800000", "#aaffc3", "#808000", "#ffd8b1", "#000075", "#808080", "#000000"]; +use rouille::{Response, router}; +use btrfs_explorer::main_error::MainError; fn main() -> Result<(), MainError> { let filename = env::args().skip(1).next().ok_or("Argument required")?; @@ -23,17 +16,6 @@ fn main() -> Result<(), MainError> { let file = OpenOptions::new().read(true).open(filename)?; let image = unsafe { MmapOptions::new().len(493921239040usize).map(&file)? }; -// return Ok(()); - - /* - let mystery_addr = 0x2f_2251_c000; - let addr_map = AddressMap::new(&image)?; - let mystery_addr_phys = addr_map.to_phys(mystery_addr).unwrap() as usize; - let mystery_node = Node::parse(&image[mystery_addr_phys .. ])?; - - println!("{:#x?}", &mystery_node); -*/ - rouille::start_server("127.0.0.1:8080", move |request| { router!( request, @@ -58,218 +40,3 @@ fn main() -> Result<(), MainError> { ) }); } - -static CIRCLE_IMAGE: &str = - "data:image/png;base64,\ - iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAP0lEQVQY02NgoBn4//+//P///yf9\ - ////DRRP+v//vzw2hZP+Y4JJ2BS+waLwDUyeiVinIStchkV+GfmeoRoAAJqLWnEf4UboAAAAAElF\ - TkSuQmCC"; - -static EXPLANATION_TEXT: &str = "\ -

Chunks

-

On the highest level, btrfs splits the disk into chunks (also called block groups). They can have different sizes, with 1GiB being typical in a large file system. Each chunk can either contain data or metadata.

- -

Here we look at the metadata chunks. They contain the B-treesm which btrfs gets its name from. They are key-value stores for different kinds of information. For example, the filesystem tree stores which files and directories are in the filesystem, and the extent tree stores which areas of the disk are in use. Each B-tree consists of a number of 16KiB nodes, here symbolized by colorful boxes, with the color indicating which tree the node belongs to. Most of the nodes are leaves, which contain the actual key-value pairs. The others are interior nodes, and we indicate them with a little white circle. They are important to find the leaf a key is stored in.

"; - -fn http_main_boxes(image: &[u8], _req: &Request) -> Response { - let mut treecolors: HashMap = HashMap::new(); - - let mut result = String::new(); - - let explanation_tablerowformat = |c: &str, t: &str| format!( - "\ -
\ -
\ - {}\ - \n", - c, c, CIRCLE_IMAGE, t); - let explanation_tablerowformat_leafonly = |c,t| format!( - "\ -
\ - \ - {}\ - \n", - c, t); - - let cellformat = |c| format!( - "\n", - c); - let cellformat_higher = |c,_| format!( - "\n", - c, CIRCLE_IMAGE); - - result.push_str(&"
\nWhat am I seeing here?"); - result.push_str(EXPLANATION_TEXT); - - // tree explanations - result.push_str(&"\n"); - result.push_str(&explanation_tablerowformat_leafonly("lightgrey", "unused or outdated node")); - treecolors.insert(1, COLORS[treecolors.len() % COLORS.len()]); - result.push_str(&explanation_tablerowformat(treecolors[&1], "root tree")); - - treecolors.insert(3, COLORS[treecolors.len() % COLORS.len()]); - result.push_str(&explanation_tablerowformat(treecolors[&3], "chunk tree")); - - let roots = Tree::root(image).unwrap(); - for item in roots.iter() { - if item.key.key_type == ItemType::Root { - let treedesc: String = match &item.key.key_id { - 1 => format!("root tree"), - 2 => format!("extent tree"), - 3 => format!("chunk tree"), - 4 => format!("device tree"), - 5 => format!("filesystem tree"), - 6 => format!("root directory"), - 7 => format!("checksum tree"), - 8 => format!("quota tree"), - 9 => format!("UUID tree"), - 10 => format!("free space tree"), - 11 => format!("block group tree"), - 0xffff_ffff_ffff_fff7 => format!("data reloc tree"), - x @ 0x100 ..= 0xffff_ffff_ffff_feff => format!("file tree, id = {}", x), - x => format!("other tree, id = {}", x), - }; - - treecolors.insert(item.key.key_id, COLORS[treecolors.len() % COLORS.len()]); - result.push_str(&explanation_tablerowformat( - treecolors[&item.key.key_id], - &treedesc - )); - } - } - result.push_str(&"
\n"); - result.push_str(&"
\n"); - - let extent_tree = Tree::new(&image, TreeID::Extent).unwrap(); - let mut extent_tree_iterator = extent_tree.iter(); - - // current_blockgroup == None: haven't encountered a blockgroup yet - // metadata_items == None: current blockgroup is not metadata or system - let mut current_blockgroup = None; - let mut metadata_items: Option>> = None; - - let metadata_blockgroups = iter::from_fn(|| { - while let Some(item) = extent_tree_iterator.next() { -// println!("Got key: {:x?}", &item.key); - match &item.value { - BlockGroup(bg) => { - println!("{:x?}", item.key); - let result = (current_blockgroup.take(), metadata_items.take()); - - let nodes_in_blockgroup = item.key.key_offset as usize / NODE_SIZE; - if bg.flags & 0x01 == 0 { - metadata_items = Some(vec![None; nodes_in_blockgroup]); - } else { - metadata_items = None; - } - current_blockgroup = Some(item); - - if let (Some(bg), met) = result { - return Some((bg, met)); - } - }, - Extent(e) => { - if let Some(bg_item) = ¤t_blockgroup { - if let Some(met) = &mut metadata_items { - let bg_start = bg_item.key.key_id; - let node_addr = item.key.key_id; - let tree_id = e.block_refs.iter().count() as u64; - let index = (node_addr - bg_start) as usize / NODE_SIZE; - if index < met.len() { - met[index] = Some((tree_id, item.key.key_offset)); - } else { - println!("Warning: extent out of block group range: {:x?}", &item.key); - } - } - } else { - println!("Warning: extent without matching block group: {:x?}", &item.key); - } - }, - _ => {},//panic!("Unexpected item in extent tree: {:x?}", item.key) - } - } - - let result = (current_blockgroup.take(), metadata_items.take()); - if let (Some(bg), met) = result { - return Some((bg, met)); - } else { - return None; - } - }); - - let mut last_key = 0; - - // colorful table - for (bg, nodes) in metadata_blockgroups { - if bg.key.key_id < last_key { - println!("Error: going backwards!"); - break; - } else { - last_key = bg.key.key_id; - } - - let bg_value = match &bg.value { - BlockGroup(bgv) => bgv, - _ => panic!("Expected BlockGroup value"), - }; - - // header - let addr_map: &AddressMap = extent_tree.reader.as_ref().addr_map(); - result.push_str( - &format!( - "

{:x} - {:x} ({}, {})

Physical: {}

\n", - bg.key.key_id, - bg.key.key_id + bg.key.key_offset, - match bg.key.key_offset { - x if x <= (1<<11) => format!("{} B", x), - x if x <= (1<<21) => format!("{} KiB", x as f64 / (1u64<<10) as f64), - x if x <= (1<<31) => format!("{} MiB", x as f64 / (1u64<<20) as f64), - x if x <= (1<<41) => format!("{} GiB", x as f64 / (1u64<<30) as f64), - x if x <= (1<<51) => format!("{} TiB", x as f64 / (1u64<<40) as f64), - x @ _ => format!("{} PiB", x as f64 / (1u64<<50) as f64), - }, - match bg_value.flags & 0x07 { - 0x01 => "Data", - 0x02 => "System", - 0x04 => "Metadata", - _ => "???", - }, - match addr_map.0.binary_search_by_key(&bg.key.key_id, |x|x.0) { - Ok(i) => format!("{:x?}", &addr_map.0[i].2), - _ => String::from(""), - } - ) - ); - - if let Some(nodes) = nodes { - result.push_str("\n\n"); - - for (i, &n) in nodes.iter().enumerate() { - if i % 64 == 0 && i != 0 { - result.push_str("\n\n"); - } - - if let Some((tid, level)) = n { - let color: Option<&str> = treecolors.get(&tid).map(|x|*x); - let color = color.unwrap_or_else(|| { - println!("Unknown color for id: {}", &tid); - let color: &str = COLORS[treecolors.len() % COLORS.len()]; - treecolors.insert(tid, color); - color - }); - if level == 0 { - result.push_str(&cellformat(color)); - } else { - result.push_str(&cellformat_higher(color, level)); - } - } else { - result.push_str(&cellformat("lightgrey")); - } - } - - result.push_str("\n
\n"); - } - } - - Response::html(result) -}