- /* Finally, the important part: extract the tree of files. */
- if (extract_flags & (WIMLIB_EXTRACT_FLAG_SEQUENTIAL |
- WIMLIB_EXTRACT_FLAG_FROM_PIPE)) {
- /* Sequential extraction requested, so two passes are needed
- * (one for directory structure, one for streams.) */
- if (progress_func)
- progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_BEGIN,
- &ctx.progress);
-
- if (!(extract_flags & WIMLIB_EXTRACT_FLAG_RESUME)) {
- ret = for_dentry_in_tree(root, dentry_extract_skeleton, &ctx);
- if (ret)
- goto out_free_realtarget;
- }
- if (progress_func)
- progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_END,
- &ctx.progress);
- if (extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE)
- ret = extract_streams_from_pipe(&ctx);
- else
- ret = extract_stream_list(&ctx);
- if (ret)
- goto out_free_realtarget;
- } else {
- /* Sequential extraction was not requested, so we can make do
- * with one pass where we both create the files and extract
- * streams. */
- if (progress_func)
- progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_BEGIN,
- &ctx.progress);
- ret = for_dentry_in_tree(root, dentry_extract, &ctx);
- if (ret)
- goto out_free_realtarget;
- if (progress_func)
- progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_END,
- &ctx.progress);
- }
-
- /* If the total number of bytes to extract was miscalculated, just jump
- * to the calculated number in order to avoid confusing the progress
- * function. This should only occur when extracting from a pipe. */
- if (ctx.progress.extract.completed_bytes != ctx.progress.extract.total_bytes)
- {
- DEBUG("Calculated %"PRIu64" bytes to extract, but actually "
- "extracted %"PRIu64,
- ctx.progress.extract.total_bytes,
- ctx.progress.extract.completed_bytes);
- }
- if (progress_func &&
- ctx.progress.extract.completed_bytes < ctx.progress.extract.total_bytes)
- {
- ctx.progress.extract.completed_bytes = ctx.progress.extract.total_bytes;
- progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS, &ctx.progress);
- }
-
- /* Apply security descriptors and timestamps. This is done at the end,
- * and in a depth-first manner, to prevent timestamps from getting
- * changed by subsequent extract operations and to minimize the chance
- * of the restored security descriptors getting in our way. */
- if (progress_func)
- progress_func(WIMLIB_PROGRESS_MSG_APPLY_TIMESTAMPS,
- &ctx.progress);
- ret = for_dentry_in_tree_depth(root, dentry_extract_final, &ctx);
- if (ret)
- goto out_free_realtarget;
-
- if (progress_func) {
- progress_func(*wim_source_path ? WIMLIB_PROGRESS_MSG_EXTRACT_TREE_END :
- WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_END,
- &ctx.progress);
- }
-
- do_extract_warnings(&ctx);
-
- ret = 0;
-out_free_realtarget:
- FREE(ctx.realtarget);
-out_teardown_stream_list:
- /* Free memory allocated as part of the mapping from each
- * wim_lookup_table_entry to the dentries that reference it. */
- if (ctx.extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL)
- list_for_each_entry(lte, &ctx.stream_list, extraction_list)
- if (lte->out_refcnt > ARRAY_LEN(lte->inline_lte_dentries))
- FREE(lte->lte_dentries);
-out_dentry_reset_needs_extraction:
- for_dentry_in_tree(root, dentry_reset_needs_extraction, NULL);
-out_finish_or_abort_extract:
- if (ret) {
- if (ctx.ops->abort_extract)
- ctx.ops->abort_extract(&ctx);
- } else {
- if (ctx.ops->finish_extract)
- ret = ctx.ops->finish_extract(&ctx);
- }