--- /dev/null
+/*
+Copyright (C) 2008  Mathias Gottschlag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in the
+Software without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef DIRENT_H_INCLUDED
+#define DIRENT_H_INCLUDED
+
+#include <sys/types.h>
+
+#define NAME_MAX 255
+
+typedef struct DIR DIR;
+
+struct dirent
+{
+       ino_t d_ino;
+       char d_name[NAME_MAX + 1];
+};
+
+DIR *opendir(const char *path);
+int closedir(DIR *dir);
+struct dirent *readdir(DIR *dir);
+void rewinddir(DIR *dir);
+void seekdir(DIR *dir, long index);
+long telldir(DIR *dir);
+
+#endif
+
 
@@ -31,9 +31,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 
 #define EOF -1
 
+#define L_tmpnam 13
+
 typedef unsigned int fpos_t;
 
-typedef int FILE;
+typedef struct FILE FILE;
 extern FILE *stderr;
 extern FILE *stdout;
 extern FILE *stdin;
@@ -42,8 +44,11 @@ FILE *fopen(const char *filename, const char *mode); 
 int fclose(FILE *file);
 FILE *freopen(const char *filename, const char *mode, FILE *file);
 int feof(FILE *file);
+int ferror(FILE *file);
 int fseek(FILE *file, long int offset, int origin);
 long int ftell(FILE *file);
+void rewind(FILE *file);
+void clearerr(FILE *file);
 
 int fgetpos(FILE *file, fpos_t *pos);
 int fsetpos(FILE *file, const fpos_t *pos);
@@ -56,7 +61,15 @@ size_t fread(void *ptr, size_t size, size_t count, FILE *file); 
 int fputc(int c, FILE *file);
 int fputs(const char *s, FILE *file);
 int fprintf(FILE *file, const char *fmt, ...);
-size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
+size_t fwrite(const void *ptr, size_t size, size_t count, FILE *file);
+
+FILE *tmpfile(void);
+char *tmpnam(char *s);
+
+int ungetc(int character, FILE *file);
+
+int rename(const char *oldname, const char *newname);
+int remove(const char *filename);
 
 int printf(const char *fmt, ...);
 int puts(const char *s);
 
@@ -167,44 +167,54 @@ int _start(int *programs) 
                uintptr_t entry = elfMapProgram(process, (void*)programs[1 + i * 3], programs[2 + i * 3]);
                keStartProcess(process, entry);
                keSleep(500);
-       }
+               if (!strcmp((char*)programs[3 + i * 3], "/bin/ramdisk"))
+               {
+                       // Mount root file system
+                       int file = open("/dev/tty0", O_RDWR);
+                       write(file, "  Hello world.\n", 15);
        
-       // Some RPC tests
-       keSleep(100);
+                       FileSystemDriver *ramdisk = initpGetFSDriver("ramdisk");
+                       if (!ramdisk)
+                       {
+                               write(file, "Ramdisk driver not found!\n", 26);
+                       }
+                       else
+                       {
+                               write(file, "Ramdisk driver found!\n", 22);
+                               uint32_t *rpcdata;
+                               keAllocMemory(0, 0, (uintptr_t*)&rpcdata, 1);
+                               rpcdata[0] = ramdisk->id;
+                               rpcdata[1] = 0;
+                               strcpy((char*)&rpcdata[2], "/");
+                               strcpy((char*)&rpcdata[2] + 256, "");
+                               uint32_t retval;
+                               rpcSend(ramdisk->pid, RPC_FS_MOUNT, rpcdata, 520, &retval);
+                               if ((int)retval == -1)
+                               {
+                                       write(file, "Could not mount ramdisk!\n", 25);
+                               }
+                               else
+                               {
+                                       write(file, "Mounted ramdisk!\n", 17);
+                                       initpRegisterFS("/", ramdisk->pid, retval);
+                               }
+                               keFreeMemory(rpcdata, 1);
+                               
+                               // Create initial directory structure
+                               mknod("/bin", S_IFDIR, 0);
+                               mknod("/usr", S_IFDIR, 0);
+                               mknod("/tmp", S_IFDIR, 0);
+                               mknod("/tmp/test", S_IFDIR, 0);
+                               mknod("/var", S_IFDIR, 0);
+                               mknod("/etc", S_IFDIR, 0);
+                       }
        
-       // File system test
-       int file = open("/dev/tty0", O_RDWR);
-       write(file, "  Hello world.\n", 15);
-       
-       FileSystemDriver *ramdisk = initpGetFSDriver("ramdisk");
-       if (!ramdisk)
-       {
-               write(file, "Ramdisk driver not found!\n", 26);
-       }
-       else
-       {
-               write(file, "Ramdisk driver found!\n", 22);
-               uint32_t *rpcdata;
-               keAllocMemory(0, 0, (uintptr_t*)&rpcdata, 1);
-               rpcdata[0] = ramdisk->id;
-               rpcdata[1] = 0;
-               strcpy((char*)&rpcdata[2], "/");
-               strcpy((char*)&rpcdata[2] + 256, "");
-               uint32_t retval;
-               rpcSend(ramdisk->pid, RPC_FS_MOUNT, rpcdata, 520, &retval);
-               if ((int)retval == -1)
-               {
-                       write(file, "Could not mount ramdisk!\n", 25);
+                       close(file);
                }
-               else
-               {
-                       write(file, "Mounted ramdisk!\n", 17);
-                       initpRegisterFS("/", ramdisk->pid, retval);
-               }
-               keFreeMemory(rpcdata, 1);
        }
        
-       close(file);
+       // Some RPC tests
+       keSleep(100);
        
        // Floppy dist test
        /*file = open("/dev/fd0", O_RDWR);
@@ -221,13 +231,12 @@ int _start(int *programs) 
        write(file, buffer2, 512);
        close(file);*/
        
