From d2a073788af5eb9fa03d7a9279147d365aa0b225 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Sat, 27 Feb 2016 10:26:53 -0700
Subject: [PATCH] Add unlink and creat

---
 scheme/main.rs | 105 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 77 insertions(+), 28 deletions(-)

diff --git a/scheme/main.rs b/scheme/main.rs
index c5d8979..330aeaa 100644
--- a/scheme/main.rs
+++ b/scheme/main.rs
@@ -13,9 +13,9 @@ use image::Image;
 
 use redoxfs::{FileSystem, Node};
 
-use system::error::{Error, Result, ENOENT, EBADF, EINVAL};
+use system::error::{Error, Result, EISDIR, EPERM, ENOENT, EBADF, EINVAL};
 use system::scheme::{Packet, Scheme};
-use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END};
+use system::syscall::{Stat, O_CREAT, SEEK_SET, SEEK_CUR, SEEK_END};
 
 pub mod image;
 
@@ -106,39 +106,75 @@ impl FileScheme {
         }
     }
 
-    fn path_node(&mut self, path: &str) -> Result<(u64, Node)> {
+    fn path_nodes(&mut self, path: &str, nodes: &mut Vec<(u64, Node)>) -> Result<(u64, Node)> {
         let mut block = self.fs.header.1.root;
+        nodes.push(try!(self.fs.node(block)));
+
         for part in path.split('/') {
             if ! part.is_empty() {
-                let next = try!(self.fs.find_node(part, block));
-                block = next.0;
+                let node = try!(self.fs.find_node(part, block));
+                block = node.0;
+                nodes.push(node);
             }
         }
 
-        self.fs.node(block)
+        Ok(nodes.pop().unwrap())
     }
 }
 
 impl Scheme for FileScheme {
     fn open(&mut self, url: &str, flags: usize, mode: usize) -> Result<usize> {
         let path = url.split(':').nth(1).unwrap_or("").trim_matches('/');
-        let node = try!(self.path_node(path));
+
+        let mut nodes = Vec::new();
+        let node_result = self.path_nodes(path, &mut nodes);
 
         let mut data = Vec::new();
-        if node.1.is_dir() {
-            let mut children = Vec::new();
-            try!(self.fs.child_nodes(&mut children, node.0));
-            for child in children.iter() {
-                if let Ok(name) = child.1.name() {
-                    if ! data.is_empty() {
-                        data.push('\n' as u8);
+        match node_result {
+            Ok(node) => if node.1.is_dir() {
+                let mut children = Vec::new();
+                try!(self.fs.child_nodes(&mut children, node.0));
+                for child in children.iter() {
+                    if let Ok(name) = child.1.name() {
+                        if ! data.is_empty() {
+                            data.push('\n' as u8);
+                        }
+                        data.extend_from_slice(&name.as_bytes());
+                    }
+                }
+            } else {
+                data.extend_from_slice(&format!("{:#?}", node).as_bytes());
+            },
+            Err(err) => if err.errno == ENOENT && flags & O_CREAT == O_CREAT {
+                let mut last_part = String::new();
+                for part in path.split('/') {
+                    if ! part.is_empty() {
+                        last_part = part.to_string();
+                    }
+                }
+                if ! last_part.is_empty() {
+                    if let Some(parent) = nodes.last() {
+                        try!(self.fs.create_node(Node::MODE_FILE, &last_part, parent.0));
+                    } else {
+                        return Err(Error::new(EPERM));
                     }
-                    data.extend_from_slice(&name.as_bytes());
+                } else {
+                    return Err(Error::new(EPERM));
                 }
+            } else {
+                return Err(err);
+            }
+        }
+        /*
+        if let Some(arg) = args.next() {
+            match  {
+                Ok(node) => println!("{}: {:#?}", node.0, node.1),
+                Err(err) => println!("mk: failed to create {}: {}", arg, err)
             }
         } else {
-            data.extend_from_slice(&format!("{:#?}", node).as_bytes());
+            println!("mk <file>");
         }
+        */
 
         let id = self.next_id as usize;
         self.next_id += 1;
@@ -149,17 +185,36 @@ impl Scheme for FileScheme {
         Ok(id)
     }
 
-    #[allow(unused_variables)]
-    fn unlink(&mut self, path: &str) -> Result<usize> {
-        println!("unlink {}", path);
+    fn mkdir(&mut self, path: &str, mode: usize) -> Result<usize> {
+        println!("mkdir {}, {:X}", path, mode);
         Err(Error::new(ENOENT))
     }
 
-    #[allow(unused_variables)]
-    fn mkdir(&mut self, path: &str, mode: usize) -> Result<usize> {
-        println!("mkdir {}, {:X}", path, mode);
+    /*
+    fn rmdir(&mut self, path: &str) -> Result<usize> {
+        println!("rmdir {}", path);
         Err(Error::new(ENOENT))
     }
+    */
+
+    fn unlink(&mut self, url: &str) -> Result<usize> {
+        let path = url.split(':').nth(1).unwrap_or("").trim_matches('/');
+        let mut nodes = Vec::new();
+        let child = try!(self.path_nodes(path, &mut nodes));
+        if let Some(parent) = nodes.last() {
+            if ! child.1.is_dir() {
+                if let Ok(child_name) = child.1.name() {
+                    self.fs.remove_node(Node::MODE_FILE, child_name, parent.0).and(Ok(0))
+                } else {
+                    Err(Error::new(ENOENT))
+                }
+            } else {
+                Err(Error::new(EISDIR))
+            }
+        } else {
+            Err(Error::new(EPERM))
+        }
+    }
 
     /* Resource operations */
     #[allow(unused_variables)]
@@ -171,7 +226,6 @@ impl Scheme for FileScheme {
         }
     }
 
-    #[allow(unused_variables)]
     fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
         if let Some(mut file) = self.files.get_mut(&id) {
             file.write(buf)
@@ -180,7 +234,6 @@ impl Scheme for FileScheme {
         }
     }
 
-    #[allow(unused_variables)]
     fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
         if let Some(mut file) = self.files.get_mut(&id) {
             file.seek(pos, whence)
@@ -189,7 +242,6 @@ impl Scheme for FileScheme {
         }
     }
 
-    #[allow(unused_variables)]
     fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
         if let Some(file) = self.files.get(&id) {
             file.path(buf)
@@ -198,7 +250,6 @@ impl Scheme for FileScheme {
         }
     }
 
-    #[allow(unused_variables)]
     fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
         println!("fstat {}, {:X}", id, stat as *mut Stat as usize);
         if let Some(file) = self.files.get(&id) {
@@ -208,7 +259,6 @@ impl Scheme for FileScheme {
         }
     }
 
-    #[allow(unused_variables)]
     fn fsync(&mut self, id: usize) -> Result<usize> {
         println!("fsync {}", id);
         if let Some(mut file) = self.files.get_mut(&id) {
@@ -218,7 +268,6 @@ impl Scheme for FileScheme {
         }
     }
 
-    #[allow(unused_variables)]
     fn ftruncate(&mut self, id: usize, len: usize) -> Result<usize> {
         println!("ftruncate {}, {}", id, len);
         Err(Error::new(EBADF))
-- 
GitLab