]> wimlib.net Git - wimlib/blobdiff - src/resource.c
Do not wait full streams for WIMLIB_PROGRESS_MSG_WRITE_STREAMS
[wimlib] / src / resource.c
index 373279c19b9caa560cb1b5458b821f2b4ea460b5..ff46114d7acc6b5f0bb457a2795dde65bf96ea22 100644 (file)
@@ -338,7 +338,7 @@ read_compressed_wim_resource(const struct wim_resource_spec * const rspec,
                        chunk_offsets_alloc_size -
                        chunk_table_size_to_read;
 
-               ret = full_pread(in_fd, chunk_table_data, chunk_table_size,
+               ret = full_pread(in_fd, chunk_table_data, chunk_table_size_to_read,
                                 file_offset_of_needed_chunk_entries);
                if (ret)
                        goto read_error;
@@ -582,8 +582,8 @@ read_error:
 /* Read raw data from a file descriptor at the specified offset, feeding the
  * data it in chunks into the specified callback function.  */
 static int
-read_raw_file_data(struct filedes *in_fd, u64 size,
-                  consume_data_callback_t cb, void *cb_ctx, u64 offset)
+read_raw_file_data(struct filedes *in_fd, u64 offset, u64 size,
+                  consume_data_callback_t cb, void *cb_ctx)
 {
        u8 buf[BUFFER_SIZE];
        size_t bytes_to_read;
@@ -672,10 +672,10 @@ read_partial_wim_resource(const struct wim_resource_spec *rspec,
                                                    cb, cb_ctx);
        } else {
                return read_raw_file_data(&rspec->wim->in_fd,
+                                         rspec->offset_in_wim + offset,
                                          size,
                                          cb,
-                                         cb_ctx,
-                                         rspec->offset_in_wim + offset);
+                                         cb_ctx);
        }
 }
 
@@ -754,7 +754,7 @@ read_file_on_disk_prefix(const struct wim_lookup_table_entry *lte, u64 size,
                return WIMLIB_ERR_OPEN;
        }
        filedes_init(&fd, raw_fd);
-       ret = read_raw_file_data(&fd, size, cb, cb_ctx, 0);
+       ret = read_raw_file_data(&fd, 0, size, cb, cb_ctx);
        filedes_close(&fd);
        return ret;
 }
@@ -790,7 +790,7 @@ typedef int (*read_stream_prefix_handler_t)(const struct wim_lookup_table_entry
  * reasons, depending on the stream location), or if @cb returned nonzero in
  * which case that error code will be returned.
  */
