* 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) {
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);
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);
.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)
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);
-
}
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) {
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);