redo error handling

This commit is contained in:
Szymon Walter 2018-03-21 20:40:39 +01:00
parent 934266ca4b
commit 117b8d4e75
7 changed files with 137 additions and 113 deletions

View file

@ -1,15 +1,60 @@
use core::fmt::{self, Display};
use alloc::String;
#[cfg(any(test, not(feature = "no_std")))] #[cfg(any(test, not(feature = "no_std")))]
use std::io; use std::io;
/// The set of all possible errors /// The set of all possible errors
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
BadMagic(u16), Other(String),
OutOfBounds(usize), BadMagic {
AddressOutOfBounds(u32, u32, usize), magic: u16,
BadBlockGroupCount(u32, u32), },
OutOfBounds {
index: usize,
},
AddressOutOfBounds {
sector: u32,
offset: u32,
size: usize,
},
BadBlockGroupCount {
by_blocks: u32,
by_inodes: u32,
},
#[cfg(any(test, not(feature = "no_std")))] #[cfg(any(test, not(feature = "no_std")))]
Io(io::Error), Io {
inner: io::Error,
},
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Other(ref msg) => write!(f, "{}", msg),
Error::BadMagic {
magic,
} => write!(f, "invalid magic value: {}", magic),
Error::OutOfBounds {
index,
} => write!(f, "index ouf of bounds: {}", index),
Error::AddressOutOfBounds {
sector,
offset,
size,
} => write!(f, "address ouf of bounds: {}:{} with a block size of: {}",
sector, offset, size),
Error::BadBlockGroupCount {
by_blocks,
by_inodes,
} => write!(f, "conflicting block group count data; by blocks: {}, by inodes: {}", by_blocks, by_inodes),
#[cfg(any(test, not(feature = "no_std")))]
Error::Io {
ref inner,
} => write!(f, "io error: {}", inner),
}
}
} }
impl From<Infallible> for Error { impl From<Infallible> for Error {
@ -20,34 +65,8 @@ impl From<Infallible> for Error {
#[cfg(any(test, not(feature = "no_std")))] #[cfg(any(test, not(feature = "no_std")))]
impl From<io::Error> for Error { impl From<io::Error> for Error {
fn from(err: io::Error) -> Error { fn from(inner: io::Error) -> Error {
Error::Io(err) Error::Io { inner }
}
}
impl PartialEq for Error {
fn eq(&self, rhs: &Error) -> bool {
match (self, rhs) {
(&Error::BadMagic(a), &Error::BadMagic(b)) => a == b,
(&Error::OutOfBounds(a), &Error::OutOfBounds(b)) => a == b,
(
&Error::BadBlockGroupCount(a1, a2),
&Error::BadBlockGroupCount(b1, b2),
) => a1 == b1 && a2 == b2,
_ => false,
}
}
fn ne(&self, rhs: &Error) -> bool {
match (self, rhs) {
(&Error::BadMagic(a), &Error::BadMagic(b)) => a != b,
(&Error::OutOfBounds(a), &Error::OutOfBounds(b)) => a != b,
(
&Error::BadBlockGroupCount(a1, a2),
&Error::BadBlockGroupCount(b1, b2),
) => a1 != b1 || a2 != b2,
_ => false,
}
} }
} }

View file

@ -30,10 +30,7 @@ pub struct Ext2<S: Size, V: Volume<u8, Address<S>>> {
block_groups: Struct<Vec<BlockGroupDescriptor>, S>, block_groups: Struct<Vec<BlockGroupDescriptor>, S>,
} }
impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
where
Error: From<V::Error>,
{
pub fn new(volume: V) -> Result<Ext2<S, V>, Error> { pub fn new(volume: V) -> Result<Ext2<S, V>, Error> {
let superblock = unsafe { Struct::from(Superblock::find(&volume)?) }; let superblock = unsafe { Struct::from(Superblock::find(&volume)?) };
let block_groups_offset = Address::with_block_size( let block_groups_offset = Address::with_block_size(
@ -45,7 +42,10 @@ where
.inner .inner
.block_group_count() .block_group_count()
.map(|count| count as usize) .map(|count| count as usize)
.map_err(|(a, b)| Error::BadBlockGroupCount(a, b))?; .map_err(|(a, b)| Error::BadBlockGroupCount {
by_blocks: a,
by_inodes: b,
})?;
let block_groups = unsafe { let block_groups = unsafe {
BlockGroupDescriptor::find_descriptor_table( BlockGroupDescriptor::find_descriptor_table(
&volume, &volume,
@ -70,7 +70,7 @@ where
self.superblock.offset, self.superblock.offset,
); );
let commit = slice.commit(); let commit = slice.commit();
self.volume.commit(commit).map_err(|err| Error::from(err))?; self.volume.commit(commit).map_err(|err| err.into())?;
} }
// block group descriptors // block group descriptors
@ -78,7 +78,7 @@ where
for descr in &self.block_groups.inner { for descr in &self.block_groups.inner {
let slice = VolumeSlice::from_cast(descr, offset); let slice = VolumeSlice::from_cast(descr, offset);
let commit = slice.commit(); let commit = slice.commit();
self.volume.commit(commit).map_err(|err| Error::from(err))?; self.volume.commit(commit).map_err(|err| err.into())?;
offset = offset =
offset + Address::from(mem::size_of::<BlockGroupDescriptor>()); offset + Address::from(mem::size_of::<BlockGroupDescriptor>());
} }
@ -96,13 +96,18 @@ where
let block_size = self.block_size(); let block_size = self.block_size();
let offset = 0; let offset = 0;
for (data, _) in InodeBlocks::new(&inode) { for block in InodeBlocks::new(&inode) {
let data_size = block_size match block {
.min(total_size - read_size) Ok((data, _)) => {
.min(buf.len() - offset); let data_size = block_size
let end = offset + data_size; .min(total_size - read_size)
buf[offset..end].copy_from_slice(&data[..data_size]); .min(buf.len() - offset);
read_size += data_size; let end = offset + data_size;
buf[offset..end].copy_from_slice(&data[..data_size]);
read_size += data_size;
}
Err(err) => return Err(err.into()),
}
} }
Ok(read_size) Ok(read_size)
@ -180,7 +185,10 @@ impl<S: Size, V: Volume<u8, Address<S>>> Ext2<S, V> {
self.superblock() self.superblock()
.block_group_count() .block_group_count()
.map(|count| count as usize) .map(|count| count as usize)
.map_err(|(a, b)| Error::BadBlockGroupCount(a, b)) .map_err(|(a, b)| Error::BadBlockGroupCount {
by_blocks: a,
by_inodes: b,
})
} }
pub fn total_block_count(&self) -> usize { pub fn total_block_count(&self) -> usize {
@ -224,9 +232,8 @@ pub struct Inodes<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> {
index: usize, index: usize,
} }
impl<'a, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator for Inodes<'a, S, V> impl<'a, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
where for Inodes<'a, S, V>
Error: From<V::Error>,
{ {
type Item = (Inode<'a, S, V>, Address<S>); type Item = (Inode<'a, S, V>, Address<S>);
@ -293,7 +300,7 @@ impl<'a, S: 'a + Size, V: 'a + Volume<u8, Address<S>>> Inode<'a, S, V> {
); );
let size = Address::from(4_u64); let size = Address::from(4_u64);
let slice = self.fs.volume.slice(addr..addr + size); let slice = self.fs.volume.slice(addr..addr + size);
slice.and_then(|slice| unsafe { slice.ok().and_then(|slice| unsafe {
NonZero::new(u32::from_le(slice.dynamic_cast::<u32>().0)) NonZero::new(u32::from_le(slice.dynamic_cast::<u32>().0))
}) })
} else if index < bs4 * bs4 + bs4 + 12 { } else if index < bs4 * bs4 + bs4 + 12 {
@ -344,9 +351,8 @@ pub struct InodeBlocks<'a: 'b, 'b, S: 'a + Size, V: 'a + Volume<u8, Address<S>>>
index: usize, index: usize,
} }
impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> InodeBlocks<'a, 'b, S, V> impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>>
where InodeBlocks<'a, 'b, S, V>
Error: From<V::Error>,
{ {
pub fn new(inode: &'b Inode<'a, S, V>) -> InodeBlocks<'a, 'b, S, V> { pub fn new(inode: &'b Inode<'a, S, V>) -> InodeBlocks<'a, 'b, S, V> {
InodeBlocks { inode, index: 0 } InodeBlocks { inode, index: 0 }
@ -355,10 +361,8 @@ where
impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator impl<'a, 'b, S: Size, V: 'a + Volume<u8, Address<S>>> Iterator
for InodeBlocks<'a, 'b, S, V> for InodeBlocks<'a, 'b, S, V>
where
Error: From<V::Error>,
{ {
type Item = (VolumeSlice<'a, u8, Address<S>>, Address<S>); type Item = Result<(VolumeSlice<'a, u8, Address<S>>, Address<S>), V::Error>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let block = self.inode.block(self.index); let block = self.inode.block(self.index);
@ -377,7 +381,7 @@ where
self.inode.fs.log_block_size(), self.inode.fs.log_block_size(),
) )
}) })
.and_then(|block| { .map(|block| {
let offset = block.start; let offset = block.start;
self.inode self.inode
.fs .fs
@ -467,7 +471,7 @@ mod tests {
println!("{:?}", inode.0); println!("{:?}", inode.0);
let size = inode.0.size(); let size = inode.0.size();
for block in InodeBlocks::new(&inode.0) { for block in InodeBlocks::new(&inode.0) {
let (data, _) = block; let (data, _) = block.unwrap();
assert_eq!(data.len(), fs.block_size()); assert_eq!(data.len(), fs.block_size());
println!("{:?}", &data[..size]); println!("{:?}", &data[..size]);
let _ = str::from_utf8(&data[..size]) let _ = str::from_utf8(&data[..size])
@ -490,9 +494,11 @@ mod tests {
buf.set_len(inode.size()); buf.set_len(inode.size());
} }
let size = fs.read_inode(&mut buf[..], &inode); let size = fs.read_inode(&mut buf[..], &inode);
assert_eq!(size, Ok(inode.size())); assert!(size.is_ok());
let size = size.unwrap();
assert_eq!(size, inode.size());
unsafe { unsafe {
buf.set_len(size.unwrap()); buf.set_len(size);
} }
} }
} }

View file

@ -5,15 +5,16 @@
#![feature(const_fn)] #![feature(const_fn)]
#![feature(step_trait)] #![feature(step_trait)]
#![feature(nonzero)] #![feature(nonzero)]
#![feature(associated_type_defaults)]
#![cfg_attr(all(not(test), feature = "no_std"), no_std)] #![cfg_attr(all(not(test), feature = "no_std"), no_std)]
#[macro_use] #[macro_use]
extern crate alloc; extern crate alloc;
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
#[cfg(any(test, not(feature = "no_std")))] #[cfg(any(test, not(feature = "no_std")))]
extern crate core; extern crate core;
extern crate spin;
pub mod error; pub mod error;
pub mod sys; pub mod sys;

View file

@ -55,18 +55,15 @@ impl BlockGroupDescriptor {
pub unsafe fn find_descriptor<S: Size, V: Volume<u8, Address<S>>>( pub unsafe fn find_descriptor<S: Size, V: Volume<u8, Address<S>>>(
haystack: &V, haystack: &V,
offset: Address<S>, offset: Address<S>,
) -> Result<(BlockGroupDescriptor, Address<S>), Error> ) -> Result<(BlockGroupDescriptor, Address<S>), Error> {
where
Error: From<V::Error>,
{
let end = let end =
offset + Address::from(mem::size_of::<BlockGroupDescriptor>()); offset + Address::from(mem::size_of::<BlockGroupDescriptor>());
if haystack.size() < end { if haystack.size() < end {
return Err(Error::AddressOutOfBounds( return Err(Error::AddressOutOfBounds {
end.sector(), sector: end.sector(),
end.offset(), offset: end.offset(),
end.sector_size(), size: end.sector_size(),
)); });
} }
let descr = haystack let descr = haystack
@ -80,18 +77,15 @@ impl BlockGroupDescriptor {
haystack: &V, haystack: &V,
offset: Address<S>, offset: Address<S>,
count: usize, count: usize,
) -> Result<(Vec<BlockGroupDescriptor>, Address<S>), Error> ) -> Result<(Vec<BlockGroupDescriptor>, Address<S>), Error> {
where
Error: From<V::Error>,
{
let end = offset let end = offset
+ Address::from(count * mem::size_of::<BlockGroupDescriptor>()); + Address::from(count * mem::size_of::<BlockGroupDescriptor>());
if haystack.size() < end { if haystack.size() < end {
return Err(Error::AddressOutOfBounds( return Err(Error::AddressOutOfBounds {
end.sector(), sector: end.sector(),
end.offset(), offset: end.offset(),
end.sector_size(), size: end.sector_size(),
)); });
} }
let mut vec = Vec::with_capacity(count); let mut vec = Vec::with_capacity(count);

View file

@ -101,21 +101,18 @@ impl Inode {
haystack: &V, haystack: &V,
offset: Address<S>, offset: Address<S>,
size: usize, size: usize,
) -> Result<(Inode, Address<S>), Error> ) -> Result<(Inode, Address<S>), Error> {
where
Error: From<V::Error>,
{
if size != mem::size_of::<Inode>() { if size != mem::size_of::<Inode>() {
unimplemented!("inodes with a size != 128"); unimplemented!("inodes with a size != 128");
} }
let end = offset + Address::from(size); let end = offset + Address::from(size);
if haystack.size() < end { if haystack.size() < end {
return Err(Error::AddressOutOfBounds( return Err(Error::AddressOutOfBounds {
end.sector(), sector: end.sector(),
end.offset(), offset: end.offset(),
end.sector_size(), size: end.sector_size(),
)); });
} }
let inode = haystack let inode = haystack

View file

@ -197,18 +197,15 @@ impl Debug for Superblock {
impl Superblock { impl Superblock {
pub unsafe fn find<S: Size, V: Volume<u8, Address<S>>>( pub unsafe fn find<S: Size, V: Volume<u8, Address<S>>>(
haystack: &V, haystack: &V,
) -> Result<(Superblock, Address<S>), Error> ) -> Result<(Superblock, Address<S>), Error> {
where
Error: From<V::Error>,
{
let offset = Address::from(1024_usize); let offset = Address::from(1024_usize);
let end = offset + Address::from(mem::size_of::<Superblock>()); let end = offset + Address::from(mem::size_of::<Superblock>());
if haystack.size() < end { if haystack.size() < end {
return Err(Error::AddressOutOfBounds( return Err(Error::AddressOutOfBounds {
end.sector(), sector: end.sector(),
end.offset(), offset: end.offset(),
end.sector_size(), size: end.sector_size(),
)); });
} }
let superblock = { let superblock = {
@ -218,7 +215,9 @@ impl Superblock {
}; };
if superblock.0.magic != EXT2_MAGIC { if superblock.0.magic != EXT2_MAGIC {
Err(Error::BadMagic(superblock.0.magic)) Err(Error::BadMagic {
magic: superblock.0.magic,
})
} else { } else {
Ok(superblock) Ok(superblock)
} }

View file

@ -6,7 +6,7 @@ use alloc::Vec;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::borrow::{Cow, ToOwned}; use alloc::borrow::{Cow, ToOwned};
use error::Infallible; use error::Error;
use sector::{Address, Size}; use sector::{Address, Size};
pub mod length; pub mod length;
@ -17,7 +17,7 @@ where
[T]: ToOwned, [T]: ToOwned,
Idx: PartialEq + PartialOrd, Idx: PartialEq + PartialOrd,
{ {
type Error; type Error: Into<Error>;
fn size(&self) -> Length<Idx>; fn size(&self) -> Length<Idx>;
fn commit( fn commit(
@ -32,13 +32,7 @@ where
fn slice<'a>( fn slice<'a>(
&'a self, &'a self,
range: Range<Idx>, range: Range<Idx>,
) -> Option<VolumeSlice<'a, T, Idx>> { ) -> Result<VolumeSlice<'a, T, Idx>, Self::Error>;
if self.size() >= range.end && self.size() > range.start {
unsafe { Some(self.slice_unchecked(range)) }
} else {
None
}
}
} }
pub struct VolumeSlice<'a, T: 'a, Idx> pub struct VolumeSlice<'a, T: 'a, Idx>
@ -233,7 +227,7 @@ macro_rules! impl_slice {
T: Clone, T: Clone,
[T]: ToOwned, [T]: ToOwned,
{ {
type Error = Infallible; type Error = Error;
fn size(&self) -> Length<Address<S>> { fn size(&self) -> Length<Address<S>> {
Length::Bounded( Length::Bounded(
@ -244,7 +238,7 @@ macro_rules! impl_slice {
fn commit( fn commit(
&mut self, &mut self,
slice: Option<VolumeCommit<T, Address<S>>>, slice: Option<VolumeCommit<T, Address<S>>>,
) -> Result<(), Infallible> { ) -> Result<(), Self::Error> {
slice.map(|slice| { slice.map(|slice| {
let index = slice.at_index().into_index() as usize; let index = slice.at_index().into_index() as usize;
let end = index + slice.as_ref().len(); let end = index + slice.as_ref().len();
@ -269,6 +263,21 @@ macro_rules! impl_slice {
index, index,
) )
} }
fn slice<'a>(
&'a self,
range: Range<Address<S>>,
) -> Result<VolumeSlice<'a, T, Address<S>>, Self::Error> {
if self.size() >= range.end {
unsafe { Ok(self.slice_unchecked(range)) }
} else {
Err(Error::AddressOutOfBounds {
sector: range.end.sector(),
offset: range.end.offset(),
size: range.end.sector_size()
})
}
}
} }
}; };
($volume:ty) => { ($volume:ty) => {
@ -344,7 +353,7 @@ mod file {
fn slice<'a>( fn slice<'a>(
&'a self, &'a self,
range: Range<Address<S>>, range: Range<Address<S>>,
) -> Option<VolumeSlice<'a, u8, Address<S>>> { ) -> Result<VolumeSlice<'a, u8, Address<S>>, Self::Error> {
let index = range.start; let index = range.start;
let mut vec = Vec::with_capacity((range.end - range.start) let mut vec = Vec::with_capacity((range.end - range.start)
.into_index() .into_index()
@ -357,7 +366,6 @@ mod file {
.seek(SeekFrom::Start(index.into_index())) .seek(SeekFrom::Start(index.into_index()))
.and_then(|_| refmut.read_exact(&mut vec[..])) .and_then(|_| refmut.read_exact(&mut vec[..]))
.map(move |_| VolumeSlice::new_owned(vec, index)) .map(move |_| VolumeSlice::new_owned(vec, index))
.ok()
} }
} }
} }