Skip to content
Snippets Groups Projects
mod.rs 2.36 KiB
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 anyhow::Result;
use conquer_once::spin::OnceCell;
use self::block::Superblock;
use self::entry::Entry;
use self::inode::{Inode, TypePermissions, ROOT_INODE_INDEX};
use crate::kernel::device::storage::Device;
use crate::println;

#[allow(clippy::same_name_method)]
#[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() as *const 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 mut binding = DEVICE.get().expect("The device has not been initialized yet").lock();
    let block_size = binding.block_size();

    let mut buffer_size = 0_usize;
    while buffer_size < n {
        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)?;

    println!("{:x?} {:?}", root_inode, TypePermissions::from_bits(root_inode.type_and_permissions));

    let root = Entry::new(&root_inode)?;

    println!("{:?}", root);