diff --git a/Cargo.toml b/Cargo.toml index acec5ca..5811eff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" authors = ["WangRunji "] [dependencies] -spin = "0.4" \ No newline at end of file +spin = "0.4" +bit-set = "0.5" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index a2a1f1e..34b1939 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,15 @@ #![feature(alloc)] #![no_std] +#[cfg(test)] +#[macro_use] +extern crate std; + extern crate spin; extern crate alloc; +extern crate bit_set; -mod vfs; +mod sfs; mod structs; #[cfg(test)] mod tests; \ No newline at end of file diff --git a/src/sfs.rs b/src/sfs.rs new file mode 100644 index 0000000..a8497da --- /dev/null +++ b/src/sfs.rs @@ -0,0 +1,69 @@ +use spin::Mutex; +use bit_set::BitSet; +use alloc::{boxed::Box, Vec}; +use super::structs::*; +use core::mem::{uninitialized, size_of}; +use core::slice; + +/// Interface for SFS to read & write +/// TODO: use std::io::{Read, Write} +pub trait Device { + fn read_at(&mut self, offset: u64, buf: &mut [u8]) -> Option; + fn write_at(&mut self, offset: u64, buf: &[u8]) -> Option; +} + +/// inode for sfs +pub struct Inode { + /// on-disk inode + disk_inode: *mut DiskInode, + /// inode number + id: u32, + /// true if inode modified + dirty: bool, + /// kill inode if it hits zero + reclaim_count: u32, + /// semaphore for din + mutex: Mutex<()>, +} + +/// filesystem for sfs +pub struct SimpleFileSystem { + /// on-disk superblock + super_block: SuperBlock, + /// blocks in use are mared 0 + free_map: BitSet, + /// true if super/freemap modified + super_dirty: bool, + /// buffer for non-block aligned io +// buffer: u8, + /// semaphore for fs +// fs_mutex: Mutex<()>, + /// semaphore for link/unlink and rename +// link_mutex: Mutex<()>, + /// inode list +// inodes: Vec, + /// device + device: Mutex>, +} + +impl SimpleFileSystem { + /// Create a new SFS with device + pub fn new(mut device: Box) -> Option { + let mut super_block: SuperBlock = unsafe{ uninitialized() }; + let slice = unsafe{ slice::from_raw_parts_mut( + &mut super_block as *mut SuperBlock as *mut u8, size_of::()) }; + if device.read_at(0, slice).is_none() { + return None; + } + if super_block.check() == false { + return None; + } + + Some(SimpleFileSystem { + super_block, + free_map: BitSet::new(), + super_dirty: false, + device: Mutex::new(device), + }) + } +} \ No newline at end of file diff --git a/src/structs.rs b/src/structs.rs index e23d2e3..8f23d4c 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -1,81 +1,49 @@ -use spin::Mutex; -use alloc::Vec; -//use core::fmt::{Debug, Formatter, Error}; - /// On-disk superblock #[repr(C, packed)] -struct SuperBlock { +pub struct SuperBlock { /// magic number, should be SFS_MAGIC - magic: u32, + pub magic: u32, /// number of blocks in fs - blocks: u32, + pub blocks: u32, /// number of unused blocks in fs - unused_blocks: u32, + pub unused_blocks: u32, /// infomation for sfs - info: [u8; MAX_INFO_LEN + 1], + pub info: [u8; MAX_INFO_LEN + 1], } /// inode (on disk) #[repr(C, packed)] #[derive(Debug)] -struct DiskInode { +pub struct DiskInode { /// size of the file (in bytes) - size: u32, + pub size: u32, /// one of SYS_TYPE_* above - type_: u16, + pub type_: u16, /// number of hard links to this file - nlinks: u16, + pub nlinks: u16, /// number of blocks - blocks: u32, + pub blocks: u32, /// direct blocks - direct: [u32; NDIRECT], + pub direct: [u32; NDIRECT], /// indirect blocks - indirect: u32, + pub indirect: u32, /// double indirect blocks - db_indirect: u32, + pub db_indirect: u32, } /// file entry (on disk) #[repr(C, packed)] -struct DiskEntry { +pub struct DiskEntry { /// inode number - inode_number: u32, + pub inode_number: u32, /// file name - name: [u8; MAX_FNAME_LEN + 1], -} - -/// inode for sfs -struct Inode { - /// on-disk inode - disk_inode: *mut DiskInode, - /// inode number - id: u32, - /// true if inode modified - dirty: bool, - /// kill inode if it hits zero - reclaim_count: u32, - /// semaphore for din - mutex: Mutex<()>, + pub name: [u8; MAX_FNAME_LEN + 1], } -/// filesystem for sfs -struct SimpleFileSystem { - /// on-disk superblock - super_block: SuperBlock, - /// blocks in use are mared 0 - free_map: [u8; 0], - /// true if super/freemap modified - super_dirty: bool, - /// buffer for non-block aligned io - buffer: [u8; 0], - /// semaphore for fs - fs_mutex: Mutex<()>, - /// semaphore for io - io_mutex: Mutex<()>, - /// semaphore for link/unlink and rename - link_mutex: Mutex<()>, - /// inode list - inodes: Vec +impl SuperBlock { + pub fn check(&self) -> bool { + self.magic == MAGIC + } } /* @@ -83,29 +51,29 @@ struct SimpleFileSystem { * and is used by tools that work on SFS volumes, such as mksfs. */ /// magic number for sfs -const MAGIC: usize = 0x2f8dbe2a; +pub const MAGIC: u32 = 0x2f8dbe2a; /// size of block -const BLKSIZE: usize = 4096; +pub const BLKSIZE: usize = 4096; /// number of direct blocks in inode -const NDIRECT: usize = 12; +pub const NDIRECT: usize = 12; /// max length of infomation -const MAX_INFO_LEN: usize = 31; +pub const MAX_INFO_LEN: usize = 31; /// max length of filename -const MAX_FNAME_LEN: usize = 255; +pub const MAX_FNAME_LEN: usize = 255; /// max file size (128M) -const MAX_FILE_SIZE: usize = 1024 * 1024 * 128; +pub const MAX_FILE_SIZE: usize = 1024 * 1024 * 128; /// block the superblock lives in -const BLKN_SUPER: usize = 0; +pub const BLKN_SUPER: usize = 0; /// location of the root dir inode -const BLKN_ROOT: usize = 1; +pub const BLKN_ROOT: usize = 1; /// 1st block of the freemap -const BLKN_FREEMAP: usize = 2; +pub const BLKN_FREEMAP: usize = 2; /// number of bits in a block -const BLKBITS: usize = BLKSIZE * 8; +pub const BLKBITS: usize = BLKSIZE * 8; /// number of entries in a block -const BLK_NENTRY: usize = BLKSIZE / 4; +pub const BLK_NENTRY: usize = BLKSIZE / 4; /// file types -enum FileType { +pub enum FileType { Invalid = 0, File = 1, Dir = 2, Link = 3, } \ No newline at end of file diff --git a/src/tests.rs b/src/tests.rs index 43f948c..3d6a79d 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,4 +1,28 @@ +use std::fs::File; +use std::io::{Read, Write, Seek, SeekFrom}; +use std::boxed::Box; +use super::sfs::*; + +impl Device for File { + fn read_at(&mut self, offset: u64, buf: &mut [u8]) -> Option { + match self.seek(SeekFrom::Start(offset)) { + Ok(real_offset) if real_offset == offset => self.read(buf).ok(), + _ => None, + } + } + + fn write_at(&mut self, offset: u64, buf: &[u8]) -> Option { + match self.seek(SeekFrom::Start(offset)) { + Ok(real_offset) if real_offset == offset => self.write(buf).ok(), + _ => None, + } + } +} + #[test] fn test() { - + let file = File::open("sfs.img") + .expect("failed to open sfs.img"); + let sfs = SimpleFileSystem::new(Box::new(file)) + .expect("failed to create SFS"); } \ No newline at end of file