forked from Rativel/BurritOS
226 lines
6.6 KiB
Rust
226 lines
6.6 KiB
Rust
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<u8>) -> 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<u8>,
|
|
) -> 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<u8> = 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);
|
|
}
|
|
}
|