ahrightos-fs 0.1.0

Portable filesystem, block-device, and IPC primitives for the AhRightOS teaching kernel.
Documentation
use crate::file::FileError;
use alloc::sync::Arc;
use alloc::vec::Vec;
use spin::Mutex;

pub const BLOCK_SIZE: usize = 512;

pub trait BlockDevice: Send + Sync {
    fn read_block(&self, block_no: usize, buf: &mut [u8]) -> Result<(), FileError>;
    fn write_block(&self, block_no: usize, buf: &[u8]) -> Result<(), FileError>;
    fn block_count(&self) -> usize;
    fn flush(&self) -> Result<(), FileError> {
        Ok(())
    }
}

pub struct DummyBlockDev {
    data: Mutex<Vec<u8>>,
    blocks: usize,
}

impl DummyBlockDev {
    pub fn new(blocks: usize) -> Self {
        Self {
            data: Mutex::new(alloc::vec![0u8; blocks * BLOCK_SIZE]),
            blocks,
        }
    }
}

impl BlockDevice for DummyBlockDev {
    fn read_block(&self, block_no: usize, buf: &mut [u8]) -> Result<(), FileError> {
        if block_no >= self.blocks || buf.len() != BLOCK_SIZE {
            return Err(FileError::InvalidOperation);
        }
        let start = block_no * BLOCK_SIZE;
        let data = self.data.lock();
        buf.copy_from_slice(&data[start..start + BLOCK_SIZE]);
        Ok(())
    }

    fn write_block(&self, block_no: usize, buf: &[u8]) -> Result<(), FileError> {
        if block_no >= self.blocks || buf.len() != BLOCK_SIZE {
            return Err(FileError::InvalidOperation);
        }
        let start = block_no * BLOCK_SIZE;
        let mut data = self.data.lock();
        data[start..start + BLOCK_SIZE].copy_from_slice(buf);
        Ok(())
    }

    fn block_count(&self) -> usize {
        self.blocks
    }
}

pub type BlockDeviceHandle = Arc<dyn BlockDevice>;