diff --git a/src/block.rs b/src/block.rs index 96aa8b8..88475e2 100644 --- a/src/block.rs +++ b/src/block.rs @@ -4,39 +4,33 @@ use core::ops::{Add, Sub}; use core::fmt::{self, Debug, Display, LowerHex}; use core::iter::Step; -pub trait Size { - // log_block_size = log_2(block_size) - 10 - // i.e. block_size = 1024 << log_block_size +pub trait Size: PartialOrd { + // log_block_size = log_2(block_size) const LOG_SIZE: u32; - const SIZE: usize = 1024 << Self::LOG_SIZE; + const SIZE: usize = 1 << Self::LOG_SIZE; const OFFSET_MASK: usize = Self::SIZE - 1; } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct Size1024; -impl Size for Size1024 { - const LOG_SIZE: u32 = 0; +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct Size512; +impl Size for Size512 { + const LOG_SIZE: u32 = 9; } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Size2048; impl Size for Size2048 { - const LOG_SIZE: u32 = 1; + const LOG_SIZE: u32 = 11; } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Size4096; impl Size for Size4096 { - const LOG_SIZE: u32 = 2; + const LOG_SIZE: u32 = 12; } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct Size8192; -impl Size for Size8192 { - const LOG_SIZE: u32 = 3; -} - -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +/// Address in a physical sector +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Address { block: usize, offset: usize, @@ -55,14 +49,30 @@ impl Address { } pub fn new(block: usize, offset: isize) -> Address { - let block = (block as isize + (offset >> (S::LOG_SIZE + 10))) as usize; + let block = (block as isize + (offset >> S::LOG_SIZE)) as usize; let offset = offset.abs() as usize & S::OFFSET_MASK; unsafe { Address::new_unchecked(block, offset) } } + pub fn with_block_size( + block: usize, + offset: usize, + log_block_size: u32, + ) -> Address { + let log_diff = log_block_size as isize - S::LOG_SIZE as isize; + let top_offset = offset >> S::LOG_SIZE; + let offset = offset >> log_diff; + let block = block << log_diff | top_offset; + Address::new(block, offset as isize) + } + + pub fn index64(&self) -> u64 { + ((self.block as u64) << S::LOG_SIZE) + self.offset as u64 + } + pub fn into_index(&self) -> Option { self.block - .checked_shl(S::LOG_SIZE + 10) + .checked_shl(S::LOG_SIZE) .and_then(|block| block.checked_add(self.offset)) } @@ -137,9 +147,17 @@ impl LowerHex for Address { } } +impl From for Address { + fn from(idx: u64) -> Address { + let block = idx >> S::LOG_SIZE; + let offset = idx & S::OFFSET_MASK as u64; + Address::new(block as usize, offset as isize) + } +} + impl From for Address { fn from(idx: usize) -> Address { - let block = idx >> (S::LOG_SIZE + 10); + let block = idx >> S::LOG_SIZE; let offset = idx & S::OFFSET_MASK; Address::new(block, offset as isize) } @@ -172,13 +190,13 @@ mod tests { #[test] fn arithmetic() { assert_eq!( - Address::::new(0, 1024), - Address::::new(1, 0), + Address::::new(0, 512), + Address::::new(1, 0), ); assert_eq!( - Address::::new(2, -512), - Address::::new(1, 512), + Address::::new(2, -256), + Address::::new(1, 256), ); let a = Address::::new(0, 1024); @@ -186,9 +204,9 @@ mod tests { assert_eq!(a + b, Address::::new(1, 0)); assert_eq!((a + b).into_index(), Some(2048)); - let a = Address::::new(0, 4096); - let b = Address::::new(0, 512); - assert_eq!(a - b, Address::::new(3, 512)); - assert_eq!((a - b).into_index(), Some(3584)); + let a = Address::::new(0, 2048); + let b = Address::::new(0, 256); + assert_eq!(a - b, Address::::new(3, 256)); + assert_eq!((a - b).into_index(), Some(1792)); } } diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index 7b52be0..d3b5446 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -7,6 +7,7 @@ use alloc::boxed::Box; use alloc::borrow::{Cow, ToOwned}; use error::Infallible; +use block::{Address, Size}; pub mod length; use self::length::Length; @@ -21,14 +22,17 @@ where fn len(&self) -> Length; fn commit( &mut self, - slice: Option>, + slice: Option>, ) -> Result<(), Self::Error>; unsafe fn slice_unchecked<'a>( &'a self, range: Range, - ) -> BufferSlice<'a, T>; + ) -> BufferSlice<'a, T, Idx>; - fn slice<'a>(&'a self, range: Range) -> Option> { + fn slice<'a>( + &'a self, + range: Range, + ) -> Option> { if self.len() >= range.end && self.len() > range.start { unsafe { Some(self.slice_unchecked(range)) } } else { @@ -37,29 +41,34 @@ where } } -pub struct BufferSlice<'a, T: 'a> +pub struct BufferSlice<'a, T: 'a, Idx> where [T]: ToOwned, { inner: Cow<'a, [T]>, - index: usize, + index: Idx, } -impl BufferSlice<'static, T> +impl BufferSlice<'static, T, Idx> where [T]: ToOwned, { - pub fn with_static(inner: &'static [T]) -> BufferSlice<'static, T> { + pub fn with_static(inner: &'static [T]) -> BufferSlice<'static, T, Idx> { BufferSlice { inner: Cow::Borrowed(inner), - index: 0, + index: Idx::default(), } } +} +impl BufferSlice<'static, T, Idx> +where + [T]: ToOwned, +{ pub fn new_owned( inner: <[T] as ToOwned>::Owned, - index: usize, - ) -> BufferSlice<'static, T> { + index: Idx, + ) -> BufferSlice<'static, T, Idx> { BufferSlice { inner: Cow::Owned(inner), index, @@ -67,11 +76,11 @@ where } } -impl<'a, T> BufferSlice<'a, T> +impl<'a, T, Idx> BufferSlice<'a, T, Idx> where [T]: ToOwned, { - pub fn new(inner: &'a [T], index: usize) -> BufferSlice<'a, T> { + pub fn new(inner: &'a [T], index: Idx) -> BufferSlice<'a, T, Idx> { BufferSlice { inner: Cow::Borrowed(inner), index, @@ -85,14 +94,13 @@ where } } - #[inline] - pub fn at_index(&self) -> usize { - self.index + pub fn at_index(&self) -> &Idx { + &self.index } } -impl<'a> BufferSlice<'a, u8> { - pub unsafe fn dynamic_cast(&self) -> (T, usize) { +impl<'a, Idx: Copy> BufferSlice<'a, u8, Idx> { + pub unsafe fn dynamic_cast(&self) -> (T, Idx) { assert!(self.inner.len() >= mem::size_of::()); let index = self.index; let cast = mem::transmute_copy(self.inner.as_ptr().as_ref().unwrap()); @@ -101,8 +109,8 @@ impl<'a> BufferSlice<'a, u8> { pub fn from_cast( cast: &'a T, - index: usize, - ) -> BufferSlice<'a, u8> { + index: Idx, + ) -> BufferSlice<'a, u8, Idx> { let len = mem::size_of::(); let ptr = cast as *const T as *const u8; let slice = unsafe { slice::from_raw_parts(ptr, len) }; @@ -110,11 +118,11 @@ impl<'a> BufferSlice<'a, u8> { } } -impl<'a, T> BufferSlice<'a, T> +impl<'a, T, Idx> BufferSlice<'a, T, Idx> where [T]: ToOwned>, { - pub fn commit(self) -> Option> { + pub fn commit(self) -> Option> { if self.is_mutated() { Some(BufferCommit::new(self.inner.into_owned(), self.index)) } else { @@ -123,7 +131,7 @@ where } } -impl<'a, T> AsRef<[T]> for BufferSlice<'a, T> +impl<'a, T, Idx> AsRef<[T]> for BufferSlice<'a, T, Idx> where [T]: ToOwned, { @@ -132,7 +140,7 @@ where } } -impl<'a, T> AsMut<[T]> for BufferSlice<'a, T> +impl<'a, T, Idx> AsMut<[T]> for BufferSlice<'a, T, Idx> where [T]: ToOwned, <[T] as ToOwned>::Owned: AsMut<[T]>, @@ -142,7 +150,7 @@ where } } -impl<'a, T> Deref for BufferSlice<'a, T> +impl<'a, T, Idx> Deref for BufferSlice<'a, T, Idx> where [T]: ToOwned, { @@ -153,7 +161,7 @@ where } } -impl<'a, T> DerefMut for BufferSlice<'a, T> +impl<'a, T, Idx> DerefMut for BufferSlice<'a, T, Idx> where [T]: ToOwned, <[T] as ToOwned>::Owned: AsMut<[T]>, @@ -163,17 +171,22 @@ where } } -pub struct BufferCommit { +pub struct BufferCommit { inner: Vec, - index: usize, + index: Idx, } -impl BufferCommit { - pub fn with_vec(inner: Vec) -> BufferCommit { - BufferCommit { inner, index: 0 } +impl BufferCommit { + pub fn with_vec(inner: Vec) -> BufferCommit { + BufferCommit { + inner, + index: Idx::default(), + } } +} - pub fn new(inner: Vec, index: usize) -> BufferCommit { +impl BufferCommit { + pub fn new(inner: Vec, index: Idx) -> BufferCommit { BufferCommit { inner, index } } @@ -181,25 +194,24 @@ impl BufferCommit { self.inner } - #[inline] - pub fn at_index(&self) -> usize { - self.index + pub fn at_index(&self) -> &Idx { + &self.index } } -impl AsRef<[T]> for BufferCommit { +impl AsRef<[T]> for BufferCommit { fn as_ref(&self) -> &[T] { self.inner.as_ref() } } -impl AsMut<[T]> for BufferCommit { +impl AsMut<[T]> for BufferCommit { fn as_mut(&mut self) -> &mut [T] { self.inner.as_mut() } } -impl Deref for BufferCommit { +impl Deref for BufferCommit { type Target = [T]; fn deref(&self) -> &Self::Target { @@ -207,7 +219,7 @@ impl Deref for BufferCommit { } } -impl DerefMut for BufferCommit { +impl DerefMut for BufferCommit { fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut() } @@ -215,20 +227,20 @@ impl DerefMut for BufferCommit { macro_rules! impl_slice { (@inner $buffer:ty $( , $lt:lifetime )* ) => { - impl<$( $lt, )* T> Buffer for $buffer + impl<$( $lt, )* S: Size + PartialOrd + Copy, T> Buffer> for $buffer where T: Clone, [T]: ToOwned, { type Error = Infallible; - fn len(&self) -> Length { - Length::Bounded(>::as_ref(self).len()) + fn len(&self) -> Length> { + Length::Bounded(Address::from(>::as_ref(self).len())) } - fn commit(&mut self, slice: Option>) -> Result<(), Infallible> { + fn commit(&mut self, slice: Option>>) -> Result<(), Infallible> { slice.map(|slice| { - let index = slice.at_index(); + let index = slice.at_index().index64() as usize; let end = index + slice.as_ref().len(); // XXX: it would be much better to drop the contents of dst // and move the contents of slice instead of cloning @@ -241,9 +253,10 @@ macro_rules! impl_slice { unsafe fn slice_unchecked<'a>( &'a self, - range: Range, - ) -> BufferSlice<'a, T> { + range: Range>, + ) -> BufferSlice<'a, T, Address> { let index = range.start; + let range = range.start.index64() as usize..range.end.index64() as usize; BufferSlice::new( >::as_ref(self).get_unchecked(range), index, @@ -270,33 +283,35 @@ mod file { use std::fs::File; use std::cell::RefCell; + use block::{Address, Size}; + use super::{Buffer, BufferCommit, BufferSlice}; use super::length::Length; - impl Buffer for RefCell { + impl Buffer> for RefCell { type Error = io::Error; - fn len(&self) -> Length { + fn len(&self) -> Length> { Length::Bounded( self.borrow() .metadata() - .map(|data| data.len() as usize) - .unwrap_or(0), + .map(|data| Address::from(data.len())) + .unwrap_or(Address::from(0_usize)), ) } fn commit( &mut self, - slice: Option>, + slice: Option>>, ) -> Result<(), Self::Error> { slice .map(|slice| { - let index = slice.at_index(); - let end = index + slice.as_ref().len(); + let index = *slice.at_index(); + let end = index + Address::from(slice.as_ref().len()); let mut refmut = self.borrow_mut(); refmut - .seek(SeekFrom::Start(index as u64)) - .and_then(|_| refmut.write(&slice.as_ref()[index..end])) + .seek(SeekFrom::Start(index.index64())) + .and_then(|_| refmut.write(slice.as_ref())) .map(|_| ()) }) .unwrap_or(Ok(())) @@ -304,15 +319,15 @@ mod file { unsafe fn slice_unchecked<'a>( &'a self, - range: Range, - ) -> BufferSlice<'a, u8> { + range: Range>, + ) -> BufferSlice<'a, u8, Address> { let index = range.start; let len = range.end - range.start; - let mut vec = Vec::with_capacity(len); - vec.set_len(len); + let mut vec = Vec::with_capacity(len.index64() as usize); + vec.set_len(len.index64() as usize); let mut refmut = self.borrow_mut(); refmut - .seek(SeekFrom::Start(index as u64)) + .seek(SeekFrom::Start(index.index64())) .and_then(|_| refmut.read_exact(&mut vec[..])) .unwrap_or_else(|err| { panic!("could't read from File Buffer: {:?}", err) @@ -322,14 +337,16 @@ mod file { fn slice<'a>( &'a self, - range: Range, - ) -> Option> { + range: Range>, + ) -> Option>> { let index = range.start; - let mut vec = Vec::with_capacity(range.end - range.start); + let mut vec = Vec::with_capacity( + (range.end - range.start).index64() as usize, + ); let mut refmut = self.borrow_mut(); refmut - .seek(SeekFrom::Start(index as u64)) - .and_then(|_| refmut.read_exact(&mut vec[range])) + .seek(SeekFrom::Start(index.index64())) + .and_then(|_| refmut.read_exact(&mut vec[..])) .map(move |_| BufferSlice::new_owned(vec, index)) .ok() } @@ -338,13 +355,19 @@ mod file { #[cfg(test)] mod tests { + use block::{Address, Size512}; use super::*; #[test] fn buffer() { let mut buffer = vec![0; 1024]; let commit = { - let mut slice = buffer.slice(256..512).unwrap(); + let mut slice = buffer + .slice( + Address::::from(256_usize) + ..Address::::from(512_usize), + ) + .unwrap(); slice.iter_mut().for_each(|x| *x = 1); slice.commit() }; diff --git a/src/error.rs b/src/error.rs index 83be4e2..7c3a8f9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,7 @@ use std::io; pub enum Error { BadMagic(u16), OutOfBounds(usize), + AddressOutOfBounds(usize, usize, usize), BadBlockGroupCount(u32, u32), #[cfg(any(test, not(feature = "no_std")))] Io(io::Error), diff --git a/src/fs.rs b/src/fs.rs index 2acc507..1c90de1 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,41 +1,45 @@ use core::mem; +use core::marker::PhantomData; + use alloc::Vec; use error::Error; -use block::Address; // TODO +use block::{Address, Size}; use buffer::{Buffer, BufferSlice}; use sys::superblock::Superblock; use sys::block_group::BlockGroupDescriptor; use sys::inode::Inode; -struct Struct { +struct Struct { pub inner: T, - pub offset: usize, + pub offset: Address, } -impl From<(T, usize)> for Struct { +impl From<(T, Address)> for Struct { #[inline] - fn from((inner, offset): (T, usize)) -> Struct { + fn from((inner, offset): (T, Address)) -> Struct { Struct { inner, offset } } } /// Safe wrapper for raw sys structs -pub struct Ext2> { +pub struct Ext2>> { buffer: B, - superblock: Struct, - block_groups: Struct>, + superblock: Struct, + block_groups: Struct, S>, } -impl> Ext2 +impl>> Ext2 where Error: From, { - pub fn new(buffer: B) -> Result, Error> { + pub fn new(buffer: B) -> Result, Error> { let superblock = unsafe { Struct::from(Superblock::find(&buffer)?) }; - let block_size = superblock.inner.block_size(); - let block_groups_offset = - (superblock.inner.first_data_block as usize + 1) * block_size; + let block_groups_offset = Address::with_block_size( + superblock.inner.first_data_block as usize + 1, + 0, + superblock.inner.log_block_size + 10, + ); let block_groups_count = superblock .inner .block_group_count() @@ -74,7 +78,8 @@ where let slice = BufferSlice::from_cast(descr, offset); let commit = slice.commit(); self.buffer.commit(commit).map_err(|err| Error::from(err))?; - offset += mem::size_of::(); + offset = + offset + Address::from(mem::size_of::()); } Ok(()) @@ -83,35 +88,36 @@ where #[allow(dead_code)] fn update_inode( &mut self, - &(ref inode, offset): &(Inode, usize), + &(ref inode, offset): &(Inode, Address), ) -> Result<(), Error> { let slice = BufferSlice::from_cast(inode, offset); let commit = slice.commit(); self.buffer.commit(commit).map_err(|err| Error::from(err)) } - pub fn root_inode(&self) -> (Inode, usize) { + pub fn root_inode(&self) -> (Inode, Address) { self.inode_nth(2).unwrap() } - pub fn inode_nth(&self, index: usize) -> Option<(Inode, usize)> { + pub fn inode_nth(&self, index: usize) -> Option<(Inode, Address)> { self.inodes_nth(index).next() } - pub fn inodes<'a>(&'a self) -> Inodes<'a, B> { + pub fn inodes<'a>(&'a self) -> Inodes<'a, S, B> { self.inodes_nth(1) } - pub fn inodes_nth<'a>(&'a self, index: usize) -> Inodes<'a, B> { + pub fn inodes_nth<'a>(&'a self, index: usize) -> Inodes<'a, S, B> { assert!(index > 0, "inodes are 1-indexed"); Inodes { buffer: &self.buffer, block_groups: &self.block_groups.inner, - block_size: self.block_size(), + log_block_size: self.log_block_size(), inode_size: self.inode_size(), inodes_per_group: self.inodes_count(), inodes_count: self.total_inodes_count(), index, + _phantom: PhantomData, } } @@ -163,23 +169,29 @@ where pub fn block_size(&self) -> usize { self.superblock().block_size() } + + pub fn log_block_size(&self) -> u32 { + self.superblock().log_block_size + } } -pub struct Inodes<'a, B: 'a + Buffer> { +pub struct Inodes<'a, S: Size, B: 'a + Buffer>> { buffer: &'a B, block_groups: &'a [BlockGroupDescriptor], - block_size: usize, + log_block_size: u32, inode_size: usize, inodes_per_group: usize, inodes_count: usize, index: usize, + _phantom: PhantomData, } -impl<'a, B: 'a + Buffer> Iterator for Inodes<'a, B> +impl<'a, S: Size + Copy, B: 'a + Buffer>> Iterator + for Inodes<'a, S, B> where Error: From, { - type Item = (Inode, usize); + type Item = (Inode, Address); fn next(&mut self) -> Option { if self.index < self.inodes_count { @@ -190,8 +202,11 @@ where let inodes_block = self.block_groups[block_group].inode_table_block as usize; - let offset = - inodes_block * self.block_size + index * self.inode_size; + let offset = Address::with_block_size( + inodes_block, + index * self.inode_size, + self.log_block_size, + ); unsafe { Inode::find_inode(self.buffer, offset, self.inode_size).ok() } @@ -206,6 +221,7 @@ mod tests { use std::fs::File; use std::cell::RefCell; + use block::{Address, Size512}; use buffer::Buffer; use super::Ext2; @@ -213,13 +229,21 @@ mod tests { #[test] fn file_len() { let file = RefCell::new(File::open("ext2.img").unwrap()); - assert_eq!(unsafe { file.slice_unchecked(1024..2048).len() }, 1024); + assert_eq!( + unsafe { + file.slice_unchecked( + Address::::from(1024_usize) + ..Address::::from(2048_usize), + ).len() + }, + 1024 + ); } #[test] fn file() { let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Ext2::new(file); + let fs = Ext2::::new(file); assert!( fs.is_ok(), @@ -237,7 +261,7 @@ mod tests { #[test] fn inodes() { let file = RefCell::new(File::open("ext2.img").unwrap()); - let fs = Ext2::new(file); + let fs = Ext2::::new(file); assert!( fs.is_ok(), diff --git a/src/sys/block_group.rs b/src/sys/block_group.rs index 6963bc5..aeb8738 100644 --- a/src/sys/block_group.rs +++ b/src/sys/block_group.rs @@ -4,6 +4,7 @@ use core::fmt::{self, Debug}; use alloc::Vec; use error::Error; +use block::{Address, Size}; use buffer::Buffer; /// The Block Group Descriptor Table contains a descriptor for each block group @@ -51,16 +52,24 @@ impl Debug for BlockGroupDescriptor { } impl BlockGroupDescriptor { - pub unsafe fn find_descriptor>( + pub unsafe fn find_descriptor< + S: Size + Copy + PartialOrd, + B: Buffer>, + >( haystack: &B, - offset: usize, - ) -> Result<(BlockGroupDescriptor, usize), Error> + offset: Address, + ) -> Result<(BlockGroupDescriptor, Address), Error> where Error: From, { - let end = offset + mem::size_of::(); + let end = + offset + Address::from(mem::size_of::()); if haystack.len() < end { - return Err(Error::OutOfBounds(end)); + return Err(Error::AddressOutOfBounds( + end.block(), + end.offset(), + end.block_size(), + )); } let descr = haystack @@ -70,22 +79,31 @@ impl BlockGroupDescriptor { Ok(descr) } - pub unsafe fn find_descriptor_table>( + pub unsafe fn find_descriptor_table< + S: Size + Copy + PartialOrd, + B: Buffer>, + >( haystack: &B, - offset: usize, + offset: Address, count: usize, - ) -> Result<(Vec, usize), Error> + ) -> Result<(Vec, Address), Error> where Error: From, { - let end = offset + count * mem::size_of::(); + let end = offset + + Address::from(count * mem::size_of::()); if haystack.len() < end { - return Err(Error::OutOfBounds(end)); + return Err(Error::AddressOutOfBounds( + end.block(), + end.offset(), + end.block_size(), + )); } let mut vec = Vec::with_capacity(count); for i in 0..count { - let offset = offset + i * mem::size_of::(); + let offset = offset + + Address::from(i * mem::size_of::()); vec.push({ BlockGroupDescriptor::find_descriptor(haystack, offset)?.0 }); @@ -97,13 +115,18 @@ impl BlockGroupDescriptor { #[cfg(test)] mod tests { + use block::{Address, Size512}; use super::*; #[test] fn find() { let buffer = vec![0_u8; 4096]; let table = unsafe { - BlockGroupDescriptor::find_descriptor_table(&buffer, 2048, 8) + BlockGroupDescriptor::find_descriptor_table( + &buffer, + Address::::new(4, 0), + 8, + ) }; assert!( table.is_ok(), diff --git a/src/sys/inode.rs b/src/sys/inode.rs index 52ba803..bd37647 100644 --- a/src/sys/inode.rs +++ b/src/sys/inode.rs @@ -2,6 +2,7 @@ use core::mem; use core::fmt::{self, Debug}; use error::Error; +use block::{Address, Size}; use buffer::Buffer; /// An inode is a structure on the disk that represents a file, directory, @@ -96,11 +97,14 @@ impl Debug for Inode { } impl Inode { - pub unsafe fn find_inode>( + pub unsafe fn find_inode< + S: Size + Copy + PartialOrd, + B: Buffer>, + >( haystack: &B, - offset: usize, + offset: Address, size: usize, - ) -> Result<(Inode, usize), Error> + ) -> Result<(Inode, Address), Error> where Error: From, { @@ -108,9 +112,13 @@ impl Inode { unimplemented!("inodes with a size != 128"); } - let end = offset + size; + let end = offset + Address::from(size); if haystack.len() < end { - return Err(Error::OutOfBounds(end)); + return Err(Error::AddressOutOfBounds( + end.block(), + end.offset(), + end.block_size(), + )); } let inode = haystack diff --git a/src/sys/superblock.rs b/src/sys/superblock.rs index d2cb36c..8db45f3 100644 --- a/src/sys/superblock.rs +++ b/src/sys/superblock.rs @@ -2,6 +2,7 @@ use core::mem; use core::fmt::{self, Debug}; use error::Error; +use block::{Address, Size}; use buffer::Buffer; /// Ext2 signature (0xef53), used to help confirm the presence of Ext2 on a @@ -194,16 +195,20 @@ impl Debug for Superblock { } impl Superblock { - pub unsafe fn find>( + pub unsafe fn find>>( haystack: &B, - ) -> Result<(Superblock, usize), Error> + ) -> Result<(Superblock, Address), Error> where Error: From, { - let offset = 1024; - let end = offset + mem::size_of::(); + let offset = Address::from(1024_usize); + let end = offset + Address::from(mem::size_of::()); if haystack.len() < end { - return Err(Error::OutOfBounds(end)); + return Err(Error::AddressOutOfBounds( + end.block(), + end.offset(), + end.block_size(), + )); } let superblock = { @@ -291,6 +296,7 @@ bitflags! { #[cfg(test)] mod tests { + use block::Size512; use super::*; #[test] @@ -299,7 +305,7 @@ mod tests { // magic buffer[1024 + 56] = EXT2_MAGIC as u8; buffer[1024 + 57] = (EXT2_MAGIC >> 8) as u8; - let superblock = unsafe { Superblock::find(&buffer) }; + let superblock = unsafe { Superblock::find::(&buffer) }; assert!( superblock.is_ok(), "Err({:?})", @@ -314,7 +320,7 @@ mod tests { use std::fs::File; let file = RefCell::new(File::open("ext2.img").unwrap()); - let superblock = unsafe { Superblock::find(&file) }; + let superblock = unsafe { Superblock::find::(&file) }; assert!( superblock.is_ok(), "Err({:?})",