Orion
Barry Importing existing Orion kernel d41a53c (3 years, 2 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;
+}