98 lines
2.4 KiB
C
98 lines
2.4 KiB
C
#include "user/errno.h"
|
|
#include "fs/node.h"
|
|
#include "fs/vfs.h"
|
|
#include "sys/assert.h"
|
|
#include "sys/string.h"
|
|
#include "fs/fs.h"
|
|
#include "sys/debug.h"
|
|
#include "sys/panic.h"
|
|
#include "sys/heap.h"
|
|
#include "sys/mem/slab.h"
|
|
|
|
static struct slab_cache *vnode_cache = NULL;
|
|
|
|
struct vnode *vnode_create(enum vnode_type t, const char *name) {
|
|
if (!vnode_cache) {
|
|
vnode_cache = slab_cache_get(sizeof(struct vnode));
|
|
kdebug("Initialized vnode cache\n");
|
|
}
|
|
struct vnode *node = slab_calloc(vnode_cache);
|
|
_assert(node);
|
|
|
|
node->type = t;
|
|
if (name) {
|
|
_assert(strlen(name) < NODE_MAXLEN);
|
|
strcpy(node->name, name);
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
void vnode_destroy(struct vnode *vn) {
|
|
_assert(vnode_cache);
|
|
_assert(!vn->open_count);
|
|
slab_free(vnode_cache, vn);
|
|
}
|
|
|
|
void vnode_attach(struct vnode *parent, struct vnode *child) {
|
|
_assert(parent);
|
|
_assert(child);
|
|
_assert(!child->parent);
|
|
|
|
child->parent = parent;
|
|
child->next_child = parent->first_child;
|
|
parent->first_child = child;
|
|
}
|
|
|
|
void vnode_detach(struct vnode *node) {
|
|
_assert(node);
|
|
|
|
struct vnode *parent = node->parent;
|
|
node->parent = NULL;
|
|
|
|
if (!parent) {
|
|
return;
|
|
}
|
|
|
|
if (node == parent->first_child) {
|
|
parent->first_child = node->next_child;
|
|
node->next_child = NULL;
|
|
return;
|
|
}
|
|
|
|
for (struct vnode *ch = parent->first_child; ch; ch = ch->next_child) {
|
|
if (ch->next_child == node) {
|
|
ch->next_child = node->next_child;
|
|
node->next_child = NULL;
|
|
return;
|
|
}
|
|
}
|
|
|
|
panic("Parent has no link to its child node\n");
|
|
}
|
|
|
|
// Only dumps cached nodes in filesystem tree
|
|
void vnode_dump_tree(int level, struct vnode *node, int depth) {
|
|
// XXX: I'll reimplement this with proper symlink support
|
|
}
|
|
|
|
// NOTE: Only looks up in-memory nodes, does not perform any operations to fetch
|
|
// the nodes from storage
|
|
// NOTE: Resolution of .. and . is performed when resolving paths, as a node can
|
|
// have multiple parents (roots of filesystems mounted at different locations)
|
|
int vnode_lookup_child(struct vnode *of, const char *name, struct vnode **child) {
|
|
_assert(of);
|
|
_assert(child);
|
|
_assert(name);
|
|
_assert(strlen(name) < NODE_MAXLEN);
|
|
|
|
for (struct vnode *ch = of->first_child; ch; ch = ch->next_child) {
|
|
if (!strcmp(ch->name, name)) {
|
|
*child = ch;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -ENOENT;
|
|
}
|