diff --git a/scheme/image.rs b/scheme/image.rs
index b17b91408baa33a9584736ffddcc2dc1df962fbf..37444584898948d2baa31a0883c86cb3d749ad95 100644
--- a/scheme/image.rs
+++ b/scheme/image.rs
@@ -31,7 +31,7 @@ impl Image {
 
 impl Disk for Image {
     fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
-        println!("Image read at {}", block);
+        // println!("Image read at {}", block);
         try_disk!(self.file.seek(SeekFrom::Start(block * 512)));
         let count = try_disk!(self.file.read(buffer));
         Ok(count)
diff --git a/scheme/resource.rs b/scheme/resource.rs
index a72eebdf9a8708747e78237092bb11765d12223a..52e907ec3787d67fadb4934eb5ff6162b282ef6d 100644
--- a/scheme/resource.rs
+++ b/scheme/resource.rs
@@ -1,24 +1,44 @@
+use redoxfs::FileSystem;
+
 use std::cmp::{min, max};
 
 use system::error::{Error, Result, EINVAL};
-use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END};
+use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END, MODE_DIR, MODE_FILE};
 
-pub struct FileResource {
+pub trait Resource {
+    fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem) -> Result<usize>;
+
+    fn write(&mut self, buf: &[u8], fs: &mut FileSystem) -> Result<usize>;
+
+    fn seek(&mut self, offset: usize, whence: usize) -> Result<usize>;
+
+    fn path(&self, buf: &mut [u8]) -> Result<usize>;
+
+    fn stat(&self, _stat: &mut Stat) -> Result<usize>;
+
+    fn sync(&mut self) -> Result<usize>;
+
+    fn truncate(&mut self, len: usize) -> Result<usize>;
+}
+
+pub struct DirResource {
     path: String,
     data: Vec<u8>,
     seek: usize,
 }
 
