diff --git a/Cargo.lock b/Cargo.lock
index 9a025e95e0f5a73909ad69360bc32295273d1e6d..bd85205f42980f7fe3113ff1cd665206f3745308 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,7 +2,7 @@
 # It is not intended for manual editing.
 [[package]]
 name = "cfg-if"
-version = "0.1.7"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -15,7 +15,7 @@ name = "fuse"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -24,7 +24,7 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.54"
+version = "0.2.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -40,7 +40,7 @@ name = "log"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -53,7 +53,7 @@ name = "rand"
 version = "0.3.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -63,7 +63,7 @@ version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -92,16 +92,16 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.54"
+version = "0.1.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "redoxfs"
-version = "0.3.3"
+version = "0.3.4"
 dependencies = [
  "fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -116,8 +116,8 @@ name = "time"
 version = "0.1.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -149,10 +149,10 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
-"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
+"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
 "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
 "checksum fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e57070510966bfef93662a81cb8aa2b1c7db0964354fa9921434f04b9e8660"
-"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6"
+"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
 "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
@@ -161,7 +161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
 "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
-"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
+"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
 "checksum thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99"
 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
 "checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22"
diff --git a/Cargo.toml b/Cargo.toml
index 636417a7ee7ccec2d35120304c2daaf84938b81e..310080d3de787b221ef23a5cc11e65410c996838 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,7 +2,7 @@
 name = "redoxfs"
 description = "The Redox Filesystem"
 repository = "https://gitlab.redox-os.org/redox-os/redoxfs"
-version = "0.3.3"
+version = "0.3.4"
 license-file = "LICENSE"
 readme = "README.md"
 authors = ["Jeremy Soller <jackpot51@gmail.com>"]
diff --git a/src/archive.rs b/src/archive.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f5ad9b68d24a13540d33e3b41eff458ec2099a45
--- /dev/null
+++ b/src/archive.rs
@@ -0,0 +1,101 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+use std::os::unix::ffi::OsStrExt;
+use std::os::unix::fs::MetadataExt;
+
+use crate::{BLOCK_SIZE, Disk, Extent, FileSystem, Node};
+
+fn syscall_err(err: syscall::Error) -> io::Error {
+    io::Error::from_raw_os_error(err.errno)
+}
+
+fn archive_at<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_path: P, parent_block: u64) -> io::Result<()> {
+    for entry_res in fs::read_dir(parent_path)? {
+        let entry = entry_res?;
+
+        let metadata = entry.metadata()?;
+        let file_type = metadata.file_type();
+
+        let name = entry.file_name().into_string().map_err(|_|
+            io::Error::new(
+                io::ErrorKind::InvalidData,
+                "filename is not valid UTF-8"
+            )
+        )?;
+
+        let mode_type = if file_type.is_dir() {
+            Node::MODE_DIR
+        } else if file_type.is_file() {
+            Node::MODE_FILE
+        } else if file_type.is_symlink() {
+            Node::MODE_SYMLINK
+        } else {
+            return Err(io::Error::new(
+                io::ErrorKind::Other,
+                format!("Does not support parsing {:?}", file_type)
+            ));
+        };
+
+        let mode = mode_type | (metadata.mode() as u16 & Node::MODE_PERM);
+        let mut node = fs.create_node(
+            mode,
+            &name,
+            parent_block,
+            metadata.ctime() as u64,
+            metadata.ctime_nsec() as u32
+        ).map_err(syscall_err)?;
+        node.1.uid = metadata.uid();
+        node.1.gid = metadata.gid();
+        fs.write_at(node.0, &node.1).map_err(syscall_err)?;
+
+        let path = entry.path();
+        if file_type.is_dir() {
+            archive_at(fs, path, node.0)?;
+        } else if file_type.is_file() {
+            let data = fs::read(path)?;
+            fs.write_node(
+                node.0,
+                0,
+                &data,
+                metadata.mtime() as u64,
+                metadata.mtime_nsec() as u32
+            ).map_err(syscall_err)?;
+        } else if file_type.is_symlink() {
+            let destination = fs::read_link(path)?;
+            let data = destination.as_os_str().as_bytes();
+            fs.write_node(
+                node.0,
+                0,
+                &data,
+                metadata.mtime() as u64,
+                metadata.mtime_nsec() as u32
+            ).map_err(syscall_err)?;
+        } else {
+            return Err(io::Error::new(
+                io::ErrorKind::Other,
+                format!("Does not support creating {:?}", file_type)
+            ));
+        }
+    }
+
+    Ok(())
+}
+
+pub fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_path: P) -> io::Result<u64> {
+    let root_block = fs.header.1.root;
+    archive_at(fs, parent_path, root_block)?;
+
+    let free_block = fs.header.1.free;
+    let mut free = fs.node(free_block).map_err(syscall_err)?;
+    let end_block = free.1.extents[0].block;
+    let end_size = end_block * BLOCK_SIZE;
+    free.1.extents[0] = Extent::default();
+    fs.write_at(free.0, &free.1).map_err(syscall_err)?;
+
+    fs.header.1.size = end_size;
+    let header = fs.header;
+    fs.write_at(header.0, &header.1).map_err(syscall_err)?;
+
+    Ok(header.0 * BLOCK_SIZE + end_size)
+}
diff --git a/src/bin/ar.rs b/src/bin/ar.rs
index 139b893380a2352377a2621ee53689341fed29ff..1b7ac036bf52ed35b11b9f052770956638831e92 100644
--- a/src/bin/ar.rs
+++ b/src/bin/ar.rs
@@ -3,110 +3,12 @@ extern crate syscall;
 extern crate uuid;
 
 use std::{env, fs, process};
