This is a repeat of code, but it is basically the ext2_get_inode function from the fs/ext2/inode.c file. I inserted another function and got rid of the goto's.
To call the function you will need a pointer to the VFS super block, an inode number, an empty pointer to a buffer_head struct. Basically the can be achieved like this:
struct ext2_inode *e; struct buffer_head *bh; ts = get_current(); e = ino_to_ext2inode(ts->fs->root->d_sb, inode_number, &bh);
Here is the code ino_to_ext2inode:
#include < linux/fs.h > #include < linux/ext2_fs.h > #include < linux/buffer_head.h >static struct ext2_inode *ino_to_ext2inode( struct super_block *sb, ino_t ino, struct buffer_head **p) { struct buffer_head * bh; unsigned long block_group; unsigned long block; unsigned long offset; struct ext2_group_desc * gdp; unsigned long group_desc; struct ext2_group_desc * desc; struct ext2_sb_info *sbi = EXT2_SB(sb); *p = NULL; if ((ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb)) || ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count)) return NULL; block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb); if (block_group >= sbi->s_groups_count) return NULL; group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(sb); offset = block_group & (EXT2_DESC_PER_BLOCK(sb) - 1); if (!sbi->s_group_desc[group_desc]) return NULL; desc = (struct ext2_group_desc *) sbi->s_group_desc[group_desc]->b_data; bh = sbi->s_group_desc[group_desc]; gdp = (struct ext2_group_desc *) (desc + offset); if (!gdp) return NULL; offset = ((ino - 1) % EXT2_INODES_PER_GROUP(sb)) * EXT2_INODE_SIZE(sb); block = le32_to_cpu(gdp->bg_inode_table) + (offset >> EXT2_BLOCK_SIZE_BITS(sb)); if (!(bh = sb_bread(sb, block))) return NULL; // include linux/buffer_head.h *p = bh; offset &= (EXT2_BLOCK_SIZE(sb) - 1); return (struct ext2_inode *) (bh->b_data + offset); }
Now with a ext2 inode pointer we can find out what type of inode it is. But really we are only concerned with getting regular files. Additionally we should make sure that the file doesn't have a deletion time, because the functin above will retreive a pointer to an inode even if it was deleted. As a side note, ext2 does not delete the inode and its data, it just marks it as free.
if (S_ISREG(ext2inode->i_mode) && !ext2inode->i_dtime) printk(“Useable inode number!\n”);
If it passes this test we can do a simple check to see if it has enough slack space, in the case of this project we just need 1024 or more.
if (ts->fs->root->d_sb->s_blocksize – (ext2inode->i_size % ts->fs->root->d_sb->s_blocksize) > 1024) printk(“Enough slack space\n”);