diff --git a/src/extent.rs b/src/extent.rs index 336ed13871..7a0010b51f 100644 --- a/src/extent.rs +++ b/src/extent.rs @@ -7,6 +7,13 @@ pub struct Extent { } impl Extent { + pub fn default() -> Extent { + Extent { + block: 0, + length: 0 + } + } + pub fn new(block: u64, length: u64) -> Extent { Extent { block: block, diff --git a/src/filesystem.rs b/src/filesystem.rs index f42cd2e133..aa8e09dfe7 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -60,19 +60,19 @@ impl FileSystem { } pub fn allocate(&mut self) -> Result, E> { - let mut block = None; + let mut block_option = None; for mut extent in self.free.1.extents.iter_mut() { if extent.length >= 512 { - block = Some(extent.block); + block_option = Some(extent.block); extent.length -= 512; extent.block += 1; break; } } - if block.is_some() { + if block_option.is_some() { try!(self.disk.write_at(self.free.0, &self.free.1)); } - Ok(block) + Ok(block_option) } pub fn deallocate(&mut self, _block: u64) -> Result { @@ -178,7 +178,9 @@ impl FileSystem { } pub fn create_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result, E> { - if let Some(block) = try!(self.allocate()) { + 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)); try!(self.disk.write_at(node.0, &node.1)); @@ -192,7 +194,71 @@ impl FileSystem { } } - pub fn remove_node(&mut self, _name: &str) -> Result { + fn remove_block(&mut self, block: u64, parent_block: u64) -> Result { + if parent_block == 0 { + return Ok(false); + } + + let mut removed = false; + let mut replace_option = None; + let mut parent = try!(self.node(parent_block)); + for mut extent in parent.1.extents.iter_mut() { + if block >= extent.block && block < extent.block + extent.length/512 { + //Inside + removed = true; + + let left = Extent::new(extent.block, (block - extent.block) * 512); + let right = Extent::new(block + 1, ((extent.block + extent.length/512) - (block + 1)) * 512); + + if left.length > 0 { + *extent = left; + + if right.length > 0 { + replace_option = Some(right); + } + } else if right.length > 0 { + *extent = right; + } else { + *extent = Extent::default(); + } + + break; + } + } + + if let Some(_replace) = replace_option { + //do it! + } + + if removed { + 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 { + return Ok(false); + } + } + + self.remove_block(block, parent.1.next) + } + } + + pub fn remove_node(&mut self, mode: u16, name: &str, parent_block: u64) -> Result { + if let Some(mut node) = try!(self.find_node(name, parent_block)) { + if node.1.mode & Node::MODE_TYPE == mode { + 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); + } + } + } Ok(false) } } diff --git a/utility/main.rs b/utility/main.rs index 9f5a02aa16..02fa2e1892 100644 --- a/utility/main.rs +++ b/utility/main.rs @@ -137,6 +137,19 @@ fn shell(mut fs: FileSystem){ Err(err) => println!("ls: failed to read {}: {}", block, err) } }, + "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) + }, + Err(err) => println!("mk: failed to create {}: {}", arg, err) + } + } else { + println!("mk "); + } + }, "mkdir" => { if let Some(arg) = args.next() { match fs.create_node(Node::MODE_DIR, arg, block) { @@ -147,23 +160,38 @@ fn shell(mut fs: FileSystem){ Err(err) => println!("mkdir: failed to create {}: {}", arg, err) } } else { - println!("mkdir "); + println!("mkdir "); } }, - "touch" => { + "rm" => { 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!("touch: not enough space for {}", arg) + match fs.remove_node(Node::MODE_FILE, arg, block) { + Ok(found) => if found { + println!("rm {}", arg); + }else{ + println!("rm: did not find {}", arg); }, - Err(err) => println!("touch: failed to create {}: {}", arg, err) + Err(err) => println!("rm: failed to remove {}: {}", arg, err) } } else { - println!("touch "); + println!("rm "); } }, - _ => println!("commands: exit header node root free find ls mkdir touch") + "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); + }, + Err(err) => println!("rmdir: failed to remove {}: {}", arg, err) + } + } else { + println!("rmdir "); + } + }, + _ => println!("commands: exit header node root free find ls mk mkdir rm rmdir") } } }