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