Orion
Barry Adding pipes e59e4fe (2 years, 4 months 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; }