use core::panic; use std::fs::File; use std::io; use std::io::prelude::*; use std::io::SeekFrom; use std::os::unix::prelude::FileExt; pub const SECTORS_PER_TRACK: i32 = 32; pub const NUM_TRACKS: i32 = 64; pub const NUM_SECTORS: i32 = SECTORS_PER_TRACK * NUM_TRACKS; pub const SECTOR_SIZE: i32 = 4; //4 octects ? pub const DISK_PATH: &str = "disk_file"; pub const MAGIC_NUMBER: u32 = 0xABBACDDC; //taille en octets, a confirmer pub const DISK_SIZE: i32 = 4 + NUM_SECTORS * SECTOR_SIZE; //4 <=> sizeof(u32) pub struct Disk { pub last_sector: i32, //Secteur accédé lors de la précédente requête de lecture/ecriture pub active: bool, //C'est notre lock -> Une seule requête de lecture/ecriture à la fois pub disk_file: File, //On simule le disque sur un fichier //Manque une ref a une fonction type handler, fournie via constructeur dans Nachos } impl Disk { pub fn init_disk() -> Disk { //see Rust File impl FileExt for File For UNIX mode let mut magic_buff: [u8; 4] = [0u8; 4]; let mut readed_magic_number: u32; let disk_file: File; let result_open = File::options().read(true).write(true).open(DISK_PATH); let magic_to_write: [u8; 4] = [0xAB, 0xBA, 0xCD, 0xDC]; match result_open { Err(e) => { //On creer le fichier et on y écrit le magic number println!("Error opening file : {}", e); disk_file = File::options() .read(true) .write(true) .create_new(true) .open(DISK_PATH) .unwrap(); disk_file.set_len(DISK_SIZE as u64); disk_file.write_at(&magic_to_write[..], 0); } Ok(f) => { disk_file = f; disk_file.set_len(DISK_SIZE as u64); disk_file.write_at(&magic_to_write[..], 0); } } match disk_file.read_at(&mut magic_buff[..], 0) { Ok(t) => { println!("init_disk :: on a lu {} octets", t); readed_magic_number = ((magic_buff[0] as u32) << 24) + ((magic_buff[1] as u32) << 16) + ((magic_buff[2] as u32) << 8) + ((magic_buff[3] as u32) << 0); if readed_magic_number != MAGIC_NUMBER { panic!( "init_disk :: Did not recognize magic number at the beginning of disk_file, On a lu {:#08x}, Panic", readed_magic_number ); } else { println!( "init_disk :: on a lu le magic_number {:#08x}", readed_magic_number ); } } Err(e) => { println!("init_disk :: Error reading file : {}", e); } } Disk { last_sector: 0, active: false, disk_file: disk_file, } } /// read data from a disk, at a certain sector number /// /// `panic!` when the disk is already active or the sector number is impossible /// /// ### parameters /// /// - **disk** to read from /// - **sector_number** sector where to read the data /// - **data** where the readed data will be stored pub fn read_request(disk: &mut Disk, sector_number: i32, data: &mut Vec) -> io::Result<()> { if disk.active { panic!("Only one request at time"); } if sector_number < 0 || sector_number >= NUM_SECTORS { panic!("sector_number isn't right"); } disk.active = true; disk.disk_file .seek(SeekFrom::Start((sector_number * SECTOR_SIZE) as u64))?; let mut buffer = [0; SECTOR_SIZE as usize]; disk.disk_file.read(&mut buffer)?; for byte in buffer { data.push(byte); } disk.active = false; Ok(()) } /// write data into a disk, at a certain sector number /// /// `panic!` when the disk is already active or the sector number is impossible /// /// ### parameters /// /// - **disk** to write data into /// - **sector_number** sector where to write the data /// - **data** where the data to write is stored pub fn write_request( disk: &mut Disk, sector_number: i32, data: &mut Vec, ) -> io::Result<()> { if disk.active { panic!("Only one request at time"); } if sector_number < 0 || sector_number >= NUM_SECTORS { panic!("sector_number isn't right"); } disk.active = true; disk.disk_file .seek(SeekFrom::Start((sector_number * SECTOR_SIZE) as u64))?; let mut i = 0; let mut buff = Vec::new(); for value in data { buff.push(*value); i = i + 1; if i >= SECTOR_SIZE { break; } } let res = disk.disk_file.write(&buff); match res { Ok(_) => println!("Data written successfully"), Err(e) => println!("{:?}", e), } disk.active = false; Ok(()) } } pub fn stupid_fct(buf: &[u8]) { println!("Size of unknown sized parameter buffer : {}", buf.len()); for i in 0..buf.len() { println!("buf[{}] = {}", i, buf[i]); } } #[cfg(test)] mod test { use serial_test::serial; use crate::Disk; use super::stupid_fct; #[test] #[serial] fn test_init_stupid_fct() { let buffy: [u8; 6] = [1, 2, 3, 4, 5, 6]; stupid_fct(&buffy); //EN passant par une ref , on s'abstrait du besoin de connaitre la taille au moment de la compilation } #[test] #[serial] fn test_init_disk() { let disk = Disk::init_disk(); } #[test] #[serial] fn test_read_write_disk() { let mut disk = Disk::init_disk(); let mut data = Vec::new(); data.push(0 as u8); data.push(0 as u8); data.push(0 as u8); data.push(0 as u8); let mut data1 = Vec::new(); data1.push(1 as u8); data1.push(1 as u8); data1.push(1 as u8); data1.push(1 as u8); let mut data2: Vec = Vec::new(); Disk::write_request(&mut disk, 0, &mut data); Disk::write_request(&mut disk, 1, &mut data1); Disk::read_request(&mut disk, 1, &mut data2); assert_eq!(data1, data2); assert_ne!(data, data1); assert_ne!(data, data2); } }