]> wimlib.net Git - wimlib/blobdiff - src/extract.c
extract.c: Fix extract_from_tmpfile()
[wimlib] / src / extract.c
index bbd0a5ed6801276a98a9b4b9ca4a3b92d5eba5ee..eaee41dd155a275ded55f1ee581e92cfa14ca6cf 100644 (file)
@@ -311,6 +311,7 @@ begin_extract_stream_wrapper(struct wim_lookup_table_entry *lte, void *_ctx)
        struct apply_ctx *ctx = _ctx;
 
        ctx->cur_stream = lte;
+       ctx->cur_stream_offset = 0;
 
        if (unlikely(lte->out_refcnt > MAX_OPEN_STREAMS))
                return create_temporary_file(&ctx->tmpfile_fd, &ctx->tmpfile_name);
@@ -325,9 +326,13 @@ extract_chunk_wrapper(const void *chunk, size_t size, void *_ctx)
        union wimlib_progress_info *progress = &ctx->progress;
        int ret;
 
+       ctx->cur_stream_offset += size;
+
        if (likely(ctx->supported_features.hard_links)) {
                progress->extract.completed_bytes +=
                        (u64)size * ctx->cur_stream->out_refcnt;
+               if (ctx->cur_stream_offset == ctx->cur_stream->size)
+                       progress->extract.completed_streams += ctx->cur_stream->out_refcnt;
        } else {
                const struct stream_owner *owners = stream_owners(ctx->cur_stream);
                for (u32 i = 0; i < ctx->cur_stream->out_refcnt; i++) {
@@ -339,6 +344,8 @@ extract_chunk_wrapper(const void *chunk, size_t size, void *_ctx)
                                            d_extraction_alias_node)
                        {
                                progress->extract.completed_bytes += size;
+                               if (ctx->cur_stream_offset == ctx->cur_stream->size)
+                                       progress->extract.completed_streams++;
                        }
                }
        }
@@ -394,10 +401,13 @@ extract_from_tmpfile(const tchar *tmpfile_name, struct apply_ctx *ctx)
 {
        struct wim_lookup_table_entry tmpfile_lte;
        struct wim_lookup_table_entry *orig_lte = ctx->cur_stream;
-       const struct stream_owner *owners = stream_owners(orig_lte);
        const struct read_stream_list_callbacks *cbs = ctx->saved_cbs;
        int ret;
 
+       BUILD_BUG_ON(MAX_OPEN_STREAMS < ARRAY_LEN(orig_lte->inline_stream_owners));
+
+       struct stream_owner *owners = orig_lte->stream_owners;
+
        /* Copy the stream's data from the temporary file to each of its
         * destinations.
         *
@@ -408,10 +418,8 @@ extract_from_tmpfile(const tchar *tmpfile_name, struct apply_ctx *ctx)
        memcpy(&tmpfile_lte, orig_lte, sizeof(struct wim_lookup_table_entry));
        tmpfile_lte.resource_location = RESOURCE_IN_FILE_ON_DISK;
        tmpfile_lte.file_on_disk = ctx->tmpfile_name;
-       tmpfile_lte.out_refcnt = 1;
-
+       ret = 0;
        for (u32 i = 0; i < orig_lte->out_refcnt; i++) {
-               tmpfile_lte.inline_stream_owners[0] = owners[i];
 
                /* Note: it usually doesn't matter whether we pass the original
                 * stream entry to callbacks provided by the extraction backend
@@ -422,9 +430,12 @@ extract_from_tmpfile(const tchar *tmpfile_name, struct apply_ctx *ctx)
                 * because it needs the original stream location in order to
                 * create the external backing reference.  */
 
+               orig_lte->out_refcnt = 1;
+               orig_lte->inline_stream_owners[0] = owners[i];
+
                ret = (*cbs->begin_stream)(orig_lte, cbs->begin_stream_ctx);
                if (ret)
-                       return ret;
+                       break;
 
                /* Extra SHA-1 isn't necessary here, but it shouldn't hurt as
                 * this case is very rare anyway.  */
@@ -432,10 +443,13 @@ extract_from_tmpfile(const tchar *tmpfile_name, struct apply_ctx *ctx)
                                     cbs->consume_chunk,
                                     cbs->consume_chunk_ctx);
 
-               return (*cbs->end_stream)(orig_lte, ret,
-                                         cbs->end_stream_ctx);
+               ret = (*cbs->end_stream)(orig_lte, ret, cbs->end_stream_ctx);
+               if (ret)
+                       break;
        }
-       return 0;
+       FREE(owners);
+       orig_lte->out_refcnt = 0;
+       return ret;
 }
 
 static int
@@ -961,7 +975,7 @@ ref_stream(struct wim_lookup_table_entry *lte, u32 stream_idx,
                return 0;
 
        ctx->progress.extract.total_bytes += lte->size;
-       ctx->progress.extract.num_streams++;
+       ctx->progress.extract.total_streams++;
 
        if (inode->i_visited)
                return 0;
@@ -1504,12 +1518,16 @@ check_extract_flags(const WIMStruct *wim, int *extract_flags_p)
        }
 #endif
 
-#ifndef __WIN32__
        if (extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT) {
+#ifdef __WIN32__
+               if (!wim->filename)
+                       return WIMLIB_ERR_NO_FILENAME;
+#else
                ERROR("WIMBoot extraction is only supported on Windows!");
                return WIMLIB_ERR_UNSUPPORTED;
-       }
 #endif
+       }
+
 
        if ((extract_flags & (WIMLIB_EXTRACT_FLAG_RPFIX |
                              WIMLIB_EXTRACT_FLAG_NORPFIX |