aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/user/vfs.c')
-rw-r--r--src/kernel/user/vfs.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c
new file mode 100644
index 0000000..ebd5808
--- /dev/null
+++ b/src/kernel/user/vfs.c
@@ -0,0 +1,126 @@
+#include <debug.h>
+#include <vfs.h>
+#include <string.h>
+
+// ============================= //
+// FILESYSTEM DRIVER REGISTERING //
+// ============================= //
+
+typedef struct fs_driver {
+ const char* name;
+ fs_driver_ops_t *ops;
+ struct fs_driver *next;
+} fs_driver_t;
+
+fs_driver_t *drivers = 0;
+
+void register_fs_driver(const char* name, fs_driver_ops_t *ops) {
+ fs_driver_t *d = (fs_driver_t*)malloc(sizeof(fs_driver_t));
+ ASSERT(d != 0); // should we fail in a more graceful manner ?
+
+ d->name = name;
+ d->ops = ops;
+ d->next = drivers;
+ drivers = d;
+}
+
+// ================================== //
+// CREATING AND DELETINF FILE SYSTEMS //
+// ================================== //
+
+fs_t *make_fs(const char* drv_name, fs_handle_t *source, char* opts) {
+ // Look for driver
+ fs_driver_t *d = 0;
+ for(fs_driver_t *i = drivers; i != 0; i = i->next) {
+ if (drv_name != 0 && strcmp(i->name, drv_name) == 0) d = i;
+ if (drv_name == 0 && source != 0 && i->ops->detect && i->ops->detect(source)) d = i;
+ if (d != 0) break;
+ }
+
+ // Open file system
+ fs_t *fs = (fs_t*)malloc(sizeof(fs_t));
+ if (fs == 0) return 0;
+
+ if (d->ops->make(source, opts, fs)) {
+ return fs;
+ } else {
+ free(fs);
+ return 0;
+ }
+}
+
+bool fs_add_source(fs_t *fs, fs_handle_t *source) {
+ return fs->ops->add_source && fs->ops->add_source(fs->data, source);
+}
+
+void ref_fs(fs_t *fs) {
+ fs->refs++;
+}
+
+void unref_fs(fs_t *fs) {
+ fs->refs--;
+ if (fs->refs == 0) {
+ fs->ops->shutdown(fs->data);
+ free(fs);
+ }
+}
+
+// DOING THINGS IN FLESYSTEMS //
+
+bool fs_delete(fs_t *fs, const char* file) {
+ return fs->ops->delete && fs->ops->delete(fs->data, file);
+}
+
+bool fs_rename(fs_t *fs, const char* from, const char* to) {
+ return fs->ops->rename && fs->ops->rename(fs->data, from, to);
+}
+
+bool fs_stat(fs_t *fs, const char* name, stat_t *st) {
+ return fs->ops->stat && fs->ops->stat(fs->data, name, st);
+}
+
+int fs_ioctl(fs_t *fs, const char* file, int command, void* data) {
+ return fs->ops->ioctl && fs->ops->ioctl(fs->data, file, command, data);
+}
+
+// =================== //
+// OPERATIONS ON FILES //
+// =================== //
+
+fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) {
+ fs_handle_t *h = (fs_handle_t*)malloc(sizeof(fs_handle_t));
+ if (h == 0) return 0;
+
+ if (fs->ops->open(fs->data, file, mode, h)) {
+ return h;
+ } else {
+ free(h);
+ return 0;
+ }
+}
+
+void ref_file(fs_handle_t *file) {
+ file->refs++;
+}
+
+void unrefe_file(fs_handle_t *file) {
+ file->refs--;
+ if (file->refs == 0) {
+ file->ops->close(file->data);
+ free(file);
+ }
+}
+
+size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf) {
+ return f->ops->read && f->ops->read(f->data, offset, len, buf);
+}
+
+size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) {
+ return f->ops->write && f->ops->write(f->data, offset, len, buf);
+}
+
+int file_get_mode(fs_handle_t *f) {
+ return f->mode;
+}
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/