Nucleus
Barry Read-only Ext2 file system driver 648c56b (3 years, 2 months ago)
diff --git a/vfs/ext2fs/inode.c b/vfs/ext2fs/inode.c
new file mode 100644
index 0000000..2208ab6
--- /dev/null
+++ b/vfs/ext2fs/inode.c
@@ -0,0 +1,85 @@
+#include <stdint.h>
+#include <string.h>
+#include <nucleus/vfs.h>
+#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;
+}