sizeof (struct grub_ext2_block_group), blkgrp);
}
-static struct grub_ext4_extent_header *
+static grub_err_t
grub_ext4_find_leaf (struct grub_ext2_data *data,
struct grub_ext4_extent_header *ext_block,
- grub_uint32_t fileblock)
+ grub_uint32_t fileblock,
+ struct grub_ext4_extent_header **leaf)
{
struct grub_ext4_extent_idx *index;
void *buf = NULL;
+ *leaf = NULL;
while (1)
{
goto fail;
if (ext_block->depth == 0)
- return ext_block;
+ {
+ *leaf = ext_block;
+ return GRUB_ERR_NONE;
+ }
for (i = 0; i < grub_le_to_cpu16 (ext_block->entries); i++)
{
}
if (--i < 0)
- goto fail;
+ {
+ grub_free (buf);
+ return GRUB_ERR_NONE;
+ }
block = grub_le_to_cpu16 (index[i].leaf_hi);
block = (block << 32) | grub_le_to_cpu32 (index[i].leaf);
}
fail:
grub_free (buf);
- return 0;
+ return GRUB_ERR_BAD_FS;
}
static grub_disk_addr_t
int i;
grub_disk_addr_t ret;
- leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock);
- if (! leaf)
+ if (grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
+ fileblock, &leaf) != GRUB_ERR_NONE)
{
grub_error (GRUB_ERR_BAD_FS, "invalid extent");
return -1;
}
+ if (leaf == NULL)
+ /* Leaf for the given block is absent (i.e. sparse) */
+ return 0;
+
ext = (struct grub_ext4_extent *) (leaf + 1);
for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
{