- 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->original_resource_size = size;
- chunk_tab->bytes_per_chunk_entry = (size >= (1ULL << 32)) ? 8 : 4;
- chunk_tab->table_disk_size = chunk_tab->bytes_per_chunk_entry *
- (num_chunks - 1);
- chunk_tab->cur_offset = 0;
- chunk_tab->cur_offset_p = chunk_tab->offsets;
-
- 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;
+ /* Make sure the resource is actually located in a WIM file and is not
+ * somewhere else. */
+ wimlib_assert(lte->resource_location == RESOURCE_IN_WIM);
+
+ /* Retrieve input file descriptor for the WIM file. */
+ in_fd = <e->wim->in_fd;
+
+ /* Don't allow raw reads (either full or chunks) of uncompressed
+ * resources. */
+ wimlib_assert(!(flags & WIMLIB_READ_RESOURCE_FLAG_RAW) ||
+ resource_is_compressed(<e->resource_entry));
+
+ /* Don't allow seek-only reads unless reading from a pipe; also don't
+ * allow combining SEEK_ONLY with either RAW flag. */
+ wimlib_assert(!(flags & WIMLIB_READ_RESOURCE_FLAG_SEEK_ONLY) ||
+ (!filedes_is_seekable(in_fd) &&
+ !(flags & WIMLIB_READ_RESOURCE_FLAG_RAW)));
+
+ DEBUG("Reading WIM resource: %"PRIu64" @ +%"PRIu64" "
+ "from %"PRIu64" @ +%"PRIu64" (readflags 0x%08x, resflags 0x%02x%s)",
+ size, offset,
+ lte->resource_entry.original_size, lte->resource_entry.offset,
+ flags, lte->resource_entry.flags,
+ (lte->is_pipable ? ", pipable" : ""));
+
+ if ((flags & WIMLIB_READ_RESOURCE_FLAG_RAW_FULL) ||
+ !resource_is_compressed(<e->resource_entry))
+ {
+ /* Reading raw resource contents or reading uncompressed
+ * resource. */
+ wimlib_assert(offset + size <= lte->resource_entry.size);
+ offset += lte->resource_entry.offset;
+ if (flags & WIMLIB_READ_RESOURCE_FLAG_SEEK_ONLY) {
+ if (lte->resource_entry.size != 0) {
+ u8 dummy;
+ ret = full_pread(in_fd, &dummy, 1,
+ offset + lte->resource_entry.size - 1);
+ if (ret)
+ goto read_error;
+ }
+ } else if (cb) {
+ /* Send data to callback function */
+ u8 buf[min(WIM_CHUNK_SIZE, size)];
+ while (size) {
+ size_t bytes_to_read = min(WIM_CHUNK_SIZE,
+ size);
+ ret = full_pread(in_fd, buf, bytes_to_read,
+ offset);
+ if (ret)
+ goto read_error;
+ ret = cb(buf, bytes_to_read, ctx_or_buf);
+ if (ret)
+ goto out;
+ size -= bytes_to_read;
+ offset += bytes_to_read;
+ }
+ } else {
+ /* Send data directly to a buffer */
+ ret = full_pread(in_fd, ctx_or_buf, size, offset);
+ if (ret)
+ goto read_error;
+ }
+ ret = 0;
+ } else if (lte->is_pipable && !filedes_is_seekable(in_fd)) {
+ /* Reading compressed, pipable resource from pipe. */
+ ret = read_pipable_resource(lte, size, cb,
+ ctx_or_buf, flags, offset);
+ } else {
+ /* Reading compressed, possibly pipable resource from seekable
+ * file. */
+ ret = read_compressed_resource(lte, size, cb,
+ ctx_or_buf, flags, offset);