improved error handling
This commit is contained in:
parent
5d0ac786b1
commit
4d1e08863a
@ -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();
|
||||
|
@ -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..])?;
|
||||
|
17
src/main.rs
17
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user