From 2fe66e4f80b194b27912c8ccc5c06c3899840b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Fri, 10 Mar 2017 23:25:25 +0100 Subject: [PATCH] [FS] VFS and mountpoints --- init/init.c | 20 ----- kernel/boot/kmain.c | 11 +++ kernel/fs/vfs.c | 161 ++++++++++++++++++++++++++++++++++++++++ kernel/include/string.h | 3 + kernel/include/vfs.h | 58 +++++++++++++++ kernel/mem/string.c | 22 ++++++ 6 files changed, 255 insertions(+), 20 deletions(-) create mode 100644 kernel/fs/vfs.c create mode 100644 kernel/include/vfs.h diff --git a/init/init.c b/init/init.c index 79833ec..2593356 100644 --- a/init/init.c +++ b/init/init.c @@ -7,26 +7,6 @@ int main(int argc, char **argv) (void) argc; (void) argv; - if(!fork()) - { - if(!fork()) - return 200; - return 100; - } - - for(int j=0; j <= 10; j++) - { - if(!fork()) - return j; - } - while(1) - { - int retval; - int pid = wait(&retval); - printf("Pid: %d exited with %d\n", pid, retval); - } - - for(;;); return 0; } diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index 68de325..4b12a6b 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -11,6 +11,7 @@ #include #include #include +#include int kernel_execve(process_t *p, void *image, char *argv[], char *envp[]); int kmain(uint64_t multiboot_magic, void *multiboot_data) @@ -36,6 +37,16 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) scheduler_insert(th); procmm_print_map(p1->mmap); + fs_mount(0, "/"); + fs_mount(0, "/dev"); + fs_mount(0, "/home/user/mnt/photos"); + + + fs_namef("/"); + fs_namef("/usr/local/bin/python"); + fs_namef("/dev/tty0"); + fs_namef("/home/thomas"); + fs_namef("/home/user/mnt/photos/2016/june"); asm("sti"); debug_info("BOOT COMPLETE\n"); diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c new file mode 100644 index 0000000..edd595d --- /dev/null +++ b/kernel/fs/vfs.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include + +file_t *fs_get(file_t *file) +{ + if(!file) + file = kcalloc(1, sizeof(file_t)); + file->refs += 1; + return file; +} +file_t *fs_put(file_t *file) +{ + if(!file) + return file; + file->refs -= 1; + if(!file->refs) + { + kfree(file); + file = 0; + } + return file; +} + +int fs_open(file_t *file, uint64_t flags) +{ + if(file && file->driver && file->driver->open) + return file->driver->open(file, flags); + return -1; +} + +int fs_close(file_t *file) +{ + if(file && file->driver && file->driver->close) + return file->driver->close(file); + return -1; +} + +size_t fs_read(file_t *file, void *buffer, size_t nbyte, size_t offset) +{ + if(file && file->driver && file->driver->read) + return file->driver->read(file, buffer, nbyte, offset); + return -1; +} + +size_t fs_write(file_t *file, void *buffer, size_t nbyte, size_t offset) +{ + if(file && file->driver && file->driver->write) + return file->driver->write(file, buffer, nbyte, offset); + return -1; +} + +int fs_readdir(file_t *dir, dirent_t *entry, uint64_t offset) +{ + if(dir && dir->driver && dir->driver->readdir) + return dir->driver->readdir(dir, entry, offset); + return 0; +} + +file_t *fs_finddir(file_t *dir, char *name) +{ + dirent_t entry; + int offset = 0; + while(1) + { + int retval = fs_readdir(dir, &entry, offset++); + if(!retval) + break; + if(strcmp((&entry)->name, name)) + { + fs_put(entry.file); + continue; + } + return entry.file; + } + return 0; +} + + +void fs_mount(file_t *root, const char *path) +{ + struct mountpoint *mp = kcalloc(1, sizeof(struct mountpoint) + strlen(path) + 1); + mp->root = fs_get(root); + mp->path_len = strlen(path); + memcpy(mp->path, path, mp->path_len); + mp->path[mp->path_len] = '\0'; + LIST_APPEND(mountpoints, mp, mountpoints); +} + +void fs_umount(const char *path) +{ + LIST_FOREACH(mountpoints, struct mountpoint, mp, mountpoints) + { + if(!strcmp(mp->path, path)) + { + LIST_REMOVE(mountpoints, mp, mountpoints); + fs_put(mp->root); + kfree(mp); + return; + } + } +} + +struct mountpoint *fs_closest_mp(const char *path) +{ + uint64_t best_len = 0; + struct mountpoint *best = 0; + LIST_FOREACH(mountpoints, struct mountpoint, mp, mountpoints) + { + uint64_t len = mp->path_len; + if((!strncmp(mp->path, path, len-1)) && (len > best_len)) + { + best = mp; + best_len = len; + } + } + return best; +} + + +char *pathtok(char **p) +{ + char sep = '/'; + + if(!**p) return 0; + + while(**p && **p == sep) (*p)++; + char *ret = *p; + while(**p && **p != sep) (*p)++; + if(**p) **p = '\0', (*p)++; + return ret; +} + +file_t *fs_namef(const char *path) +{ + char *name; + char *p = strdup(path); + char *q = p; + struct mountpoint *mp = fs_closest_mp(path); + file_t *root = mp->root; + p += mp->path_len; + file_t *dir = fs_get(root); + + while((name = pathtok(&p))) + { + file_t *next = fs_finddir(dir, name); + if(!next) + { + dir = 0; + goto end; + } + fs_put(dir); + dir = next; + } +end: + kfree(q); + return dir; +} diff --git a/kernel/include/string.h b/kernel/include/string.h index f9719b2..b9407ed 100644 --- a/kernel/include/string.h +++ b/kernel/include/string.h @@ -11,3 +11,6 @@ void *memmove(void *dest, const void *src, size_t n); int memcmp(const void *s1, const void *s2, size_t n); size_t strlen(const char *s); +int strncmp(const char *s1, const char *s2, size_t n); +int strcmp(const char *s1, const char *s2); +char *strdup(const char *s); diff --git a/kernel/include/vfs.h b/kernel/include/vfs.h new file mode 100644 index 0000000..699e3ab --- /dev/null +++ b/kernel/include/vfs.h @@ -0,0 +1,58 @@ +#pragma once +#include +#include +#include + +typedef struct vfs_node_st * INODE; + +typedef struct file_st +{ + uint64_t refs; + uint64_t type; + struct fs_driver_st *driver; + void *data; +} file_t; + +typedef struct dirent_st +{ + char name[256]; + file_t *file; +} dirent_t; + +#define FS_FILE 0x1 +#define FS_DIR 0x2 +#define FS_PIPE 0x3 + +typedef struct fs_driver_st +{ + int (*open)(file_t *file, uint64_t flags); + int (*close)(file_t *file); + size_t (*read)(file_t *file, void *buffer, size_t nbyte, size_t offset); + size_t (*write)(file_t *file, void *buffer, size_t nbyte, size_t offset); + int (*readdir)(file_t *dir, dirent_t *entry, uint64_t offset); +} fs_driver_t; + +int fs_open(file_t *file, uint64_t flags); +int fs_close(file_t *file); +size_t fs_read(file_t *file, void *buffer, size_t nbyte, size_t offset); +size_t fs_write(file_t *file, void *buffer, size_t nbyte, size_t offset); +int fs_readdir(file_t *dir, dirent_t *entry, uint64_t offset); + + +struct mountpoint +{ + LIST(struct mountpoint, mountpoints); + file_t *root; + uint64_t path_len; + char path[]; +}; + +file_t *fs_get(file_t *file); +file_t *fs_put(file_t *file); + +LIST(struct mountpoint, mountpoints); + +void fs_mount(file_t *root, const char *path); +void fs_umount(const char *path); + +file_t *fs_namef(const char *path); diff --git a/kernel/mem/string.c b/kernel/mem/string.c index 132f4ad..60780af 100644 --- a/kernel/mem/string.c +++ b/kernel/mem/string.c @@ -1,6 +1,7 @@ #include #include #include +#include // Standard function required by gcc // Just the naĆ­ve implementations for now @@ -44,3 +45,24 @@ size_t strlen(const char *s) while(*s++) len++; return len; } + +int strncmp(const char *s1, const char *s2, size_t n) +{ + while(n && *s1 && (*s1==*s2)) + s1++, s2++, n--; + return *(const unsigned char*)s1-*(const unsigned char*)s2; +} + +int strcmp(const char *s1, const char *s2) +{ + while(*s1 && (*s1==*s2)) + s1++, s2++; + return *(const unsigned char*)s1-*(const unsigned char*)s2; +} + +char *strdup(const char *s) +{ + char *ret = kmalloc(strlen(s)+1); + memcpy(ret, s, strlen(s)+1); + return ret; +}