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.c60
1 files changed, 33 insertions, 27 deletions
diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c
index 05b4a2c..1fa1cc2 100644
--- a/src/kernel/user/vfs.c
+++ b/src/kernel/user/vfs.c
@@ -121,24 +121,32 @@ void unref_fs_node(fs_node_t *n) {
mutex_lock(&n->lock);
n->refs--;
if (n->refs == 0) {
- ASSERT (n != n->fs->root);
+ // delete object!
+ if (n->fs) {
+ ASSERT (n != n->fs->root);
- ASSERT(n->parent != 0);
- ASSERT(n->name != 0);
+ ASSERT(n->parent != 0);
+ ASSERT(n->name != 0);
- mutex_lock(&n->parent->lock);
- hashtbl_remove(n->parent->children, n->name);
- if (n->ops->dispose) n->ops->dispose(n->data);
- mutex_unlock(&n->parent->lock);
+ mutex_lock(&n->parent->lock);
+ hashtbl_remove(n->parent->children, n->name);
+ if (n->ops->dispose) n->ops->dispose(n->data);
+ mutex_unlock(&n->parent->lock);
- unref_fs_node(n->parent);
- unref_fs(n->fs);
+ unref_fs_node(n->parent);
+ unref_fs(n->fs);
- if (n->children != 0) {
- ASSERT(hashtbl_count(n->children) == 0);
- delete_hashtbl(n->children);
+ if (n->children != 0) {
+ ASSERT(hashtbl_count(n->children) == 0);
+ delete_hashtbl(n->children);
+ }
+ } else {
+ // stand-alone IPC/SHM object
+ ASSERT(n->parent == 0 && n->children == 0);
+
+ if (n->ops->dispose) n->ops->dispose(n->data);
}
- free(n->name);
+ if (n->name) free(n->name);
free(n);
} else {
mutex_unlock(&n->lock);
@@ -427,8 +435,6 @@ fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) {
h->fs = fs;
h->node = n;
h->mode = mode;
- h->ops = n->ops;
- h->data = n->data;
// our reference to node n is transferred to the file handle
mutex_unlock(&n->lock);
@@ -449,8 +455,8 @@ void ref_file(fs_handle_t *file) {
void unref_file(fs_handle_t *file) {
file->refs--;
if (file->refs == 0) {
- file->ops->close(file);
- if (file->node) unref_fs_node(file->node);
+ if (file->node->ops->close) file->node->ops->close(file);
+ unref_fs_node(file->node);
if (file->fs) unref_fs(file->fs);
free(file);
}
@@ -463,44 +469,44 @@ int file_get_mode(fs_handle_t *f) {
size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf) {
if (!(f->mode & FM_READ)) return 0;
- if (f->ops->read == 0) return 0;
+ if (f->node->ops->read == 0) return 0;
- return f->ops->read(f, offset, len, buf);
+ return f->node->ops->read(f, offset, len, buf);
}
size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) {
if (!(f->mode & FM_WRITE)) return 0;
- if (f->ops->write == 0) return 0;
+ if (f->node->ops->write == 0) return 0;
- return f->ops->write(f, offset, len, buf);
+ return f->node->ops->write(f, offset, len, 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);
}
int file_ioctl(fs_handle_t *f, int command, void* data) {
if (!(f->mode & FM_IOCTL)) return -1;
- if (f->ops->ioctl == 0) return -1;
+ if (f->node->ops->ioctl == 0) return -1;
- return f->ops->ioctl(f->data, command, data);
+ return f->node->ops->ioctl(f->node->data, command, data);
}
bool file_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d) {
if (!(f->mode & FM_READDIR)) return 0;
- return f->ops->readdir && f->ops->readdir(f, ent_no, d);
+ return f->node->ops->readdir && f->node->ops->readdir(f, ent_no, d);
}
int file_poll(fs_handle_t *f, void** out_wait_obj) {
- if (!f->ops->poll) {
+ if (!f->node->ops->poll) {
if (out_wait_obj) *out_wait_obj = 0;
return 0;
}
- return f->ops->poll(f, out_wait_obj);
+ return f->node->ops->poll(f, out_wait_obj);
}
/* vim: set ts=4 sw=4 tw=0 noet :*/