X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fextract.c;h=90b6ce39eca37c69e36b420a6a775c65c21c8eab;hp=145ea78ada5a0cfeea3d9c2c5bef8a1450031778;hb=3d7805d6132d821c4e29bc90e58518bfe3acb15c;hpb=edd7e04ddef20c47975bd2535960b6223496d99b diff --git a/src/extract.c b/src/extract.c index 145ea78a..90b6ce39 100644 --- a/src/extract.c +++ b/src/extract.c @@ -63,7 +63,7 @@ static int extract_regular_file_linked(const struct dentry *dentry, * instead either symlinks or hardlinks *all* identical files in * the WIM, even if they are in a different image (in the case * of a multi-image extraction) */ - wimlib_assert(lte->extracted_file); + wimlib_assert(lte->extracted_file != NULL); if (extract_flags & WIMLIB_EXTRACT_FLAG_HARDLINK) { if (link(lte->extracted_file, output_path) != 0) { @@ -301,18 +301,9 @@ static int extract_dentry(struct dentry *dentry, void *arg) size_t len = strlen(args->output_dir); char output_path[len + dentry->full_path_utf8_len + 1]; - if (dentry_is_directory(dentry)) { - if (extract_flags & WIMLIB_EXTRACT_FLAG_SKIP_DIRS) + if (extract_flags & WIMLIB_EXTRACT_FLAG_NO_STREAMS) + if (inode_unnamed_lte(dentry->d_inode, w->lookup_table) != NULL) return 0; - } else { - if (extract_flags & WIMLIB_EXTRACT_FLAG_DIRS_ONLY) - return 0; - } - - if ((extract_flags & WIMLIB_EXTRACT_FLAG_EMPTY_ONLY) - && (!dentry_is_regular_file(dentry) || - inode_unnamed_lte(dentry->d_inode, w->lookup_table) != NULL)) - return 0; if (extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) { wimlib_assert(dentry->full_path_utf8); @@ -440,16 +431,48 @@ static int sort_stream_list_by_wim_position(struct list_head *stream_list) INIT_LIST_HEAD(stream_list); for (i = 0; i < num_streams; i++) - list_add(&array[i]->staging_list, stream_list); + list_add_tail(&array[i]->staging_list, stream_list); FREE(array); return 0; } +static u64 calculate_bytes_to_extract(struct list_head *stream_list, + int extract_flags) +{ + struct lookup_table_entry *lte; + struct dentry *dentry; + u64 total_size = 0; + list_for_each_entry(lte, stream_list, staging_list) { + u64 size = wim_resource_size(lte); + if (extract_flags & + (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) + { + total_size += size; + } else { + list_for_each_entry(dentry, <e->dentry_list, + tmp_list) + { + dentry->d_inode->found = false; + } + list_for_each_entry(dentry, <e->dentry_list, + tmp_list) + { + if (!dentry->d_inode->found) { + dentry->d_inode->found = true; + total_size += size; + } + } + } + } + return total_size; +} + static int extract_single_image(WIMStruct *w, int image, const char *output_dir, int extract_flags) { int ret; struct dentry *root; + const char *image_name; DEBUG("Extracting image %d", image); @@ -466,8 +489,24 @@ static int extract_single_image(WIMStruct *w, int image, .num_lutimes_warnings = 0, }; - if (extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL) - args.extract_flags |= WIMLIB_EXTRACT_FLAG_DIRS_ONLY; + image_name = wimlib_get_image_name(w, image); + if (!image_name) + image_name = "unnamed"; + + if (extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL) { + for_lookup_table_entry(w->lookup_table, lte_zero_out_refcnt, + NULL); + args.extract_flags |= WIMLIB_EXTRACT_FLAG_NO_STREAMS; + if (args.extract_flags & WIMLIB_EXTRACT_FLAG_SHOW_PROGRESS) { + printf("Creating directory structure for image %d (%s)...\n", + image, image_name); + } + } else { + if (args.extract_flags & WIMLIB_EXTRACT_FLAG_SHOW_PROGRESS) { + printf("Extracting image %d (%s)...\n", + image, image_name); + } + } ret = for_dentry_in_tree(root, extract_dentry, &args); if (ret != 0) @@ -475,42 +514,54 @@ static int extract_single_image(WIMStruct *w, int image, if (extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL) { struct list_head stream_list; + struct lookup_table_entry *lte; + struct lookup_table_entry *tmp; + struct dentry *dentry; + u64 total_size; + u64 cur_size; + u64 next_size; + u64 one_percent; + unsigned cur_percent; + INIT_LIST_HEAD(&stream_list); w->private = &stream_list; for_dentry_in_tree(root, dentry_add_streams_for_extraction, w); ret = sort_stream_list_by_wim_position(&stream_list); - args.extract_flags &= ~WIMLIB_EXTRACT_FLAG_DIRS_ONLY; - if (ret == 0) { - args.extract_flags |= WIMLIB_EXTRACT_FLAG_SKIP_DIRS; - struct lookup_table_entry *lte; - struct lookup_table_entry *tmp; - struct dentry *dentry; - list_for_each_entry_safe(lte, tmp, &stream_list, staging_list) { - list_del(<e->staging_list); - lte->extracted_file = NULL; - list_for_each_entry(dentry, <e->dentry_list, tmp_list) { - ret = extract_dentry(dentry, &args); - if (ret != 0) - return ret; - } - FREE(lte->extracted_file); - } - args.extract_flags |= WIMLIB_EXTRACT_FLAG_EMPTY_ONLY; - ret = for_dentry_in_tree(root, extract_dentry, &args); - if (ret != 0) - return ret; - args.extract_flags &= ~(WIMLIB_EXTRACT_FLAG_SKIP_DIRS | - WIMLIB_EXTRACT_FLAG_EMPTY_ONLY); - } else { + args.extract_flags &= ~WIMLIB_EXTRACT_FLAG_NO_STREAMS; + if (ret != 0) { WARNING("Falling back to non-sequential image extraction"); ret = for_dentry_in_tree(root, extract_dentry, &args); if (ret != 0) return ret; + goto out; } - } + total_size = calculate_bytes_to_extract(&stream_list, args.extract_flags); + one_percent = total_size / 100; + cur_size = 0; + next_size = 0; + cur_percent = 0; + puts("Extracting files..."); + list_for_each_entry_safe(lte, tmp, &stream_list, staging_list) { + list_del(<e->staging_list); + list_for_each_entry(dentry, <e->dentry_list, tmp_list) { + if ((!dentry->d_inode->extracted_file) && + (args.extract_flags & WIMLIB_EXTRACT_FLAG_SHOW_PROGRESS)) + { + show_stream_op_progress(&cur_size, &next_size, + total_size, one_percent, + &cur_percent, lte, + "extracted"); + } + ret = extract_dentry(dentry, &args); + if (ret != 0) + return ret; + } + } + finish_stream_op_progress(total_size, "extracted"); + } +out: return for_dentry_in_tree_depth(root, apply_dentry_timestamps, &args); - } @@ -587,12 +638,13 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, w->lookup_table = joined_tab; } - for_lookup_table_entry(w->lookup_table, lte_zero_out_refcnt, NULL); - - if (!(extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL)) { + if (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | + WIMLIB_EXTRACT_FLAG_HARDLINK)) + { for_lookup_table_entry(w->lookup_table, lte_zero_extracted_file, NULL); + extract_flags &= ~WIMLIB_EXTRACT_FLAG_SEQUENTIAL; } if (image == WIM_ALL_IMAGES) { @@ -606,7 +658,10 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, int image, free_lookup_table(w->lookup_table); w->lookup_table = w_tab_save; } - if (!(extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL)) { + + if (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | + WIMLIB_EXTRACT_FLAG_HARDLINK)) + { for_lookup_table_entry(w->lookup_table, lte_free_extracted_file, NULL);