- /* To reduce memory usage and improve speed, read and write BUFFER_SIZE
- * bytes at a time. */
- while (len != 0) {
- n = min(len, BUFFER_SIZE);
- if (fread(buf, 1, n, in_fp) != n) {
- if (feof(in_fp)) {
- ERROR("Unexpected EOF when copying data "
- "between files");
- } else {
- ERROR_WITH_ERRNO("Error copying data between "
- "files");
- }
- return WIMLIB_ERR_READ;
- }
-
- if (fwrite(buf, 1, n, out_fp) != n) {
- ERROR_WITH_ERRNO("Error copying data between files");
- return WIMLIB_ERR_WRITE;
- }
- len -= n;
- }
- return 0;
-}
-
-
-/*
- * Uncompresses a WIM file resource and writes it uncompressed to a file stream.
- *
- * @in_fp: The file stream that contains the file resource.
- * @size: The size of the resource in the input file.
- * @original_size: The original (uncompressed) size of the resource.
- * @offset: The offset of the start of the resource in @in.
- * @input_ctype: The compression type of the resource in @in.
- * @out_fp: The file stream to write the file resource to.
- */
-static int uncompress_resource(FILE *in_fp, u64 size, u64 original_size,
- off_t offset, int input_ctype, FILE *out_fp)
-{
- int ret;
- u8 buf[WIM_CHUNK_SIZE];
- /* Determine how many compressed chunks the file is divided into. */
- u64 num_chunks;
- u64 i;
- u64 uncompressed_offset;
- u64 uncompressed_chunk_size;
-
- num_chunks = (original_size + WIM_CHUNK_SIZE - 1) / WIM_CHUNK_SIZE;
-
- for (i = 0; i < num_chunks; i++) {
-
- uncompressed_offset = i * WIM_CHUNK_SIZE;
- uncompressed_chunk_size = min(WIM_CHUNK_SIZE, original_size -
- uncompressed_offset);
-
- ret = read_resource(in_fp, size, original_size, offset,
- input_ctype, uncompressed_chunk_size,
- uncompressed_offset, buf);
- if (ret != 0)
- return ret;
-
- if (fwrite(buf, 1, uncompressed_chunk_size, out_fp) !=
- uncompressed_chunk_size)
- {
- ERROR_WITH_ERRNO("Failed to write file resource");
- return WIMLIB_ERR_WRITE;
+ if (cb) {
+ /* Send data to callback function */
+ u8 buf[min(WIM_CHUNK_SIZE, size)];
+ size_t bytes_to_read;
+ while (size) {
+ bytes_to_read = min(WIM_CHUNK_SIZE, size);
+ bytes_read = full_read(fd, buf, bytes_to_read);
+ if (bytes_read != bytes_to_read)
+ goto read_error;
+ ret = cb(buf, bytes_read, ctx_or_buf);
+ if (ret)
+ goto out_close;
+ size -= bytes_read;