-       mknod("/tmp", S_IFDIR, 0);
-       
-       file = open("/tmp/test", O_RDWR | O_CREAT);
+       // File system test
+       int file = open("/tmp/test/test", O_RDWR | O_CREAT);
        char test[] = "Hello world!\n";
        write(file, test, strlen(test));
        close(file);
-       file = open("/tmp/test", O_RDWR);
+       file = open("/tmp/test/test", O_RDWR);
        lseek(file, 4, SEEK_CUR);
        char test2[50];
        int size = read(file, test2, 49);
 
@@ -26,6 +26,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 #include <kernel.h>
 #include <string.h>
 #include <stdlib.h>
+#include <dirent.h>
 
 typedef struct FileHandle
 {
@@ -63,9 +64,6 @@ int open(const char *path, int oflag, ...) 
                keFreeMemory(rpcdata, 1);
                return -1;
        }
-       keDebug("Path (relative to FS): ");
-       keDebug((char*)&rpcdata[2]);
-       keDebug("\n");
        
        // Open file
        pid_t fspid = rpcdata[0];
@@ -233,3 +231,26 @@ int mknod(const char *path, mode_t mode, dev_t dev) 
        return retval;
 }
 
+DIR *opendir(const char *path)
+{
+       return 0;
+}
+int closedir(DIR *dir)
+{
+       return -1;
+}
+struct dirent *readdir(DIR *dir)
+{
+       return 0;
+}
+void rewinddir(DIR *dir)
+{
+}
+void seekdir(DIR *dir, long index)
+{
+}
+long telldir(DIR *dir)
+{
+       return -1;
+}
+
 
@@ -21,6 +21,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
 
 #include <stdio.h>
 #include <kernel.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define ERROR_EOF 1
+#define ERROR_ERROR 2
+
+struct FILE
+{
+       int fd;
+       int append;
+       int error;
+};
 
 FILE *stderr = 0;
 FILE *stdout = 0;
