ext4-rs/src/lib.rs

94 lines
2.2 KiB
Rust
Raw Normal View History

use std::io::SeekFrom;
2025-07-15 16:45:08 +02:00
pub use crate::superblock::{SUPERBLOCK_SIZE, Superblock};
pub use crate::utils::group_has_superblock;
mod group_descriptor;
mod mmp;
mod superblock;
mod utils;
pub trait FileLike {
fn read_at_offset(&mut self, offset: u64, buf: &mut [u8]) -> anyhow::Result<()>;
fn write_at_offset(&mut self, offset: u64, bytes: &[u8]) -> anyhow::Result<()>;
fn read_at_offset_const<const N: usize>(&mut self, offset: u64) -> anyhow::Result<[u8; N]> {
let mut buf = [0; N];
self.read_at_offset(offset, &mut buf)?;
Ok(buf)
}
}
impl<F: std::io::Read + std::io::Write + std::io::Seek> FileLike for F {
fn read_at_offset(&mut self, offset: u64, buf: &mut [u8]) -> anyhow::Result<()> {
self.seek(SeekFrom::Start(offset))?;
self.read_exact(buf)?;
Ok(())
}
fn write_at_offset(&mut self, offset: u64, bytes: &[u8]) -> anyhow::Result<()> {
self.seek(SeekFrom::Start(offset))?;
self.write_all(bytes)?;
Ok(())
}
}
// impl FileLike for &mut [u8] {
// fn read_at_offset(&mut self, offset: u64, buf: &mut [u8]) -> anyhow::Result<()> {
// anyhow::ensure!(
// offset as usize + buf.len() <= self.len(),
// "reading {} bytes at offset {} is out of bounds for slice of len {}",
// buf.len(),
// offset,
// self.len()
// );
//
// buf.copy_from_slice(&self[offset as usize..][..buf.len()]);
//
// Ok(())
// }
//
// fn write_at_offset(&mut self, offset: u64, bytes: &[u8]) -> anyhow::Result<()> {
// anyhow::ensure!(
// offset as usize + bytes.len() <= self.len(),
// "writing {} bytes at offset {} is out of bounds for slice of len {}",
// bytes.len(),
// offset,
// self.len()
// );
//
// self[offset as usize..][..bytes.len()].copy_from_slice(bytes);
//
// Ok(())
// }
// }
pub struct Ext4Fs<F: FileLike> {
#[allow(dead_code)]
file: F,
superblock: superblock::Superblock,
}
impl<F: FileLike> Ext4Fs<F> {
pub fn load(file: F) -> Result<Ext4Fs<F>, anyhow::Error> {
let mut file = file;
let superblock_bytes = file.read_at_offset_const::<SUPERBLOCK_SIZE>(1024)?;
let superblock = Superblock::from_bytes(&superblock_bytes)?;
Ok(Ext4Fs { file, superblock })
}
pub fn super_block(&self) -> &Superblock {
&self.superblock
}
}