diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-12 22:35:07 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-12 22:35:07 +0100 |
commit | 9004213b4422e7a43c8ec8aac99d4ecc92553f20 (patch) | |
tree | 2e98e49e582494ce2f514fb388fa351637e5dffc | |
parent | 862b93742237ed959e9b8dc12a536880ea45d0cf (diff) | |
download | kogata-9004213b4422e7a43c8ec8aac99d4ecc92553f20.tar.gz kogata-9004213b4422e7a43c8ec8aac99d4ecc92553f20.zip |
Begin implementation of nullfs.
-rw-r--r-- | src/common/include/fs.h | 6 | ||||
-rw-r--r-- | src/common/include/mutex.h | 3 | ||||
-rw-r--r-- | src/common/mutex.c | 6 | ||||
-rw-r--r-- | src/common/string.c | 2 | ||||
-rw-r--r-- | src/kernel/core/kmain.c | 4 | ||||
-rw-r--r-- | src/kernel/include/nullfs.h | 10 | ||||
-rw-r--r-- | src/kernel/include/vfs.h | 11 | ||||
-rw-r--r-- | src/kernel/user/nullfs.c | 493 | ||||
-rw-r--r-- | src/kernel/user/vfs.c | 30 |
9 files changed, 313 insertions, 252 deletions
diff --git a/src/common/include/fs.h b/src/common/include/fs.h index 2ab0760..1ee3d5e 100644 --- a/src/common/include/fs.h +++ b/src/common/include/fs.h @@ -11,6 +11,8 @@ #define FT_FIFO (0x10) // #define FT_SOCKET (0x20) // Not yet! Semantics not defined. (TODO) +// FM_* enum describes modes for opening a file as well as authorized operations in stat_t +// (some flags are used only for open() or only in stat_t.access) #define FM_READ (0x01) #define FM_WRITE (0x02) #define FM_READDIR (0x04) @@ -18,6 +20,9 @@ #define FM_CREATE (0x10) #define FM_TRUNC (0x20) #define FM_APPEND (0x40) +#define FM_DCREATE (0x100) // create file in directory +#define FM_DMOVE (0x200) // move file from directory +#define FM_DUNLINK (0x400) // delete file from directory typedef struct { int type; @@ -30,6 +35,7 @@ typedef struct { typedef struct { char name[DIR_MAX]; + stat_t st; } dirent_t; diff --git a/src/common/include/mutex.h b/src/common/include/mutex.h index 6814adf..88c077e 100644 --- a/src/common/include/mutex.h +++ b/src/common/include/mutex.h @@ -1,6 +1,7 @@ #pragma once #include <stdint.h> +#include <stdbool.h> #define MUTEX_LOCKED 1 #define MUTEX_UNLOCKED 0 @@ -9,7 +10,7 @@ typedef uint32_t mutex_t; void mutex_lock(mutex_t* mutex); //wait for mutex to be free -int mutex_try_lock(mutex_t* mutex); //lock mutex only if free, returns !0 if locked, 0 if was busy +bool mutex_try_lock(mutex_t* mutex); //lock mutex only if free, returns true when locked, false when was busy void mutex_unlock(mutex_t* mutex); // the mutex code assumes a yield() function is defined somewhere diff --git a/src/common/mutex.c b/src/common/mutex.c index cda8049..b345ee5 100644 --- a/src/common/mutex.c +++ b/src/common/mutex.c @@ -13,11 +13,11 @@ void mutex_lock(uint32_t* mutex) { } } -int mutex_try_lock(uint32_t* mutex) { +bool mutex_try_lock(uint32_t* mutex) { if (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) { - return 0; + return false; } - return 1; + return true; } void mutex_unlock(uint32_t* mutex) { diff --git a/src/common/string.c b/src/common/string.c index b50356a..f6c27b4 100644 --- a/src/common/string.c +++ b/src/common/string.c @@ -57,7 +57,7 @@ int strcmp(const char *s1, const char *s2) { return (*(unsigned char*)s1 - *(unsigned char*)s2); } -int strcmp(const char *s1, const char *s2, size_t n) { +int strncmp(const char *s1, const char *s2, size_t n) { size_t i = 0; while ((*s1) && (*s1 == *s2) && i != n) { s1++; diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c index 490d463..57d49e5 100644 --- a/src/kernel/core/kmain.c +++ b/src/kernel/core/kmain.c @@ -242,8 +242,6 @@ void kernel_init_stage2(void* data) { register_nullfs_driver(); fs_t *devfs = make_fs("nullfs", 0, "cd"); ASSERT(devfs != 0); - nullfs_t *devfs_n = as_nullfs(devfs); - ASSERT(devfs_n != 0); // Add kernel command line to devfs { @@ -284,7 +282,7 @@ void kernel_init_stage2(void* data) { // But since we have a nullfs, we can do it that way to prevent useless data copies : ASSERT(nullfs_add_ram_file(devfs, name, (char*)mods[i].mod_start, - len, false, FM_READ, FM_MMAP)); + len, false, FM_READ | FM_MMAP)); } // TEST : read /cmdline diff --git a/src/kernel/include/nullfs.h b/src/kernel/include/nullfs.h index ba6a9c8..6ab8760 100644 --- a/src/kernel/include/nullfs.h +++ b/src/kernel/include/nullfs.h @@ -7,13 +7,11 @@ // - d : allow deletion of arbitrary nodes // - m : allow move operation -typedef struct nullfs nullfs_t; - void register_nullfs_driver(); -nullfs_t* as_nullfs(fs_t *fs); - -bool nullfs_add_node(nullfs_t *f, const char* name, fs_node_ptr data, fs_node_ops_t *ops); -bool nullfs_add_ram_file(nullfs_t *f, const char* name, char* data, size_t init_sz, bool copy, int ok_modes); +// These calls can be done on the fs_t corresponding to a nullfs +// Of course they fail if the fs is not actually a nullfs. +bool nullfs_add_node(fs_t *f, const char* name, fs_node_ptr data, fs_node_ops_t *ops); +bool nullfs_add_ram_file(fs_t *f, const char* name, char* data, size_t init_sz, bool copy, int ok_modes); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/vfs.h b/src/kernel/include/vfs.h index b0fd146..2a5f3d8 100644 --- a/src/kernel/include/vfs.h +++ b/src/kernel/include/vfs.h @@ -30,7 +30,6 @@ struct fs_handle; typedef struct { size_t (*read)(fs_handle_ptr f, size_t offset, size_t len, char* buf); size_t (*write)(fs_handle_ptr f, size_t offset, size_t len, const char* buf); - bool (*stat)(fs_handle_ptr f, stat_t *st); bool (*readdir)(fs_handle_ptr f, dirent_t *d); void (*close)(fs_handle_ptr f); } fs_handle_ops_t; @@ -38,7 +37,7 @@ typedef struct { typedef struct fs_handle { // These two field are filled by the VFS's generic open() code struct fs *fs; - struct fs_node *n; + struct fs_node *node; int refs; // These fields are filled by the FS's specific open() code @@ -54,7 +53,7 @@ typedef struct fs_handle { // Remarks : // - fs_node_t not to be used in public interface // - nodes keep a reference to their parent -// - delete() is expected to delete the node (make it inaccessible), but not dispose +// - unink() is expected to unink the node from its parent (make it inaccessible), but not dispose // of its data before dispos() is called !! // - the root node of a filesystem is created when the filesystem is created // - dispose() is not called on the root node when a filesystem is shutdown @@ -63,8 +62,8 @@ typedef struct { bool (*open)(fs_node_ptr n, int mode, fs_handle_t *s); // open current node bool (*stat)(fs_node_ptr n, stat_t *st); bool (*walk)(fs_node_ptr n, const char* file, struct fs_node *node_d); - bool (*delete)(fs_node_ptr n); - bool (*move)(fs_node_ptr n, struct fs_node *new_parent, const char *new_name); // TODO : not sure about this ? + bool (*unlink)(fs_node_ptr n, const char* file); + bool (*move)(fs_node_ptr dir, const char* old_name, struct fs_node *new_parent, const char *new_name); bool (*create)(fs_node_ptr n, const char* name, int type); // create sub-node in directory int (*ioctl)(fs_node_ptr n, int command, void* data); void (*dispose)(fs_node_ptr n); @@ -131,7 +130,7 @@ void ref_fs(fs_t *fs); void unref_fs(fs_t *fs); bool fs_create(fs_t *fs, const char* file, int type); -bool fs_delete(fs_t *fs, const char* file); +bool fs_unlink(fs_t *fs, const char* file); bool fs_move(fs_t *fs, const char* from, const char* to); bool fs_stat(fs_t *fs, const char* file, stat_t *st); int fs_ioctl(fs_t *fs, const char* file, int command, void* data); diff --git a/src/kernel/user/nullfs.c b/src/kernel/user/nullfs.c index a2975b4..ec80fb1 100644 --- a/src/kernel/user/nullfs.c +++ b/src/kernel/user/nullfs.c @@ -1,335 +1,384 @@ #include <hashtbl.h> +#include <mutex.h> #include <string.h> #include <debug.h> #include <nullfs.h> -static bool nullfs_i_make(fs_handle_t *source, char* opts, fs_t *d); +// nullfs driver +static bool nullfs_fs_make(fs_handle_t *source, char* opts, fs_t *d); -static bool nullfs_i_open(void* fs, const char* file, int mode, fs_handle_t *s); -static bool nullfs_i_delete(void* fs, const char* file); -static void nullfs_i_shutdown(void* fs); -static bool nullfs_i_fs_stat(void* fs, const char* file, stat_t *st); -static int nullfs_i_fs_ioctl(void* fs, const char* file, int command, void* data); +// nullfs fs_t +static void nullfs_fs_shutdown(fs_ptr fs); -static bool nullfs_i_f_stat(void* f, stat_t *st); -static size_t nullfs_i_read(void* f, size_t offset, size_t len, char* buf); -static size_t nullfs_i_write(void* f, size_t offset, size_t len, const char* buf); -static void nullfs_i_close(void* f); +// nullfs directory node +static bool nullfs_d_open(fs_node_ptr n, int mode, fs_handle_t *s); +static bool nullfs_d_stat(fs_node_ptr n, stat_t *st); +static bool nullfs_d_walk(fs_node_ptr n, const char* file, struct fs_node *node_d); +static bool nullfs_d_unlink(fs_node_ptr n, const char* file); +static bool nullfs_d_move(fs_node_ptr n, const char* old_name, fs_node_t *new_parent, const char *new_name); +static bool nullfs_d_create(fs_node_ptr n, const char* file, int type); +static void nullfs_d_dispose(fs_node_ptr n); +// nullfs directory handle +static bool nullfs_dh_readdir(fs_handle_ptr f, dirent_t *d); +static void nullfs_dh_close(fs_handle_ptr f); + +// nullfs ram file node +static bool nullfs_f_open(fs_node_ptr n, int mode, fs_handle_t *s); +static bool nullfs_f_stat(fs_node_ptr n, stat_t *st); +static void nullfs_f_dispose(fs_node_ptr n); + +// nullfs ram file handle +static size_t nullfs_fh_read(fs_handle_ptr f, size_t offset, size_t len, char* buf); +static size_t nullfs_fh_write(fs_handle_ptr f, size_t offset, size_t len, const char* buf); +static void nullfs_fh_close(fs_handle_ptr f); + +// VTables that go with it static fs_driver_ops_t nullfs_driver_ops = { - .make = nullfs_i_make, + .make = nullfs_fs_make, .detect = 0, }; static fs_ops_t nullfs_ops = { - .open = nullfs_i_open, - .delete = nullfs_i_delete, - .rename = 0, - .stat = nullfs_i_fs_stat, - .ioctl = nullfs_i_fs_ioctl, + .shutdown = nullfs_fs_shutdown, .add_source = 0, - .shutdown = nullfs_i_shutdown }; -static fs_handle_ops_t nullfs_h_ops = { - .read = nullfs_i_read, - .write = nullfs_i_write, - .close = nullfs_i_close, - .stat = nullfs_i_f_stat +static fs_node_ops_t nullfs_d_ops = { + .open = nullfs_d_open, + .stat = nullfs_d_stat, + .walk = nullfs_d_walk, + .unlink = nullfs_d_unlink, + .move = nullfs_d_move, + .create = nullfs_d_create, + .dispose = nullfs_d_dispose, + .ioctl = 0, }; -// Internal nullfs structures +static fs_handle_ops_t nullfs_dh_ops = { + .readdir = nullfs_dh_readdir, + .close = nullfs_dh_close, + .read = 0, + .write = 0, +}; + +static fs_node_ops_t nullfs_f_ops = { + .open = nullfs_f_open, + .stat = nullfs_f_stat, + .dispose = nullfs_f_dispose, + .walk = 0, + .create = 0, + .unlink = 0, + .move = 0, + .ioctl =0, +}; + +static fs_handle_ops_t nullfs_fh_ops = { + .read = nullfs_fh_read, + .write = nullfs_fh_write, + .close = nullfs_fh_close, + .readdir = 0, +}; + + +// ====================== // +// NULLFS DATA STRUCTURES // +// ====================== // typedef struct { - void* data; - nullfs_node_ops_t *ops; + bool can_create, can_move, can_unlink; +} nullfs_t; + +typedef struct nullfs_item { + char* name; + fs_node_ptr data; + fs_node_ops_t *ops; + + struct nullfs_item *next; } nullfs_item_t; typedef struct { - nullfs_item_t *item; - void* data; -} nullfs_handle_t; - -typedef struct nullfs { - hashtbl_t *items; - bool can_delete; - bool can_create; -} nullfs_t; + nullfs_item_t *items_list; + hashtbl_t *items_idx; + + mutex_t lock; // always locked when open (cannot create/delete/move) + + nullfs_t *fs; +} nullfs_dir_t; + +typedef struct { + nullfs_item_t *it; + nullfs_dir_t *d; +} nullfs_dh_t; + +typedef struct { + char* data; + size_t size; + bool own_data; + int ok_modes; + + mutex_t lock; +} nullfs_file_t; + +// No nullfs_file_handle_t struct, we don't need it. The handle's data +// pointer is simply a pointer to the file node. -// Nullfs management +// ===================== // +// NULLFS IMPLEMENTATION // +// ===================== // void register_nullfs_driver() { register_fs_driver("nullfs", &nullfs_driver_ops); } -nullfs_t *as_nullfs(fs_t *it) { - if (it->ops != &nullfs_ops) return 0; - return (nullfs_t*)it->data; -} - -bool nullfs_i_make(fs_handle_t *source, char* opts, fs_t *d) { +bool nullfs_fs_make(fs_handle_t *source, char* opts, fs_t *fs_s) { nullfs_t *fs = (nullfs_t*)malloc(sizeof(nullfs_t)); if (fs == 0) return false; - fs->items = create_hashtbl(str_key_eq_fun, str_hash_fun, free, 0); - if (fs->items == 0) { + fs->can_create = (strchr(opts, 'c') != 0); + fs->can_move = (strchr(opts, 'm') != 0); + fs->can_unlink = (strchr(opts, 'd') != 0); + + nullfs_dir_t *root = (nullfs_dir_t*)malloc(sizeof(nullfs_dir_t)); + if (root == 0) { free(fs); return false; } - fs->can_delete = (strchr(opts, 'd') != 0); - fs->can_create = (strchr(opts, 'c') != 0); + root->fs = fs; + root->items_list = 0; + root->lock = MUTEX_UNLOCKED; + root->items_idx = create_hashtbl(str_key_eq_fun, str_hash_fun, 0, 0); + if (root->items_idx == 0) { + free(root); + free(fs); + return false; + } - d->data = fs; - d->ops = &nullfs_ops; + fs_s->ops = &nullfs_ops; + fs_s->data = fs; + fs_s->root.ops = &nullfs_d_ops; + fs_s->root.data = root; return true; } -bool nullfs_add(nullfs_t *f, const char* name, void* data, nullfs_node_ops_t *ops) { - nullfs_item_t *i = (nullfs_item_t*)malloc(sizeof(nullfs_item_t)); - if (i == 0) return false; +void nullfs_fs_shutdown(fs_ptr fs) { + // TODO free all +} - char* n = strdup(name); - if (n == 0) { - free(i); - return false; - } +bool nullfs_add_node(fs_t *fs, const char* name, fs_node_ptr data, fs_node_ops_t *ops) { + char file_name[DIR_MAX]; + + fs_node_t *n = fs_walk_path_except_last(&fs->root, name, file_name); + if (n == 0) return false; + if (n->ops != &nullfs_d_ops) return false; + + nullfs_dir_t *d = (nullfs_dir_t*)n->data; + mutex_lock(&d->lock); + + nullfs_item_t *i = (nullfs_item_t*)malloc(sizeof(nullfs_item_t)); + if (i == 0) goto error; + + i->name = strdup(file_name); + if (i->name == 0) goto error; i->data = data; i->ops = ops; - if (!hashtbl_add(f->items, n, i)) { - free(n); - free(i); - return false; - } + bool add_ok = hashtbl_add(d->items_idx, i->name, i); + if (!add_ok) goto error; + + i->next = d->items_list; + d->items_list = i; + + mutex_unlock(&d->lock); return true; -} -static void nullfs_i_free_item(void* x) { - nullfs_item_t *i = (nullfs_item_t*)x; - if (i->ops->dispose) i->ops->dispose(i->data); - free(i); +error: + if (i && i->name) free(i->name); + if (i) free(i); + mutex_unlock(&d->lock); + return false; } -void nullfs_i_shutdown(void* fs) { - nullfs_t *f = (nullfs_t*)fs; +bool nullfs_add_ram_file(fs_t *fs, const char* name, char* data, size_t init_sz, bool copy, int ok_modes) { + nullfs_file_t *f = (nullfs_file_t*)malloc(sizeof(nullfs_file_t)); + if (f == 0) return false; + + f->size = init_sz; + if (copy) { + f->data = malloc(init_sz); + memcpy(f->data, data, init_sz); + f->own_data = true; + } else { + f->data = data; + f->own_data = false; + } + f->ok_modes = ok_modes; + f->lock = MUTEX_UNLOCKED; + + bool add_ok = nullfs_add_node(fs, name, f, &nullfs_f_ops); + if (!add_ok) { + if (f->own_data) free(f->data); + free(f); + return false; + } - delete_hashtbl(f->items, nullfs_i_free_item); - free(f); + return true; } -// Nullfs operations +// -- Directory node -- -bool nullfs_i_open(void* fs, const char* file, int mode, fs_handle_t *s) { - nullfs_t *f = (nullfs_t*)fs; +bool nullfs_d_open(fs_node_ptr n, int mode, fs_handle_t *s) { + if (mode != FM_READDIR) return false; - nullfs_item_t *x = (nullfs_item_t*)(hashtbl_find(f->items, file)); - if (x == 0) { - if (f->can_create) { - if (nullfs_add_ram_file(fs, file, 0, 0, false, - FM_READ | FM_WRITE | FM_APPEND | FM_TRUNC | FM_MMAP)) { - x = (nullfs_item_t*)(hashtbl_find(f->items, file)); - ASSERT(x != 0); - } else { - return false; - } - } else { - return false; - } - } + nullfs_dir_t* d = (nullfs_dir_t*)n; - nullfs_handle_t *h = (nullfs_handle_t*)malloc(sizeof(nullfs_handle_t)); - if (h == 0) return false; + bool got_lock = mutex_try_lock(&d->lock); + if (!got_lock) return false; - h->item = x; - h->data = x->ops->open(x->data, mode, s); - if (h->data == 0) { - free(h); + nullfs_dh_t *h = (nullfs_dh_t*)malloc(sizeof(nullfs_dh_t)); + if (h == 0) { + mutex_unlock(&d->lock); return false; } + h->it = d->items_list; + h->d = d; + s->data = h; - s->ops = &nullfs_h_ops; + s->ops = &nullfs_dh_ops; + s->mode = FM_READDIR; + return true; } -bool nullfs_i_fs_stat(void* fs, const char* file, stat_t *st) { - nullfs_t *f = (nullfs_t*)fs; +bool nullfs_d_stat(fs_node_ptr n, stat_t *st) { + nullfs_dir_t* d = (nullfs_dir_t*)n; - nullfs_item_t *x = (nullfs_item_t*)(hashtbl_find(f->items, file)); - if (x == 0) return false; + mutex_lock(&d->lock); - return x->ops->stat && x->ops->stat(x->data, st); -} + st->type = FT_DIR; + st->access = FM_READDIR + | (d->fs->can_create ? FM_DCREATE : 0) + | (d->fs->can_move ? FM_DMOVE : 0) + | (d->fs->can_unlink ? FM_DUNLINK : 0); -int nullfs_i_fs_ioctl(void* fs, const char* file, int command, void* data) { - nullfs_t *f = (nullfs_t*)fs; + st->size = 0; + for (nullfs_item_t *i = d->items_list; i != 0; i = i->next) + st->size++; - nullfs_item_t *x = (nullfs_item_t*)(hashtbl_find(f->items, file)); - if (x == 0) return 0; - if (x->ops->ioctl == 0) return 0; + mutex_unlock(&d->lock); - return x->ops->ioctl(x->data, command, data); + return true; } -bool nullfs_i_delete(void* fs, const char* file) { - nullfs_t *f = (nullfs_t*)fs; +bool nullfs_d_walk(fs_node_ptr n, const char* file, struct fs_node *node_d) { + nullfs_dir_t* d = (nullfs_dir_t*)n; + + mutex_lock(&d->lock); + + nullfs_item_t* x = (nullfs_item_t*)hashtbl_find(d->items_idx, file); + if (x == 0) { + mutex_unlock(&d->lock); + return false; + } - if (!f->can_delete) return false; + node_d->ops = x->ops; + node_d->data = x->data; - nullfs_item_t *x = (nullfs_item_t*)(hashtbl_find(f->items, file)); - if (x == 0) return false; + mutex_unlock(&d->lock); - hashtbl_remove(f->items, file); - nullfs_i_free_item(x); return true; } -bool nullfs_i_f_stat(void* f, stat_t *st) { - nullfs_handle_t *h = (nullfs_handle_t*)f; - return h->item->ops->stat && h->item->ops->stat(h->item->data, st); +bool nullfs_d_unlink(fs_node_ptr n, const char* file) { + return false; //TODO } -size_t nullfs_i_read(void* f, size_t offset, size_t len, char* buf) { - nullfs_handle_t *h = (nullfs_handle_t*)f; - if (!h->item->ops->read) return 0; - return h->item->ops->read(h->data, offset, len, buf); +bool nullfs_d_move(fs_node_ptr n, const char* old_name, fs_node_t *new_parent, const char *new_name) { + return false; //TODO } -size_t nullfs_i_write(void* f, size_t offset, size_t len, const char* buf) { - nullfs_handle_t *h = (nullfs_handle_t*)f; - if (!h->item->ops->write) return 0; - return h->item->ops->write(h->data, offset, len, buf); +bool nullfs_d_create(fs_node_ptr n, const char* file, int type) { + return false; //TODO } -void nullfs_i_close(void* f) { - nullfs_handle_t *h = (nullfs_handle_t*)f; - if (h->item->ops->close) h->item->ops->close(h->data); - free(h); +void nullfs_d_dispose(fs_node_ptr n) { + //TODO } -// ====================================================== // -// THE FUNCTIONS FOR HAVING RAM FILES (nullfs as ramdisk) // -// ====================================================== // - -static void* nullfs_i_ram_open(void* f, int mode, fs_handle_t *h); -static size_t nullfs_i_ram_read(void* f, size_t offset, size_t len, char* buf); -static size_t nullfs_i_ram_write(void* f, size_t offset, size_t len, const char* buf); -static void nullfs_i_ram_dispose(void* f); -static bool nullfs_i_ram_stat(void* f, stat_t *st); - -static nullfs_node_ops_t nullfs_ram_ops = { - .open = nullfs_i_ram_open, - .read = nullfs_i_ram_read, - .write = nullfs_i_ram_write, - .stat = nullfs_i_ram_stat, - .close = 0, - .ioctl = 0, - .dispose = nullfs_i_ram_dispose -}; -typedef struct { - void* data; - bool data_owned; - size_t size; - int ok_modes; -} nullfs_ram_file_t; +// -- Directory handle -- -bool nullfs_add_ram_file(nullfs_t *f, const char* name, void* data, size_t init_sz, bool copy, int ok_modes) { - nullfs_ram_file_t *x = (nullfs_ram_file_t*)malloc(sizeof(nullfs_ram_file_t)); - if (x == 0) return false; +bool nullfs_dh_readdir(fs_handle_ptr f, dirent_t *d) { + nullfs_dh_t *h = (nullfs_dh_t*)f; - if (copy) { - x->data = malloc(init_sz); - if (x->data == 0) { - free(x); - return false; - } - memcpy(x->data, data, init_sz); - x->data_owned = true; - } else { - x->data = data; - x->data_owned = false; - } - x->size = init_sz; - x->ok_modes = ok_modes; - - if (!nullfs_add(f, name, x, &nullfs_ram_ops)) { - if (x->data_owned) free(x->data); - free(x); + if (h->it == 0) { return false; + } else { + strncpy(d->name, h->it->name, DIR_MAX); + d->name[DIR_MAX-1] = 0; // make sur it's null-terminated + if (h->it->ops->stat) { + h->it->ops->stat(h->it->data, &d->st); + } else { + // no stat operation : should we do something else ? + memset(&d->st, 0, sizeof(stat_t)); + } + h->it = h->it->next; + + return true; } - return true; } -void* nullfs_i_ram_open(void* fi, int mode, fs_handle_t *h) { - nullfs_ram_file_t *f = (nullfs_ram_file_t*)fi; - - if (mode & ~f->ok_modes) { - return 0; - } - mode &= ~FM_CREATE; +void nullfs_dh_close(fs_handle_ptr f) { + nullfs_dh_t *h = (nullfs_dh_t*)f; - if (mode & FM_TRUNC) { - if (f->data_owned) free(f->data); - f->data = 0; - f->size = 0; - f->data_owned = 0; - } + mutex_unlock(&h->d->lock); - h->mode = mode; - return fi; + free(h); } -size_t nullfs_i_ram_read(void* fi, size_t offset, size_t len, char* buf) { - nullfs_ram_file_t *f = (nullfs_ram_file_t*)fi; - - if (offset >= f->size) return 0; - if (offset + len > f->size) len = f->size - offset; +// -- File node -- - memcpy(buf, f->data + offset, len); - return len; -} +bool nullfs_f_open(fs_node_ptr n, int mode, fs_handle_t *s) { + nullfs_file_t *f = (nullfs_file_t*)n; -size_t nullfs_i_ram_write(void* fi, size_t offset, size_t len, const char* buf) { - nullfs_ram_file_t *f = (nullfs_ram_file_t*)fi; + if (mode & ~f->ok_modes) return false; - if (offset + len > f->size) { - // resize buffer (zero out new portion) - void* new_buffer = malloc(offset + len); - if (new_buffer == 0) return 0; + mutex_lock(&f->lock); - memcpy(new_buffer, f->data, f->size); - if (offset > f->size) - memset(new_buffer + f->size, 0, offset - f->size); + s->mode = mode; + s->data = f; + s->ops = &nullfs_fh_ops; - if (f->data_owned) free(f->data); - f->data = new_buffer; - f->data_owned = true; - f->size = offset + len; - } + return true; +} - memcpy(f->data + offset, buf, len); - return len; +bool nullfs_f_stat(fs_node_ptr n, stat_t *st) { + return false; //TODO } -void nullfs_i_ram_dispose(void* fi) { - nullfs_ram_file_t *f = (nullfs_ram_file_t*)fi; - - if (f->data_owned) free(f->data); - free(f); +void nullfs_f_dispose(fs_node_ptr n) { + // TODO } -bool nullfs_i_ram_stat(void* fi, stat_t *st) { - nullfs_ram_file_t *f = (nullfs_ram_file_t*)fi; +// -- File handle -- - st->size = f->size; - return true; +static size_t nullfs_fh_read(fs_handle_ptr f, size_t offset, size_t len, char* buf) { + return 0; //TODO } +static size_t nullfs_fh_write(fs_handle_ptr f, size_t offset, size_t len, const char* buf) { + return 0; //TODO +} + +static void nullfs_fh_close(fs_handle_ptr h) { + nullfs_file_t *f = (nullfs_file_t*)h; + mutex_unlock(&f->lock); +} /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c index 38b88d7..67b335c 100644 --- a/src/kernel/user/vfs.c +++ b/src/kernel/user/vfs.c @@ -212,24 +212,34 @@ bool fs_create(fs_t *fs, const char* file, int type) { return ret; } -bool fs_delete(fs_t *fs, const char* file) { - fs_node_t* n = fs_walk_path(&fs->root, file); +bool fs_unlink(fs_t *fs, const char* file) { + char name[DIR_MAX]; + + fs_node_t* n = fs_walk_path_except_last(&fs->root, file, name); if (n == 0) return false; - bool ret = n->ops->delete && n->ops->delete(n->data); + bool ret = n->ops->unlink && n->ops->unlink(n->data, name); unref_fs_node(n); return ret; } bool fs_move(fs_t *fs, const char* from, const char* to) { - fs_node_t *n = fs_walk_path(&fs->root, from); - if (n == 0) return false; + char old_name[DIR_MAX]; + fs_node_t *old_parent = fs_walk_path_except_last(&fs->root, from, old_name); + if (old_parent == 0) return false; char new_name[DIR_MAX]; fs_node_t *new_parent = fs_walk_path_except_last(&fs->root, to, new_name); - if (new_parent == 0) return false; + if (new_parent == 0) { + unref_fs_node(old_parent); + return false; + } + + bool ret = old_parent->ops->move && old_parent->ops->move(old_parent->data, old_name, new_parent, new_name); - return n->ops->move && n->ops->move(n->data, new_parent, new_name); + unref_fs_node(old_parent); + unref_fs_node(new_parent); + return ret; } bool fs_stat(fs_t *fs, const char* file, stat_t *st) { @@ -266,7 +276,7 @@ fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) { h->refs = 1; h->fs = fs; - h->n = n; + h->node = n; if (n->ops->open(n->data, mode, h)) { // our reference to node n is transferred to the file handle @@ -287,7 +297,7 @@ void unref_file(fs_handle_t *file) { file->refs--; if (file->refs == 0) { file->ops->close(file->data); - unref_fs_node(file->n); + unref_fs_node(file->node); unref_fs(file->fs); free(file); } @@ -312,7 +322,7 @@ size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) { } bool file_stat(fs_handle_t *f, stat_t *st) { - return f->ops->stat && f->ops->stat(f->data, st); + return f->node->ops->stat && f->node->ops->stat(f->node->data, st); } bool file_readdir(fs_handle_t *f, dirent_t *d) { |