use crate::drivers::drv_disk; 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 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) as i32 { 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) as i32{ 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); } } ///Fetch contents of file header from disk. fn fetch_from(&mut self, sector: i32, drv_disk: &mut DrvDisk) { //temporary buffer let mut sector_img = vec![0; SECTOR_SIZE as usize / std::mem::size_of::() ]; let mut data_sectors = vec![0; MAX_DATA_SECTORS as usize]; // Fills the temporary buffer with zeros sector_img.fill(0); // Read the header from the disk // and put it in the temporary buffer DrvDisk::read_sector(&mut drv_disk, sector, &mut sector_img); // Set up the memory image of the file header // from the newly read buffer self.is_dir = sector_img[0] as i32; self.num_bytes = sector_img[1] as i32; self.num_sectors = sector_img[2] as i32; self.num_header_sectors = sector_img[3] as i32; // Get the first header sector self.header_sectors[0] = *FileHdr::next_header_sector(sector_img); // Get the number of the data sectors stored into // the header sector in disk for i in 4..DATAS_IN_SECTOR as usize { data_sectors[i - 4] = sector_img[i]; } // Get the other numbers of header sectors and data sectors for i in 0..self.num_header_sectors as usize { // Fill the temporary buffer with zeroes sector_img.fill(0); DrvDisk::read_sector(&mut drv_disk, self.header_sectors[i], &mut sector_img); for j in 0..DATAS_IN_SECTOR as usize { data_sectors[DATAS_IN_FIRST_SECTOR as usize + i * DATAS_IN_SECTOR as usize + j] = sector_img[j]; } // Make sure we don't go out of bounds if i + 1 < self.num_header_sectors as usize { self.header_sectors[i + 1] = *FileHdr::next_header_sector(&mut sector_img); } } } fn write_back(&self, sector: i32, drv_disk: &mut DrvDisk) { let mut sector_img = vec![0; DATAS_IN_SECTOR as usize]; // Fills the temporary buffer with zeroes sector_img.fill(0); // Fills the header of the first header sector sector_img[0] = self.is_dir; sector_img[1] = self.num_bytes; sector_img[2] = self.num_sectors; sector_img[3] = self.num_header_sectors; // Fills the number of the data sectors and the first header // sector in the temporary buffer for i in 4..DATAS_IN_SECTOR as usize { sector_img[i] = self.data_sectors[(i - 4)]; } // Write the first header sector into disk *FileHdr::next_header_sector(&mut sector_img) = self.header_sectors[0]; let mut vec_u8: Vec = sector_img.iter().map(|&x| x as u8).collect(); DrvDisk::write_sector(&mut drv_disk, sector, &mut vec_u8); // Write the following header sectors into disk for i in 0..self.num_header_sectors { sector_img.fill(0); for j in 0..DATAS_IN_SECTOR { sector_img[j as usize] = self.data_sectors[(j + DATAS_IN_FIRST_SECTOR + i * DATAS_IN_SECTOR) as usize]; } if i + 1 < self.num_header_sectors { *FileHdr::next_header_sector(&mut sector_img) = self.header_sectors[(i + 1) as usize]; } else { *FileHdr::next_header_sector(&mut sector_img) = 0; } let mut vec_u8: Vec = sector_img.iter().map(|&x| x as u8).collect(); DrvDisk::write_sector(&mut drv_disk, self.header_sectors[i as usize], &mut vec_u8); } } pub fn next_header_sector(hdr_sector: &mut [i32]) -> &mut i32 { let sector_size = SECTOR_SIZE as usize / std::mem::size_of::(); &mut hdr_sector[sector_size - 1] } pub fn byte_to_sector(&self,offset: usize) -> 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, drv_disk: &mut DrvDisk) { 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 { 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() { } }