BarryServer : Git

All the code for all my projects
// BarryServer : Git / Orion / commit / d41a53cbc7d055b1c00cf0a339dbed6925f4f02c / vfs / inode.c

// Related

Orion

Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)
diff --git a/vfs/inode.c b/vfs/inode.c
new file mode 100644
index 0000000..34b5c65
--- /dev/null
+++ b/vfs/inode.c
@@ -0,0 +1,204 @@
+/*
+ * This file deals with inode operations.  Most of the functions here are just
+ * wrappers for the inode operations.  They generally check if the operation
+ * exists and use it if it does.  If it doesn't they may implement a generic
+ * action, or just simply return.  They also perform the necessary validation to
+ * ensure the operation can be called on the particular inode.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include "vfs.h"
+#include "cache.h"
+#include "inode.h"
+#include "super.h"
+#include "../mem/heap.h"
+#include "../screen.h"
+
+/* Get an Inode */
+Inode *
+inode_get(Inode *inode)
+{
+	/* Add the inode to the Inode List */
+	if (!inode->usage && inode->super) {
+		if (!inode->super->inodes) {
+			inode->super->inodes = inode;
+		} else {
+			inode->lnext = inode->super->inodes;
+			inode->super->inodes = inode;
+		}
+		inode->super->cachedInodes++;
+	}
+
+	inode->usage++;
+	return inode;
+}
+
+/* Put an Inode */
+void
+inode_put(Inode *inode)
+{
+	ASSERT(inode->usage);
+	if (--inode->usage)
+		return;
+
+	/* Remove the inode from the Inode List */
+	Inode *search, *prev = NULL;
+	if (inode->super) {
+		for (search = inode->super->inodes; search;
+		     prev = search, search = search->lnext)
+			if (search == inode)
+				break;
+		if (search) {
+			if (prev)
+				prev->lnext = search->lnext;
+			else
+				inode->super->inodes = search->lnext;
+		}
+	}
+
+	/* Clean up */
+	if (S_ISDIR(inode->mode))
+		entry_clean(inode);
+	else
+		page_clean(inode);
+
+	kfree(inode);
+}
+
+/* Create an inode */
+int
+inode_create(Inode *inode, DirEntry *entry, mode_t mode)
+{
+	if (!inode->ops)
+		return -EINVAL;
+	if (!inode->ops->create)
+		return -EINVAL;
+	acquire(&inode->lock);
+	int err = inode->ops->create(inode, entry, mode);
+	if (!err) {
+		entry_add(inode, entry);
+		entry->inode = super_alloc_inode(inode->super);
+		entry->inode->mode = mode | S_IFREG;
+	}
+	release(&inode->lock);
+	return err;
+}
+
+/* Find a child inode in a directory inode */
+DirEntry *
+inode_lookup(Inode *inode, const char *name)
+{
+	if (!S_ISDIR(inode->mode))
+		return NULL;
+
+	acquire(&inode->lock);
+
+	/* Check cache first */
+	DirEntry *de = entry_find(inode, name);
+	if (de) {
+		entry_get(de);
+		if (de->inode) {
+			release(&inode->lock);
+			return de;
+		}
+	}
+	/* Try file system lookup */
+	if (!inode->ops) {
+		release(&inode->lock);
+		return NULL;
+	}
+	if (!inode->ops->lookup) {
+		release(&inode->lock);
+		return NULL;
+	}
+	Inode *child = inode->ops->lookup(inode, name);
+
+	/* The file doesn't exist */
+	if (!child) {
+		if (de)
+			entry_remove(inode, name);
+		release(&inode->lock);
+		return NULL;
+	}
+
+	/* Fill in DirEntry */
+	if (!de) {
+		de = kmalloc(sizeof(DirEntry));
+		strncpy(de->name, name, NAME_MAX);
+		de->super = inode->super;
+		entry_add(inode, de);
+	}
+	de->inode = inode_get(child);
+	de->mnt = NULL;
+	release(&inode->lock);
+
+	return entry_get(de);
+}
+
+/* Make a directory */
+int
+inode_mkdir(Inode *inode, DirEntry *entry, mode_t mode)
+{
+	if (!inode->ops)
+		return -EINVAL;
+	if (!inode->ops->mkdir)
+		return -EINVAL;
+	acquire(&inode->lock);
+	int err = inode->ops->mkdir(inode, entry, mode);
+	if (!err) {
+		entry_add(inode, entry);
+		entry->inode = super_alloc_inode(inode->super);
+		entry->inode->mode = mode | S_IFDIR;
+	}
+	release(&inode->lock);
+	return err;
+}
+
+/* Remove a directory */
+int
+inode_rmdir(Inode *inode, DirEntry *entry)
+{
+	if (!inode->ops)
+		return -EINVAL;
+	if (!inode->ops->rmdir)
+		return -EINVAL;
+	acquire(&inode->lock);
+	int err = inode->ops->rmdir(inode, entry);
+	if (!err)
+		entry_remove(inode, entry->name);
+	release(&inode->lock);
+	return err;
+}
+
+/* Make a node */
+int
+inode_mknod(Inode *inode, DirEntry *entry, mode_t mode, dev_t dev)
+{
+	if (!inode->ops)
+		return -EINVAL;
+	if (!inode->ops->mknod)
+		return -EINVAL;
+	acquire(&inode->lock);
+
+	int err = inode->ops->mknod(inode, entry, mode, dev);
+	if (!err) {
+		entry_add(inode, entry);
+		entry->inode = super_alloc_inode(inode->super);
+		entry->inode->mode = mode; /* FIXME */
+		entry->inode->dev = dev;
+	}
+	release(&inode->lock);
+	return err;
+}
+
+/* Rename/mode a directory entry */
+int
+inode_rename(Inode *si, DirEntry *sde, Inode *di, DirEntry *dde)
+{
+	if (!si->ops)
+		return -EINVAL;
+	if (!si->ops->rename)
+		return -EINVAL;
+	return 0;
+}