+ /* 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);
+ }
+ goto out;