Newer
Older
//! Implementation of the Second Extended Filesystem (ext2fs) filesystem
use alloc::slice;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::{mem, ptr};
use spin::Mutex;
use self::inode::{Inode, ROOT_INODE_INDEX};
use crate::kernel::device::storage::Device;
#[allow(clippy::same_name_method)]
mod inode;
/// Device on which the Ext2 filesystem is located
static DEVICE: OnceCell<Arc<Mutex<dyn Device + Send>>> = OnceCell::uninit();
/// Superblock of the device
static SUPERBLOCK: OnceCell<Superblock> = OnceCell::uninit();
/// Reads the device at the given offset **in bytes** and returns the expected structure
///
/// # Safety
///
/// Must ensure that the structure `T` is present on the device at the given offset
unsafe fn read<T>(offset: usize) -> Result<T> {
Ok(ptr::read(read_raw(offset, mem::size_of::<T>())?.as_ptr().cast::<T>()))
}
/// Reads the device at the given offset **in bytes** and returns the `n` raw bytes
///
/// # Safety
///
/// Must ensure that the structure `T` is present on the device at the given offset
unsafe fn read_raw(offset: usize, n: usize) -> Result<&'static [u8]> {
let binding = DEVICE.get().expect("The device has not been initialized yet").lock();
let block_size = binding.block_size();
let mut buffer_size = 0_usize;
buffer_size += block_size;
}
let (raw_buffer, _, _) = Vec::<u8>::with_capacity(buffer_size).into_raw_parts();
let buffer = slice::from_raw_parts_mut(raw_buffer, buffer_size);
binding.read(buffer, offset / block_size, buffer_size / block_size)?;
Ok(buffer[offset % block_size..offset % block_size + n].as_ref())
/// Searches for an Ext2 filesystem, and returns the root if found
pub fn search(device: &Arc<Mutex<dyn Device + Send>>) -> Result<Arc<Mutex<dyn super::node::Directory + Send>>> {
DEVICE.init_once(|| Arc::clone(device));
let superblock = Superblock::new()?;
SUPERBLOCK.init_once(|| superblock);
let root_inode = Inode::new(ROOT_INODE_INDEX)?;
info!("Found the root of the filesystem : {:?}", root);