cl_error_t cli_egg_open(fmap_t* map, size_t sfx_offset, void** hArchive, char*** comments, uint32_t* nComments)
{
    cl_error_t status = CL_EPARSE;
    cl_error_t retval;
    egg_handle* handle   = NULL;
    uint32_t magic       = 0;
    const uint8_t* index = 0;

    if (!map || !hArchive) {
        cli_errmsg("cli_egg_open: Invalid args!\n");
        return CL_EARG;
    }

    handle = (egg_handle*)cli_calloc(1, sizeof(egg_handle));
    if (NULL == handle) {
        cli_errmsg("cli_egg_open: Failed to allocate memory for egg_handle.\n");
        status = CL_EMEM;
        goto done;
    }
    handle->map    = map;
    handle->offset = sfx_offset;

    /*
     * 1st:
     *   Parse the archive headers.
     */
    if (CL_SUCCESS != (retval = egg_parse_archive_headers(handle))) {
        cli_warnmsg("cli_egg_open: Failed to parse archive headers!\n");
        goto done;
    }

    /*
     * 2nd:
     *   Archive headers may be followed by:
     *      a) 0+ file headers
     *      b) 0+ block headers
     *      c) 0+ archive comment headers
     */
    while (CL_SUCCESS == retval) {

        /* Get the next magic32_t */
        index = (const uint8_t*)fmap_need_off_once(handle->map, handle->offset, sizeof(magic32_t));
        if (!index) {
            cli_dbgmsg("cli_egg_open: No more data in archive.\n");
            break;
        }

        magic = le32_to_host(*((uint32_t*)index));

        if (EOFARC == magic) {
            /*
             * Archive headers should conclude with EOFARC magic bytes.
             */
            handle->offset += sizeof(magic32_t);

            if (handle->map->len > handle->offset) {
                cli_warnmsg("Apparent end to EGG archive, but an addition %zu bytes of data exists in the file!\n",
                            handle->map->len - handle->offset);
            } else {
                cli_dbgmsg("cli_egg_open: Successfully indexed EGG archive!\n");
            }

            break; /* Break out of the loop */
        } else if (FILE_HEADER_MAGIC == magic) {
            /*
             * Archive File Header
             */
            egg_file* found_file = NULL;
            if (CL_SUCCESS != (retval = egg_parse_file_headers(handle, &found_file))) {
                cli_dbgmsg("cli_egg_open: Issue parsing file header. Error code: %u\n", retval);
                goto done;
            } else if (found_file == NULL) {
                cli_errmsg("cli_egg_open: Logic error! Succesfully parsed file headers,"
                           " but did not return egg_file information!\n");
                goto done;
            } else {
                /* Add file to list. */
                egg_file** files_tmp;

                files_tmp = (egg_file**)cli_realloc(
                    (void*)handle->files,
                    sizeof(egg_file*) * (handle->nFiles + 1));
                if (NULL == files_tmp) {
                    status = CL_EMEM;
                    goto done;
                }
                handle->files                 = files_tmp;
                handle->files[handle->nFiles] = found_file;
                handle->nFiles++;
            }
        } else if (BLOCK_HEADER_MAGIC == magic) {
            /*
             * Archive Block Header
             */
            egg_block* found_block = NULL;
            if (CL_SUCCESS != (retval = egg_parse_block_headers(handle, &found_block))) {
                cli_dbgmsg("cli_egg_open: Issue parsing block header. Error code: %u\n", retval);
                goto done;
            } else if (found_block == NULL) {
                cli_errmsg("cli_egg_open: Logic error! Succesfully parsed block headers,"
                           " but did not return egg_block information!\n");
                goto done;
            } else {
                /* Add block to list. */
                if (handle->bSolid) {
                    egg_block** blocks_tmp;

                    blocks_tmp = (egg_block**)cli_realloc(
                        (void*)handle->blocks,
                        sizeof(egg_block*) * (handle->nBlocks + 1));
                    if (NULL == blocks_tmp) {
                        status = CL_EMEM;
                        goto done;
                    }
                    handle->blocks                  = blocks_tmp;
                    handle->blocks[handle->nBlocks] = found_block;
                    handle->nBlocks++;
                } else {
                    egg_file* eggFile = NULL;
                    /*
                     * Associate block with most recently added file.
                     */
                    if (handle->nFiles == 0) {
                        cli_dbgmsg("cli_egg_open: No file found for block in non-solid archive.\n");
                        // TODO: create an unamed block.
                    } else {
                        egg_block** blocks_tmp;

                        eggFile = handle->files[handle->nFiles - 1];

                        /* Add block to list. */
                        blocks_tmp = (egg_block**)cli_realloc(
                            (void*)eggFile->blocks,
                            sizeof(egg_block*) * (eggFile->nBlocks + 1));
                        if (NULL == blocks_tmp) {
                            status = CL_EMEM;
                            goto done;
                        }
                        eggFile->blocks                   = blocks_tmp;
                        eggFile->blocks[eggFile->nBlocks] = found_block;
                        eggFile->nBlocks++;
                    }
                }
            }
        } else if (COMMENT_HEADER_MAGIC == magic) {
            /*
             * Parse extra field for archive comment header.
             */
            char** comments_tmp;
            extra_field* extraField = NULL;
            char* comment           = NULL;
            uint32_t size           = 0;

            index = (const uint8_t*)fmap_need_off_once(handle->map, handle->offset, sizeof(extra_field));
            if (!index) {
                cli_dbgmsg("cli_egg_open: File buffer too small to contain extra_field header.\n");
                goto done;
            }

            extraField = (extra_field*)index;

            cli_dbgmsg("cli_egg_open: archive comment extra_field->magic:    %08x (%s)\n", le32_to_host(extraField->magic), getMagicHeaderName(le32_to_host(extraField->magic)));
            cli_dbgmsg("cli_egg_open: archive comment extra_field->bit_flag: %02x\n", extraField->bit_flag);

            handle->offset += sizeof(extra_field);

            if (extraField->bit_flag & EXTRA_FIELD_FLAGS_SIZE_IS_4BYTES) {
                /* size is uint32_t */
                index = (const uint8_t*)fmap_need_off_once(handle->map, handle->offset, sizeof(uint32_t));
                if (!index) {
                    cli_dbgmsg("cli_egg_open: File buffer too small to contain archive comment extra_field header.\n");
                    goto done;
                }

                size = le32_to_host(*(uint32_t*)index);

                handle->offset += sizeof(uint32_t);
            } else {
                /* size is uint16_t */
                index = (const uint8_t*)fmap_need_off_once(handle->map, handle->offset, sizeof(uint16_t));
                if (!index) {
                    cli_dbgmsg("cli_egg_open: File buffer too small to contain archive comment extra_field header.\n");
                    goto done;
                }

                size = le16_to_host(*(uint16_t*)index);

                handle->offset += sizeof(uint16_t);
            }

            cli_dbgmsg("cli_egg_open: archive comment extra_field->size:     %u\n", size);

            index = (const uint8_t*)fmap_need_off_once(handle->map, handle->offset, size);
            if (!index) {
                cli_dbgmsg("cli_egg_open: File buffer too small to contain extra_field header.\n");
                goto done;
            }

            retval = egg_parse_comment_header(index, size, extraField, &comment);
            if (CL_SUCCESS != retval) {
                cli_dbgmsg("cli_egg_open: Failed to parse archive comment extra_field data.\n");
                goto done;
            }

            comments_tmp = (char**)cli_realloc(
                (void*)handle->comments,
                sizeof(char**) * (handle->nComments + 1));
            if (NULL == comments_tmp) {
                status = CL_EMEM;
                goto done;
            }
            handle->comments                    = comments_tmp;
            handle->comments[handle->nComments] = comment;
            handle->nComments++;
            handle->offset += size;
        } else {
            cli_dbgmsg("cli_egg_open: unexpected header magic:               %08x (%s)\n", magic, getMagicHeaderName(magic));
            status = CL_EPARSE;
            goto done;
        }
    }

    if (CL_SUCCESS != retval) {
        if (CL_BREAK == retval) {
            /* End of archive. */
            if ((handle->bSplit) && (handle->splitInfo->next_file_id != 0))
                cli_warnmsg("cli_egg_open: Abrupt end to EGG volume!\n");
            else
                cli_dbgmsg("cli_egg_open: End of EGG volume in split archive.\n");
        } else {
            /* Something went wrong. */
            cli_warnmsg("cli_egg_open: Failed to parse file headers!\n");
        }
    }

    *hArchive  = handle;
    *comments  = handle->comments;
    *nComments = handle->nComments;

    status = CL_SUCCESS;

done:
    if (CL_SUCCESS != status) {
        if (handle) {
            egg_free_egg_handle(handle);
        }
        *hArchive = NULL;
    }
    return status;
}