From 946efa2fb5e39669a7fcfc4faf33ed01e92af1ee Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jeremy@system76.com> Date: Wed, 8 May 2019 21:07:21 -0600 Subject: [PATCH] Add sparse disk file to not require image to be sized initially. --- src/bin/ar.rs | 9 +++++---- src/disk/mod.rs | 2 ++ src/disk/sparse.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 src/disk/sparse.rs diff --git a/src/bin/ar.rs b/src/bin/ar.rs index 037958a..6332e91 100644 --- a/src/bin/ar.rs +++ b/src/bin/ar.rs @@ -7,7 +7,7 @@ use std::io::{self, Read}; use std::path::Path; use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use redoxfs::{BLOCK_SIZE, Disk, DiskFile, Extent, FileSystem, Node}; +use redoxfs::{BLOCK_SIZE, Disk, DiskSparse, Extent, FileSystem, Node}; use uuid::Uuid; fn syscall_err(err: syscall::Error) -> io::Error { @@ -72,14 +72,15 @@ fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_path: P, ctim let free_block = fs.header.1.free; let mut free = fs.node(free_block).map_err(syscall_err)?; let end_block = free.1.extents[0].block; + let end_size = end_block * BLOCK_SIZE; free.1.extents[0] = Extent::default(); fs.write_at(free.0, &free.1).map_err(syscall_err)?; - fs.header.1.size = end_block; + fs.header.1.size = end_size; let header = fs.header; fs.write_at(header.0, &header.1).map_err(syscall_err)?; - Ok(end_block * BLOCK_SIZE) + Ok(end_size) } fn main() { @@ -103,7 +104,7 @@ fn main() { let bootloader_path_opt = args.next(); - let disk = match DiskFile::open(&disk_path) { + let disk = match DiskSparse::create(&disk_path) { Ok(disk) => disk, Err(err) => { println!("redoxfs-ar: failed to open image {}: {}", disk_path, err); diff --git a/src/disk/mod.rs b/src/disk/mod.rs index 941fa6f..73b5db3 100644 --- a/src/disk/mod.rs +++ b/src/disk/mod.rs @@ -2,9 +2,11 @@ use syscall::error::Result; pub use self::cache::DiskCache; pub use self::file::DiskFile; +pub use self::sparse::DiskSparse; mod cache; mod file; +mod sparse; /// A disk pub trait Disk { diff --git a/src/disk/sparse.rs b/src/disk/sparse.rs new file mode 100644 index 0000000..dd7d799 --- /dev/null +++ b/src/disk/sparse.rs @@ -0,0 +1,48 @@ +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write, Seek, SeekFrom}; +use std::u64; +use syscall::error::{Error, Result, EIO}; + +use BLOCK_SIZE; +use disk::Disk; + +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 DiskSparse { + pub file: File, +} + +impl DiskSparse { + pub fn create(path: &str) -> Result<DiskSparse> { + let file = try_disk!(OpenOptions::new().read(true).write(true).create(true).open(path)); + Ok(DiskSparse { + file + }) + } +} + +impl Disk for DiskSparse { + fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> { + 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<usize> { + 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<u64> { + Ok(u64::MAX) + } +} diff --git a/src/lib.rs b/src/lib.rs index 2e51ab1..a6bc814 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ pub const SIGNATURE: &'static [u8; 8] = b"RedoxFS\0"; pub const VERSION: u64 = 3; pub static IS_UMT: AtomicUsize = AtomicUsize::new(0); -pub use self::disk::{Disk, DiskCache, DiskFile}; +pub use self::disk::{Disk, DiskCache, DiskFile, DiskSparse}; pub use self::ex_node::ExNode; pub use self::extent::Extent; pub use self::filesystem::FileSystem; -- GitLab