-int
+static int
 read_stream_prefix(const struct wim_lookup_table_entry *lte, u64 size,
                   consume_data_callback_t cb, void *cb_ctx)
 {
@@ -898,11 +898,22 @@ wim_reshdr_to_data(const struct wim_reshdr *reshdr, WIMStruct *wim, void **buf_r
 struct streamifier_context {
        struct read_stream_list_callbacks cbs;
        struct wim_lookup_table_entry *cur_stream;
+       struct wim_lookup_table_entry *next_stream;
        u64 cur_stream_offset;
        struct wim_lookup_table_entry *final_stream;
        size_t list_head_offset;
 };
 
+static struct wim_lookup_table_entry *
+next_stream(struct wim_lookup_table_entry *lte, size_t list_head_offset)
+{
+       struct list_head *cur;
+
+       cur = (struct list_head*)((u8*)lte + list_head_offset);
+
+       return (struct wim_lookup_table_entry*)((u8*)cur->next - list_head_offset);
+}
+
 /* A consume_data_callback_t implementation that translates raw resource data
  * into streams, calling the begin_stream, consume_chunk, and end_stream
  * callback functions as appropriate.  */
@@ -937,28 +948,22 @@ streamifier_cb(const void *chunk, size_t size, void *_ctx)
        if (ctx->cur_stream_offset == ctx->cur_stream->size) {
                /* Finished reading all the data for a stream.  */
 
-               struct list_head *cur, *next;
-
-               cur = (struct list_head *)
-                       ((u8*)ctx->cur_stream + ctx->list_head_offset);
-               next = cur->next;
-
                DEBUG("End stream (size=%"PRIu64").", ctx->cur_stream->size);
                ret = (*ctx->cbs.end_stream)(ctx->cur_stream, 0,
                                             ctx->cbs.end_stream_ctx);
                if (ret)
                        return ret;
 
-               if (ctx->cur_stream != ctx->final_stream) {
-                       /* Advance to next stream.  */
-                       ctx->cur_stream = (struct wim_lookup_table_entry *)
-                                       ((u8*)next - ctx->list_head_offset);
-
-                       ctx->cur_stream_offset = 0;
-               } else {
-                       /* No more streams.  */
-                       ctx->cur_stream = NULL;
+               /* Advance to next stream.  */
+               ctx->cur_stream = ctx->next_stream;
+               if (ctx->cur_stream != NULL) {
+                       if (ctx->cur_stream != ctx->final_stream)
+                               ctx->next_stream = next_stream(ctx->cur_stream,
+                                                              ctx->list_head_offset);
+                       else
+                               ctx->next_stream = NULL;
                }
+               ctx->cur_stream_offset = 0;
        }
        return 0;
 }
@@ -1109,7 +1114,24 @@ read_full_stream_with_sha1(struct wim_lookup_table_entry *lte,
  * @cbs
  *     Callback functions to accept the stream data.
  * @flags
+ *     Bitwise OR of zero or more of the following flags:
  *
+ *     VERIFY_STREAM_HASHES:
+ *             For all streams being read that have already had SHA1 message
+ *             digests computed, calculate the SHA1 message digest of the read
+ *             data and compare it with the previously computed value.  If they
+ *             do not match, return WIMLIB_ERR_INVALID_RESOURCE_HASH.
+ *
+ *     COMPUTE_MISSING_STREAM_HASHES
+ *             For all streams being read that have not yet had their SHA1
+ *             message digests computed, calculate and save their SHA1 message
+ *             digests.
+ *
+ *     STREAM_LIST_ALREADY_SORTED
+ *             @stream_list is already sorted in sequential order for reading.
+ *
+ * The callback functions are allowed to delete the current stream from the list
+ * if necessary.
  *
  * Returns 0 on success; a nonzero error code on failure.  Failure can occur due
  * to an error reading the data or due to an error status being returned by any
@@ -1219,6 +1241,7 @@ read_stream_list(struct list_head *stream_list,
                                struct streamifier_context streamifier_ctx = {
                                        .cbs                    = *sink_cbs,
                                        .cur_stream             = lte,
+                                       .next_stream            = next_stream(lte, list_head_offset),
                                        .cur_stream_offset      = 0,
                                        .final_stream           = lte_last,
                                        .list_head_offset       = list_head_offset,
@@ -1261,6 +1284,7 @@ int
 extract_stream(struct wim_lookup_table_entry *lte, u64 size,
               consume_data_callback_t extract_chunk, void *extract_chunk_arg)
 {
+       wimlib_assert(size <= lte->size);
        if (size == lte->size) {
                /* Do SHA1.  */
                struct read_stream_list_callbacks cbs = {
@@ -1313,15 +1337,15 @@ sha1_stream(struct wim_lookup_table_entry *lte)
  * specification.  */
 void
 wim_res_hdr_to_spec(const struct wim_reshdr *reshdr, WIMStruct *wim,
-                   struct wim_resource_spec *spec)
+                   struct wim_resource_spec *rspec)
 {
-       spec->wim = wim;
-       spec->offset_in_wim = reshdr->offset_in_wim;
-       spec->size_in_wim = reshdr->size_in_wim;
-       spec->uncompressed_size = reshdr->uncompressed_size;
-       INIT_LIST_HEAD(&spec->stream_list);
-       spec->flags = reshdr->flags;
-       spec->is_pipable = wim_is_pipable(wim);
+       rspec->wim = wim;
+       rspec->offset_in_wim = reshdr->offset_in_wim;
+       rspec->size_in_wim = reshdr->size_in_wim;
+       rspec->uncompressed_size = reshdr->uncompressed_size;
+       INIT_LIST_HEAD(&rspec->stream_list);
+       rspec->flags = reshdr->flags;
+       rspec->is_pipable = wim_is_pipable(wim);
 }
 
 /* Convert a stand-alone resource specification to a WIM resource header.  */