file.rs 1.51 KB
Newer Older
Jeremy Soller's avatar
Jeremy Soller committed
1 2
use std::fs::{File, OpenOptions};
use std::io::{Read, Write, Seek, SeekFrom};
3
use std::path::Path;
Jeremy Soller's avatar
Jeremy Soller committed
4
use syscall::error::{Error, Result, EIO};
Jeremy Soller's avatar
Jeremy Soller committed
5

Jeremy Soller's avatar
Jeremy Soller committed
6
use BLOCK_SIZE;
7 8
use disk::Disk;

Jeremy Soller's avatar
Jeremy Soller committed
9 10 11 12
macro_rules! try_disk {
    ($expr:expr) => (match $expr {
        Ok(val) => val,
        Err(err) => {
13
            eprintln!("Disk I/O Error: {}", err);
Jeremy Soller's avatar
Jeremy Soller committed
14 15 16 17 18
            return Err(Error::new(EIO));
        }
    })
}

19
pub struct DiskFile {
Jeremy Soller's avatar
Jeremy Soller committed
20
    pub file: File
Jeremy Soller's avatar
Jeremy Soller committed
21 22
}

23
impl DiskFile {
24
    pub fn open<P: AsRef<Path>>(path: P) -> Result<DiskFile> {
Jeremy Soller's avatar
Jeremy Soller committed
25
        let file = try_disk!(OpenOptions::new().read(true).write(true).open(path));
26
        Ok(DiskFile {
Jeremy Soller's avatar
Jeremy Soller committed
27 28 29 30
            file: file
        })
    }

31
    pub fn create<P: AsRef<Path>>(path: P, size: u64) -> Result<DiskFile> {
Jeremy Soller's avatar
Jeremy Soller committed
32 33
        let file = try_disk!(OpenOptions::new().read(true).write(true).create(true).open(path));
        try_disk!(file.set_len(size));
34
        Ok(DiskFile {
Jeremy Soller's avatar
Jeremy Soller committed
35 36 37 38 39
            file: file
        })
    }
}

40
impl Disk for DiskFile {
Jeremy Soller's avatar
Jeremy Soller committed
41
    fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
42
        try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE)));
Jeremy Soller's avatar
Jeremy Soller committed
43 44 45 46 47
        let count = try_disk!(self.file.read(buffer));
        Ok(count)
    }

    fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
48
        try_disk!(self.file.seek(SeekFrom::Start(block * BLOCK_SIZE)));
Jeremy Soller's avatar
Jeremy Soller committed
49 50 51 52 53 54 55 56 57
        let count = try_disk!(self.file.write(buffer));
        Ok(count)
    }

    fn size(&mut self) -> Result<u64> {
        let size = try_disk!(self.file.seek(SeekFrom::End(0)));
        Ok(size)
    }
}