Skip to content
Snippets Groups Projects
Commit 8ff4863b authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Cleanup, add node and header commands

parent d116ce57
No related branches found
No related tags found
No related merge requests found
//use core::result::Result;
use core::fmt::Display;
/// A disk /// A disk
pub trait Disk<E: Display> { pub trait Disk<E> {
fn name(&self) -> &str;
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize, 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 write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize, E>;
} }
use alloc::boxed::Box; use alloc::boxed::Box;
use collections::{BTreeMap, String};
use core::cmp;
use core::fmt::Display;
use super::{Disk, Header, Node}; use super::{Disk, Header, Node};
/// A file system /// A file system
pub struct FileSystem<E> { pub struct FileSystem<E> {
pub disk: Box<Disk<E>>, pub disk: Box<Disk<E>>,
pub header: Header, pub header: Header,
pub nodes: BTreeMap<u64, Node>,
} }
impl<E: Display> FileSystem<E> { impl<E> FileSystem<E> {
/// Create a file system from a disk /// Open a file system on a disk
pub fn new(mut disk: Box<Disk<E>>) -> Result<Self, String> { pub fn open(mut disk: Box<Disk<E>>) -> Result<Option<Self>, E> {
let mut header = Header::new(); let mut header = Header::default();
try!(disk.read_at(1, &mut header).map_err(|err| format!("{}: could not read header: {}", disk.name(), err))); try!(disk.read_at(1, &mut header));
if header.valid() { if header.valid() {
let mut nodes = BTreeMap::new(); Ok(Some(FileSystem {
for extent in &header.extents {
if extent.block > 0 && extent.length > 0 {
let current_sectors = (extent.length + 511) / 512;
let max_size = current_sectors * 512;
let size = cmp::min(extent.length, max_size);
for i in 0..size / 512 {
let node_block = extent.block + i;
let mut node = Node::new();
try!(disk.read_at(node_block, &mut node).map_err(|err| format!("{}: could not read node {}: {}", disk.name(), node_block, err)));
nodes.insert(node_block, node);
}
}
}
Ok(FileSystem {
disk: disk, disk: disk,
header: header, header: header,
nodes: nodes, }))
})
}else{ }else{
Err(format!("{}: invalid header", disk.name())) Ok(None)
} }
} }
/// 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));
Ok(FileSystem {
disk: disk,
header: header,
})
}
pub fn node(&mut self, block: u64) -> Result<Node, E> {
let mut node = Node::default();
try!(self.disk.read_at(block, &mut node));
Ok(node)
}
} }
use core::{mem, slice}; use core::{mem, slice};
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
use super::Extent;
/// The header of the filesystem /// The header of the filesystem
#[derive(Debug)]
#[repr(packed)] #[repr(packed)]
pub struct Header { pub struct Header {
/// Signature, should be b"REDOXFS\0"
pub signature: [u8; 8], pub signature: [u8; 8],
/// Version, should be 1
pub version: u64, pub version: u64,
pub free_space: Extent, /// Disk ID, a 128-byte unique identifier
pub padding: [u8; 224], pub uuid: [u8; 16],
pub extents: [Extent; 16], /// Disk size, in 512-byte sectors
pub size: u64,
/// Block of root node
pub root: u64,
/// Block of free space node
pub free_space: u64,
} }
impl Header { impl Header {
pub fn new() -> Header { pub fn default() -> Header {
Header { Header {
signature: [0; 8], signature: [0; 8],
version: 0, version: 0,
free_space: Extent::default(), uuid: [0; 16],
padding: [0; 224], size: 0,
extents: [Extent::default(); 16] root: 0,
free_space: 0,
}
}
pub fn new() -> Header {
Header {
signature: *b"REDOXFS\0",
version: 1,
uuid: [0; 16],
size: 0,
root: 0,
free_space: 0,
} }
} }
...@@ -45,3 +63,8 @@ impl DerefMut for Header { ...@@ -45,3 +63,8 @@ impl DerefMut for Header {
} }
} }
} }
#[test]
fn header_size_test(){
assert!(mem::size_of::<Header>() <= 512);
}
#![crate_name="redoxfs"]
#![crate_type="lib"]
#![feature(alloc)] #![feature(alloc)]
#![feature(collections)] #![feature(collections)]
#![no_std] #![no_std]
......
use core::{mem, slice}; use core::{fmt, mem, ops, slice, str};
use core::ops::{Deref, DerefMut};
use super::Extent; use super::Extent;
...@@ -7,19 +6,42 @@ use super::Extent; ...@@ -7,19 +6,42 @@ use super::Extent;
#[repr(packed)] #[repr(packed)]
pub struct Node { pub struct Node {
pub name: [u8; 256], pub name: [u8; 256],
pub extents: [Extent; 16], pub mode: u64,
pub next: u64,
pub extents: [Extent; 15],
} }
impl Node { impl Node {
pub fn new() -> Node { pub fn default() -> Node {
Node { Node {
name: [0; 256], name: [0; 256],
extents: [Extent::default(); 16] mode: 0,
next: 0,
extents: [Extent::default(); 15]
} }
} }
pub fn name(&self) -> Result<&str, str::Utf8Error> {
let mut len = 0;
for &b in self.name.iter() {
if b == 0 {
break;
}
len += 1;
}
str::from_utf8(&self.name[..len])
}
} }
impl Deref for Node { 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)
}
}
impl ops::Deref for Node {
type Target = [u8]; type Target = [u8];
fn deref(&self) -> &[u8] { fn deref(&self) -> &[u8] {
unsafe { unsafe {
...@@ -28,10 +50,15 @@ impl Deref for Node { ...@@ -28,10 +50,15 @@ impl Deref for Node {
} }
} }
impl DerefMut for Node { impl ops::DerefMut for Node {
fn deref_mut(&mut self) -> &mut [u8] { fn deref_mut(&mut self) -> &mut [u8] {
unsafe { unsafe {
slice::from_raw_parts_mut(self as *mut Node as *mut u8, mem::size_of::<Node>()) as &mut [u8] slice::from_raw_parts_mut(self as *mut Node as *mut u8, mem::size_of::<Node>()) as &mut [u8]
} }
} }
} }
#[test]
fn node_size_test(){
assert!(mem::size_of::<Node>() <= 512);
}
use std::fs::File; use std::fs::File;
use std::io::{Error, Result, Read, Write, Seek, SeekFrom}; use std::io::{Error, Read, Write, Seek, SeekFrom};
use redoxfs::Disk; use redoxfs::Disk;
pub struct FileDisk { pub struct Image {
path: String,
file: File file: File
} }
impl FileDisk { impl Image {
pub fn new(path: &str) -> Result<FileDisk> { pub fn open(path: &str) -> Result<Image, Error> {
let file = try!(File::open(path)); let file = try!(File::open(path));
Ok(FileDisk { Ok(Image {
path: path.to_string(),
file: file file: file
}) })
} }
}
impl Disk<Error> for FileDisk { pub fn create(path: &str) -> Result<Image, Error> {
fn name(&self) -> &str { let file = try!(File::create(path));
&self.path Ok(Image {
file: file
})
} }
}
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> { impl Disk<Error> for Image {
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize, Error> {
try!(self.file.seek(SeekFrom::Start(block * 512))); try!(self.file.seek(SeekFrom::Start(block * 512)));
self.file.read(buffer) self.file.read(buffer)
} }
fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> { fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize, Error> {
try!(self.file.seek(SeekFrom::Start(block * 512))); try!(self.file.seek(SeekFrom::Start(block * 512)));
self.file.write(buffer) self.file.write(buffer)
} }
......
#![deny(warnings)]
extern crate redoxfs; extern crate redoxfs;
use std::env; use std::env;
use std::fmt::Display;
use std::io::{self, Write}; use std::io::{self, Write};
use std::path::Path;
use redoxfs::{Disk, FileSystem}; use redoxfs::FileSystem;
use file_disk::FileDisk; use image::Image;
pub mod file_disk; pub mod image;
fn shell<E>(filesystem: FileSystem<E>){ fn shell<E: Display>(mut fs: FileSystem<E>){
let mut stdout = io::stdout(); let mut stdout = io::stdout();
let stdin = io::stdin(); let stdin = io::stdin();
...@@ -24,7 +28,27 @@ fn shell<E>(filesystem: FileSystem<E>){ ...@@ -24,7 +28,27 @@ fn shell<E>(filesystem: FileSystem<E>){
if let Some(command) = args.next() { if let Some(command) = args.next() {
match command { match command {
"" => (), "" => (),
"exit" => break,
"header" => {
println!("{:#?}", fs.header);
},
"node" => {
if let Some(arg) = args.next() {
match arg.parse::<u64>() {
Ok(block) => {
match fs.node(block) {
Ok(node) => println!("{:#?}", node),
Err(err) => println!("node: failed to read {}: {}", block, err)
}
},
Err(err) => println!("node: invalid block {}: {}", arg, err)
}
} else {
println!("node <block>")
}
},
"ls" => { "ls" => {
/*
let path = args.next().unwrap_or("/"); let path = args.next().unwrap_or("/");
for (node_block, node) in filesystem.nodes.iter() { for (node_block, node) in filesystem.nodes.iter() {
let mut name = "/".to_string(); let mut name = "/".to_string();
...@@ -39,6 +63,8 @@ fn shell<E>(filesystem: FileSystem<E>){ ...@@ -39,6 +63,8 @@ fn shell<E>(filesystem: FileSystem<E>){
println!("{}: {}", node_block, name); println!("{}: {}", node_block, name);
} }
} }
*/
println!("TODO: ls");
}, },
_ => println!("unknown command: {}", command) _ => println!("unknown command: {}", command)
} }
...@@ -49,15 +75,30 @@ fn shell<E>(filesystem: FileSystem<E>){ ...@@ -49,15 +75,30 @@ fn shell<E>(filesystem: FileSystem<E>){
fn main() { fn main() {
let mut args = env::args(); let mut args = env::args();
if let Some(path) = args.nth(1) { if let Some(path) = args.nth(1) {
match FileDisk::new(&path) { if Path::new(&path).exists() {
Ok(disk) => match FileSystem::new(Box::new(disk)) { match Image::open(&path) {
Ok(filesystem) => shell(filesystem), Ok(disk) => match FileSystem::open(Box::new(disk)) {
Err(err) => { Ok(filesystem_option) => match filesystem_option {
println!("redoxfs: failed to open filesystem: {}", err); Some(filesystem) => {
} println!("redoxfs: opened filesystem {}", path);
}, shell(filesystem);
Err(err) => { },
println!("redoxfs: failed to open disk: {}", err); None => println!("redoxfs: no filesystem found in {}", path)
},
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
}
}else{
match Image::create(&path) {
Ok(disk) => match FileSystem::create(Box::new(disk)) {
Ok(filesystem) => {
println!("redoxfs: created filesystem {}", path);
shell(filesystem);
},
Err(err) => println!("redoxfs: failed to create filesystem {}: {}", path, err)
},
Err(err) => println!("redoxfs: failed to create image {}: {}", path, err)
} }
} }
} else { } else {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment