X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fextract_image.c;h=d9912c7bb0b313c9e5c11b59073c568b283eedf1;hp=22b12ba1ef52bf9ed59aff8760dc923b7bfc5089;hb=4f0d1a0407a25ecae2ad7b73597075bea810baf7;hpb=40beb80283a2df7af88c8359ca41adb814585e9a diff --git a/src/extract_image.c b/src/extract_image.c index 22b12ba1..d9912c7b 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -28,7 +28,6 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ - #include "config.h" #include @@ -175,7 +174,7 @@ static int extract_regular_file_unlinked(struct dentry *dentry, goto out; } - ret = extract_full_wim_resource_to_fd(lte, out_fd); + ret = extract_wim_resource_to_fd(lte, out_fd, wim_resource_size(lte)); if (ret != 0) { ERROR("Failed to extract resource to `%s'", output_path); goto out; @@ -284,25 +283,8 @@ static int extract_directory(const char *output_path, bool is_root) static int apply_dentry_normal(struct dentry *dentry, void *arg) { struct apply_args *args = arg; - int extract_flags = args->extract_flags; struct inode *inode = dentry->d_inode; size_t len; - int ret; - - if (dentry->is_extracted) - return 0; - - if (extract_flags & WIMLIB_EXTRACT_FLAG_NO_STREAMS) - if (inode_unnamed_lte_resolved(inode)) - return 0; - - if ((extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) && - args->progress_func) - { - args->progress.extract.cur_path = dentry->full_path_utf8; - args->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY, - &args->progress); - } len = strlen(args->target); char output_path[len + dentry->full_path_utf8_len + 1]; @@ -311,14 +293,11 @@ static int apply_dentry_normal(struct dentry *dentry, void *arg) output_path[len + dentry->full_path_utf8_len] = '\0'; if (inode_is_symlink(inode)) - ret = extract_symlink(dentry, args, output_path); + return extract_symlink(dentry, args, output_path); else if (inode_is_directory(inode)) - ret = extract_directory(output_path, false); + return extract_directory(output_path, false); else - ret = extract_regular_file(dentry, args, output_path); - if (ret == 0) - dentry->is_extracted = 1; - return ret; + return extract_regular_file(dentry, args, output_path); } /* Apply timestamp to extracted file */ @@ -362,6 +341,30 @@ static int apply_dentry_timestamps_normal(struct dentry *dentry, void *arg) return 0; } +static int maybe_apply_dentry(struct dentry *dentry, void *arg) +{ + struct apply_args *args = arg; + int ret; + + if (dentry->is_extracted) + return 0; + + if (args->extract_flags & WIMLIB_EXTRACT_FLAG_NO_STREAMS) + if (inode_unnamed_lte_resolved(dentry->d_inode)) + return 0; + + if ((args->extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE) && + args->progress_func) { + args->progress.extract.cur_path = dentry->full_path_utf8; + args->progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DENTRY, + &args->progress); + } + ret = args->apply_dentry(dentry, args); + if (ret == 0) + dentry->is_extracted = 1; + return ret; +} + static int cmp_streams_by_wim_position(const void *p1, const void *p2) { const struct lookup_table_entry *lte1, *lte2; @@ -530,12 +533,15 @@ static int apply_stream_list(struct list_head *stream_list, struct lookup_table_entry *lte; struct inode *inode; struct dentry *dentry; - int ret = 0; + int ret; - /* This complicated loop is actually just looping through the dentries - * (as for_dentry_in_tree() does), but the outer loop is actually over - * the distinct streams to be extracted so that sequential reading of - * the WIM can be implemented. */ + /* This complicated loop is essentially looping through the dentries, + * although dentries may be visited more than once (if a dentry contains + * two different nonempty streams) or not at all (if a dentry contains + * no non-empty streams). + * + * The outer loop is over the distinct streams to be extracted so that + * sequential reading of the WIM can be implemented. */ /* For each distinct stream to be extracted */ list_for_each_entry(lte, stream_list, staging_list) { @@ -543,22 +549,31 @@ static int apply_stream_list(struct list_head *stream_list, list_for_each_entry(inode, <e->inode_list, lte_inode_list) { /* For each dentry that points to the inode */ inode_for_each_dentry(dentry, inode) { - ret = ops->apply_dentry(dentry, args); + /* Extract the dentry if it was not already + * extracted */ + ret = maybe_apply_dentry(dentry, args); if (ret != 0) - goto out; + return ret; if (progress_func && - args->progress.extract.completed_bytes >= next_progress && - args->progress.extract.total_bytes != 0) + args->progress.extract.completed_bytes >= next_progress) { progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS, &args->progress); - next_progress += bytes_per_progress; + if (args->progress.extract.completed_bytes >= + args->progress.extract.total_bytes) + { + next_progress = ~0ULL; + } else { + next_progress = + min (args->progress.extract.completed_bytes + + bytes_per_progress, + args->progress.extract.total_bytes); + } } } } } -out: - return ret; + return 0; } static int extract_single_image(WIMStruct *w, int image, @@ -632,7 +647,8 @@ static int extract_single_image(WIMStruct *w, int image, } args.extract_flags |= WIMLIB_EXTRACT_FLAG_NO_STREAMS; - ret = for_dentry_in_tree(wim_root_dentry(w), ops->apply_dentry, &args); + args.apply_dentry = ops->apply_dentry; + ret = for_dentry_in_tree(wim_root_dentry(w), maybe_apply_dentry, &args); args.extract_flags &= ~WIMLIB_EXTRACT_FLAG_NO_STREAMS; if (ret != 0) goto out; @@ -646,8 +662,10 @@ static int extract_single_image(WIMStruct *w, int image, if (ret != 0) goto out; - if (progress_func) - progress_func(WIMLIB_PROGRESS_MSG_APPLY_TIMESTAMPS, NULL); + if (progress_func) { + progress_func(WIMLIB_PROGRESS_MSG_APPLY_TIMESTAMPS, + &args.progress); + } ret = for_dentry_in_tree_depth(wim_root_dentry(w), ops->apply_dentry_timestamps, &args);