int cli_chm_open(int fd, const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx) { struct stat statbuf; int retval; cli_dbgmsg("in cli_chm_open\n"); if ((retval = chm_init_metadata(metadata)) != CL_SUCCESS) { return retval; } if (fstat(fd, &statbuf) == 0) { if (statbuf.st_size < CHM_ITSF_MIN_LEN) { return CL_ESTAT; } metadata->m_length = statbuf.st_size; metadata->map = fmap(fd, 0, metadata->m_length); if (!metadata->map) { return CL_EMAP; } } else { char err[128]; cli_warnmsg("fstat() failed: %s\n", cli_strerror(errno, err, sizeof(err))); return CL_ESTAT; } if (!itsf_read_header(metadata)) { goto abort; } itsf_print_header(&metadata->itsf_hdr); if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) { goto abort; } itsp_print_header(&metadata->itsp_hdr); metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN; /* TODO: need to check this first calculation, currently have no files of this type */ if (metadata->itsp_hdr.index_head > 0) { metadata->chunk_offset += metadata->itsp_hdr.index_head * metadata->itsp_hdr.block_len; } metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1; /* Versions before 3 didn't have a data_offset */ /* TODO: need to check this calculation, currently have no files of this type */ if (metadata->itsf_hdr.version < 3) { metadata->itsf_hdr.data_offset = metadata->itsf_hdr.dir_offset + CHM_ITSP_LEN + (metadata->itsp_hdr.block_len*metadata->itsp_hdr.num_blocks); } while (metadata->num_chunks) { if (read_chunk(metadata) != CL_SUCCESS) { cli_dbgmsg("read_chunk failed\n"); goto abort; } if (read_control_entries(metadata) == FALSE) { goto abort; } metadata->num_chunks--; metadata->chunk_offset += metadata->itsp_hdr.block_len; } if (!metadata->sys_content.length || !metadata->sys_control.length || !metadata->sys_reset.length) { cli_dbgmsg("sys file missing\n"); goto abort; } metadata->ufd = chm_decompress_stream(fd, metadata, dirname, ctx); if (metadata->ufd == -1) { goto abort; } metadata->chunk_entries = 0; metadata->chunk_data = NULL; metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN; metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1; return CL_SUCCESS; abort: funmap(metadata->map); return CL_EFORMAT; }
int cli_chm_open(const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx) { STATBUF statbuf; int retval; cli_dbgmsg("in cli_chm_open\n"); if ((retval = chm_init_metadata(metadata)) != CL_SUCCESS) { return retval; } metadata->map = *ctx->fmap; if(metadata->map->len < CHM_ITSF_MIN_LEN) return CL_ESTAT; metadata->m_length = metadata->map->len; if (!itsf_read_header(metadata)) { goto abort; } itsf_print_header(&metadata->itsf_hdr); if (!itsp_read_header(metadata, metadata->itsf_hdr.dir_offset)) { goto abort; } itsp_print_header(&metadata->itsp_hdr); metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN; /* TODO: need to check this first calculation, currently have no files of this type */ if (metadata->itsp_hdr.index_head > 0) { metadata->chunk_offset += metadata->itsp_hdr.index_head * metadata->itsp_hdr.block_len; } metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1; /* Versions before 3 didn't have a data_offset */ /* TODO: need to check this calculation, currently have no files of this type */ if (metadata->itsf_hdr.version < 3) { metadata->itsf_hdr.data_offset = metadata->itsf_hdr.dir_offset + CHM_ITSP_LEN + (metadata->itsp_hdr.block_len*metadata->itsp_hdr.num_blocks); } while (metadata->num_chunks) { if (read_chunk(metadata) != CL_SUCCESS) { cli_dbgmsg("read_chunk failed\n"); goto abort; } if (read_control_entries(metadata) == FALSE) { goto abort; } metadata->num_chunks--; metadata->chunk_offset += metadata->itsp_hdr.block_len; } if (!metadata->sys_content.length || !metadata->sys_control.length || !metadata->sys_reset.length) { cli_dbgmsg("sys file missing\n"); goto abort; } metadata->ufd = chm_decompress_stream(metadata, dirname, ctx); if (metadata->ufd == -1) { goto abort; } metadata->chunk_entries = 0; metadata->chunk_data = NULL; metadata->chunk_offset = metadata->itsf_hdr.dir_offset+CHM_ITSP_LEN; metadata->num_chunks = metadata->itsp_hdr.index_tail - metadata->itsp_hdr.index_head + 1; return CL_SUCCESS; abort: return CL_EFORMAT; }