Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)diff --git a/vfs/ext2fs/inode.c b/vfs/ext2fs/inode.c new file mode 100644 index 0000000..3437220 --- /dev/null +++ b/vfs/ext2fs/inode.c @@ -0,0 +1,94 @@ +/* + * This file contains the Ext2 inode implementation. It contains the functions + * for the inode operations, as well as several internal operations relating to + * inodes required for the full Ext2 implementation. + */ + +#include <stdint.h> +#include <string.h> +#include <fcntl.h> +#include "fs.h" +#include "../vfs.h" +#include "../super.h" +#include "../../mem/heap.h" + +Inode *ext2fs_lookup(Inode *inode, const char *name); + +InodeOps ext2fsInodeOps = { + .lookup = ext2fs_lookup, +}; + +/* Read an Ext2 inode as a VFS inode */ +void +ext2_read_vnode(SuperBlock *super, uint32_t index, Inode *res) +{ + Ext2Inode inode; + ext2_read_inode(super, index, &inode); + + res->ino = index; + res->usage = 0; + res->uid = inode.uid; + res->gid = inode.gid; + res->mode = inode.type; + res->nlink = inode.numHardLinks; + res->size = inode.lsize; + res->ops = &ext2fsInodeOps; + res->fileOps = &ext2fsFileOps; + res->super = super; +} + +/* Read an Ext2 inode */ +void +ext2_read_inode(SuperBlock *super, uint32_t index, Ext2Inode *res) +{ + Ext2Super *rsuper = super->data; + + /* Find the Block Group Descriptor */ + Ext2BlockGroupDesc bgd; + uint32_t groups = rsuper->numBlocks / rsuper->blocksPerGroup; + uint32_t group = (index - 1) / rsuper->inodesPerGroup; + index = (index - 1) % rsuper->inodesPerGroup; + if (rsuper->numBlocks % rsuper->blocksPerGroup) + groups++; + super->back->pos = (rsuper->blockSize ? 1 : 2) + * (1024 << rsuper->blockSize); + super->back->pos += sizeof(Ext2BlockGroupDesc) * group; + file_read(super->back, (char *) &bgd, sizeof(Ext2BlockGroupDesc)); + /* Read Inode */ + super->back->pos = bgd.inodeTable * (1024 << rsuper->blockSize); + super->back->pos += rsuper->inodeSize * index; + file_read(super->back, (char *) res, sizeof(Ext2Inode)); +} + +/* Look up a file */ +Inode * +ext2fs_lookup(Inode *vnode, const char *name) +{ + char buf[4096]; + uint32_t block, blk = 0; + Ext2DirEntry *de; + Ext2Inode inode; + ext2_read_inode(vnode->super, vnode->ino, &inode); + for (blk = 0; blk < 0xFFFF; blk++) { + block = ext2_get_data_addr(vnode->super, &inode, blk); + if (!block) + return NULL; + ext2_read_block(vnode->super, block, buf); + for (de = (Ext2DirEntry *) buf; + strncmp(de->name, name, de->nameLen) + && de < (Ext2DirEntry *) (buf + 4096); + de = (void *) ((char *) de + de->size)); + if (de >= (Ext2DirEntry *) (buf + 4096)) + return NULL; + if (!strncmp(de->name, name, de->nameLen)) + break; + } + if (!de->ino) + return NULL; + Inode *res = super_find_inode(vnode->super, de->ino); + if (res) + return res; + res = kmalloc(sizeof(Inode)); + ext2_read_vnode(vnode->super, de->ino, res); + return res; +}