use crate::{simulator::disk::SECTOR_SIZE, utility::bitmap::BitMap}; pub const MAX_HEADER_SECTORS: i32 = 32; pub const DATAS_IN_FIRST_SECTOR: i32 = (SECTOR_SIZE - 5 * 8) /8; pub const DATAS_IN_SECTOR: i32 = (SECTOR_SIZE - 1 * 8) /8; pub const MAX_DATA_SECTORS: i32 = ((MAX_HEADER_SECTORS-1) * DATAS_IN_SECTOR + DATAS_IN_FIRST_SECTOR); pub const MAX_FILE_LENGTH: i32 = ((MAX_DATA_SECTORS) * SECTOR_SIZE); use crate::DrvDisk; use crate::Disk; use crate::OpenFile; use std::mem; use super::openfile::OpenFile; pub struct FileHdr { is_dir: i32, num_bytes: i32, num_sectors: i32, data_sectors: Vec, num_header_sectors: i32, header_sectors: [i32; MAX_HEADER_SECTORS as usize], } impl FileHdr { pub fn init_file_hdr() -> FileHdr { FileHdr { is_dir: 0, num_bytes: 0, num_sectors: 0, data_sectors: Vec::new(), num_header_sectors: 0, header_sectors: [0;MAX_HEADER_SECTORS as usize], } } pub fn allocate(&mut self, mut free_map: BitMap, file_size: i32) -> bool { self.num_bytes = file_size; if file_size > MAX_FILE_LENGTH { panic!("file size is too long"); } self.num_sectors = (file_size + SECTOR_SIZE -1) / SECTOR_SIZE; self.num_header_sectors = ((self.num_sectors - DATAS_IN_FIRST_SECTOR)+DATAS_IN_SECTOR-1) / DATAS_IN_SECTOR; // Check if there is enough free sectors for both of them if free_map.num_clear() < self.num_sectors + self.num_header_sectors { return false; } for i in 0..self.num_header_sectors { self.header_sectors[i as usize] = free_map.find(); } self.data_sectors = vec![0; MAX_DATA_SECTORS as usize]; for i in 0..self.num_sectors { self.data_sectors[i as usize] = free_map.find(); } return true; } pub fn re_allocate(&mut self, mut free_map: BitMap, old_file_size: i32, new_file_size: i32) -> bool { let mut new_num_sectors = ((new_file_size + SECTOR_SIZE -1) / SECTOR_SIZE) - self.num_sectors; self.num_bytes = new_file_size; let mut new_num_header_sectors = (((self.num_sectors - DATAS_IN_FIRST_SECTOR)+DATAS_IN_SECTOR-1) / DATAS_IN_SECTOR) - self.num_header_sectors; assert!(new_file_size <= MAX_FILE_LENGTH); if free_map.num_clear() < new_num_sectors + new_num_header_sectors { return false; } for i in 0..new_num_header_sectors { self.header_sectors[(i + self.num_header_sectors)as usize] = free_map.find(); } for i in 0..new_num_sectors { self.data_sectors[(i + self.num_sectors) as usize] = free_map.find(); } return true; } pub fn deallocate(&mut self, mut free_map: BitMap) { for i in 0..self.num_sectors { assert!(free_map.test(self.data_sectors[i as usize] as usize)); free_map.clear(self.data_sectors[i as usize]as usize); } for i in 0..self.num_header_sectors { assert!(free_map.test(self.header_sectors[i as usize] as usize)); free_map.clear(self.header_sectors[i as usize]as usize); } } pub fn fetch_from(&self, file: OpenFile) { file.read_at(self.table,self.table_size * mem::size_of::() as i32); } pub fn write_back(&self, file: OpenFile) { file.write_at(self.table,self.table_size * mem::size_of::() as i32); } pub fn byte_to_sector(&self,offset: i32) -> i32 { return self.data_sectors[ (offset / SECTOR_SIZE) as usize]; } pub fn file_length(&self) -> i32 { return self.num_bytes; } pub fn change_file_length(&mut self, new_size: i32) { self.num_bytes = new_size; assert!(new_size <= MAX_FILE_LENGTH); } pub fn max_file_length(&self) -> i32 { return self.num_sectors * SECTOR_SIZE; } pub fn print(&self) { let mut data = Vec::new(); println!("FileHeader contents. File size: {}. File blocks:", self.num_bytes); for i in 0..self.num_sectors { print!("{} ", self.data_sectors[i as usize]); } println!("\nFile contents:"); let mut k = 0; for i in 0..self.num_sectors { let disk = Disk::init_disk(); let mut drv_disk = DrvDisk::init_drv_disk(disk); drv_disk.read_sector(self.data_sectors[i as usize], &mut data); for j in 0..SECTOR_SIZE.min(self.num_bytes - k) { let c = data[j as usize]; if c >= 0x20 && c <= 0x7E { print!("{}", c as char); } else { print!("\\{:x}", c); } k += 1; } println!(""); } } pub fn is_dir(&self) -> bool{ return self.is_dir == 1; } pub fn set_file(&mut self) { self.is_dir = 0; } pub fn set_dir(&mut self) { self.is_dir = 1; } } #[cfg(test)] mod test { #[test] fn test_allocate() { } }