Orion
Barry Importing existing Orion kernel d41a53c (3 years, 2 months ago)
/*
* 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;
}