-struct chunk_table {
- off_t file_offset;
- u64 num_chunks;
- u64 original_resource_size;
- u64 bytes_per_chunk_entry;
- u64 table_disk_size;
- u64 cur_offset;
- u64 *cur_offset_p;
- u64 offsets[0];
-};
-
-static int
-begin_wim_resource_chunk_tab(const struct lookup_table_entry *lte,
- FILE *out_fp,
- off_t file_offset,
- struct chunk_table **chunk_tab_ret)
-{
- u64 size = wim_resource_size(lte);
- u64 num_chunks = (size + WIM_CHUNK_SIZE - 1) / WIM_CHUNK_SIZE;
- struct chunk_table *chunk_tab = MALLOC(sizeof(struct chunk_table) +
- num_chunks * sizeof(u64));
- int ret = 0;
-
- if (!chunk_tab) {
- ERROR("Failed to allocate chunk table for %"PRIu64" byte "
- "resource", size);
- ret = WIMLIB_ERR_NOMEM;
- goto out;
- }
- chunk_tab->file_offset = file_offset;
- chunk_tab->num_chunks = num_chunks;
- chunk_tab->cur_offset_p = chunk_tab->offsets;
- chunk_tab->original_resource_size = lte->resource_entry.original_size;
- chunk_tab->bytes_per_chunk_entry =
- (lte->resource_entry.original_size >= (1ULL << 32))
- ? 8 : 4;
- chunk_tab->table_disk_size = chunk_tab->bytes_per_chunk_entry *
- (num_chunks - 1);
-
- if (fwrite(chunk_tab, 1, chunk_tab->table_disk_size, out_fp) !=
- chunk_tab->table_disk_size)
- {
- ERROR_WITH_ERRNO("Failed to write chunk table in compressed "
- "file resource");
- ret = WIMLIB_ERR_WRITE;
- goto out;
- }
-
- *chunk_tab_ret = chunk_tab;
-out:
- return ret;
-}
-
-static int compress_chunk(const u8 chunk[], unsigned chunk_sz,
- u8 compressed_chunk[],
- unsigned *compressed_chunk_len_ret,
- int ctype)
-{
- unsigned compressed_chunk_sz;
- int (*compress)(const void *, unsigned, void *, unsigned *);
- if (ctype == WIM_COMPRESSION_TYPE_LZX)
- compress = lzx_compress;
- else
- compress = xpress_compress;
- return (*compress)(chunk, chunk_sz, compressed_chunk,
- compressed_chunk_len_ret);
-}
-
-static int write_wim_resource_chunk(const u8 chunk[], unsigned chunk_size,
- FILE *out_fp, int out_ctype,
- struct chunk_table *chunk_tab)
-{
- const u8 *out_chunk;
- unsigned out_chunk_size;
-
- if (out_ctype == WIM_COMPRESSION_TYPE_NONE) {
- out_chunk = chunk;
- out_chunk_size = chunk_size;
- } else {
- u8 *compressed_chunk = alloca(chunk_size);
- int ret;
- unsigned compressed_chunk_len;
-
- wimlib_assert(chunk_tab != NULL);
-
- ret = compress_chunk(chunk, chunk_size, compressed_chunk,
- &out_chunk_size, out_ctype);
- if (ret > 0)
- return ret;
- else if (ret < 0) {
- out_chunk = chunk;
- out_chunk_size = chunk_size;
- } else {
- out_chunk = compressed_chunk;
- }
- *chunk_tab->cur_offset_p++ = chunk_tab->cur_offset;
- chunk_tab->cur_offset += out_chunk_size;
- }
-
- if (fwrite(out_chunk, 1, out_chunk_size, out_fp) != out_chunk_size) {
- ERROR_WITH_ERRNO("Failed to write WIM resource chunk");
- return WIMLIB_ERR_WRITE;
- }
- return 0;
-}
-
-static int
-finish_wim_resource_chunk_tab(struct chunk_table *chunk_tab,
- FILE *out_fp, u64 *compressed_size_p)