const char *wimfile;
const char *dir;
const char *image_num_or_name;
- int extract_flags = WIMLIB_EXTRACT_FLAG_SEQUENTIAL;
+ int extract_flags = WIMLIB_EXTRACT_FLAG_SEQUENTIAL |
+ WIMLIB_EXTRACT_FLAG_SHOW_PROGRESS;
const char *swm_glob = NULL;
WIMStruct **additional_swms = NULL;
/* %true iff verify_inode() has run on this dentry. */
u8 verified : 1;
+ /* temporary flag */
+ u8 found : 1;
+
/* Number of alternate data streams associated with this inode */
u16 num_ads;
* 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)
{
.num_lutimes_warnings = 0,
};
- if (extract_flags & WIMLIB_EXTRACT_FLAG_SEQUENTIAL)
- args.extract_flags |= WIMLIB_EXTRACT_FLAG_DIRS_ONLY;
+ 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)
+ puts("Creating directory structure...");
+ }
ret = for_dentry_in_tree(root, extract_dentry, &args);
if (ret != 0)
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;
+ args.extract_flags &= ~WIMLIB_EXTRACT_FLAG_NO_STREAMS;
if (ret == 0) {
- args.extract_flags |= WIMLIB_EXTRACT_FLAG_SKIP_DIRS;
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;
+
+ 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);
- lte->extracted_file = NULL;
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;
}
- 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);
+ finish_stream_op_progress(total_size, "extracted");
} else {
WARNING("Falling back to non-sequential image extraction");
ret = for_dentry_in_tree(root, extract_dentry, &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);
* extraction mode. In these mode, all identical files are linked
* together, and @extracted_file will be set to the filename of the
* first extracted file containing this stream. */
- char *extracted_file;
+ struct {
+ char *extracted_file;
+ bool extracted;
+ };
/* List of lookup table entries that correspond to streams that have
* been extracted to the staging directory when modifying a read-write
/** Read the WIM file sequentially while extracting the image. */
#define WIMLIB_EXTRACT_FLAG_SEQUENTIAL 0x00000010
+/** Print progress information while extracting the image. */
+#define WIMLIB_EXTRACT_FLAG_SHOW_PROGRESS 0x00000020
+
/**
* Possible values of the error code returned by many functions in wimlib.
*
struct lookup_table *lookup_table,
struct lookup_table_entry **lte_ret);
+extern void show_stream_op_progress(u64 *cur_size, u64 *next_size,
+ u64 total_size, u64 one_percent,
+ unsigned *cur_percent,
+ const struct lookup_table_entry *cur_lte,
+ const char *op);
+
+extern void finish_stream_op_progress(u64 total_size, const char *op);
+
/* wim.c */
extern WIMStruct *new_wim_struct();
extern int select_wim_image(WIMStruct *w, int image);
/* Internal use only */
#define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000
-#define WIMLIB_EXTRACT_FLAG_DIRS_ONLY 0x40000000
-#define WIMLIB_EXTRACT_FLAG_SKIP_DIRS 0x20000000
-#define WIMLIB_EXTRACT_FLAG_EMPTY_ONLY 0x10000000
-#define WIMLIB_EXTRACT_MASK_PUBLIC 0x0fffffff
+#define WIMLIB_EXTRACT_FLAG_NO_STREAMS 0x40000000
+#define WIMLIB_EXTRACT_MASK_PUBLIC 0x2fffffff
/* write.c */
}
#endif
-static void show_stream_write_progress(u64 *cur_size, u64 *next_size,
- u64 total_size, u64 one_percent,
- unsigned *cur_percent,
- const struct lookup_table_entry *cur_lte)
+void show_stream_op_progress(u64 *cur_size, u64 *next_size,
+ u64 total_size, u64 one_percent,
+ unsigned *cur_percent,
+ const struct lookup_table_entry *cur_lte,
+ const char *op)
{
if (*cur_size >= *next_size) {
printf("\r%"PRIu64" MiB of %"PRIu64" MiB "
- "(uncompressed) written (%u%% done)",
+ "(uncompressed) %s (%u%% done)",
*cur_size >> 20,
- total_size >> 20, *cur_percent);
+ total_size >> 20, op, *cur_percent);
fflush(stdout);
*next_size += one_percent;
(*cur_percent)++;
*cur_size += wim_resource_size(cur_lte);
}
-static void finish_stream_write_progress(u64 total_size)
+void finish_stream_op_progress(u64 total_size, const char *op)
{
printf("\r%"PRIu64" MiB of %"PRIu64" MiB "
- "(uncompressed) written (100%% done)\n",
- total_size >> 20, total_size >> 20);
+ "(uncompressed) %s (100%% done)\n",
+ total_size >> 20, total_size >> 20, op);
fflush(stdout);
}
list_for_each_entry(lte, stream_list, staging_list) {
if (write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS) {
- show_stream_write_progress(&cur_size, &next_size,
- total_size, one_percent,
- &cur_percent, lte);
+ show_stream_op_progress(&cur_size, &next_size,
+ total_size, one_percent,
+ &cur_percent, lte, "written");
}
ret = write_wim_resource(lte, out_fp, out_ctype,
<e->output_resource_entry,
return ret;
}
if (write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS)
- finish_stream_write_progress(total_size);
+ finish_stream_op_progress(total_size, "written");
return 0;
}
if (msg->begin_chunk == 0) {
DEBUG2("Begin chunk tab");
if (write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS) {
- show_stream_write_progress(&cur_size,
- &next_size,
- total_size,
- one_percent,
- &cur_percent,
- cur_lte);
+ show_stream_op_progress(&cur_size,
+ &next_size,
+ total_size,
+ one_percent,
+ &cur_percent,
+ cur_lte,
+ "written");
}
// This is the first set of chunks. Leave space
staging_list)
{
if (write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS) {
- show_stream_write_progress(&cur_size,
- &next_size,
- total_size,
- one_percent,
- &cur_percent,
- lte);
+ show_stream_op_progress(&cur_size,
+ &next_size,
+ total_size,
+ one_percent,
+ &cur_percent,
+ lte,
+ "written");
}
ret = write_wim_resource(lte,
if (ret == 0) {
list_for_each_entry(lte, &my_resources, staging_list) {
if (write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS) {
- show_stream_write_progress(&cur_size,
- &next_size,
- total_size,
- one_percent,
- &cur_percent,
- lte);
+ show_stream_op_progress(&cur_size,
+ &next_size,
+ total_size,
+ one_percent,
+ &cur_percent,
+ lte,
+ "written");
}
ret = write_wim_resource(lte, out_fp,
out_ctype,
break;
}
if (write_flags & WIMLIB_WRITE_FLAG_SHOW_PROGRESS)
- finish_stream_write_progress(total_size);
+ finish_stream_op_progress(total_size, "written");
} else {
size_t num_available_msgs = 0;
struct list_head *cur;