/* * 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 #include #include #include #include #include #include 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; }