From bae24a54b00a7dd13f08a17f21859f05ca66e18b Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Wed, 24 Feb 2016 18:23:25 -0700 Subject: [PATCH] Improve debugging and image creation --- .gitignore | 3 +++ src/disk.rs | 1 + src/extent.rs | 9 +++++++++ src/filesystem.rs | 39 ++++++++++++++++++++++++++++++++------- src/header.rs | 12 ++++++------ src/lib.rs | 1 + src/node.rs | 32 +++++++++++++++++++++++++++++++- utility/image.rs | 13 +++++++++---- utility/main.rs | 8 ++++---- 9 files changed, 96 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index f857248..54a3b4d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ # Generated by Cargo Cargo.lock /target/ + +# Images +*.bin diff --git a/src/disk.rs b/src/disk.rs index 495ba4e..1546766 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -2,4 +2,5 @@ pub trait Disk<E> { fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize, E>; fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize, E>; + fn size(&mut self) -> Result<u64, E>; } diff --git a/src/extent.rs b/src/extent.rs index def358c..336ed13 100644 --- a/src/extent.rs +++ b/src/extent.rs @@ -5,3 +5,12 @@ pub struct Extent { pub block: u64, pub length: u64, } + +impl Extent { + pub fn new(block: u64, length: u64) -> Extent { + Extent { + block: block, + length: length + } + } +} diff --git a/src/filesystem.rs b/src/filesystem.rs index a30128e..63a0e55 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -1,22 +1,33 @@ use alloc::boxed::Box; -use super::{Disk, Header, Node}; +use super::{Disk, Extent, Header, Node}; /// A file system pub struct FileSystem<E> { pub disk: Box<Disk<E>>, - pub header: Header, + pub header: (u64, Header), + pub root: (u64, Node), + pub free: (u64, Node) } impl<E> FileSystem<E> { /// Open a file system on a disk pub fn open(mut disk: Box<Disk<E>>) -> Result<Option<Self>, E> { - let mut header = Header::default(); - try!(disk.read_at(1, &mut header)); - if header.valid() { + let mut header = (1, Header::default()); + try!(disk.read_at(header.0, &mut header.1)); + + if header.1.valid() { + let mut root = (header.1.root, Node::default()); + try!(disk.read_at(root.0, &mut root.1)); + + let mut free = (header.1.free, Node::default()); + try!(disk.read_at(free.0, &mut free.1)); + Ok(Some(FileSystem { disk: disk, header: header, + root: root, + free: free })) }else{ Ok(None) @@ -25,11 +36,25 @@ impl<E> FileSystem<E> { /// Create a file system on a disk pub fn create(mut disk: Box<Disk<E>>) -> Result<Self, E> { - let header = Header::new(); - try!(disk.write_at(1, &header)); + let size = try!(disk.size()); + + assert!(size > 4); + + let mut free = (3, Node::new("free", Node::MODE_DIR)); + free.1.extents[0] = Extent::new(4, (size - 4 * 512)); + try!(disk.write_at(free.0, &free.1)); + + let root = (2, Node::new("root", Node::MODE_DIR)); + try!(disk.write_at(root.0, &root.1)); + + let header = (1, Header::new(size, root.0, free.0)); + try!(disk.write_at(header.0, &header.1)); + Ok(FileSystem { disk: disk, header: header, + root: root, + free: free }) } diff --git a/src/header.rs b/src/header.rs index 5b5d950..c0306e8 100644 --- a/src/header.rs +++ b/src/header.rs @@ -16,7 +16,7 @@ pub struct Header { /// Block of root node pub root: u64, /// Block of free space node - pub free_space: u64, + pub free: u64, } impl Header { @@ -27,18 +27,18 @@ impl Header { uuid: [0; 16], size: 0, root: 0, - free_space: 0, + free: 0, } } - pub fn new() -> Header { + pub fn new(size: u64, root: u64, free: u64) -> Header { Header { signature: *b"REDOXFS\0", version: 1, uuid: [0; 16], - size: 0, - root: 0, - free_space: 0, + size: size, + root: root, + free: free, } } diff --git a/src/lib.rs b/src/lib.rs index 412d412..32f1493 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![crate_name="redoxfs"] #![crate_type="lib"] #![feature(alloc)] +#![feature(associated_consts)] #![feature(collections)] #![no_std] diff --git a/src/node.rs b/src/node.rs index ef287da..3882f6d 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,3 +1,5 @@ +use collections::Vec; + use core::{fmt, mem, ops, slice, str}; use super::Extent; @@ -12,6 +14,10 @@ pub struct Node { } impl Node { + pub const MODE_MASK: u64 = 0xF000; + pub const MODE_FILE: u64 = 0x8000; + pub const MODE_DIR: u64 = 0x4000; + pub fn default() -> Node { Node { name: [0; 256], @@ -21,6 +27,20 @@ impl Node { } } + pub fn new(name: &str, mode: u64) -> Node { + let mut bytes = [0; 256]; + for (mut b, c) in bytes.iter_mut().zip(name.bytes()) { + *b = c; + } + + Node { + name: bytes, + mode: mode, + next: 0, + extents: [Extent::default(); 15] + } + } + pub fn name(&self) -> Result<&str, str::Utf8Error> { let mut len = 0; @@ -33,11 +53,21 @@ impl Node { str::from_utf8(&self.name[..len]) } + + pub fn size(&self) -> u64 { + self.extents.iter().fold(0, |size, extent| size + extent.length) + } } impl fmt::Debug for Node { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Node {{ name: {:?}, mode: {:?}, next: {:?}, extents: {:?} }}", self.name(), self.mode, self.next, self.extents) + let extents: Vec<&Extent> = self.extents.iter().filter(|extent| -> bool { extent.length > 0 }).collect(); + f.debug_struct("Node") + .field("name", &self.name()) + .field("mode", &self.mode) + .field("next", &self.next) + .field("extents", &extents) + .finish() } } diff --git a/utility/image.rs b/utility/image.rs index 77e461c..439b8b0 100644 --- a/utility/image.rs +++ b/utility/image.rs @@ -1,4 +1,4 @@ -use std::fs::File; +use std::fs::{File, OpenOptions}; use std::io::{Error, Read, Write, Seek, SeekFrom}; use redoxfs::Disk; @@ -9,14 +9,15 @@ pub struct Image { impl Image { pub fn open(path: &str) -> Result<Image, Error> { - let file = try!(File::open(path)); + let file = try!(OpenOptions::new().read(true).write(true).open(path)); Ok(Image { file: file }) } - pub fn create(path: &str) -> Result<Image, Error> { - let file = try!(File::create(path)); + pub fn create(path: &str, size: u64) -> Result<Image, Error> { + let file = try!(OpenOptions::new().read(true).write(true).create(true).open(path)); + try!(file.set_len(size)); Ok(Image { file: file }) @@ -33,4 +34,8 @@ impl Disk<Error> for Image { try!(self.file.seek(SeekFrom::Start(block * 512))); self.file.write(buffer) } + + fn size(&mut self) -> Result<u64, Error> { + self.file.seek(SeekFrom::End(0)) + } } diff --git a/utility/main.rs b/utility/main.rs index e956c9d..8e75a88 100644 --- a/utility/main.rs +++ b/utility/main.rs @@ -29,9 +29,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){ match command { "" => (), "exit" => break, - "header" => { - println!("{:#?}", fs.header); - }, + "header" => println!("{:#?}", fs.header), "node" => { if let Some(arg) = args.next() { match arg.parse::<u64>() { @@ -76,6 +74,7 @@ fn main() { let mut args = env::args(); if let Some(path) = args.nth(1) { if Path::new(&path).exists() { + //Open an existing image match Image::open(&path) { Ok(disk) => match FileSystem::open(Box::new(disk)) { Ok(filesystem_option) => match filesystem_option { @@ -90,7 +89,8 @@ fn main() { Err(err) => println!("redoxfs: failed to open image {}: {}", path, err) } }else{ - match Image::create(&path) { + //Create a 1 GB disk image + match Image::create(&path, 1024 * 1024 * 1024) { Ok(disk) => match FileSystem::create(Box::new(disk)) { Ok(filesystem) => { println!("redoxfs: created filesystem {}", path); -- GitLab