- int ret;
- int (*compress)(const void *, uint, void *, uint *);
- if (output_ctype == WIM_COMPRESSION_TYPE_LZX)
- compress = lzx_compress;
- else
- compress = xpress_compress;
-
- u8 uncompressed_buf[WIM_CHUNK_SIZE];
- u8 compressed_buf[WIM_CHUNK_SIZE - 1];
-
- /* Determine how many compressed chunks the file needs to be divided
- * into. */
- u64 num_chunks = (original_size + WIM_CHUNK_SIZE - 1) / WIM_CHUNK_SIZE;
-
- u64 num_chunk_entries = num_chunks - 1;
-
- /* Size of the chunk entries--- 8 bytes for files over 4GB, otherwise 4
- * bytes */
- uint chunk_entry_size = (original_size >= (u64)1 << 32) ? 8 : 4;
-
- /* Array in which to construct the chunk offset table. */
- u64 chunk_offsets[num_chunk_entries];
-
- /* Offset of the start of the chunk table in the output file. */
- off_t chunk_tab_offset = ftello(out);
-
- /* Total size of the chunk table (as written to the file) */
- u64 chunk_tab_size = chunk_entry_size * num_chunk_entries;
-
- /* Reserve space for the chunk table. */
- if (fwrite(chunk_offsets, 1, chunk_tab_size, out) != chunk_tab_size) {
- ERROR("Failed to write chunk offset table: %m\n");
- return WIMLIB_ERR_WRITE;
- }
-
- /* Read each chunk of the file, compress it, write it to the output
- * file, and update th chunk offset table. */
- u64 cur_chunk_offset = 0;
- for (u64 i = 0; i < num_chunks; i++) {
-
- u64 uncompressed_offset = i * WIM_CHUNK_SIZE;
- u64 uncompressed_chunk_size = min(WIM_CHUNK_SIZE,
- original_size - uncompressed_offset);
-
- const u8 *uncompressed_p;
- if (uncompressed_resource != NULL) {
- uncompressed_p = uncompressed_resource +
- uncompressed_offset;
-
- } else {
- /* Read chunk i of the file into uncompressed_buf. */
- ret = read_resource(in, size, original_size, offset, input_ctype,
- uncompressed_chunk_size,
- uncompressed_offset,
- uncompressed_buf);
- if (ret != 0)
- return ret;
- uncompressed_p = uncompressed_buf;
- }
-
- if (i != 0)
- chunk_offsets[i - 1] = cur_chunk_offset;
-
- uint compressed_len;
-
- ret = compress(uncompressed_p, uncompressed_chunk_size,
- compressed_buf, &compressed_len);
-
- /* if compress() returned nonzero, the compressed chunk would
- * have been at least as large as the uncompressed chunk. In
- * this situation, the WIM format requires that the uncompressed
- * chunk be written instead. */
- const u8 *buf_to_write;
- uint len_to_write;
- if (ret == 0) {
- buf_to_write = compressed_buf;
- len_to_write = compressed_len;
- } else {
- buf_to_write = uncompressed_p;
- len_to_write = uncompressed_chunk_size;
- }
-
- if (fwrite(buf_to_write, 1, len_to_write, out) != len_to_write) {
- ERROR("Failed to write compressed file resource: %m\n");
- return WIMLIB_ERR_WRITE;
- }
- cur_chunk_offset += len_to_write;
- }