-use std::io::{self, Read};
-use std::path::Path;
+use std::io::Read;
 use std::time::{SystemTime, UNIX_EPOCH};
-use std::os::unix::ffi::OsStrExt;
-use std::os::unix::fs::MetadataExt;
 
-use redoxfs::{BLOCK_SIZE, Disk, DiskSparse, Extent, FileSystem, Node};
+use redoxfs::{DiskSparse, FileSystem, archive};
 use uuid::Uuid;
 
-fn syscall_err(err: syscall::Error) -> io::Error {
-    io::Error::from_raw_os_error(err.errno)
-}
-
-fn archive_at<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_path: P, parent_block: u64) -> io::Result<()> {
-    for entry_res in fs::read_dir(parent_path)? {
-        let entry = entry_res?;
-
-        let metadata = entry.metadata()?;
-        let file_type = metadata.file_type();
-
-        let name = entry.file_name().into_string().map_err(|_|
-            io::Error::new(
-                io::ErrorKind::InvalidData,
-                "filename is not valid UTF-8"
-            )
-        )?;
-
-        let mode_type = if file_type.is_dir() {
-            Node::MODE_DIR
-        } else if file_type.is_file() {
-            Node::MODE_FILE
-        } else if file_type.is_symlink() {
-            Node::MODE_SYMLINK
-        } else {
-            return Err(io::Error::new(
-                io::ErrorKind::Other,
-                format!("Does not support parsing {:?}", file_type)
-            ));
-        };
-
-        let mode = mode_type | (metadata.mode() as u16 & Node::MODE_PERM);
-        let mut node = fs.create_node(
-            mode,
-            &name,
-            parent_block,
-            metadata.ctime() as u64,
-            metadata.ctime_nsec() as u32
-        ).map_err(syscall_err)?;
-        node.1.uid = metadata.uid();
-        node.1.gid = metadata.gid();
-        fs.write_at(node.0, &node.1).map_err(syscall_err)?;
-
-        let path = entry.path();
-        if file_type.is_dir() {
-            archive_at(fs, path, node.0)?;
-        } else if file_type.is_file() {
-            let data = fs::read(path)?;
-            fs.write_node(
-                node.0,
-                0,
-                &data,
-                metadata.mtime() as u64,
-                metadata.mtime_nsec() as u32
-            ).map_err(syscall_err)?;
-        } else if file_type.is_symlink() {
-            let destination = fs::read_link(path)?;
-            let data = destination.as_os_str().as_bytes();
-            fs.write_node(
-                node.0,
-                0,
-                &data,
-                metadata.mtime() as u64,
-                metadata.mtime_nsec() as u32
-            ).map_err(syscall_err)?;
-        } else {
-            return Err(io::Error::new(
-                io::ErrorKind::Other,
-                format!("Does not support creating {:?}", file_type)
-            ));
-        }
-    }
-
-    Ok(())
-}
-
-
-fn archive<D: Disk, P: AsRef<Path>>(fs: &mut FileSystem<D>, parent_path: P) -> io::Result<u64> {
-    let root_block = fs.header.1.root;
-    archive_at(fs, parent_path, root_block)?;
-
-    let free_block = fs.header.1.free;
-    let mut free = fs.node(free_block).map_err(syscall_err)?;
-    let end_block = free.1.extents[0].block;
-    let end_size = end_block * BLOCK_SIZE;
-    free.1.extents[0] = Extent::default();
-    fs.write_at(free.0, &free.1).map_err(syscall_err)?;
-
-    fs.header.1.size = end_size;
-    let header = fs.header;
-    fs.write_at(header.0, &header.1).map_err(syscall_err)?;
-
-    Ok(header.0 * BLOCK_SIZE + end_size)
-}
-
 fn main() {
     let mut args = env::args().skip(1);
 
diff --git a/src/lib.rs b/src/lib.rs
index a6bc8147810238d96f105e53afbf0eac747b71d0..b9c6cd4f78658d87b43a4cfccfdc0ced22aaa763 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -11,6 +11,7 @@ pub const SIGNATURE: &'static [u8; 8] = b"RedoxFS\0";
 pub const VERSION: u64 = 3;
 pub static IS_UMT: AtomicUsize = AtomicUsize::new(0);
 
+pub use self::archive::archive;
 pub use self::disk::{Disk, DiskCache, DiskFile, DiskSparse};
 pub use self::ex_node::ExNode;
 pub use self::extent::Extent;
@@ -19,6 +20,7 @@ pub use self::header::Header;
 pub use self::mount::mount;
 pub use self::node::Node;
 
+mod archive;
 mod disk;
 mod ex_node;
 mod extent;