check size of items
This commit is contained in:
		
							parent
							
								
									bc852d6b6a
								
							
						
					
					
						commit
						b41547ddcb
					
				| @ -12,11 +12,11 @@ pub const NODE_SIZE: usize = 0x4000; | ||||
| #[derive(Debug,Clone,Copy,AllVariants,PartialEq,Eq,PartialOrd,Ord)] | ||||
| #[repr(u8)] | ||||
| pub enum ItemType { | ||||
| 	Invalid = 0x00,           // invalid
 | ||||
| 	Invalid = 0x00,           // invalid, but seems to exist?
 | ||||
| 	Inode = 0x01,             // implemented
 | ||||
| 	Ref = 0x0c,               // implemented
 | ||||
| 	ExtRef = 0x0d, | ||||
| 	XAttr = 0x18, | ||||
| 	XAttr = 0x18,             // TODO
 | ||||
| 	VerityDesc = 0x24, | ||||
| 	VerityMerkle = 0x25, | ||||
| 	Orphan = 0x30, | ||||
| @ -25,12 +25,12 @@ pub enum ItemType { | ||||
| 	Dir = 0x54,               // implemented (better with len feature; allow multiple?)
 | ||||
| 	DirIndex = 0x60,          // implemented
 | ||||
| 	ExtentData = 0x6c,        // implemented
 | ||||
| 	ExtentCsum = 0x80, | ||||
| 	ExtentCsum = 0x80,        // TODO
 | ||||
| 	Root = 0x84,              // implemented
 | ||||
| 	RootBackRef = 0x90, | ||||
| 	RootRef = 0x9c, | ||||
| 	Extent = 0xa8,            // implemented (with only one version of extra data)
 | ||||
| 	Metadata = 0xa9,          // implemented (with only one version of extra data)
 | ||||
| 	RootBackRef = 0x90,       // implemented
 | ||||
| 	RootRef = 0x9c,           // implemented
 | ||||
| 	Extent = 0xa8,            // implemented (with only one version of extra data!!)
 | ||||
| 	Metadata = 0xa9,          // implemented (with only one version of extra data!!)
 | ||||
| 	TreeBlockRef = 0xb0, | ||||
| 	ExtentDataRef = 0xb2, | ||||
| 	ExtentRefV0 = 0xb4, | ||||
| @ -53,7 +53,7 @@ pub enum ItemType { | ||||
| 	UUIDSubvol = 0xfb,        // implemented
 | ||||
| 	UUIDReceivedSubvol = 0xfc, | ||||
| 	String = 0xfd, | ||||
| 	InvalidMax = 0xff, | ||||
| 	InvalidMax = 0xff,        // invalid
 | ||||
| } | ||||
| 
 | ||||
| #[allow(unused)] | ||||
| @ -309,6 +309,8 @@ pub struct RootItem { | ||||
| 	pub otime: Time, | ||||
| 	pub stime: Time, | ||||
| 	pub rtime: Time, | ||||
| 
 | ||||
| 	data: Vec<u8>, | ||||
| } | ||||
| 
 | ||||
| #[allow(unused)] | ||||
| @ -320,7 +322,7 @@ pub struct DirItem { | ||||
| 	pub name_len: u16, | ||||
| 	pub dir_type: u8, | ||||
| 
 | ||||
| //	#[len = "name_len"]
 | ||||
| 	#[len = "name_len"] | ||||
| 	pub name: CString, | ||||
| } | ||||
| 
 | ||||
| @ -406,7 +408,7 @@ pub struct RefItem { | ||||
| 	pub index: u64, | ||||
| 	pub name_len: u16, | ||||
| 
 | ||||
| 	//	#[len = "name_len"]
 | ||||
| 	#[len = "name_len"] | ||||
| 	pub name: CString, | ||||
| } | ||||
| 
 | ||||
| @ -416,6 +418,8 @@ pub struct RootRefItem { | ||||
| 	pub directory: u64, | ||||
| 	pub index: u64, | ||||
| 	pub name_len: u16, | ||||
| 
 | ||||
| 	#[len = "name_len"] | ||||
| 	pub name: CString, | ||||
| } | ||||
| 
 | ||||
| @ -571,6 +575,14 @@ impl ParseBin for ItemType { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn parse_check_size<T: ParseBin>(bytes: &[u8]) -> Result<T, ParseError> { | ||||
| 	let (result, real_len) = T::parse_len(bytes)?; | ||||
| 	if real_len != bytes.len() { | ||||
| 		eprintln!("{} parsing incomplete! Parsed {} of {} bytes", std::any::type_name::<T>(), real_len, bytes.len()); | ||||
| 	} | ||||
| 	Ok(result) | ||||
| } | ||||
| 
 | ||||
| impl ParseBin for Node { | ||||
| 	fn parse_len(bytes: &[u8]) -> Result<(Node, usize), ParseError> { | ||||
| 
 | ||||
| @ -604,45 +616,45 @@ impl ParseBin for Node { | ||||
| 
 | ||||
| 				let value = match key.key_type { | ||||
| 					ItemType::BlockGroup => | ||||
| 						Value::BlockGroup(BlockGroupItem::parse(data_slice)?), | ||||
| 						Value::BlockGroup(parse_check_size(data_slice)?), | ||||
| 					ItemType::Metadata => { | ||||
| 						let item = ExtentItem::parse(data_slice)?; | ||||
| 						let item: ExtentItem = parse_check_size(data_slice)?; | ||||
| 						if item.flags != 2 || item.refs > 1 { | ||||
| 							println!("Metadata item with refs = {}, flags = {}, data = {:x?}", item.refs, item.flags, &data_slice[0x18..]); | ||||
| 						} | ||||
| 						Value::Extent(item) | ||||
| 					}, | ||||
| 					ItemType::Extent => | ||||
| 						Value::Extent(ExtentItem::parse(data_slice)?), | ||||
| 						Value::Extent(parse_check_size(data_slice)?), | ||||
| 					ItemType::Inode => | ||||
| 						Value::Inode(InodeItem::parse(data_slice)?), | ||||
| 						Value::Inode(parse_check_size(data_slice)?), | ||||
| 					ItemType::Root => | ||||
| 						Value::Root(RootItem::parse(data_slice)?), | ||||
| 						Value::Root(parse_check_size(data_slice)?), | ||||
| 					ItemType::Dir => | ||||
| 						Value::Dir(DirItem::parse(data_slice)?), | ||||
| 						Value::Dir(parse_check_size(data_slice)?), | ||||
| 					ItemType::DirIndex => | ||||
| 						Value::DirIndex(DirItem::parse(data_slice)?), | ||||
| 						Value::DirIndex(parse_check_size(data_slice)?), | ||||
| 					ItemType::Chunk => | ||||
| 						Value::Chunk(ChunkItem::parse(data_slice)?), | ||||
| 						Value::Chunk(parse_check_size(data_slice)?), | ||||
| 					ItemType::FreeSpaceInfo => | ||||
| 						Value::FreeSpaceInfo(FreeSpaceInfoItem::parse(data_slice)?), | ||||
| 						Value::FreeSpaceInfo(parse_check_size(data_slice)?), | ||||
| 					ItemType::FreeSpaceExtent => | ||||
| 						Value::FreeSpaceExtent, | ||||
| 					ItemType::UUIDSubvol => | ||||
| 						Value::UUIDSubvol(UUIDSubvolItem::parse(data_slice)?), | ||||
| 						Value::UUIDSubvol(parse_check_size(data_slice)?), | ||||
| 					ItemType::Dev => | ||||
| 						Value::Dev(DevItem::parse(data_slice)?), | ||||
| 						Value::Dev(parse_check_size(data_slice)?), | ||||
| 					ItemType::DevExtent => | ||||
| 						Value::DevExtent(DevExtentItem::parse(data_slice)?), | ||||
| 						Value::DevExtent(parse_check_size(data_slice)?), | ||||
| 					ItemType::ExtentData => | ||||
| 						Value::ExtentData(ExtentDataItem::parse(data_slice)?), | ||||
| 						Value::ExtentData(parse_check_size(data_slice)?), | ||||
| 					ItemType::Ref => { | ||||
| 						Value::Ref(RefItem::parse(data_slice)?) | ||||
| 						Value::Ref(parse_check_size(data_slice)?) | ||||
| 					} | ||||
| 					ItemType::RootRef => | ||||
| 						Value::RootRef(RootRefItem::parse(data_slice)?), | ||||
| 						Value::RootRef(parse_check_size(data_slice)?), | ||||
| 					ItemType::RootBackRef => | ||||
| 						Value::RootRef(RootRefItem::parse(data_slice)?), | ||||
| 						Value::RootRef(parse_check_size(data_slice)?), | ||||
| 					_ => | ||||
| 						Value::Unknown(Vec::from(data_slice)), | ||||
| 				}; | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| use crate::btrfs_structs::{Item, Key, ItemType, Value, ExtentDataBody}; | ||||
| use crate::render_common::{DebugRender, Hex, size_name}; | ||||
| use crate::render_common::{Hex, size_name}; | ||||
| use maud::{Markup, html, DOCTYPE, PreEscaped}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| @ -205,7 +205,7 @@ fn item_value_string(tree_id: u64, item: &Item) -> Markup { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn item_details_string(tree_id: u64, item: &Item) -> Markup { | ||||
| fn item_details_string(_tree_id: u64, item: &Item) -> Markup { | ||||
| 	match &item.value { | ||||
| 		Value::Inode(inode_item) => { | ||||
| 			html! { table { tbody { | ||||
| @ -222,7 +222,7 @@ fn item_details_string(tree_id: u64, item: &Item) -> Markup { | ||||
| 		}, | ||||
| 		Value::ExtentData(extent_item) => { | ||||
| 			match &extent_item.data { | ||||
| 				ExtentDataBody::Inline(data) => { | ||||
| 				ExtentDataBody::Inline(_data) => { | ||||
| 					html! {} // we really want data as string / hex
 | ||||
| 				}, | ||||
| 				ExtentDataBody::External(ext_extent) => { | ||||
| @ -255,7 +255,6 @@ fn item_details_string(tree_id: u64, item: &Item) -> Markup { | ||||
| 			}}} | ||||
| 		}, | ||||
| 		Value::Root(root_item) => { | ||||
| 			let inode = &root_item.inode; | ||||
| 			html! { table { tbody { | ||||
| 				tr { td { "root dir id" } td { (format!("{:X}", root_item.root_dirid)) } } | ||||
| 				tr { td { "logical address" } td { (format!("{:X}", root_item.bytenr)) } } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use std::{ | ||||
| 	collections::HashMap, env, fs::{File, OpenOptions}, iter, | ||||
| }; | ||||
| use memmap2::{Mmap, MmapOptions}; | ||||
| use memmap2::MmapOptions; | ||||
| use rouille::{Request, Response, router}; | ||||
| use btrfs_explorer::{ | ||||
| 	btrfs_structs::{TreeID, Value::Extent, Value::BlockGroup, NODE_SIZE, ItemType}, | ||||
| @ -20,7 +20,6 @@ fn main() -> Result<(), MainError> { | ||||
| 	let image = unsafe { Mmap::map(&file)? }; | ||||
| 	*/ | ||||
| 
 | ||||
| 	const O_DIRECT: i32 = 0x4000; | ||||
| 	let file = OpenOptions::new().read(true).open(filename)?; | ||||
| 	let image = unsafe { MmapOptions::new().len(493921239040usize).map(&file)? }; | ||||
| 
 | ||||
|  | ||||
| @ -1,9 +1,4 @@ | ||||
| extern crate proc_macro; | ||||
| extern crate syn; | ||||
| #[macro_use] | ||||
| extern crate quote; | ||||
| extern crate proc_macro2; | ||||
| 
 | ||||
| use quote::{quote, format_ident}; | ||||
| use proc_macro2::Span; | ||||
| use proc_macro::TokenStream; | ||||
| use syn::{DeriveInput, Data::Enum, parse_macro_input}; | ||||
| @ -40,7 +35,7 @@ pub fn derive_parse_bin(input: TokenStream) -> TokenStream { | ||||
| 		syn::Data::Struct(struct_item) => { | ||||
| 			match struct_item.fields { | ||||
| 				syn::Fields::Named(fields_named) => { | ||||
| 					return derive_parse_bin_struct(&name, &fields_named.named); | ||||
| 					derive_parse_bin_struct(&name, &fields_named.named) | ||||
| 				}, | ||||
| 				syn::Fields::Unnamed(fields_unnamed) => { | ||||
| 					if fields_unnamed.unnamed.len() != 1 { | ||||
| @ -48,13 +43,13 @@ pub fn derive_parse_bin(input: TokenStream) -> TokenStream { | ||||
| 					} | ||||
| 
 | ||||
| 					let inner_type = fields_unnamed.unnamed.into_iter().next().unwrap().ty; | ||||
| 					return derive_parse_bin_alias(name, inner_type); | ||||
| 					derive_parse_bin_alias(name, inner_type) | ||||
| 				}, | ||||
| 				_ => panic!("ParseBin on unit structs makes no sense!"), | ||||
| 			} | ||||
| 		}, | ||||
| 		_ => panic!("ParseBin only works on structs so far!"), | ||||
| 	}; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn derive_parse_bin_alias(name: syn::Ident, ty: syn::Type) -> TokenStream { | ||||
| @ -113,49 +108,48 @@ fn derive_parse_bin_struct<'a, T>(name: &syn::Ident, fields: T) -> TokenStream | ||||
| 		if let Some(varname) = veclen { | ||||
| 			let field_name_item = format_ident!("{}_item", field_name); | ||||
| 
 | ||||
| 			let field_type_item: &syn::Type = match &field_type { | ||||
| 				syn::Type::Path(tp) => { | ||||
| 					match tp.path.segments.iter().next() { | ||||
| 						Some(single) => { | ||||
| 							if &single.ident.to_string() == "Vec" { | ||||
| 								match &single.arguments { | ||||
| 									syn::PathArguments::AngleBracketed(args) => { | ||||
| 										match args.args.iter().next() { | ||||
| 											Some(firstarg) => { | ||||
| 												match firstarg { | ||||
| 													syn::GenericArgument::Type(ty) => { | ||||
| 														Some(ty) | ||||
| 													}, | ||||
| 													_ => None, | ||||
| 												} | ||||
| 											}, | ||||
| 											None => None, | ||||
| 										} | ||||
| 									}, | ||||
| 									_ => None, | ||||
| 								} | ||||
| 							} else { | ||||
| 								None | ||||
| 							} | ||||
| 						}, | ||||
| 						None => None, | ||||
| 					} | ||||
| 				}, | ||||
| 				_ => None, | ||||
| 			}.expect("The len attribute is only allowed on type Vec<_>"); | ||||
| 			enum FieldType<'a> { | ||||
| 				Vec(&'a syn::Type), | ||||
| 				CString, | ||||
| 			} | ||||
| 
 | ||||
| 			let syn::Type::Path(tp) = &field_type else { panic!() }; | ||||
| 			let single = tp.path.segments.iter().next().unwrap(); | ||||
| 
 | ||||
| 			let field_type = if &single.ident.to_string() ==  "Vec" { | ||||
| 				let syn::PathArguments::AngleBracketed(args) = &single.arguments else { panic!() }; | ||||
| 				let firstarg = args.args.iter().next().unwrap(); | ||||
| 				let syn::GenericArgument::Type(ty) = firstarg else { panic!() }; | ||||
| 				FieldType::Vec(ty) | ||||
| 			} else if &single.ident.to_string() == "CString" { | ||||
| 				FieldType::CString | ||||
| 			} else { | ||||
| 				panic!("The len attribute is only allowed on Vec<_> or CString") | ||||
| 			}; | ||||
| 
 | ||||
| 			let varname_ident = syn::Ident::new(&varname, Span::call_site()); | ||||
| 
 | ||||
| 			parsing_statements.push(quote!{ | ||||
| 				let mut #field_name = Vec::new(); | ||||
| 				for i in 0 .. #varname_ident.0 as usize { | ||||
| 					let #field_name_item = <#field_type_item>::parse_len(&bytes[__parse_bin_derive_size..])?; | ||||
| 					__parse_bin_derive_size += #field_name_item.1; | ||||
| 					#field_name.push(#field_name_item.0); | ||||
| 				} | ||||
| 			}); | ||||
| 
 | ||||
| 			combining_expressions.push(quote!(#field_name: #field_name)); | ||||
| 			match field_type { | ||||
| 				FieldType::Vec(field_type_item) => { | ||||
| 					parsing_statements.push(quote!{ | ||||
| 						let mut #field_name = Vec::new(); | ||||
| 						for i in 0 .. #varname_ident.0 as usize { | ||||
| 							let #field_name_item = <#field_type_item>::parse_len(&bytes[__parse_bin_derive_size..])?; | ||||
| 							__parse_bin_derive_size += #field_name_item.1; | ||||
| 							#field_name.push(#field_name_item.0); | ||||
| 						} | ||||
| 					}); | ||||
| 					combining_expressions.push(quote!(#field_name: #field_name)); | ||||
| 				}, | ||||
| 				FieldType::CString => { | ||||
| 					parsing_statements.push(quote!{ | ||||
| 						let #field_name = CString::parse_len(&bytes[__parse_bin_derive_size .. __parse_bin_derive_size + #varname_ident.0 as usize])?; | ||||
| 						__parse_bin_derive_size += #varname_ident.0 as usize; | ||||
| 					}); | ||||
| 					combining_expressions.push(quote!(#field_name: #field_name.0)); | ||||
| 				}, | ||||
| 			} | ||||
| 		} else { | ||||
| 			parsing_statements.push(quote!{ | ||||
| 				let #field_name = <#field_type>::parse_len(&bytes[__parse_bin_derive_size..])?; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user