improved error handling

This commit is contained in:
Florian Stecker 2023-08-03 19:38:41 -04:00
parent 5d0ac786b1
commit 4d1e08863a
3 changed files with 25 additions and 22 deletions

View File

@ -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<AddressMap,String> {
pub fn new(image: &[u8]) -> Result<AddressMap, ParseError> {
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<AddressMap,String> {
pub fn from_superblock(superblock: &Superblock) -> Result<AddressMap, ParseError> {
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();

View File

@ -390,15 +390,15 @@ impl From<ParseError> 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<Self, String> {
fn parse(bytes: &[u8]) -> Result<Self, ParseError> {
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<const N: usize> 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<const N: usize> ParseBin for [u8; N] {
// we use Vec<u8> for "unknown extra data", so just eat up everything
impl ParseBin for Vec<u8> {
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<u8> 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..])?;

View File

@ -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);