diff --git a/create.sh b/create.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a5f28ca7426234da0b4d710206d4c4237746f4ff
--- /dev/null
+++ b/create.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+rm -f ../../filesystem/etc/redoxfs.bin
+cargo run ../../filesystem/etc/redoxfs.bin <<-EOF
+    mk a_file
+    mkdir a_directory
+    cd a_directory
+    mk b_file
+    mk c_file
+    exit
+EOF
diff --git a/scheme/image.rs b/scheme/image.rs
new file mode 100644
index 0000000000000000000000000000000000000000..586e9638a3e39e69fcf5a4ef2c1eeb70efd630c9
--- /dev/null
+++ b/scheme/image.rs
@@ -0,0 +1,48 @@
+use std::fs::File;
+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> {
+        let file = try_disk!(File::open(path));
+        Ok(Image {
+            file: file
+        })
+    }
+}
+
+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> {
+        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> {
+        let size = try_disk!(self.file.seek(SeekFrom::End(0)));
+        Ok(size)
+    }
+}
diff --git a/scheme/main.rs b/scheme/main.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1262285cd95d8afcb00c102dd2bd0137c8eaaf6c
--- /dev/null
+++ b/scheme/main.rs
@@ -0,0 +1,241 @@
+extern crate redoxfs;
+
+extern crate system;
+
+use std::cmp::{min, max};
+use std::collections::BTreeMap;
+use std::env;
+use std::fs::File;
+use std::io::{Read, Write};
+use std::mem::size_of;
+
+use image::Image;
+
+use redoxfs::FileSystem;
+
+use system::error::{Error, Result, ENOENT, EBADF, EINVAL};
+use system::scheme::{Packet, Scheme};
+use system::syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END};
+
+pub mod image;
+
+struct FileResource {
+    path: String,
+    data: Vec<u8>,
+    seek: usize,
+}
+
+impl FileResource {
+    fn new(path: &str) -> FileResource {
+        FileResource {
+            path: path.to_string(),
+            data: Vec::new(),
+            seek: 0,
+        }
+    }
+
+    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
+        let mut i = 0;
+        while i < buf.len() && self.seek < self.data.len() {
+            buf[i] = self.data[self.seek];
+            i += 1;
+            self.seek += 1;
+        }
+        Ok(i)
+    }
+
+    fn write(&mut self, buf: &[u8]) -> Result<usize> {
+        let mut i = 0;
+        while i < buf.len() && self.seek < self.data.len() {
+            self.data[self.seek] = buf[i];
+            i += 1;
+            self.seek += 1;
+        }
+        Ok(i)
+    }
+
+    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))
+        }
+    }
+
+    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() {
+            buf[i] = path[i];
+            i += 1;
+        }
+        Ok(i)
+    }
+
+    fn stat(&self, _stat: &mut Stat) -> Result<usize> {
+        Ok(0)
+    }
+
+    fn sync(&mut self) -> Result<usize> {
+        Ok(0)
+    }
+}
+
+struct FileScheme {
+    fs: FileSystem,
+    next_id: isize,
+    files: BTreeMap<usize, FileResource>
+}
+
+impl FileScheme {
+    fn new(fs: FileSystem) -> FileScheme {
+        FileScheme {
+            fs: fs,
+            next_id: 1,
+            files: BTreeMap::new()
+        }
+    }
+}
+
+impl Scheme for FileScheme {
+    fn open(&mut self, path: &str, flags: usize, mode: usize) -> Result<usize> {
+        println!("open {:X} = {}, {:X}, {:X}", path.as_ptr() as usize, path, flags, mode);
+        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(path));
+        Ok(id)
+    }
+
+    #[allow(unused_variables)]
+    fn unlink(&mut self, path: &str) -> Result<usize> {
+        println!("unlink {}", path);
+        Err(Error::new(ENOENT))
+    }
+
+    #[allow(unused_variables)]
+    fn mkdir(&mut self, path: &str, mode: usize) -> Result<usize> {
+        println!("mkdir {}, {:X}", path, mode);
+        Err(Error::new(ENOENT))
+    }
+
+    /* Resource operations */
+    #[allow(unused_variables)]
+    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
+        println!("read {}, {:X}, {}", id, buf.as_mut_ptr() as usize, buf.len());
+        if let Some(mut file) = self.files.get_mut(&id) {
+            file.read(buf)
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
+    #[allow(unused_variables)]
+    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)
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
+    #[allow(unused_variables)]
+    fn seek(&mut self, id: usize, pos: usize, whence: usize) -> Result<usize> {
+        println!("seek {}, {}, {}", id, pos, whence);
+        if let Some(mut file) = self.files.get_mut(&id) {
+            file.seek(pos, whence)
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
+    #[allow(unused_variables)]
+    fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {
+        println!("fpath {}, {:X}, {}", id, buf.as_mut_ptr() as usize, buf.len());
+        if let Some(file) = self.files.get(&id) {
+            file.path(buf)
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
+    #[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) {
+            file.stat(stat)
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
+    #[allow(unused_variables)]
+    fn fsync(&mut self, id: usize) -> Result<usize> {
+        println!("fsync {}", id);
+        if let Some(mut file) = self.files.get_mut(&id) {
+            file.sync()
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
+    #[allow(unused_variables)]
+    fn ftruncate(&mut self, id: usize, len: usize) -> Result<usize> {
+        println!("ftruncate {}, {}", id, len);
+        Err(Error::new(EBADF))
+    }
+
+    fn close(&mut self, id: usize) -> Result<usize> {
+        println!("close {}", id);
+        if self.files.remove(&id).is_some() {
+            Ok(0)
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+}
+
+fn scheme(fs: FileSystem) {
+   //In order to handle example:, we create :example
+   let mut scheme = FileScheme::new(fs);
+   let mut socket = File::create(":redoxfs").unwrap();
+   loop {
+       let mut packet = Packet::default();
+       while socket.read(&mut packet).unwrap() == size_of::<Packet>() {
+           scheme.handle(&mut packet);
+           socket.write(&packet).unwrap();
+       }
+   }
+}
+
+fn main() {
+    let mut args = env::args();
+    if let Some(path) = args.nth(1) {
+        //Open an existing image
+        match Image::open(&path) {
+            Ok(disk) => match FileSystem::open(Box::new(disk)) {
+                Ok(filesystem) => {
+                    println!("redoxfs: opened filesystem {}", path);
+                    scheme(filesystem);
+                },
+                Err(err) => println!("redoxfs: failed to open filesystem {}: {}", path, err)
+            },
+            Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
+        }
+    } else {
+        println!("redoxfs: no disk image provided");
+    }
+}
diff --git a/utility/main.rs b/utility/main.rs
index b1924f60cd22d40bf57656998e6d3901739d6ca2..1c2a4143e34a14d569c2cf89ec68e8e1b9ce2ccb 100644
--- a/utility/main.rs
+++ b/utility/main.rs
@@ -188,8 +188,8 @@ fn main() {
                 Err(err) => println!("redoxfs: failed to open image {}: {}", path, err)
             }
         }else{
-            //Create a 1 GB disk image
-            let size = 1024 * 1024 * 1024;
+            //Create a 4 MB disk image
+            let size = 4 * 1024 * 1024;
             match Image::create(&path, size) {
                 Ok(disk) => match FileSystem::create(Box::new(disk)) {
                     Ok(filesystem) => {