-impl FileResource {
-    pub fn new(path: &str, data: Vec<u8>) -> FileResource {
-        FileResource {
+impl DirResource {
+    pub fn new(path: &str, data: Vec<u8>) -> DirResource {
+        DirResource {
             path: path.to_string(),
             data: data,
             seek: 0,
         }
     }
+}
 
-    pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
+impl Resource for DirResource {
+    fn read(&mut self, buf: &mut [u8], _fs: &mut FileSystem) -> Result<usize> {
         let mut i = 0;
         while i < buf.len() && self.seek < self.data.len() {
             buf[i] = self.data[self.seek];
@@ -28,39 +48,91 @@ impl FileResource {
         Ok(i)
     }
 
-    pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
+    fn write(&mut self, _buf: &[u8], _fs: &mut FileSystem) -> Result<usize> {
+        Err(Error::new(EINVAL))
+    }
+
+    fn seek(&mut self, offset: usize, whence: usize) -> Result<usize> {
+        match whence {
+            SEEK_SET => self.seek = min(0, max(self.data.len() as isize, offset as isize)) as usize,
+            SEEK_CUR => self.seek = min(0, max(self.data.len() as isize, self.seek as isize + offset as isize)) as usize,
+            SEEK_END => self.seek = min(0, max(self.data.len() as isize, self.data.len() as isize + offset as isize)) as usize,
+            _ => return Err(Error::new(EINVAL))
+        }
+        Ok(self.seek)
+    }
+
+    fn path(&self, buf: &mut [u8]) -> Result<usize> {
         let mut i = 0;
-        while i < buf.len() {
-            if self.seek < self.data.len() {
-                self.data[self.seek] = buf[i];
-            } else {
-                self.data.push(buf[i]);
-            }
+        let path = self.path.as_bytes();
+        while i < buf.len() && i < path.len() {
+            buf[i] = path[i];
             i += 1;
-            self.seek += 1;
         }
         Ok(i)
     }
 
-    pub fn seek(&mut self, offset: usize, whence: usize) -> Result<usize> {
+    fn stat(&self, stat: &mut Stat) -> Result<usize> {
+        stat.st_mode = MODE_DIR;
+        stat.st_size = self.data.len() as u64;
+        Ok(0)
+    }
+
+    fn sync(&mut self) -> Result<usize> {
+        Err(Error::new(EINVAL))
+    }
+
+    fn truncate(&mut self, _len: usize) -> Result<usize> {
+        Err(Error::new(EINVAL))
+    }
+}
+
+pub struct FileResource {
+    path: String,
+    block: u64,
+    seek: u64,
+    size: u64,
+}
+
+impl FileResource {
+    pub fn new(path: &str, block: u64, size: u64) -> FileResource {
+        FileResource {
+            path: path.to_string(),
+            block: block,
+            seek: 0,
+            size: size,
+        }
+    }
+}
+
+impl Resource for FileResource {
+    fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem) -> Result<usize> {
+        let count = try!(fs.read_node(self.block, self.seek, buf));
+        self.seek += count as u64;
+        Ok(count)
+    }
+
+    fn write(&mut self, buf: &[u8], fs: &mut FileSystem) -> Result<usize> {
+        let count = try!(fs.write_node(self.block, self.seek, buf));
+        self.seek += count as u64;
+        if self.seek > self.size {
+            self.size = self.seek;
+        }
+        Ok(count)
+    }
+
+    fn seek(&mut self, offset: usize, whence: usize) -> Result<usize> {
         match whence {
-            SEEK_SET => {
-                self.seek = min(0, max(self.data.len() as isize, offset as isize)) as usize;
-                Ok(self.seek)
-            },
-            SEEK_CUR => {
-                self.seek = min(0, max(self.data.len() as isize, self.seek as isize + offset as isize)) as usize;
-                Ok(self.seek)
-            },
-            SEEK_END => {
-                self.seek = min(0, max(self.data.len() as isize, self.data.len() as isize + offset as isize)) as usize;
-                Ok(self.seek)
-            },
-            _ => Err(Error::new(EINVAL))
+            SEEK_SET => self.seek = min(0, max(self.size as i64, offset as i64)) as u64,
+            SEEK_CUR => self.seek = min(0, max(self.size as i64, self.seek as i64 + offset as i64)) as u64,
+            SEEK_END => self.seek = min(0, max(self.size as i64, self.size as i64 + offset as i64)) as u64,
+            _ => return Err(Error::new(EINVAL))
         }
+
+        Ok(self.seek as usize)
     }
 
-    pub fn path(&self, buf: &mut [u8]) -> Result<usize> {
+    fn path(&self, buf: &mut [u8]) -> Result<usize> {
         let mut i = 0;
         let path = self.path.as_bytes();
         while i < buf.len() && i < path.len() {
@@ -70,15 +142,17 @@ impl FileResource {
         Ok(i)
     }
 
-    pub fn stat(&self, _stat: &mut Stat) -> Result<usize> {
+    fn stat(&self, stat: &mut Stat) -> Result<usize> {
+        stat.st_mode = MODE_FILE;
+        stat.st_size = self.size;
         Ok(0)
     }
 
-    pub fn sync(&mut self) -> Result<usize> {
+    fn sync(&mut self) -> Result<usize> {
         Ok(0)
     }
 
-    pub fn truncate(&mut self, len: usize) -> Result<usize> {
+    fn truncate(&mut self, len: usize) -> Result<usize> {
         Ok(0)
     }
 }
diff --git a/scheme/scheme.rs b/scheme/scheme.rs
index d0ba94369b77d37a274a0a804bff9d6b8168f721..410699e722127f9387814432bb4fbf45fb584540 100644
--- a/scheme/scheme.rs
+++ b/scheme/scheme.rs
@@ -1,4 +1,4 @@
-use resource::FileResource;
+use resource::{Resource, DirResource, FileResource};
 
 use redoxfs::{FileSystem, Node};
 
@@ -11,7 +11,7 @@ use system::syscall::{Stat, O_CREAT};
 pub struct FileScheme {
     fs: FileSystem,
     next_id: isize,
-    files: BTreeMap<usize, FileResource>
+    files: BTreeMap<usize, Box<Resource>>
 }
 
 impl FileScheme {
@@ -22,26 +22,22 @@ impl FileScheme {
             files: BTreeMap::new()
         }
     }
-}
 
-impl Scheme for FileScheme {
-    fn open(&mut self, url: &str, flags: usize, _mode: usize) -> Result<usize> {
+    fn open_inner(&mut self, url: &str, flags: usize) -> Result<Box<Resource>> {
         let path = url.split(':').nth(1).unwrap_or("").trim_matches('/');
 
-        // println!("Open '{}' {:X}", path, flags);
-
         let mut nodes = Vec::new();
         let node_result = self.fs.path_nodes(path, &mut nodes);
 
-        let mut data = Vec::new();
         match node_result {
             Ok(node) => if node.1.is_dir() {
+                let mut data = Vec::new();
                 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.push(b'\n');
                         }
                         data.extend_from_slice(&name.as_bytes());
                         if child.1.is_dir() {
@@ -49,12 +45,10 @@ impl Scheme for FileScheme {
                         }
                     }
                 }
+                return Ok(Box::new(DirResource::new(url, data)));
             } else {
-                for i in 0..(try!(self.fs.node_len(node.0)) + 511)/512 {
-                    let mut sector = [0; 512];
-                    try!(self.fs.read_node(node.0, i as u64 * 512, &mut sector));
-                    data.extend_from_slice(&sector);
-                }
+                let size = try!(self.fs.node_len(node.0));
+                return Ok(Box::new(FileResource::new(url, node.0, size)));
             },
             Err(err) => if err.errno == ENOENT && flags & O_CREAT == O_CREAT {
                 let mut last_part = String::new();
@@ -65,7 +59,8 @@ impl Scheme for FileScheme {
                 }
                 if ! last_part.is_empty() {
                     if let Some(parent) = nodes.last() {
-                        try!(self.fs.create_node(Node::MODE_FILE, &last_part, parent.0));
+                        let node = try!(self.fs.create_node(Node::MODE_FILE, &last_part, parent.0));
+                        return Ok(Box::new(FileResource::new(url, node.0, 0)));
                     } else {
                         return Err(Error::new(EPERM));
                     }
@@ -76,23 +71,23 @@ impl Scheme for FileScheme {
                 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 {
-            println!("mk <file>");
-        }
-        */
+    }
+}
+
+impl Scheme for FileScheme {
+    fn open(&mut self, url: &str, flags: usize, _mode: usize) -> Result<usize> {
+        // println!("Open '{}' {:X}", path, flags);
+
+        let resource = try!(self.open_inner(url, flags));
 
         let id = self.next_id as usize;
         self.next_id += 1;
         if self.next_id < 0 {
             self.next_id = 1;
         }
-        self.files.insert(id, FileResource::new(url, data));
+
+        self.files.insert(id, resource);
+
         Ok(id)
     }
 
@@ -176,7 +171,7 @@ impl Scheme for FileScheme {
         // println!("Read {}, {:X} {}", id, buf.as_ptr() as usize, buf.len());
 
         if let Some(mut file) = self.files.get_mut(&id) {
-            file.read(buf)
+            file.read(buf, &mut self.fs)
         } else {
             Err(Error::new(EBADF))
         }
@@ -185,7 +180,7 @@ impl Scheme for FileScheme {
     fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
         // println!("Write {}, {:X} {}", id, buf.as_ptr() as usize, buf.len());
         if let Some(mut file) = self.files.get_mut(&id) {
-            file.write(buf)
+            file.write(buf, &mut self.fs)
         } else {
             Err(Error::new(EBADF))
         }
diff --git a/src/filesystem.rs b/src/filesystem.rs
index 4552a8cf34bedccb4e46632dd7d769dd387cb5e1..4252eebaa4170459db6b7215ade080395470a4a9 100644
--- a/src/filesystem.rs
+++ b/src/filesystem.rs
@@ -378,9 +378,11 @@ impl FileSystem {
                 let mut sector = [0; 512];
                 try!(self.read_at(block, &mut sector));
 
-                for (s_b, mut b) in sector[byte_offset..size].iter().zip(buf[i..].iter_mut()) {
-                    *b = *s_b;
-                    i += 1;
+                if byte_offset < size && i < buf.len() {
+                    for (s_b, mut b) in sector[byte_offset..size].iter().zip(buf[i..].iter_mut()) {
+                        *b = *s_b;
+                        i += 1;
+                    }
                 }
 
                 byte_offset = 0;
@@ -404,12 +406,14 @@ impl FileSystem {
             for (block, size) in extent.blocks() {
                 let mut sector = [0; 512];
 
-                for (mut s_b, b) in sector[byte_offset..size].iter_mut().zip(buf[i..].iter()) {
-                    *s_b = *b;
-                    i += 1;
-                }
+                if byte_offset < size && i < buf.len() {
+                    for (mut s_b, b) in sector[byte_offset..size].iter_mut().zip(buf[i..].iter()) {
+                        *s_b = *b;
+                        i += 1;
+                    }
 
-                try!(self.write_at(block, &sector));
+                    try!(self.write_at(block, &sector));
+                }
 
                 byte_offset = 0;
             }