use crate::disk::inode::Inode; use std::ffi::{OsStr, OsString}; use std::os::unix::ffi::OsStrExt; pub trait Block: Default + Clone {} #[repr(C)] pub struct SuperBlock { pub(crate) data_bitmap_block_number: u64, pub(crate) inode_bitmap_block_number: u64, pub(crate) inode_block_number: u64, pub(crate) data_block_number: u64, pub(crate) total_block_number: u64, pub(crate) used_inode_number: u64, pub(crate) used_block_number: u64, padding: [u8; 4040], } impl SuperBlock { pub(crate) fn new( data_bitmap_block_number: usize, inode_bitmap_block_number: usize, inode_block_number: usize, data_block_number: usize, total_block_number: usize, used_inode_number: u64, used_block_number: u64, ) -> Self { Self { data_bitmap_block_number: data_bitmap_block_number as u64, inode_bitmap_block_number: inode_bitmap_block_number as u64, inode_block_number: inode_block_number as u64, data_block_number: data_block_number as u64, total_block_number: total_block_number as u64, used_inode_number, used_block_number, padding: [0; 4040], } } } #[repr(C)] #[derive(Clone)] pub struct DataBlock(pub(crate) [u8; 4096]); impl Default for DataBlock { fn default() -> Self { Self([0; 4096]) } } impl Block for DataBlock {} #[repr(C)] #[derive(Clone)] pub struct InodeBlock { pub(crate) inodes: [Inode; 32], } impl Default for InodeBlock { fn default() -> Self { Self { inodes: [ Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), Inode::empty(), ], } } } impl Block for InodeBlock {} #[repr(C)] #[derive(Clone)] pub struct DirectoryEntry { pub inode: u32, pub record_len: u16, pub name_len: u8, pub file_type: u8, pub name: [u8; 256], } impl DirectoryEntry { pub(crate) fn name(&self) -> OsString { let name = &self.name[0..self.name_len as usize]; OsStr::from_bytes(name).to_os_string() } } impl Default for DirectoryEntry { fn default() -> Self { Self { inode: 0, record_len: 0, name_len: 0, file_type: 0x0, name: [0; 256], } } } #[repr(C)] #[derive(Clone)] pub struct DirectoryBlock { pub entries: [DirectoryEntry; 15], pub occupancy: [u8; 2], reserved: [u8; 134], } impl Default for DirectoryBlock { fn default() -> Self { Self { entries: [ DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), DirectoryEntry::default(), ], occupancy: [0x80, 0x00], // 0b1000_0000 reserved: [0xFF; 134], } } } impl DirectoryBlock { pub(crate) fn query(&self, mut index: usize) -> bool { if index < 7 { // 0-6, first u8 index = index + 1; self.occupancy[0] & (1 << (7 - index)) as u8 != 0 } else if index < 15 { // 7-14, second u8 index = index - 7; self.occupancy[1] & (1 << (7 - index)) as u8 != 0 } else { false } } pub(crate) fn allocate(&mut self, mut index: usize) -> bool { if index < 7 { index = index + 1; let mask = (1 << (7 - index)) as u8; if self.occupancy[0] & mask != 0 { false } else { self.occupancy[0] |= mask; true } } else { index = index - 7; let mask = (1 << (7 - index)) as u8; if self.occupancy[1] & mask != 0 { false } else { self.occupancy[1] |= mask; true } } } pub(crate) fn reset(&mut self) { self.occupancy[0] = 0x80; self.occupancy[1] = 0x00; } #[allow(unused)] pub(crate) fn deallocate(&mut self, mut index: usize) { if index < 7 { index = index + 1; self.occupancy[0] &= !((1 << (7 - index)) as u8); } else if index < 15 { // 7-14, second u8 index = index - 7; self.occupancy[1] &= !((1 << (7 - index)) as u8); } } } impl Block for DirectoryBlock {} #[repr(C)] #[derive(Clone)] pub struct IndirectBlock { pub entries: [u32; 1024], } impl Default for IndirectBlock { fn default() -> Self { Self { entries: [0; 1024] } } } impl Block for IndirectBlock {} #[repr(C)] #[derive(Clone)] pub struct DoubleIndirectBlock { pub indirect: [u32; 1024], } impl Default for DoubleIndirectBlock { fn default() -> Self { Self { indirect: [0; 1024], } } } impl Block for DoubleIndirectBlock {} #[repr(C)] #[derive(Clone)] pub struct TripleIndirectBlock { pub double_indirect: [u32; 1024], } impl Default for TripleIndirectBlock { fn default() -> Self { Self { double_indirect: [0; 1024], } } } impl Block for TripleIndirectBlock {} const_assert_eq!(std::mem::size_of::(), 4096); const_assert_eq!(std::mem::size_of::(), 4096); const_assert_eq!(std::mem::size_of::(), 4096); const_assert_eq!(std::mem::size_of::(), 4096); const_assert_eq!(std::mem::size_of::(), 4096); const_assert_eq!(std::mem::size_of::(), 4096); const_assert_eq!(std::mem::size_of::(), 4096);