@@ -28,45 +41,125 @@ FILE *stdin = 0; 
 
 FILE *fopen(const char *filename, const char *mode)
 {
-       return 0;
+       // Open file
+       int openmode = 0;
+       if (strchr(mode, 'r')) openmode = O_RDONLY;
+       else if (strchr(mode, 'w')) openmode = O_WRONLY | O_CREAT;
+       else if (strchr(mode, 'a')) openmode = O_WRONLY | O_CREAT;
+       if (strchr(mode, '+')) openmode = (openmode & ~O_ACCMODE) | O_RDWR;
+       int fd = open(filename, openmode);
+       if (fd == -1) return 0;
+       // Return file structure
+       FILE *file = malloc(sizeof(FILE));
+       memset(file, 0, sizeof(FILE));
+       file->fd = fd;
+       if (strchr(mode, 'a')) file->append = 1;
+       return file;
 }
 int fclose(FILE *file)
 {
-       return EOF;
+       if (!file) return EOF;
+       close(file->fd);
+       free(file);
+       return 0;
 }
 FILE *freopen(const char *filename, const char *mode, FILE *file)
 {
-       return EOF;
+       if (fclose(file) == EOF) return 0;
+       return fopen(filename, mode);
 }
 int feof(FILE *file)
 {
-       return -1;
+       return (file->error & ERROR_EOF) != 0;
+}
+int ferror(FILE *file)
+{
+       return (file->error & ERROR_ERROR) != 0;
 }
 int fseek(FILE *file, long int offset, int origin)
 {
-       return -1;
+       if (!file) return EOF;
+       file->error = 0;
+       if (lseek(file->fd, offset, origin) == (off_t)-1) return EOF;
+       return 0;
 }
 long int ftell(FILE *file)
 {
-       return -1;
+       if (!file) return EOF;
+       long int pos = lseek(file->fd, 0, SEEK_CUR);
+       return pos;
+}
+void rewind(FILE *file)
+{
+       fseek(file, 0, SEEK_SET);
+}
+void clearerr(FILE *file)
+{
+       file->error = 0;
 }
 
 int fgetpos(FILE *file, fpos_t *pos)
 {
-       return -1;
+       if (!file || !pos) return EOF;
+
+       long int position = lseek(file->fd, 0, SEEK_CUR);
+       if (position == -1)
+       {
+               *pos = 0;
+               return EOF;
+       }
+       *pos = position;
+       return 0;
 }
 int fsetpos(FILE *file, const fpos_t *pos)
 {
-       return -1;
+       if (!file || !pos) return EOF;
+       file->error = 0;
+       if (lseek(file->fd, *pos, SEEK_SET) == (off_t)-1) return -1;
+       return 0;
 }
 
 int fgetc(FILE *file)
 {
-       return -1;
+       if (!file) return EOF;
+       char c = 0;
+       int size = read(file->fd, &c, 1);
+       if (size == 0)
+       {
+               file->error = ERROR_EOF;
+               return EOF;
+       }
+       else if (size == -1)
+       {
+               file->error = ERROR_ERROR;
+               return EOF;
+       }
+       return c;
 }
 char *fgets(char *str, int num, FILE *file)
 {
-       return 0;
+       int n = 0;
+       while (n < num)
+       {
+               char c = fgetc(file);
+               if ((c == EOF) && ferror(file)) return 0;
+               if ((c == EOF) && (n == 0))
+               {
+                       return 0;
+               }
+               else if ((c == EOF) || (c == '\n') || (c == 0))
+               {
+                       str[n] = 0;
+                       return str;
+               }
+               else
+               {
+                       str[n] = c;
+               }
+               n++;
+       }
+       str[n - 1] = 0;
+       return str;
 }
 int fscanf(FILE *file, const char *fmt, ...)
 {
@@ -74,29 +167,105 @@ int fscanf(FILE *file, const char *fmt, ...) 
 }
 size_t fread(void *ptr, size_t size, size_t count, FILE *file)
 {
-       return -1;
+       if (!file) return 0;
+       int bytecount = read(file->fd, ptr, size * count);
+       if (bytecount == -1)
+       {
+               file->error = ERROR_ERROR;
+               return 0;
+       }
+       if (bytecount != (int)(size * count))
+       {
+               file->error = ERROR_EOF;
+       }
+       return bytecount;
 }
 
 int fputc(int c, FILE *file)
 {
-       return -1;
+       if (!file) return EOF;
+       if (file->append) lseek(file->fd, 0, SEEK_END);
+       int size = write(file->fd, &c, 1);
+       if (size == 0)
+       {
+               file->error = ERROR_EOF;
+               return EOF;
+       }
+       else if (size == -1)
+       {
+               file->error = ERROR_ERROR;
+               return EOF;
+       }
+       return c;
 }
 int fputs(const char *s, FILE *file)
 {
-       return -1;
+       if (!file) return EOF;
+       if (file->append) lseek(file->fd, 0, SEEK_END);
+       int size = write(file->fd, s, strlen(s));
+       if (size == -1)
+       {
+               file->error = ERROR_ERROR;
+               return EOF;
+       }
+       return size;
 }
 int fprintf(FILE *file, const char *fmt, ...)
 {
+       if (!file) return EOF;
+       if (file->append) lseek(file->fd, 0, SEEK_END);
+       // FIXME: Greater length?
+       char buffer[1024];
+       va_list args;
+       va_start(args, fmt);
+       vsnprintf(buffer, 1024, fmt, args);
+       va_end(args);
+
+       int written = write(file->fd, buffer, strlen(buffer));
+       if (written == -1)
+       {
+               file->error = ERROR_ERROR;
+               return EOF;
+       }
+       return written;
+}
+size_t fwrite(const void *ptr, size_t size, size_t count, FILE *file)
+{
+       if (!file) return EOF;
+       if (file->append) lseek(file->fd, 0, SEEK_END);
+       int written = write(file->fd, ptr, size * count);
+       if (written == -1) return EOF;
+       return written;
+}
+
+FILE *tmpfile(void)
+{
+       // TODO
+       return 0;
+}
+char *tmpnam(char *s)
+{
+       // TODO
+       return s;
+}
+
+int ungetc(int character, FILE *file)
+{
+       return EOF;
+}
+
+int rename(const char *oldname, const char *newname)
+{
        return -1;
 }
