Nucleus
Barry FS Object wrapper functions 77a8df8 (3 years, 3 months ago)
diff --git a/vfs/inode.c b/vfs/inode.c
index 6f49c67..c64542d 100644
--- a/vfs/inode.c
+++ b/vfs/inode.c
@@ -7,8 +7,12 @@
* operation can be called on the particular inode.
*/
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
#include <nucleus/object.h>
#include <nucleus/memory.h>
+#include <nucleus/task.h>
#include <nucleus/vfs.h>
static void inode_new(Object *);
@@ -16,6 +20,7 @@ static void inode_delete(Object *);
/* Inode object type */
ObjectType inodeType = {
+ .name = "INODE",
.size = sizeof(Inode),
.new = inode_new,
.delete = inode_delete,
@@ -26,6 +31,7 @@ static void
inode_new(Object *obj)
{
Inode *inode = (void *) obj;
+ inode->dirEntries = create_list(&dirEntryType);
inode->pages = create_list(&pageType);
}
@@ -36,9 +42,90 @@ inode_delete(Object *obj)
Inode *inode = (void *) obj;
/* Remove inode from the SuperBlock's list */
-// if (inode->super)
+ if (inode->super) {
// super_remove_inode(inode->super, inode);
+ put(inode->super);
+ }
/* Clean cache */
destroy_list(inode->pages);
}
+
+/* Check if a process has permission to access an inode */
+int
+permission(Inode *inode, int mask)
+{
+ if (!inode)
+ return 0;
+
+ int mode = inode->mode;
+ if (current->euid == inode->uid)
+ mode >>= 6;
+ else if (current->egid == inode->gid)
+ mode >>= 3;
+
+ if (((mode & mask & 0007) == mask) || super_user())
+ return 1;
+ return 0;
+}
+
+/* Create an inode wrapper */
+int
+inode_create(Inode *inode, DirEntry *entry, mode_t mode)
+{
+ if (!inode->ops || !inode->ops->create)
+ return -EINVAL;
+ lock(inode);
+ int err = inode->ops->create(inode, entry, mode);
+ if (!err) {
+ add(inode->dirEntries, entry);
+ entry->inode = super_alloc_inode(inode->super);
+ entry->inode->mode = mode | S_IFREG;
+ }
+ unlock(inode);
+ return err;
+}
+
+/* Find a named entry in a directory inode */
+DirEntry *
+inode_lookup(Inode *inode, const char *name)
+{
+ if (!S_ISDIR(inode->mode))
+ return NULL;
+ lock(inode);
+
+ /* Check cache first */
+ DirEntry *entry = find_direntry(inode->dirEntries, name);
+ if (entry) {
+ get(entry);
+ if (entry->inode)
+ goto end;
+ }
+ /* Try file system lookup */
+ if (!inode->ops || !inode->ops->lookup) {
+ entry = NULL;
+ goto end;
+ }
+ Inode *child = inode->ops->lookup(inode, name);
+
+ /* The file doesn't exist */
+ if (!child) {
+ if (entry)
+ remove(inode->dirEntries, entry);
+ entry = NULL;
+ goto end;
+ }
+
+ /* Fill in DirEntry */
+ if (!entry) {
+ entry = new(&dirEntryType);
+ strncpy(entry->name, name, NAME_MAX);
+ entry->super = inode->super;
+ add(inode->dirEntries, entry);
+ }
+ entry->inode = get(child);
+
+end:
+ unlock(inode);
+ return entry;
+}