1
0
forked from Rativel/BurritOS
Files
BurritOS/src/filesys/filehdr.rs
2023-04-05 16:14:40 +02:00

260 lines
8.5 KiB
Rust

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<i32>,
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::<i32>() ];
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<u8> = 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<u8> = 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::<i32>();
&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() {
}
}