diff --git a/src/filesystem.rs b/src/filesystem.rs index 03c9df31c3234ba1f7813099f425452dd738d3f6..21aa59474733b168d5212393eabc698a7e7d8844 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -1,12 +1,13 @@ use alloc::boxed::Box; -use super::{Disk, Extent, Header, Node}; +use collections::vec::Vec; + +use super::{Disk, ExNode, Extent, Header, Node}; /// A file system pub struct FileSystem<E> { pub disk: Box<Disk<E>>, pub header: (u64, Header), - pub root: (u64, Node), pub free: (u64, Node) } @@ -26,7 +27,6 @@ impl<E> FileSystem<E> { Ok(Some(FileSystem { disk: disk, header: header, - root: root, free: free })) }else{ @@ -52,7 +52,6 @@ impl<E> FileSystem<E> { Ok(Some(FileSystem { disk: disk, header: header, - root: root, free: free })) } else { @@ -80,118 +79,120 @@ impl<E> FileSystem<E> { Ok(false) } - pub fn node(&mut self, block: u64) -> Result<Node, E> { + pub fn node(&mut self, block: u64) -> Result<(u64, Node), E> { let mut node = Node::default(); try!(self.disk.read_at(block, &mut node)); - Ok(node) + Ok((block, node)) } - pub fn find_node(&mut self, name: &str) -> Result<Option<(u64, Node)>, E> { - let mut parent_node = (self.header.1.root, Node::default()); - loop { - if parent_node.0 > 0 { - try!(self.disk.read_at(parent_node.0, &mut parent_node.1)); - }else{ - return Ok(None); - } + pub fn ex_node(&mut self, block: u64) -> Result<(u64, ExNode), E> { + let mut node = ExNode::default(); + try!(self.disk.read_at(block, &mut node)); + Ok((block, node)) + } - for extent in parent_node.1.extents.iter() { - for i in 0 .. extent.length/512 { - let mut child_node = (extent.block + i, Node::default()); - try!(self.disk.read_at(child_node.0, &mut child_node.1)); + pub fn child_nodes(&mut self, children: &mut Vec<(u64, Node)>, parent_block: u64) -> Result<(), E> { + if parent_block == 0 { + return Ok(()); + } - let mut matches = false; - if let Ok(child_name) = child_node.1.name() { - if child_name == name { - matches = true; - } - } - if matches { - return Ok(Some(child_node)); - } - } + let parent = try!(self.node(parent_block)); + for extent in parent.1.extents.iter() { + for i in 0 .. extent.length/512 { + children.push(try!(self.node(extent.block + i))); } - - parent_node.0 = parent_node.1.next; - parent_node.1 = Node::default(); } + + self.child_nodes(children, parent.1.next) } - fn create_node(&mut self, name: &str, mode: u64) -> Result<Option<(u64, Node)>, E> { - if let Some(block) = try!(self.allocate()) { - let node = (block, Node::new(name, mode)); - try!(self.disk.write_at(node.0, &node.1)); + pub fn find_node(&mut self, name: &str, parent_block: u64) -> Result<Option<(u64, Node)>, E> { + if parent_block == 0 { + return Ok(None); + } - let mut inserted = false; - let mut last_node = (0, Node::default()); - let mut next_node = (self.header.1.root, Node::default()); - while ! inserted { - if next_node.0 > 0 { - try!(self.disk.read_at(next_node.0, &mut next_node.1)); - }else{ - if let Some(block) = try!(self.allocate()) { - next_node.0 = block; - if last_node.0 > 0 { - last_node.1.next = block; - if last_node.0 == self.root.0 { - self.root.1.next = last_node.1.next; - } - try!(self.disk.write_at(last_node.0, &last_node.1)); - } else { - panic!("last_node was 0"); - } - } else { - return Ok(None); + let parent = try!(self.node(parent_block)); + for extent in parent.1.extents.iter() { + for i in 0 .. extent.length/512 { + let child = try!(self.node(extent.block + i)); + + let mut matches = false; + if let Ok(child_name) = child.1.name() { + if child_name == name { + matches = true; } } - for mut extent in next_node.1.extents.iter_mut() { - if extent.block + extent.length/512 == block { - inserted = true; - extent.length += 512; - break; - } else if extent.length == 0 { - inserted = true; - extent.block = block; - extent.length = 512; - break; - } + if matches { + return Ok(Some(child)); } + } + } - if inserted { - if next_node.0 == self.root.0 { - self.root.1.extents = next_node.1.extents; - } - try!(self.disk.write_at(next_node.0, &next_node.1)); + self.find_node(name, parent.1.next) + } + + fn insert_block(&mut self, block: u64, parent_block: u64) -> Result<bool, E> { + if parent_block == 0 { + return Ok(false); + } + + let mut inserted = false; + let mut parent = try!(self.node(parent_block)); + for mut extent in parent.1.extents.iter_mut() { + if extent.length == 0 { + //New extent + inserted = true; + extent.block = block; + extent.length = 512; + break; + } else if extent.block == block + 1 { + //At beginning + inserted = true; + extent.block = block; + extent.length += 512; + } else if extent.block + extent.length/512 == block { + //At end + inserted = true; + extent.length += 512; + break; + } + } + + if inserted { + try!(self.disk.write_at(parent.0, &parent.1)); + Ok(true) + } 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 { - last_node = next_node; - next_node = (last_node.1.next, Node::default()); + return Ok(false); } } - Ok(Some(node)) - } else { - Ok(None) + self.insert_block(block, parent.1.next) } } - pub fn create_dir(&mut self, name: &str) -> Result<Option<(u64, Node)>, E> { - self.create_node(name, Node::MODE_DIR) - } + pub fn create_node(&mut self, name: &str, mode: u64, parent_block: u64) -> Result<Option<(u64, Node)>, E> { + if let Some(block) = try!(self.allocate()) { + let node = (block, Node::new(name, mode)); + try!(self.disk.write_at(node.0, &node.1)); - pub fn create_file(&mut self, name: &str) -> Result<Option<(u64, Node)>, E> { - self.create_node(name, Node::MODE_FILE) + if try!(self.insert_block(block, parent_block)) { + Ok(Some(node)) + } else { + Ok(None) + } + } else { + Ok(None) + } } - fn remove_node(&mut self, _name: &str, _mode: u64) -> Result<bool, E> { + pub fn remove_node(&mut self, _name: &str, _mode: u64) -> Result<bool, E> { Ok(false) } - - pub fn remove_dir(&mut self, name: &str) -> Result<bool, E> { - self.remove_node(name, Node::MODE_DIR) - } - - pub fn remove_file(&mut self, name: &str) -> Result<bool, E> { - self.remove_node(name, Node::MODE_FILE) - } } diff --git a/utility/main.rs b/utility/main.rs index c88f76b747da8d2194294aa2d397a560d1f0aac1..3bc4860326cdaad0dae1352ae39160bc99c76a38 100644 --- a/utility/main.rs +++ b/utility/main.rs @@ -7,7 +7,7 @@ use std::fmt::Display; use std::io::{self, Write}; use std::path::Path; -use redoxfs::FileSystem; +use redoxfs::{FileSystem, Node}; use image::Image; @@ -35,7 +35,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){ match arg.parse::<u64>() { Ok(block) => { match fs.node(block) { - Ok(node) => println!("{}: {:#?}", block, node), + Ok(node) => println!("{}: {:#?}", node.0, node.1), Err(err) => println!("node: failed to read {}: {}", block, err) } }, @@ -45,9 +45,24 @@ fn shell<E: Display>(mut fs: FileSystem<E>){ println!("node <block>"); } }, + "root" => { + let block = fs.header.1.root; + match fs.node(block) { + Ok(node) => println!("{}: {:#?}", node.0, node.1), + Err(err) => println!("node: failed to read {}: {}", block, err) + } + }, + "free" => { + let block = fs.header.1.free; + match fs.node(block) { + Ok(node) => println!("{}: {:#?}", node.0, node.1), + Err(err) => println!("node: failed to read {}: {}", block, err) + } + }, "find" => { if let Some(arg) = args.next() { - match fs.find_node(arg) { + let root_block = fs.header.1.root; + match fs.find_node(arg, root_block) { Ok(node_option) => match node_option { Some(node) => println!("{}: {:#?}", node.0, node.1), None => println!("find: did not find {}", arg) @@ -59,22 +74,19 @@ fn shell<E: Display>(mut fs: FileSystem<E>){ } }, "ls" => { - let mut blocks = Vec::new(); - for extent in fs.root.1.extents.iter() { - for i in 0 .. extent.length/512 { - blocks.push(extent.block + i); - } - } - for &block in blocks.iter() { - match fs.node(block) { - Ok(node) => println!("{}: {:#?}", block, node), - Err(err) => println!("ls: failed to read {}: {}", block, err) - } + let root_block = fs.header.1.root; + let mut children = Vec::new(); + match fs.child_nodes(&mut children, root_block) { + Ok(()) => for node in children.iter() { + println!("{}: {:#?}", node.0, node.1); + }, + Err(err) => println!("ls: failed to read {}: {}", root_block, err) } }, "mkdir" => { if let Some(arg) = args.next() { - match fs.create_dir(arg) { + let root_block = fs.header.1.root; + match fs.create_node(arg, Node::MODE_DIR, root_block) { Ok(node_option) => match node_option { Some(node) => println!("{}: {:#?}", node.0, node.1), None => println!("mkdir: not enough space for {}", arg) @@ -87,7 +99,8 @@ fn shell<E: Display>(mut fs: FileSystem<E>){ }, "touch" => { if let Some(arg) = args.next() { - match fs.create_file(arg) { + let root_block = fs.header.1.root; + match fs.create_node(arg, Node::MODE_FILE, root_block) { Ok(node_option) => match node_option { Some(node) => println!("{}: {:#?}", node.0, node.1), None => println!("touch: not enough space for {}", arg) @@ -98,7 +111,7 @@ fn shell<E: Display>(mut fs: FileSystem<E>){ println!("touch <file>"); } }, - _ => println!("commands: exit header node find ls mkdir touch") + _ => println!("commands: exit header node root free find ls mkdir touch") } } }