static EXT2Err _LoadBlockNumbersFromInode()

in lsvmutils/ext2.c [937:1074]


static EXT2Err _LoadBlockNumbersFromInode(
    const EXT2* ext2,
    const EXT2Inode* inode,
    BOOLEAN include_block_blocks,
    BufU32 *buf)
{
    EXT2_DECLARE_ERR(err);

    /* Check parameters */
    if (!EXT2Valid(ext2) || !inode || !buf)
    {
        err = EXT2_ERR_INVALID_PARAMETER;
        GOTO(done);
    }

    /* Handle the direct blocks */
    if (EXT2_IFERR(err = _AppendDirectBlockNumbers(
        inode->i_block,
        EXT2_SINGLE_INDIRECT_BLOCK,
        buf)))
    {
        GOTO(done);
    }

    /* Handle single-indirect blocks */
    if (inode->i_block[EXT2_SINGLE_INDIRECT_BLOCK])
    {
        EXT2Block block;
        UINT32 block_no = inode->i_block[EXT2_SINGLE_INDIRECT_BLOCK];

        /* Read the next block */
        if (EXT2_IFERR(err = EXT2ReadBlock(ext2, block_no, &block)))
        {
            GOTO(done);
        }

        if (include_block_blocks)
        {
            if (EXT2_IFERR(err = BufU32Append(buf, &block_no, 1)))
            {
                GOTO(done);
            }
        }

        /* Append the block numbers from this block */
        if (EXT2_IFERR(err = _AppendDirectBlockNumbers(
            (const UINT32*)block.data,
            block.size / sizeof(UINT32),
            buf)))
        {
            GOTO(done);
        }
    }

    /* Handle double-indirect blocks */
    if (inode->i_block[EXT2_DOUBLE_INDIRECT_BLOCK])
    {
        EXT2Block block;
        UINT32 block_no = inode->i_block[EXT2_DOUBLE_INDIRECT_BLOCK];

        /* Read the next block */
        if (EXT2_IFERR(err = EXT2ReadBlock(ext2, block_no, &block)))
        {
            GOTO(done);
        }

        if (include_block_blocks)
        {
            if (EXT2_IFERR(err = BufU32Append(buf, &block_no, 1)))
                GOTO(done);
        }

        if (EXT2_IFERR(err = _AppendIndirectBlockNumbers(
            ext2, 
            (const UINT32*)block.data,
            block.size / sizeof(UINT32),
            include_block_blocks,
            buf)))
        {
            GOTO(done);
        }
    }

    /* Handle triple-indirect blocks */
    if (inode->i_block[EXT2_TRIPLE_INDIRECT_BLOCK])
    {
        EXT2Block block;
        UINT32 block_no = inode->i_block[EXT2_TRIPLE_INDIRECT_BLOCK];

        /* Read the next block */
        if (EXT2_IFERR(err = EXT2ReadBlock(ext2, block_no, &block)))
        {
            GOTO(done);
        }

        if (include_block_blocks)
        {
            if (EXT2_IFERR(err = BufU32Append(buf, &block_no, 1)))
                GOTO(done);
        }

        if (EXT2_IFERR(err = _AppendDoubleIndirectBlockNumbers(
            ext2, 
            (const UINT32*)block.data,
            block.size / sizeof(UINT32),
            include_block_blocks,
            buf)))
        {
            GOTO(done);
        }
    }

/* This is broken */
#if 0
    /* Check size expectations */
    if (!include_block_blocks)
    {
        UINT32 expected_size;

        expected_size = inode->i_size / ext2->block_size;

        if (inode->i_size % ext2->block_size)
            expected_size++;

        if (buf->size != expected_size)
        {
            err = EXT2_ERR_SANITY_CHECK_FAILED;
            GOTO(done);
        }
    }
#endif

    err = EXT2_ERR_NONE;

done:

    return err;
}