Nucleus
Barry FS Object wrapper functions 77a8df8 (3 years, 3 months ago)
/*
* This file implements the Inode object and associated inode operations. Most
* of the functions here are just wrappers for the file system specific inode
* operations. They generally check if the operation exists and use it if it
* does. If one does not exist, a function 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 <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 *);
static void inode_delete(Object *);
/* Inode object type */
ObjectType inodeType = {
.name = "INODE",
.size = sizeof(Inode),
.new = inode_new,
.delete = inode_delete,
};
/* Create a new Inode */
static void
inode_new(Object *obj)
{
Inode *inode = (void *) obj;
inode->dirEntries = create_list(&dirEntryType);
inode->pages = create_list(&pageType);
}
/* Destroy an Inode */
static void
inode_delete(Object *obj)
{
Inode *inode = (void *) obj;
/* Remove inode from the SuperBlock's list */
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;
}