use std::fs::{File, OpenOptions}; use std::io::{Read, Seek, SeekFrom, Write}; use std::path::Path; use syscall::error::{Error, Result, EIO}; use disk::Disk; use BLOCK_SIZE; macro_rules! try_disk { ($expr:expr) => { match $expr { Ok(val) => val, Err(err) => { eprintln!("Disk I/O Error: {}", err); return Err(Error::new(EIO)); } } }; } pub struct DiskFile { pub file: File, } impl DiskFile { pub fn open>(path: P) -> Result { let file = try_disk!(OpenOptions::new().read(true).write(true).open(path)); Ok(DiskFile { file: file }) } pub fn create>(path: P, size: u64) -> Result { let file = try_disk!(OpenOptions::new() .read(true) .write(true) .create(true) .open(path)); try_disk!(file.set_len(size)); Ok(DiskFile { file: file }) } } impl Disk for DiskFile { fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result { try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE))); let count = try_disk!(self.file.read(buffer)); Ok(count) } fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result { try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE))); let count = try_disk!(self.file.write(buffer)); Ok(count) } fn size(&mut self) -> Result { let size = try_disk!(self.file.seek(SeekFrom::End(0))); Ok(size) } }