-size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
+int remove(const char *filename)
 {
        return -1;
 }
 
-
 int printf(const char *fmt, ...)
 {
+       // TODO
        keDebug(fmt);
        return -1;
 }
@@ -123,7 +292,7 @@ int sprintf(char *buf, const char *fmt, ...) 
        return retval;
 }
 
-inline void write_char(char **buf, char **fmt, char c)
+inline void write_char(char **buf, const char **fmt, char c)
 {
        **buf = c;
        (*buf)++;
 
@@ -18,6 +18,7 @@ struct cdi_fs_file 
        struct cdi_fs_res *res;
        uint32_t id;
        int position;
+       int mode;
 };
 
 static struct cdi_fs_filesystem *fsGetFileSystem(uint32_t id)
@@ -128,6 +129,7 @@ static uint32_t fsOpen(uint32_t caller, void *data, uint32_t size) 
        memset(file, 0, sizeof(struct cdi_fs_file));
        file->id = ++fs->last_fh;
        file->res = res;
+       file->mode = flags & O_ACCMODE;
        fs->files = cdi_list_push(fs->files, file);
        
        ((uint32_t*)data)[0] = file->id;
@@ -179,6 +181,7 @@ static uint32_t fsRead(uint32_t caller, void *data, uint32_t size) 
        struct cdi_fs_file *file = fsGetFile(fs, fh);
        if (!file) keDebug("cdi_fs: File not found!\n");
        if (!file) return -1;
+       if (file->mode == O_WRONLY) return -1;
        
        // Write data to file
        struct cdi_fs_stream stream;
@@ -186,9 +189,12 @@ static uint32_t fsRead(uint32_t caller, void *data, uint32_t size) 
        stream.fs = fs;
        stream.error = 0;
        ssize_t ret = file->res->file->read(&stream, file->position, datalength, &((uint32_t*)data)[3]);
-       if (ret == 0)
+       if (ret <= 0)
        {
-               return -1;
+               if ((stream.error == CDI_FS_ERROR_EOF) || (stream.error == 0))
+                       return 0;
+               else
+                       return -1;
        }
        else
        {
@@ -210,6 +216,7 @@ static uint32_t fsWrite(uint32_t caller, void *data, uint32_t size) 
        if (size < datalength + 12) return -1;
        struct cdi_fs_file *file = fsGetFile(fs, fh);
        if (!file) return -1;
+       if (file->mode == O_RDONLY) return -1;
        
        // Write data to file
        struct cdi_fs_stream stream;