Finish up vfs_init
diff --git a/src/kernel/io.c b/src/kernel/io.c
index 55bf7a7..0cf04b2 100644
--- a/src/kernel/io.c
+++ b/src/kernel/io.c
@@ -4,13 +4,11 @@
 #include "pic.h"
 
 bool pressed_keys[LAST_KBD_KEY];
-char special_key_mappings[LAST_KBD_KEY - FIRST_KBD_KEY] =
-{
+char special_key_mappings[LAST_KBD_KEY - FIRST_KBD_KEY] = {
 	[KBD_ENTER - FIRST_KBD_KEY] = '\n',
 	[KBD_SPACEBAR - FIRST_KBD_KEY] = ' ',
 	[KBD_TAB - FIRST_KBD_KEY] = '\t',
 	[KBD_BACKSPACE - FIRST_KBD_KEY] = '\b',
-	0
 };
 
 void outb(ushort port, uchar val)
@@ -50,6 +48,31 @@
 	return dest;
 }
 
+uint strlen(char *a)
+{
+	int i = 0;
+	for (; *a; i++)
+	{
+	}
+
+	return i;
+}
+
+int strcmp(char *a, char *b)
+{
+	int al = strlen(a), bl = strlen(b);
+
+	if (al != bl)
+		return bl - al;
+
+	for (int i = 0; i < al; i++)
+	{
+		if (a[i] != b[i])
+			return -1;
+	}
+	return 0;
+}
+
 void io_wait()
 {
 	asm volatile("outb %0, $0x80" ::"a"(0));
diff --git a/src/kernel/io.h b/src/kernel/io.h
index 28af387..f251717 100644
--- a/src/kernel/io.h
+++ b/src/kernel/io.h
@@ -19,8 +19,11 @@
 uchar inb(ushort port);
 ushort inw(ushort port);
 
+/* Random string.h stuff, TODO: move to own header */
 void *memset(void *s, int c, size_t n);
 void *memcpy(void *dest, const void *src, size_t n);
+int strcmp(char *a, char *b);
+uint strlen(char *a);
 
 void io_wait();
 
diff --git a/src/kernel/main.c b/src/kernel/main.c
index 4e5b4ae..5bd8f87 100644
--- a/src/kernel/main.c
+++ b/src/kernel/main.c
@@ -5,6 +5,7 @@
 #include "paging.h"
 #include "timer.h"
 #include "vga.h"
+#include "vfs.h"
 #include "multiboot.h"
 
 int kmain(struct multiboot *mboot)
@@ -18,10 +19,6 @@
 	init_allocator();
 	init_kbd();
 
-	vga_set_color(LIGHT_GREEN, BLACK);
-	vga_write("Setup complete!\n");
-	vga_set_color(WHITE, BLACK);
-
 #ifdef TEST_ALLOC
 	test_allocator();
 #endif
@@ -35,6 +32,13 @@
 
 	kprintf("initrd is at 0x%x to 0x%x\n", initrd_loc);
 
+	init_vfs();
+	kprintf("VFS initialized\n");
+
+	vga_set_color(LIGHT_GREEN, BLACK);
+	vga_write("Setup complete!\n");
+	vga_set_color(WHITE, BLACK);
+
 	asm volatile("sti");
 
 	while (true)
diff --git a/src/kernel/vfs.c b/src/kernel/vfs.c
index 4a584eb..7b4ff0b 100644
--- a/src/kernel/vfs.c
+++ b/src/kernel/vfs.c
@@ -1,6 +1,8 @@
 #include "vfs.h"
+#include "io.h"
 
 struct fs_node root, dev, initrd;
+struct fs_vtable root_v, dev_v;
 
 uint fs_read(struct fs_node *node, size_t offset, size_t size, uchar *buffer)
 {
@@ -34,27 +36,106 @@
 	node->vtable->close(node);
 }
 
-struct fs_dirent *fs_readdir(struct fs_node *node, uint index)
+uint fs_readdir(struct fs_node *node, uint index, struct fs_dirent *out)
 {
-	if (!node || !node->vtable || !node->vtable->readdir || (node->flags & 7) != FS_DIRECTORY)
-		return NULL;
+	if (!node || !node->vtable || !node->vtable->readdir ||
+		(node->flags & 7) != FS_DIRECTORY)
+		return 1;
 
-	return node->vtable->readdir(node, index);
+	return node->vtable->readdir(node, index, out);
 }
 
-struct fs_node *fs_finddir(struct fs_node *node, char *name)
+uint fs_finddir(struct fs_node *node, char *name, struct fs_node *out)
 {
-	if (!node || !node->vtable || !node->vtable->finddir || (node->flags & 7) != FS_DIRECTORY)
-		return NULL;
+	if (!node || !node->vtable || !node->vtable->finddir ||
+		(node->flags & 7) != FS_DIRECTORY)
+		return 1;
 
-	return node->vtable->finddir(node, name);
+	return node->vtable->finddir(node, name, out);
 }
 
-struct fs_dirent *root_readdir(struct fs_node *node, uint index)
+uint root_readdir(struct fs_node *node, uint index, struct fs_dirent *out)
 {
+	if (node == &root && index == 0)
+	{
+		// devfs
+		memcpy(out->name, "dev", 4);
+		out->inode = -1;
 
+		return 0;
+	}
+	else
+		return 1;
+}
+
+uint root_finddir(struct fs_node *node, char *name, struct fs_node *out)
+{
+	if (!strcmp(name, "dev"))
+	{
+		*out = dev;
+		return 0;
+	}
+
+	return 1;
+}
+
+uint dev_readdir(struct fs_node *node, uint index, struct fs_dirent *out)
+{
+	if (node == &dev && index == 0)
+	{
+		// initrd
+		memcpy(out->name, "dirent", 7);
+		out->inode = -1;
+		return 0;
+	}
+	else
+		return 1;
+}
+
+uint dev_finddir(struct fs_node *node, char *name, struct fs_node *out)
+{
+	if (node != &dev)
+		return 1;
+
+	if (!strcmp(name, "initrd"))
+	{
+		*out = initrd;
+		return 0;
+	}
+
+	return 1;
 }
 
 void init_vfs()
 {
+	memset(&root_v, 0, sizeof(root_v));
+	memset(&dev_v, 0, sizeof(root_v));
+	memset(&root, 0, sizeof(root));
+	memset(&dev, 0, sizeof(dev));
+
+	root.flags = FS_DIRECTORY;
+	root.vtable = &root_v;
+	dev.flags = FS_DIRECTORY;
+	dev.vtable = &dev_v;
+	initrd.flags = FS_DIRECTORY;
+
+	root_v.readdir = root_readdir;
+	root_v.finddir = root_finddir;
+}
+
+uint fs_mount(struct fs_node *target, struct fs_node *source)
+{
+	if (target->flags ^ FS_DIRECTORY)
+		return 1; // target is not a directory
+
+	if (target->flags & FS_MOUNT)
+		return 2; // already mounted
+
+	if (source->flags ^ FS_DIRECTORY)
+		return 3; // source is not a directory
+
+	target->flags |= FS_MOUNT;
+	target->mount = source;
+
+	return 0;
 }
diff --git a/src/kernel/vfs.h b/src/kernel/vfs.h
index 3bd135e..1510566 100644
--- a/src/kernel/vfs.h
+++ b/src/kernel/vfs.h
@@ -31,9 +31,8 @@
 typedef void (* fs_open_t)(struct fs_node *node);
 typedef void (* fs_close_t)(struct fs_node *node);
 
-// Dirent should be FREED BY CALLER
-typedef struct fs_dirent *(* fs_readdir_t)(struct fs_node *node, uint index);
-typedef struct fs_node *(* fs_finddir_t)(struct fs_node *node, char *name);
+typedef uint (* fs_readdir_t)(struct fs_node *node, uint index, struct fs_dirent *dirent);
+typedef uint (* fs_finddir_t)(struct fs_node *node, char *name, struct fs_node *out);
 
 struct fs_vtable
 {
@@ -57,15 +56,29 @@
 	FS_MOUNT = 8,   /* Can be or'd with others */
 };
 
+extern struct fs_node root, dev, initrd;
+
 /* Not to be confused normal open, close, etc functions, these operate
- * on the VFS directly */
+ * on the VFS directly
+ * read and write return the number of bytes written/read,  */
 
 uint fs_read(struct fs_node *node, size_t offset, size_t size, uchar *buffer);
 uint fs_write(struct fs_node *node, size_t offset, size_t size, uchar *buffer);
 void fs_open(struct fs_node *node);
 void fs_close(struct fs_node *node);
 
-struct fs_dirent *fs_readdir(struct fs_node *node, uint index);
-struct fs_node *fs_finddir(struct fs_node *node, char *name);
+/* For all of the functions that return integers;
+ * 0 = okay
+ * non-zero = error */
+
+uint fs_readdir(struct fs_node *node, uint index, struct fs_dirent *out);
+uint fs_finddir(struct fs_node *node, char *name, struct fs_node *out);
+
+/* Returns the following error codes:
+ * 0: success
+ * 1: target is not a directory
+ * 2: target is already a mount point
+ * 3: source is not a directory */
+uint fs_mount(struct fs_node *target, struct fs_node *source);
 
 void init_vfs();
diff --git a/src/kernel/vfs_initrd.c b/src/kernel/vfs_initrd.c
index 9298a2d..6bbfd3f 100644
--- a/src/kernel/vfs_initrd.c
+++ b/src/kernel/vfs_initrd.c
@@ -1,4 +1,4 @@
 #include <initrd/initrd.h>
 #include "kint.h"
-
+#include "vfs.h"
 
diff --git a/src/kernel/vfs_initrd.h b/src/kernel/vfs_initrd.h
index 6f70f09..91959d6 100644
--- a/src/kernel/vfs_initrd.h
+++ b/src/kernel/vfs_initrd.h
@@ -1 +1,3 @@
 #pragma once
+
+void init_initrd_vfs();