From 0754019950e2215cd0e6059a7080a6416a1ad7ea Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jeremy@system76.com> Date: Wed, 8 May 2019 20:55:37 -0600 Subject: [PATCH] Truncate disk image --- src/bin/ar.rs | 58 ++++++++++++++++++++++++++++++++++++------------ src/disk/file.rs | 2 +- src/header.rs | 1 + 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/bin/ar.rs b/src/bin/ar.rs index b403337..037958a 100644 --- a/src/bin/ar.rs +++ b/src/bin/ar.rs @@ -2,19 +2,19 @@ extern crate redoxfs; extern crate syscall; extern crate uuid; -use std::{env, fs, process, time}; +use std::{env, fs, process}; use std::io::{self, Read}; use std::path::Path; -use std::time::{SystemTime, UNIX_EPOCH}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; -use redoxfs::{Disk, DiskFile, FileSystem, Node}; +use redoxfs::{BLOCK_SIZE, Disk, DiskFile, Extent, FileSystem, Node}; use uuid::Uuid; fn syscall_err(err: syscall::Error) -> io::Error { io::Error::from_raw_os_error(err.errno) } -fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_block: u64, parent_path: P) -> io::Result<()> { +fn archive_at<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_path: P, ctime: &Duration, parent_block: u64) -> io::Result<()> { for entry_res in fs::read_dir(parent_path)? { let entry = entry_res?; @@ -36,7 +36,6 @@ fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_block: u64, p }; let mode = mode_type | (mode_perm & Node::MODE_PERM); - let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); let mut node = fs.create_node( mode, &name, @@ -49,7 +48,7 @@ fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_block: u64, p fs.write_at(node.0, &node.1).map_err(syscall_err)?; if dir { - archive(fs, node.0, path)?; + archive_at(fs, path, ctime, node.0)?; } else { let data = fs::read(path)?; fs.write_node( @@ -65,6 +64,24 @@ fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_block: u64, p Ok(()) } + +fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_path: P, ctime: &Duration) -> io::Result<u64> { + let root_block = fs.header.1.root; + archive_at(fs, parent_path, ctime, root_block)?; + + 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; + free.1.extents[0] = Extent::default(); + fs.write_at(free.0, &free.1).map_err(syscall_err)?; + + fs.header.1.size = end_block; + let header = fs.header; + fs.write_at(header.0, &header.1).map_err(syscall_err)?; + + Ok(end_block * BLOCK_SIZE) +} + fn main() { let mut args = env::args().skip(1); @@ -111,21 +128,34 @@ fn main() { } }; - let ctime = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap(); + let ctime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); match FileSystem::create_reserved(disk, &bootloader, ctime.as_secs(), ctime.subsec_nanos()) { - Ok(mut filesystem) => { - let root = filesystem.header.1.root; - if let Err(err) = archive(&mut filesystem, root, &folder_path) { - println!("redoxfs-ar: failed to archive {}: {}", folder_path, err); + Ok(mut fs) => { + let size = match archive(&mut fs, &folder_path, &ctime) { + Ok(ok) => ok, + Err(err) => { + println!("redoxfs-ar: failed to archive {}: {}", folder_path, err); + process::exit(1); + } + }; + + if let Err(err) = fs.disk.file.set_len(size) { + println!("redoxfs-ar: failed to truncate {} to {}: {}", disk_path, size, err); process::exit(1); } - let uuid = Uuid::from_bytes(&filesystem.header.1.uuid).unwrap(); - println!("redoxfs-ar: created filesystem on {}, reserved {} blocks, size {} MB, uuid {}", disk_path, filesystem.block, filesystem.header.1.size/1000/1000, uuid.hyphenated()); + let uuid = Uuid::from_bytes(&fs.header.1.uuid).unwrap(); + println!( + "redoxfs-ar: created filesystem on {}, reserved {} blocks, size {} MB, uuid {}", + disk_path, + fs.block, + fs.header.1.size/1000/1000, + uuid.hyphenated() + ); }, Err(err) => { println!("redoxfs-ar: failed to create filesystem on {}: {}", disk_path, err); process::exit(1); } - } + }; } diff --git a/src/disk/file.rs b/src/disk/file.rs index 578194f..de1a6fb 100644 --- a/src/disk/file.rs +++ b/src/disk/file.rs @@ -16,7 +16,7 @@ macro_rules! try_disk { } pub struct DiskFile { - file: File + pub file: File } impl DiskFile { diff --git a/src/header.rs b/src/header.rs index ee11337..0c4b776 100644 --- a/src/header.rs +++ b/src/header.rs @@ -6,6 +6,7 @@ use uuid::Uuid; use {BLOCK_SIZE, SIGNATURE, VERSION}; /// The header of the filesystem +#[derive(Clone, Copy)] #[repr(packed)] pub struct Header { /// Signature, should be SIGNATURE -- GitLab