diff --git a/src/addrmap.rs b/src/addrmap.rs index eb66d60..ad0e3d4 100644 --- a/src/addrmap.rs +++ b/src/addrmap.rs @@ -1,11 +1,11 @@ -use crate::btrfs_structs::{ParseBin, Key, ChunkItem, Leaf, Value, Superblock, LogToPhys}; +use crate::btrfs_structs::{ParseBin, Key, ChunkItem, Leaf, Value, Superblock, LogToPhys, ParseError}; #[derive(Debug)] pub struct AddressMap(Vec<(u64,u64,Vec<(u64,u64)>)>); // TODO: support for internal nodes, multiple devices? impl AddressMap { - pub fn new(image: &[u8]) -> Result { + pub fn new(image: &[u8]) -> Result { let superblock = Superblock::parse(&image[0x10000..])?; let bootstrap_addr = AddressMap::from_superblock(&superblock)?; @@ -36,7 +36,7 @@ impl AddressMap { Ok(AddressMap(addr_map)) } - pub fn from_superblock(superblock: &Superblock) -> Result { + pub fn from_superblock(superblock: &Superblock) -> Result { let sys_chunk_array_size = superblock.sys_chunk_array_size; let sys_chunk_array: &[u8] = &superblock.sys_chunk_array; let mut addr_map = Vec::new(); diff --git a/src/btrfs_structs.rs b/src/btrfs_structs.rs index 2a50ace..755dd92 100644 --- a/src/btrfs_structs.rs +++ b/src/btrfs_structs.rs @@ -390,15 +390,15 @@ impl From for io::Error { } pub trait ParseBin where Self: Sized { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String>; + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError>; - fn parse(bytes: &[u8]) -> Result { + fn parse(bytes: &[u8]) -> Result { Self::parse_len(bytes).map(|x|x.0) } } impl ParseBin for u8 { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> { if bytes.len() < 1 { Err("not enough data".into()) } else { @@ -408,7 +408,7 @@ impl ParseBin for u8 { } impl ParseBin for u16 { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> { if bytes.len() < 2 { Err("not enough data".into()) } else { @@ -419,7 +419,7 @@ impl ParseBin for u16 { } impl ParseBin for u32 { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> { if bytes.len() < 4 { Err("not enough data".into()) } else { @@ -430,7 +430,7 @@ impl ParseBin for u32 { } impl ParseBin for u64 { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> { if bytes.len() < 8 { Err("not enough data".into()) } else { @@ -441,7 +441,7 @@ impl ParseBin for u64 { } impl ParseBin for [u8; N] { - fn parse_len(bytes: &[u8]) -> Result<([u8; N], usize), String> { + fn parse_len(bytes: &[u8]) -> Result<([u8; N], usize), ParseError> { if bytes.len() < N { Err("not enough data".into()) } else { @@ -452,13 +452,13 @@ impl ParseBin for [u8; N] { // we use Vec for "unknown extra data", so just eat up everything impl ParseBin for Vec { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> { Ok((Vec::from(bytes), bytes.len())) } } impl ParseBin for CString { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> { let mut chars = Vec::from(bytes); chars.push(0); Ok((CString::from_vec_with_nul(chars).unwrap(), bytes.len())) @@ -484,13 +484,13 @@ impl From for ItemType { } impl ParseBin for ItemType { - fn parse_len(bytes: &[u8]) -> Result<(ItemType, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(ItemType, usize), ParseError> { u8::parse(bytes).map(|x|(ItemType::from(x),1)) } } impl ParseBin for Leaf { - fn parse_len(bytes: &[u8]) -> Result<(Leaf, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Leaf, usize), ParseError> { if bytes.len() < 0x65 { return Err("not enough data".into()); } @@ -551,7 +551,7 @@ impl ParseBin for Leaf { // ExtentDataItem needs a custom implementation because it can have inline or external data impl ParseBin for ExtentDataItem { - fn parse_len(bytes: &[u8]) -> Result<(Self, usize), String> { + fn parse_len(bytes: &[u8]) -> Result<(Self, usize), ParseError> { let (header, header_size) = ExtentDataHeader::parse_len(bytes)?; if header.extent_type == 1 { // external extent let (body, body_size) = ExternalExtent::parse_len(&bytes[header_size..])?; diff --git a/src/main.rs b/src/main.rs index 0fdb3ef..9f54a5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,16 +21,19 @@ fn main() -> Result<(), IOError> { let file = File::open("../image")?; let image = unsafe { Mmap::map(&file)? }; - let addr = AddressMap::new(&image).map_err(|e|IOError::other(e))?; - let superblock = Superblock::parse(&image[0x10000..]).map_err(|e|IOError::other(e))?; + let addr = AddressMap::new(&image).unwrap(); + let superblock = Superblock::parse(&image[0x10000..]).unwrap(); - let chunk_root_phys = addr.to_phys(superblock.chunk_root).unwrap() as usize; - let root_phys = addr.to_phys(superblock.root).unwrap() as usize; + let chunk_root_phys = addr.to_phys(superblock.chunk_root) + .ok_or(IOError::other("Chunk root address stored in superblock is invalid"))? as usize; + let root_phys = addr.to_phys(superblock.root) + .ok_or(IOError::other("Root address stored in superblock is invalid"))? as usize; - let root_tree_leaf = Leaf::parse(&image[root_phys .. root_phys + NODE_SIZE]).map_err(|e|IOError::other(e))?; + let root_tree_leaf = Leaf::parse(&image[root_phys .. root_phys + NODE_SIZE])?; let root_key = Key::new(EXTENT_TREE, ItemType::Root, 0); - let root = root_tree_leaf.find_key(root_key).unwrap(); + let root = root_tree_leaf.find_key(root_key) + .ok_or(IOError::other("Could not find extent tree in tree of roots"))?; let root_addr = if let Value::Root(root_item) = root.value { addr.to_phys(root_item.bytenr) @@ -38,7 +41,7 @@ fn main() -> Result<(), IOError> { None }.unwrap() as usize; - let tree_leaf = Leaf::parse(&image[root_addr .. root_addr + NODE_SIZE]).map_err(|e|IOError::other(e))?; + let tree_leaf = Leaf::parse(&image[root_addr .. root_addr + NODE_SIZE])?; println!("{:#?}", &tree_leaf);