mirror of
https://codeberg.org/madmo/e2size.git
synced 2025-01-18 05:12:41 +00:00
Initial import
This commit is contained in:
commit
a7c17caebd
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "e2size"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Moritz Bitsch"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
byteorder = "1.4.3"
|
||||||
|
positioned-io = "0.2.2"
|
||||||
|
thiserror = "1.0.25"
|
131
src/lib.rs
Normal file
131
src/lib.rs
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
|
use positioned_io::ReadAt;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
/// Errors returned by e2size
|
||||||
|
pub enum E2SizeError {
|
||||||
|
/// Error reading superblock
|
||||||
|
#[error("Can't read superblock")]
|
||||||
|
Read(#[from] std::io::Error),
|
||||||
|
|
||||||
|
/// Bad magic value of superblock (corrupt fs?)
|
||||||
|
#[error("Invalid magic value (expected: 0xEF53 got: 0x{0:X})")]
|
||||||
|
BadMagic(u16),
|
||||||
|
|
||||||
|
/// Blocksize was outside allowed range (corrupt fs?)
|
||||||
|
#[error("Invalid block size: {0}")]
|
||||||
|
InvalidBlockSize(u32),
|
||||||
|
|
||||||
|
/// Filesystem outside seekable range (corrupt fs?)
|
||||||
|
#[error("Filesystem too Big")]
|
||||||
|
FilesystemTooBig,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves the size of a ext2/3/4 filesystem in bytes
|
||||||
|
///
|
||||||
|
/// Reads the superblock (1024 bytes at 1024 byte offset) from reader
|
||||||
|
pub fn e2size<T>(reader: T) -> std::result::Result<u64, E2SizeError>
|
||||||
|
where
|
||||||
|
T: ReadAt,
|
||||||
|
{
|
||||||
|
let mut superblock = [0u8; 1024];
|
||||||
|
reader.read_exact_at(1024, &mut superblock)?;
|
||||||
|
|
||||||
|
let magic = LittleEndian::read_u16(&superblock[0x38..]);
|
||||||
|
if magic != 0xEF53 {
|
||||||
|
return Err(E2SizeError::BadMagic(magic));
|
||||||
|
}
|
||||||
|
|
||||||
|
let block_count = LittleEndian::read_u32(&superblock[0x4..]);
|
||||||
|
|
||||||
|
let block_size_shift = LittleEndian::read_u32(&superblock[0x18..]);
|
||||||
|
let block_size = 1u64
|
||||||
|
.checked_shl(10 + block_size_shift)
|
||||||
|
.ok_or_else(|| E2SizeError::InvalidBlockSize(block_size_shift))?;
|
||||||
|
|
||||||
|
(block_size as u64)
|
||||||
|
.checked_mul(block_count as u64)
|
||||||
|
.ok_or_else(|| E2SizeError::FilesystemTooBig)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
fn valid_superblock() -> Result<(), E2SizeError> {
|
||||||
|
let mut superblock = [0u8; 2048];
|
||||||
|
LittleEndian::write_u16(&mut superblock[1024 + 0x38..], 0xEF53);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x4..], 256);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x18..], 2);
|
||||||
|
|
||||||
|
assert_eq!(e2size(&superblock[..])?, 1048576);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
fn huge_filesystem() -> Result<(), E2SizeError> {
|
||||||
|
let mut superblock = [0u8; 2048];
|
||||||
|
LittleEndian::write_u16(&mut superblock[1024 + 0x38..], 0xEF53);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x4..], 1 << 31);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x18..], 22);
|
||||||
|
|
||||||
|
assert_eq!(e2size(&superblock[..])?, 9223372036854775808);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
fn invalid_magic() -> Result<(), E2SizeError> {
|
||||||
|
let mut superblock = [0u8; 2048];
|
||||||
|
LittleEndian::write_u16(&mut superblock[1024 + 0x38..], 0xEF52);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x4..], 1);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x18..], 0);
|
||||||
|
|
||||||
|
match e2size(&superblock[..]) {
|
||||||
|
Err(E2SizeError::BadMagic(e)) => assert_eq!(e, 0xEF52),
|
||||||
|
_ => panic!("not reached!"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
fn invalid_block_size() -> Result<(), E2SizeError> {
|
||||||
|
let mut superblock = [0u8; 2048];
|
||||||
|
LittleEndian::write_u16(&mut superblock[1024 + 0x38..], 0xEF53);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x4..], 1);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x18..], 54);
|
||||||
|
|
||||||
|
match e2size(&superblock[..]) {
|
||||||
|
Err(E2SizeError::InvalidBlockSize(_)) => {}
|
||||||
|
Err(e) => panic!("not expected error: {}", e),
|
||||||
|
_ => panic!("not reached!"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
fn filesystem_too_big() -> Result<(), E2SizeError> {
|
||||||
|
let mut superblock = [0u8; 2048];
|
||||||
|
LittleEndian::write_u16(&mut superblock[1024 + 0x38..], 0xEF53);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x4..], 1 << 31);
|
||||||
|
LittleEndian::write_u32(&mut superblock[1024 + 0x18..], 23);
|
||||||
|
|
||||||
|
match e2size(&superblock[..]) {
|
||||||
|
Err(E2SizeError::FilesystemTooBig) => {}
|
||||||
|
Err(e) => panic!("not expected error: {}", e),
|
||||||
|
_ => panic!("not reached!"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue