#include #include #include #include "ext2fs.h" Inode *ext2fs_lookup(Inode *vnode, const char *name); InodeOps ext2fsInodeOps = { .lookup = ext2fs_lookup, }; /* Read an ext2fs inode */ void ext2fs_read_inode(SuperBlock *sb, uint32_t index, struct Ext2Inode *res) { struct Ext2Super *rsuper = sb->data; /* Find the Block Group Descriptor */ struct 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++; sb->back->pos = (rsuper->blockSize ? 1 : 2) * (1024 << rsuper->blockSize); sb->back->pos += sizeof(struct Ext2BlockGroupDesc) * group; file_read(sb->back, (char *) &bgd, sizeof(struct Ext2BlockGroupDesc)); /* Read Inode */ sb->back->pos = bgd.inodeTable * (1024 << rsuper->blockSize); sb->back->pos += rsuper->inodeSize * index; file_read(sb->back, (char *) res, sizeof(struct Ext2Inode)); } /* Read an ext2fs inode as a VFS Inode */ void ext2fs_read_vnode(SuperBlock *sb, uint32_t index, Inode *res) { struct Ext2Inode inode; ext2fs_read_inode(sb, index, &inode); res->ino = index; 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 = sb; } /* Lookup an ext2fs file */ Inode * ext2fs_lookup(Inode *vnode, const char *name) { char buf[PAGE_SIZE]; uint32_t block, blk = 0; struct Ext2DirEntry *de; struct Ext2Inode inode; ext2fs_read_inode(vnode->super, vnode->ino, &inode); for (blk = 0; blk < 0xFFFF; blk++) { block = ext2fs_get_data_addr(vnode->super, &inode, blk); if (!block) return NULL; ext2fs_read_block(vnode->super, block, buf); for (de = (struct Ext2DirEntry *) buf; strncmp(de->name, name, de->namelen) && de < (struct Ext2DirEntry *) (buf + PAGE_SIZE); de = (void *) de + de->size); if (de >= (struct Ext2DirEntry *) (buf + PAGE_SIZE)) 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) { res = new(&inodeType); ext2fs_read_vnode(vnode->super, de->ino, res); } return res; }