EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+ if (ext2fs_has_feature_journal_dev(fs->super))
+ return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP;
+
+ if (fs->blocksize < 1024)
+ return EXT2_FILSYS_CORRUPTED; /* Should never happen */
+
/*
* If fs->badblocks isn't set, then set it --- since the inode
* scanning functions require it.
*/
if (fs->badblocks == 0) {
/*
- * Temporarly save fs->get_blocks and set it to zero,
+ * Temporarily save fs->get_blocks and set it to zero,
* for compatibility with old e2fsck's.
*/
save_get_blocks = fs->get_blocks;
EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS;
scan->current_block = ext2fs_inode_table_loc(scan->fs,
scan->current_group);
+ if (scan->current_block &&
+ ((scan->current_block < fs->super->s_first_data_block) ||
+ (scan->current_block + fs->inode_blocks_per_group - 1 >=
+ ext2fs_blocks_count(fs->super)))) {
+ ext2fs_free_mem(&scan);
+ return EXT2_ET_GDESC_BAD_INODE_TABLE;
+ }
+
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
scan->blocks_left = scan->fs->inode_blocks_per_group;
if (ext2fs_has_group_desc_csum(fs)) {
(fs->blocksize / scan->inode_size - 1)) *
scan->inode_size / fs->blocksize;
}
-
+ if (scan->current_block &&
+ ((scan->current_block < fs->super->s_first_data_block) ||
+ (scan->current_block + fs->inode_blocks_per_group - 1 >=
+ ext2fs_blocks_count(fs->super))))
+ return EXT2_ET_GDESC_BAD_INODE_TABLE;
return 0;
}
{
scan->current_group = group - 1;
scan->groups_left = scan->fs->group_desc_count - group;
+ scan->bad_block_ptr = 0;
return get_next_blockgroup(scan);
}
if (blk == 0)
return 0;
+ /* Make sure bad_block_ptr is still valid */
+ if (scan->bad_block_ptr >= bb->num) {
+ scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+ return 0;
+ }
+
/*
* If the current block is greater than the bad block listed
* in the bad block list, then advance the pointer until this
/*
* Functions to read and write a single inode.
*/
-errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode, int bufsize)
+errcode_t ext2fs_read_inode2(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode, int bufsize,
+ int flags)
{
blk64_t block_nr;
- unsigned long group, block, offset;
+ dgrp_t group;
+ unsigned long block, offset;
char *ptr;
errcode_t retval;
unsigned i;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+ if (ext2fs_has_feature_journal_dev(fs->super))
+ return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP;
+
+ if (fs->blocksize < 1024)
+ return EXT2_FILSYS_CORRUPTED; /* Should never happen */
+
/* Check to see if user has an override function */
if (fs->read_inode &&
((bufsize == sizeof(struct ext2_inode)) ||
}
if (fs->flags & EXT2_FLAG_IMAGE_FILE) {
inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super);
- block_nr = fs->image_header->offset_inode / fs->blocksize;
+ block_nr = ext2fs_le32_to_cpu(fs->image_header->offset_inode) / fs->blocksize;
block_nr += (ino - 1) / inodes_per_block;
offset = ((ino - 1) % inodes_per_block) *
EXT2_INODE_SIZE(fs->super);
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!ext2fs_inode_table_loc(fs, (unsigned) group))
+ block_nr = ext2fs_inode_table_loc(fs, group);
+ if (!block_nr)
return EXT2_ET_MISSING_INODE_TABLE;
- block_nr = ext2fs_inode_table_loc(fs, group) +
- block;
+ if ((block_nr < fs->super->s_first_data_block) ||
+ (block_nr + fs->inode_blocks_per_group - 1 >=
+ ext2fs_blocks_count(fs->super)))
+ return EXT2_ET_GDESC_BAD_INODE_TABLE;
+ block_nr += block;
io = fs->io;
}
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
}
memcpy(inode, iptr, (bufsize > length) ? length : bufsize);
- if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && fail_csum)
+ if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
+ !(flags & READ_INODE_NOCSUM) && fail_csum)
return EXT2_ET_INODE_CSUM_INVALID;
return 0;
}
+errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode, int bufsize)
+{
+ return ext2fs_read_inode2(fs, ino, inode, bufsize, 0);
+}
+
errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode * inode)
{
- return ext2fs_read_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
+ return ext2fs_read_inode2(fs, ino, inode,
+ sizeof(struct ext2_inode), 0);
}
-errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
- struct ext2_inode * inode, int bufsize)
+errcode_t ext2fs_write_inode2(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode, int bufsize,
+ int flags)
{
blk64_t block_nr;
- unsigned long group, block, offset;
+ dgrp_t group;
+ unsigned long block, offset;
errcode_t retval = 0;
struct ext2_inode_large *w_inode;
char *ptr;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+ if (ext2fs_has_feature_journal_dev(fs->super))
+ return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP;
+
/* Check to see if user provided an override function */
if (fs->write_inode) {
retval = (fs->write_inode)(fs, ino, inode);
return retval;
if (bufsize < length) {
- int old_flags = fs->flags;
- fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
- retval = ext2fs_read_inode_full(fs, ino,
- (struct ext2_inode *)w_inode,
- length);
- fs->flags = (old_flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) |
- (fs->flags & ~EXT2_FLAG_IGNORE_CSUM_ERRORS);
+ retval = ext2fs_read_inode2(fs, ino,
+ (struct ext2_inode *)w_inode,
+ length, READ_INODE_NOCSUM);
if (retval)
goto errout;
}
ext2fs_swap_inode_full(fs, w_inode, w_inode, 1, length);
#endif
- retval = ext2fs_inode_csum_set(fs, ino, w_inode);
- if (retval)
- goto errout;
+ if ((flags & WRITE_INODE_NOCSUM) == 0) {
+ retval = ext2fs_inode_csum_set(fs, ino, w_inode);
+ if (retval)
+ goto errout;
+ }
group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super);
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
- if (!ext2fs_inode_table_loc(fs, (unsigned) group)) {
+ block_nr = ext2fs_inode_table_loc(fs, (unsigned) group);
+ if (!block_nr) {
retval = EXT2_ET_MISSING_INODE_TABLE;
goto errout;
}
- block_nr = ext2fs_inode_table_loc(fs, (unsigned) group) + block;
+ if ((block_nr < fs->super->s_first_data_block) ||
+ (block_nr + fs->inode_blocks_per_group - 1 >=
+ ext2fs_blocks_count(fs->super))) {
+ retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
+ goto errout;
+ }
+ block_nr += block;
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
return retval;
}
+errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
+ struct ext2_inode * inode, int bufsize)
+{
+ return ext2fs_write_inode2(fs, ino, inode, bufsize, 0);
+}
+
errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode)
{
- return ext2fs_write_inode_full(fs, ino, inode,
- sizeof(struct ext2_inode));
+ return ext2fs_write_inode2(fs, ino, inode,
+ sizeof(struct ext2_inode), 0);
}
/*