Commit 670d874d authored by Jeremy Soller's avatar Jeremy Soller

Use unix errors

parent 7f8776fa
......@@ -14,3 +14,6 @@ path = "src/lib.rs"
[[bin]]
name = "redoxfs-utility"
path = "utility/main.rs"
[dependencies]
redox-system = {path = "../system/"}
use system::error::Result;
/// A disk
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>;
pub trait Disk {
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize>;
fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize>;
fn size(&mut self) -> Result<u64>;
}
......@@ -2,17 +2,19 @@ use alloc::boxed::Box;
use collections::vec::Vec;
use system::error::{Result, Error, EEXIST, EISDIR, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY};
use super::{Disk, ExNode, Extent, Header, Node};
/// A file system
pub struct FileSystem<E> {
pub disk: Box<Disk<E>>,
pub struct FileSystem {
pub disk: Box<Disk>,
pub header: (u64, Header)
}
impl<E> FileSystem<E> {
impl FileSystem {
/// Open a file system on a disk
pub fn open(mut disk: Box<Disk<E>>) -> Result<Option<Self>, E> {
pub fn open(mut disk: Box<Disk>) -> Result<Self> {
let mut header = (1, Header::default());
try!(disk.read_at(header.0, &mut header.1));
......@@ -23,17 +25,17 @@ impl<E> FileSystem<E> {
let mut free = (header.1.free, Node::default());
try!(disk.read_at(free.0, &mut free.1));
Ok(Some(FileSystem {
Ok(FileSystem {
disk: disk,
header: header
}))
})
}else{
Ok(None)
Err(Error::new(ENOENT))
}
}
/// Create a file system on a disk
pub fn create(mut disk: Box<Disk<E>>) -> Result<Option<Self>, E> {
pub fn create(mut disk: Box<Disk>) -> Result<Self> {
let size = try!(disk.size());
if size >= 4 * 512 {
......@@ -47,16 +49,17 @@ impl<E> FileSystem<E> {
let header = (1, Header::new(size, root.0, free.0));
try!(disk.write_at(header.0, &header.1));
Ok(Some(FileSystem {
Ok(FileSystem {
disk: disk,
header: header
}))
})
} else {
Ok(None)
Err(Error::new(ENOSPC))
}
}
pub fn allocate(&mut self) -> Result<Option<u64>, E> {
pub fn allocate(&mut self) -> Result<u64> {
//TODO: traverse next pointer
let free_block = self.header.1.free;
let mut free = try!(self.node(free_block));
let mut block_option = None;
......@@ -68,30 +71,32 @@ impl<E> FileSystem<E> {
break;
}
}
if block_option.is_some() {
if let Some(block) = block_option {
try!(self.disk.write_at(free.0, &free.1));
Ok(block)
} else {
Err(Error::new(ENOSPC))
}
Ok(block_option)
}
pub fn deallocate(&mut self, block: u64) -> Result<bool, E> {
pub fn deallocate(&mut self, block: u64) -> Result<()> {
let free_block = self.header.1.free;
self.insert_block(block, free_block)
}
pub fn node(&mut self, block: u64) -> Result<(u64, Node), E> {
pub fn node(&mut self, block: u64) -> Result<(u64, Node)> {
let mut node = Node::default();
try!(self.disk.read_at(block, &mut node));
Ok((block, node))
}
pub fn ex_node(&mut self, block: u64) -> Result<(u64, ExNode), E> {
pub fn ex_node(&mut self, block: u64) -> Result<(u64, ExNode)> {
let mut node = ExNode::default();
try!(self.disk.read_at(block, &mut node));
Ok((block, node))
}
pub fn child_nodes(&mut self, children: &mut Vec<(u64, Node)>, parent_block: u64) -> Result<(), E> {
pub fn child_nodes(&mut self, children: &mut Vec<(u64, Node)>, parent_block: u64) -> Result<()> {
if parent_block == 0 {
return Ok(());
}
......@@ -106,9 +111,9 @@ impl<E> FileSystem<E> {
self.child_nodes(children, parent.1.next)
}
pub fn find_node(&mut self, name: &str, parent_block: u64) -> Result<Option<(u64, Node)>, E> {
pub fn find_node(&mut self, name: &str, parent_block: u64) -> Result<(u64, Node)> {
if parent_block == 0 {
return Ok(None);
return Err(Error::new(ENOENT));
}
let parent = try!(self.node(parent_block));
......@@ -124,7 +129,7 @@ impl<E> FileSystem<E> {
}
if matches {
return Ok(Some(child));
return Ok(child);
}
}
}
......@@ -132,9 +137,9 @@ impl<E> FileSystem<E> {
self.find_node(name, parent.1.next)
}
fn insert_block(&mut self, block: u64, parent_block: u64) -> Result<bool, E> {
fn insert_block(&mut self, block: u64, parent_block: u64) -> Result<()> {
if parent_block == 0 {
return Ok(false);
return Err(Error::new(ENOSPC));
}
let mut inserted = false;
......@@ -162,42 +167,34 @@ impl<E> FileSystem<E> {
if inserted {
try!(self.disk.write_at(parent.0, &parent.1));
Ok(true)
Ok(())
} else {
if parent.1.next == 0 {
if let Some(block) = try!(self.allocate()) {
parent.1.next = block;
try!(self.disk.write_at(parent.0, &parent.1));
try!(self.disk.write_at(parent.1.next, &Node::default()));
} else {
return Ok(false);
}
parent.1.next = try!(self.allocate());
try!(self.disk.write_at(parent.0, &parent.1));
try!(self.disk.write_at(parent.1.next, &Node::default()));
}
self.insert_block(block, parent.1.next)
}
}
pub fn create_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result<Option<(u64, Node)>, E> {
if try!(self.find_node(name, parent_block)).is_some() {
Ok(None)
} else if let Some(block) = try!(self.allocate()) {
let node = (block, Node::new(mode, name, parent_block));
pub fn create_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result<(u64, Node)> {
if self.find_node(name, parent_block).is_ok() {
Err(Error::new(EEXIST))
} else {
let node = (try!(self.allocate()), Node::new(mode, name, parent_block));
try!(self.disk.write_at(node.0, &node.1));
if try!(self.insert_block(block, parent_block)) {
Ok(Some(node))
} else {
Ok(None)
}
} else {
Ok(None)
try!(self.insert_block(node.0, parent_block));
Ok(node)
}
}
fn remove_block(&mut self, block: u64, parent_block: u64) -> Result<bool, E> {
fn remove_block(&mut self, block: u64, parent_block: u64) -> Result<()> {
if parent_block == 0 {
return Ok(false);
return Err(Error::new(ENOENT));
}
let mut removed = false;
......@@ -240,40 +237,37 @@ impl<E> FileSystem<E> {
try!(self.deallocate(block));
Ok(true)
Ok(())
} else {
if parent.1.next == 0 {
if let Some(block) = try!(self.allocate()) {
parent.1.next = block;
try!(self.disk.write_at(parent.0, &parent.1));
try!(self.disk.write_at(parent.1.next, &Node::default()));
} else {
return Ok(false);
}
parent.1.next = try!(self.allocate());
try!(self.disk.write_at(parent.0, &parent.1));
try!(self.disk.write_at(parent.1.next, &Node::default()));
}
self.remove_block(block, parent.1.next)
}
}
pub fn remove_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result<bool, E> {
if let Some(mut node) = try!(self.find_node(name, parent_block)) {
if node.1.mode & Node::MODE_TYPE == mode {
if node.1.is_dir() {
let mut children = Vec::new();
try!(self.child_nodes(&mut children, node.0));
if ! children.is_empty() {
return Ok(false);
}
}
if try!(self.remove_block(node.0, parent_block)) {
node.1 = Node::default();
try!(self.disk.write_at(node.0, &node.1));
return Ok(true);
pub fn remove_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result<()> {
let node = try!(self.find_node(name, parent_block));
if node.1.mode & Node::MODE_TYPE == mode {
if node.1.is_dir() {
let mut children = Vec::new();
try!(self.child_nodes(&mut children, node.0));
if ! children.is_empty() {
return Err(Error::new(ENOTEMPTY));
}
}
try!(self.remove_block(node.0, parent_block));
try!(self.disk.write_at(node.0, &Node::default()));
Ok(())
} else if node.1.is_dir() {
Err(Error::new(EISDIR))
} else {
Err(Error::new(ENOTDIR))
}
Ok(false)
}
}
......@@ -13,6 +13,8 @@ extern crate alloc;
#[macro_use]
extern crate collections;
extern crate system;
pub use self::disk::Disk;
pub use self::ex_node::ExNode;
pub use self::extent::Extent;
......
use std::fs::{File, OpenOptions};
use std::io::{Error, Read, Write, Seek, SeekFrom};
use std::io::{Read, Write, Seek, SeekFrom};
use redoxfs::Disk;
use system::error::{Error, Result, EIO};
macro_rules! try_disk {
($expr:expr) => (match $expr {
Ok(val) => val,
Err(err) => {
println!("Disk I/O Error: {}", err);
return Err(Error::new(EIO));
}
})
}
pub struct Image {
file: File
}
impl Image {
pub fn open(path: &str) -> Result<Image, Error> {
let file = try!(OpenOptions::new().read(true).write(true).open(path));
pub fn open(path: &str) -> Result<Image> {
let file = try_disk!(OpenOptions::new().read(true).write(true).open(path));
Ok(Image {
file: file
})
}
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));
pub fn create(path: &str, size: u64) -> Result<Image> {
let file = try_disk!(OpenOptions::new().read(true).write(true).create(true).open(path));
try_disk!(file.set_len(size));
Ok(Image {
file: file
})
}
}
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)));
self.file.read(buffer)
impl Disk for Image {
fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
let count = try_disk!(self.file.read(buffer));
Ok(count)
}
fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize, Error> {
try!(self.file.seek(SeekFrom::Start(block * 512)));
self.file.write(buffer)
fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
let count = try_disk!(self.file.write(buffer));
Ok(count)
}
fn size(&mut self) -> Result<u64, Error> {
self.file.seek(SeekFrom::End(0))
fn size(&mut self) -> Result<u64> {
let size = try_disk!(self.file.seek(SeekFrom::End(0)));
Ok(size)
}
}
......@@ -2,8 +2,9 @@
extern crate redoxfs;
extern crate system;
use std::env;
use std::fmt::Display;
use std::io::{self, Write};
use std::path::Path;
......@@ -13,7 +14,7 @@ use image::Image;
pub mod image;
fn shell<E: Display>(mut fs: FileSystem<E>){
fn shell(mut fs: FileSystem){
let mut block = fs.header.1.root;
let mut stdout = io::stdout();
......@@ -35,11 +36,9 @@ fn shell<E: Display>(mut fs: FileSystem<E>){
"node" => {
if let Some(arg) = args.next() {
match arg.parse::<u64>() {
Ok(block) => {
match fs.node(block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("node: failed to read {}: {}", block, err)
}
Ok(block) => match fs.node(block) {
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("node: failed to read {}: {}", block, err)
},
Err(err) => println!("node: invalid block {}: {}", arg, err)
}
......@@ -67,28 +66,21 @@ fn shell<E: Display>(mut fs: FileSystem<E>){
} else if arg == ".." {
match fs.node(block) {
Ok(node) => {
if node.1.parent > 0 {
block = node.1.parent;
println!("cd: {}", block);
} else {
println!("cd: no parent directory {}", block);
}
Ok(node) => if node.1.parent > 0 {
block = node.1.parent;
println!("cd: {}", block);
} else {
println!("cd: no parent directory {}", block);
},
Err(err) => println!("cd: failed to read {}: {}", block, err)
}
} else {
match fs.find_node(arg, block) {
Ok(node_option) => match node_option {
Some(node) => {
if node.1.is_dir() {
block = node.0;
println!("cd: {}", block);
} else {
println!("cd: not a dir {}", arg);
}
},
None => println!("cd: did not find {}", arg)
Ok(node) => if node.1.is_dir() {
block = node.0;
println!("cd: {}", block);
} else {
println!("cd: not a dir {}", arg);
},
Err(err) => println!("cd: failed to read {}: {}", arg, err)
}
......@@ -118,10 +110,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){
"find" => {
if let Some(arg) = args.next() {
match fs.find_node(arg, block) {
Ok(node_option) => match node_option {
Some(node) => println!("{}: {:#?}", node.0, node.1),
None => println!("find: did not find {}", arg)
},
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("find: failed to read {}: {}", arg, err)
}
} else {
......@@ -140,10 +129,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){
"mk" => {
if let Some(arg) = args.next() {
match fs.create_node(Node::MODE_FILE, arg, block) {
Ok(node_option) => match node_option {
Some(node) => println!("{}: {:#?}", node.0, node.1),
None => println!("mk: not enough space for {}", arg)
},
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("mk: failed to create {}: {}", arg, err)
}
} else {
......@@ -153,10 +139,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){
"mkdir" => {
if let Some(arg) = args.next() {
match fs.create_node(Node::MODE_DIR, arg, block) {
Ok(node_option) => match node_option {
Some(node) => println!("{}: {:#?}", node.0, node.1),
None => println!("mkdir: not enough space for {}", arg)
},
Ok(node) => println!("{}: {:#?}", node.0, node.1),
Err(err) => println!("mkdir: failed to create {}: {}", arg, err)
}
} else {
......@@ -166,11 +149,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){
"rm" => {
if let Some(arg) = args.next() {
match fs.remove_node(Node::MODE_FILE, arg, block) {
Ok(found) => if found {
println!("rm {}", arg);
}else{
println!("rm: did not find {}", arg);
},
Ok(()) => println!("rm {}", arg),
Err(err) => println!("rm: failed to remove {}: {}", arg, err)
}
} else {
......@@ -180,11 +159,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){
"rmdir" => {
if let Some(arg) = args.next() {
match fs.remove_node(Node::MODE_DIR, arg, block) {
Ok(found) => if found {
println!("rmdir {}", arg);
}else{
println!("rmdir: did not find {}", arg);
},
Ok(()) => println!("rmdir {}", arg),
Err(err) => println!("rmdir: failed to remove {}: {}", arg, err)
}
} else {
......@@ -204,12 +179,9 @@ fn main() {
//Open an existing image
match Image::open(&path) {
Ok(disk) => match FileSystem::open(Box::new(disk)) {
Ok(filesystem_option) => match filesystem_option {
Some(filesystem) => {
println!("redoxfs: opened filesystem {}", path);
shell(filesystem);
},
None => println!("redoxfs: no filesystem found in {}", path)
Ok(filesystem) => {
println!("redoxfs: opened filesystem {}", path);
shell(filesystem);
},
Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
},
......@@ -220,12 +192,9 @@ fn main() {
let size = 1024 * 1024 * 1024;
match Image::create(&path, size) {
Ok(disk) => match FileSystem::create(Box::new(disk)) {
Ok(filesystem_option) => match filesystem_option {
Some(filesystem) => {
println!("redoxfs: created filesystem {}", path);
shell(filesystem);
},
None => println!("redoxfs: not enough space for filesystem on {}", path)
Ok(filesystem) => {
println!("redoxfs: created filesystem {}", path);
shell(filesystem);
},
Err(err) => println!("redoxfs: failed to create filesystem {}: {}", path, err)
},
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment