Nucleus
Barry System headers (remove libc dependency) 18495cf (3 years, 2 months ago)
#include <stdint.h>
#include <nucleus/lib.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;
}