Orion
Barry Adding pipes e59e4fe (3 years, 1 month ago)
/*
* 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 (inode->free_extra)
inode->free_extra(inode);
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;
}