Change sector::Address implementation to use u32
This way a `u64` is guaranteed to be able to index specific bytes in a Volume.
This commit is contained in:
parent
e6218401ce
commit
d5423d7199
|
@ -6,7 +6,7 @@ use std::io;
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
BadMagic(u16),
|
BadMagic(u16),
|
||||||
OutOfBounds(usize),
|
OutOfBounds(usize),
|
||||||
AddressOutOfBounds(usize, usize, usize),
|
AddressOutOfBounds(u32, u32, usize),
|
||||||
BadBlockGroupCount(u32, u32),
|
BadBlockGroupCount(u32, u32),
|
||||||
#[cfg(any(test, not(feature = "no_std")))]
|
#[cfg(any(test, not(feature = "no_std")))]
|
||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
|
|
27
src/fs.rs
27
src/fs.rs
|
@ -37,7 +37,7 @@ where
|
||||||
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(
|
||||||
superblock.inner.first_data_block as usize + 1,
|
superblock.inner.first_data_block + 1,
|
||||||
0,
|
0,
|
||||||
superblock.inner.log_block_size + 10,
|
superblock.inner.log_block_size + 10,
|
||||||
);
|
);
|
||||||
|
@ -237,12 +237,11 @@ where
|
||||||
let index = (self.index - 1) % self.inodes_per_group;
|
let index = (self.index - 1) % self.inodes_per_group;
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
|
|
||||||
let inodes_block =
|
let inodes_block = self.block_groups[block_group].inode_table_block;
|
||||||
self.block_groups[block_group].inode_table_block as usize;
|
|
||||||
|
|
||||||
let offset = Address::with_block_size(
|
let offset = Address::with_block_size(
|
||||||
inodes_block,
|
inodes_block,
|
||||||
(index * self.inode_size) as isize,
|
(index * self.inode_size) as i32,
|
||||||
self.log_block_size,
|
self.log_block_size,
|
||||||
);
|
);
|
||||||
let raw = unsafe {
|
let raw = unsafe {
|
||||||
|
@ -267,7 +266,7 @@ impl<'a, S: 'a + Size + Copy, V: 'a + Volume<u8, Address<S>>> Inode<'a, S, V> {
|
||||||
Inode { fs, inner }
|
Inode { fs, inner }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn block(&self, index: usize) -> Option<NonZero<usize>> {
|
pub fn block(&self, index: usize) -> Option<NonZero<u32>> {
|
||||||
// number of blocks in direct table: 12
|
// number of blocks in direct table: 12
|
||||||
// number of blocks in indirect table: block_size/4
|
// number of blocks in indirect table: block_size/4
|
||||||
// why?
|
// why?
|
||||||
|
@ -284,19 +283,19 @@ impl<'a, S: 'a + Size + Copy, V: 'a + Volume<u8, Address<S>>> Inode<'a, S, V> {
|
||||||
|
|
||||||
let bs4 = self.fs.block_size() / 4;
|
let bs4 = self.fs.block_size() / 4;
|
||||||
if index < 12 {
|
if index < 12 {
|
||||||
NonZero::new(self.inner.direct_pointer[index] as usize)
|
NonZero::new(self.inner.direct_pointer[index])
|
||||||
} else if index < bs4 + 12 {
|
} else if index < bs4 + 12 {
|
||||||
let block = self.inner.indirect_pointer as usize;
|
let block = self.inner.indirect_pointer;
|
||||||
let offset = index - 12;
|
let offset = index - 12;
|
||||||
let addr = Address::with_block_size(
|
let addr = Address::with_block_size(
|
||||||
block,
|
block,
|
||||||
offset as isize,
|
offset as i32,
|
||||||
self.fs.log_block_size(),
|
self.fs.log_block_size(),
|
||||||
);
|
);
|
||||||
let size = Address::from(4_usize);
|
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.and_then(|slice| unsafe {
|
||||||
NonZero::new(u32::from_le(slice.dynamic_cast::<u32>().0) as usize)
|
NonZero::new(u32::from_le(slice.dynamic_cast::<u32>().0))
|
||||||
})
|
})
|
||||||
} else if index < bs4 * bs4 + bs4 + 12 {
|
} else if index < bs4 * bs4 + bs4 + 12 {
|
||||||
unimplemented!("doubly indirect pointer table");
|
unimplemented!("doubly indirect pointer table");
|
||||||
|
@ -405,15 +404,15 @@ mod tests {
|
||||||
fn file_len() {
|
fn file_len() {
|
||||||
let file = RefCell::new(File::open("ext2.img").unwrap());
|
let file = RefCell::new(File::open("ext2.img").unwrap());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Address::<Size512>::from(2048_usize)
|
Address::<Size512>::from(2048_u64)
|
||||||
- Address::<Size512>::from(1024_usize),
|
- Address::<Size512>::from(1024_u64),
|
||||||
Address::<Size512>::new(2, 0)
|
Address::<Size512>::new(2, 0)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
unsafe {
|
unsafe {
|
||||||
file.slice_unchecked(
|
file.slice_unchecked(
|
||||||
Address::<Size512>::from(1024_usize)
|
Address::<Size512>::from(1024_u64)
|
||||||
..Address::<Size512>::from(2048_usize),
|
..Address::<Size512>::from(2048_u64),
|
||||||
).len()
|
).len()
|
||||||
},
|
},
|
||||||
1024
|
1024
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub trait Size: PartialOrd {
|
||||||
// log_sector_size = log_2(sector_size)
|
// log_sector_size = log_2(sector_size)
|
||||||
const LOG_SIZE: u32;
|
const LOG_SIZE: u32;
|
||||||
const SIZE: usize = 1 << Self::LOG_SIZE;
|
const SIZE: usize = 1 << Self::LOG_SIZE;
|
||||||
const OFFSET_MASK: usize = Self::SIZE - 1;
|
const OFFSET_MASK: u32 = (Self::SIZE - 1) as u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
|
@ -38,14 +38,14 @@ impl Size for Size4096 {
|
||||||
/// Address in a physical sector
|
/// Address in a physical sector
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct Address<S: Size> {
|
pub struct Address<S: Size> {
|
||||||
sector: usize,
|
sector: u32,
|
||||||
offset: usize,
|
offset: u32,
|
||||||
_phantom: PhantomData<S>,
|
_phantom: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Size> Address<S> {
|
impl<S: Size> Address<S> {
|
||||||
pub unsafe fn new_unchecked(sector: usize, offset: usize) -> Address<S> {
|
pub unsafe fn new_unchecked(sector: u32, offset: u32) -> Address<S> {
|
||||||
assert!(offset < S::SIZE, "offset out of sector bounds");
|
assert!((offset as usize) < S::SIZE, "offset out of sector bounds");
|
||||||
let _phantom = PhantomData;
|
let _phantom = PhantomData;
|
||||||
Address {
|
Address {
|
||||||
sector,
|
sector,
|
||||||
|
@ -54,37 +54,31 @@ impl<S: Size> Address<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(sector: usize, offset: isize) -> Address<S> {
|
pub fn new(sector: u32, offset: i32) -> Address<S> {
|
||||||
let sector = (sector as isize + (offset >> S::LOG_SIZE)) as usize;
|
let sector = (sector as i32 + (offset >> S::LOG_SIZE)) as u32;
|
||||||
let offset = offset.abs() as usize & S::OFFSET_MASK;
|
let offset = offset.abs() as u32 & S::OFFSET_MASK;
|
||||||
unsafe { Address::new_unchecked(sector, offset) }
|
unsafe { Address::new_unchecked(sector, offset) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_block_size(
|
pub fn with_block_size(
|
||||||
block: usize,
|
block: u32,
|
||||||
offset: isize,
|
offset: i32,
|
||||||
log_block_size: u32,
|
log_block_size: u32,
|
||||||
) -> Address<S> {
|
) -> Address<S> {
|
||||||
let block = (block as isize + (offset >> log_block_size)) as usize;
|
let block = (block as i32 + (offset >> log_block_size)) as u32;
|
||||||
let offset = offset.abs() as usize & ((1 << log_block_size) - 1);
|
let offset = offset.abs() as u32 & ((1 << log_block_size) - 1);
|
||||||
|
|
||||||
let log_diff = log_block_size as isize - S::LOG_SIZE as isize;
|
let log_diff = log_block_size as i32 - S::LOG_SIZE as i32;
|
||||||
let top_offset = offset >> S::LOG_SIZE;
|
let top_offset = offset >> S::LOG_SIZE;
|
||||||
let offset = offset & ((1 << S::LOG_SIZE) - 1);
|
let offset = offset & ((1 << S::LOG_SIZE) - 1);
|
||||||
let sector = block << log_diff | top_offset;
|
let sector = block << log_diff | top_offset;
|
||||||
unsafe { Address::new_unchecked(sector, offset) }
|
unsafe { Address::new_unchecked(sector, offset) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index64(&self) -> u64 {
|
pub fn into_index(&self) -> u64 {
|
||||||
((self.sector as u64) << S::LOG_SIZE) + self.offset as u64
|
((self.sector as u64) << S::LOG_SIZE) + self.offset as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_index(&self) -> Option<usize> {
|
|
||||||
self.sector
|
|
||||||
.checked_shl(S::LOG_SIZE)
|
|
||||||
.and_then(|sector| sector.checked_add(self.offset))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn sector_size(&self) -> usize {
|
pub const fn sector_size(&self) -> usize {
|
||||||
S::SIZE
|
S::SIZE
|
||||||
}
|
}
|
||||||
|
@ -93,11 +87,11 @@ impl<S: Size> Address<S> {
|
||||||
S::LOG_SIZE
|
S::LOG_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sector(&self) -> usize {
|
pub fn sector(&self) -> u32 {
|
||||||
self.sector
|
self.sector
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset(&self) -> usize {
|
pub fn offset(&self) -> u32 {
|
||||||
self.offset
|
self.offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +99,7 @@ impl<S: Size> Address<S> {
|
||||||
impl<S: Size + Clone + PartialOrd> Step for Address<S> {
|
impl<S: Size + Clone + PartialOrd> Step for Address<S> {
|
||||||
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
||||||
if end.sector >= start.sector {
|
if end.sector >= start.sector {
|
||||||
Some(end.sector - start.sector)
|
Some(end.sector as usize - start.sector as usize)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -129,7 +123,7 @@ impl<S: Size + Clone + PartialOrd> Step for Address<S> {
|
||||||
|
|
||||||
fn add_usize(&self, n: usize) -> Option<Self> {
|
fn add_usize(&self, n: usize) -> Option<Self> {
|
||||||
self.sector
|
self.sector
|
||||||
.checked_add(n)
|
.checked_add(n as u32)
|
||||||
.map(|sector| Address::new(sector, 0))
|
.map(|sector| Address::new(sector, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,15 +154,15 @@ impl<S: Size> From<u64> for Address<S> {
|
||||||
fn from(idx: u64) -> Address<S> {
|
fn from(idx: u64) -> Address<S> {
|
||||||
let sector = idx >> S::LOG_SIZE;
|
let sector = idx >> S::LOG_SIZE;
|
||||||
let offset = idx & S::OFFSET_MASK as u64;
|
let offset = idx & S::OFFSET_MASK as u64;
|
||||||
Address::new(sector as usize, offset as isize)
|
Address::new(sector as u32, offset as i32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Size> From<usize> for Address<S> {
|
impl<S: Size> From<usize> for Address<S> {
|
||||||
fn from(idx: usize) -> Address<S> {
|
fn from(idx: usize) -> Address<S> {
|
||||||
let sector = idx >> S::LOG_SIZE;
|
let sector = idx >> S::LOG_SIZE;
|
||||||
let offset = idx & S::OFFSET_MASK;
|
let offset = idx & S::OFFSET_MASK as usize;
|
||||||
Address::new(sector, offset as isize)
|
Address::new(sector as u32, offset as i32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +171,7 @@ impl<S: Size> Add for Address<S> {
|
||||||
fn add(self, rhs: Address<S>) -> Address<S> {
|
fn add(self, rhs: Address<S>) -> Address<S> {
|
||||||
Address::new(
|
Address::new(
|
||||||
self.sector + rhs.sector,
|
self.sector + rhs.sector,
|
||||||
(self.offset + rhs.offset) as isize,
|
(self.offset + rhs.offset) as i32,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +181,7 @@ impl<S: Size> Sub for Address<S> {
|
||||||
fn sub(self, rhs: Address<S>) -> Address<S> {
|
fn sub(self, rhs: Address<S>) -> Address<S> {
|
||||||
Address::new(
|
Address::new(
|
||||||
self.sector - rhs.sector,
|
self.sector - rhs.sector,
|
||||||
self.offset as isize - rhs.offset as isize,
|
self.offset as i32 - rhs.offset as i32,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,22 +192,19 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn conv() {
|
fn conv() {
|
||||||
assert_eq!(Address::<Size512>::new(0, 1024).into_index(), Some(1024));
|
assert_eq!(Address::<Size512>::new(0, 1024).into_index(), 1024);
|
||||||
assert_eq!(
|
assert_eq!(Address::<Size512>::from(1024_u64).into_index(), 1024);
|
||||||
Address::<Size512>::from(1024_usize).into_index(),
|
|
||||||
Some(1024)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Address::<Size512>::with_block_size(1, 256, 10).into_index(),
|
Address::<Size512>::with_block_size(1, 256, 10).into_index(),
|
||||||
Some(1024 + 256)
|
1024 + 256
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Address::<Size512>::with_block_size(2, 0, 10).into_index(),
|
Address::<Size512>::with_block_size(2, 0, 10).into_index(),
|
||||||
Some(2048)
|
2048
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Address::<Size512>::with_block_size(0, 1792, 10).into_index(),
|
Address::<Size512>::with_block_size(0, 1792, 10).into_index(),
|
||||||
Some(1792)
|
1792
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,11 +223,11 @@ mod tests {
|
||||||
let a = Address::<Size2048>::new(0, 1024);
|
let a = Address::<Size2048>::new(0, 1024);
|
||||||
let b = Address::<Size2048>::new(0, 1024);
|
let b = Address::<Size2048>::new(0, 1024);
|
||||||
assert_eq!(a + b, Address::<Size2048>::new(1, 0));
|
assert_eq!(a + b, Address::<Size2048>::new(1, 0));
|
||||||
assert_eq!((a + b).into_index(), Some(2048));
|
assert_eq!((a + b).into_index(), 2048);
|
||||||
|
|
||||||
let a = Address::<Size512>::new(0, 2048);
|
let a = Address::<Size512>::new(0, 2048);
|
||||||
let b = Address::<Size512>::new(0, 256);
|
let b = Address::<Size512>::new(0, 256);
|
||||||
assert_eq!(a - b, Address::<Size512>::new(3, 256));
|
assert_eq!(a - b, Address::<Size512>::new(3, 256));
|
||||||
assert_eq!((a - b).into_index(), Some(1792));
|
assert_eq!((a - b).into_index(), 1792);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ macro_rules! impl_slice {
|
||||||
slice: Option<VolumeCommit<T, Address<S>>>,
|
slice: Option<VolumeCommit<T, Address<S>>>,
|
||||||
) -> Result<(), Infallible> {
|
) -> Result<(), Infallible> {
|
||||||
slice.map(|slice| {
|
slice.map(|slice| {
|
||||||
let index = slice.at_index().index64() 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();
|
||||||
// XXX: it would be much better to drop the contents of dst
|
// XXX: it would be much better to drop the contents of dst
|
||||||
// and move the contents of slice instead of cloning
|
// and move the contents of slice instead of cloning
|
||||||
|
@ -262,8 +262,8 @@ macro_rules! impl_slice {
|
||||||
range: Range<Address<S>>,
|
range: Range<Address<S>>,
|
||||||
) -> VolumeSlice<'a, T, Address<S>> {
|
) -> VolumeSlice<'a, T, Address<S>> {
|
||||||
let index = range.start;
|
let index = range.start;
|
||||||
let range = range.start.index64() as usize
|
let range = range.start.into_index() as usize
|
||||||
..range.end.index64() as usize;
|
..range.end.into_index() as usize;
|
||||||
VolumeSlice::new(
|
VolumeSlice::new(
|
||||||
<Self as AsRef<[T]>>::as_ref(self).get_unchecked(range),
|
<Self as AsRef<[T]>>::as_ref(self).get_unchecked(range),
|
||||||
index,
|
index,
|
||||||
|
@ -303,7 +303,7 @@ mod file {
|
||||||
self.borrow()
|
self.borrow()
|
||||||
.metadata()
|
.metadata()
|
||||||
.map(|data| Address::from(data.len()))
|
.map(|data| Address::from(data.len()))
|
||||||
.unwrap_or(Address::from(0_usize)),
|
.unwrap_or(Address::new(0, 0)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ mod file {
|
||||||
let index = *slice.at_index();
|
let index = *slice.at_index();
|
||||||
let mut refmut = self.borrow_mut();
|
let mut refmut = self.borrow_mut();
|
||||||
refmut
|
refmut
|
||||||
.seek(SeekFrom::Start(index.index64()))
|
.seek(SeekFrom::Start(index.into_index()))
|
||||||
.and_then(|_| refmut.write(slice.as_ref()))
|
.and_then(|_| refmut.write(slice.as_ref()))
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
})
|
})
|
||||||
|
@ -329,11 +329,11 @@ mod file {
|
||||||
) -> VolumeSlice<'a, u8, Address<S>> {
|
) -> VolumeSlice<'a, u8, Address<S>> {
|
||||||
let index = range.start;
|
let index = range.start;
|
||||||
let len = range.end - range.start;
|
let len = range.end - range.start;
|
||||||
let mut vec = Vec::with_capacity(len.index64() as usize);
|
let mut vec = Vec::with_capacity(len.into_index() as usize);
|
||||||
vec.set_len(len.index64() as usize);
|
vec.set_len(len.into_index() as usize);
|
||||||
let mut refmut = self.borrow_mut();
|
let mut refmut = self.borrow_mut();
|
||||||
refmut
|
refmut
|
||||||
.seek(SeekFrom::Start(index.index64()))
|
.seek(SeekFrom::Start(index.into_index()))
|
||||||
.and_then(|_| refmut.read_exact(&mut vec[..]))
|
.and_then(|_| refmut.read_exact(&mut vec[..]))
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
panic!("could't read from File Volume: {:?}", err)
|
panic!("could't read from File Volume: {:?}", err)
|
||||||
|
@ -346,15 +346,15 @@ mod file {
|
||||||
range: Range<Address<S>>,
|
range: Range<Address<S>>,
|
||||||
) -> Option<VolumeSlice<'a, u8, Address<S>>> {
|
) -> Option<VolumeSlice<'a, u8, Address<S>>> {
|
||||||
let index = range.start;
|
let index = range.start;
|
||||||
let mut vec = Vec::with_capacity(
|
let mut vec = Vec::with_capacity((range.end - range.start)
|
||||||
(range.end - range.start).index64() as usize,
|
.into_index()
|
||||||
);
|
as usize);
|
||||||
unsafe {
|
unsafe {
|
||||||
vec.set_len((range.end - range.start).index64() as usize);
|
vec.set_len((range.end - range.start).into_index() as usize);
|
||||||
}
|
}
|
||||||
let mut refmut = self.borrow_mut();
|
let mut refmut = self.borrow_mut();
|
||||||
refmut
|
refmut
|
||||||
.seek(SeekFrom::Start(index.index64()))
|
.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()
|
.ok()
|
||||||
|
@ -373,8 +373,8 @@ mod tests {
|
||||||
let commit = {
|
let commit = {
|
||||||
let mut slice = volume
|
let mut slice = volume
|
||||||
.slice(
|
.slice(
|
||||||
Address::<Size512>::from(256_usize)
|
Address::<Size512>::from(256_u64)
|
||||||
..Address::<Size512>::from(512_usize),
|
..Address::<Size512>::from(512_u64),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
slice.iter_mut().for_each(|x| *x = 1);
|
slice.iter_mut().for_each(|x| *x = 1);
|
||||||
|
|
Reference in a new issue