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];
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 */
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;
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) {
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)
{
}
}
}
-out:
- return ret;
+ return 0;
}
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;
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);