def index(ubifs, lnum, offset, inodes={}, bad_blocks=[]):
    """Walk the index gathering Inode, Dir Entry, and File nodes.

    Arguments:
    Obj:ubifs    -- UBIFS object.
    Int:lnum     -- Logical erase block number.
    Int:offset   -- Offset in logical erase block.
    Dict:inodes  -- Dict of ino/dent/file nodes keyed to inode number.

    Returns:
    Dict:inodes  -- Dict of ino/dent/file nodes keyed to inode number.
        'ino'    -- Inode node.
        'data'   -- List of data nodes if present.
        'dent'   -- List of directory entry nodes if present.
    """
    try:
        if len(bad_blocks):
            if lnum in bad_blocks:
                return

        ubifs.file.seek((ubifs.leb_size * lnum) + offset)
        buf = ubifs.file.read(UBIFS_COMMON_HDR_SZ)
        chdr = nodes.common_hdr(buf)
        log(index , '%s file addr: %s' % (chdr, ubifs.file.last_read_addr()))
        verbose_display(chdr)
        node_buf = ubifs.file.read(chdr.len - UBIFS_COMMON_HDR_SZ)
        file_offset = ubifs.file.last_read_addr()

    except Exception as e:
        if str(e) == 'Bad Read Offset Request' and settings.warn_only_block_read_errors:
            bad_blocks.append(lnum)
            return

        else:
            error(index, 'Fatal', 'LEB: %s, UBIFS offset: %s, error: %s' % (lnum, ((ubifs.leb_size * lnum) + offset), e))

    if chdr.node_type == UBIFS_IDX_NODE:
        try:
            idxn = nodes.idx_node(node_buf)

        except Exception as e:
            if settings.warn_only_block_read_errors:
                error(index, 'Error', 'Problem at file address: %s extracting idx_node: %s' % (file_offset, e))
                return

            else:
                error(index, 'Fatal', 'Problem at file address: %s extracting idx_node: %s' % (file_offset, e))

        log(index, '%s file addr: %s' % (idxn, file_offset))
        verbose_display(idxn)
        branch_idx = 0

        for branch in idxn.branches:
            verbose_log(index, '-------------------')
            log(index, '%s file addr: %s' % (branch, file_offset + UBIFS_IDX_NODE_SZ + (branch_idx * UBIFS_BRANCH_SZ)))
            verbose_display(branch)
            index(ubifs, branch.lnum, branch.offs, inodes, bad_blocks)
            branch_idx += 1

    elif chdr.node_type == UBIFS_INO_NODE:
        try:
            inon = nodes.ino_node(node_buf)

        except Exception as e:
            if settings.warn_only_block_read_errors:
                error(index, 'Error', 'Problem at file address: %s extracting ino_node: %s' % (file_offset, e))
                return

            else:
                error(index, 'Fatal', 'Problem at file address: %s extracting ino_node: %s' % (file_offset, e))

        ino_num = inon.key['ino_num']
        log(index, '%s file addr: %s, ino num: %s' % (inon, file_offset, ino_num))
        verbose_display(inon)

        if not ino_num in inodes:
            inodes[ino_num] = {}

        inodes[ino_num]['ino'] = inon

    elif chdr.node_type == UBIFS_DATA_NODE:
        try:
            datn = nodes.data_node(node_buf, (ubifs.leb_size * lnum) + UBIFS_COMMON_HDR_SZ + offset + UBIFS_DATA_NODE_SZ)

        except Exception as e:
            if settings.warn_only_block_read_errors:
                error(index, 'Error', 'Problem at file address: %s extracting data_node: %s' % (file_offset, e))
                return

            else:
                error(index, 'Fatal', 'Problem at file address: %s extracting data_node: %s' % (file_offset, e))

        ino_num = datn.key['ino_num']
        log(index, '%s file addr: %s, ino num: %s' % (datn, file_offset, ino_num))
        verbose_display(datn)

        if not ino_num in inodes:
            inodes[ino_num] = {}

        if not 'data' in inodes[ino_num]:
            inodes[ino_num]['data']= []

        inodes[ino_num]['data'].append(datn)

    elif chdr.node_type == UBIFS_DENT_NODE:
        try:
            dn = nodes.dent_node(node_buf)

        except Exception as e:
            if settings.warn_only_block_read_errors:
                error(index, 'Error', 'Problem at file address: %s extracting dent_node: %s' % (file_offset, e))
                return

            else:
                error(index, 'Fatal', 'Problem at file address: %s extracting dent_node: %s' % (file_offset, e))

        ino_num = dn.key['ino_num']
        log(index, '%s file addr: %s, ino num: %s' % (dn, file_offset, ino_num))
        verbose_display(dn)

        if not ino_num in inodes:
            inodes[ino_num] = {}

        if not 'dent' in inodes[ino_num]:
            inodes[ino_num]['dent']= []

        inodes[ino_num]['dent'].append(dn)
Walk the index gathering Inode, Dir Entry, and File nodes.

    Arguments:
    Obj:ubifs    -- UBIFS object.
    Int:lnum     -- Logical erase block number.
    Int:offset   -- Offset in logical erase block.
    Dict:inodes  -- Dict of ino/dent/file nodes keyed to inode number.

    Returns:
    Dict:inodes  -- Dict of ino/dent/file nodes keyed to inode number.
        'ino'    -- Inode node.
        'data'   -- List of data nodes if present.
        'dent'   -- List of directory entry nodes if present.