(full_path_nchars - args->wim_source_path_nchars) + 1];
p = output_path;
- /*print_dentry(dentry, NULL);*/
- /*ERROR("%"TS" %"TS, args->target, dentry->_full_path);*/
- /*ERROR("");*/
-
tmemcpy(p, args->target, args->target_nchars);
p += args->target_nchars;
#endif
}
-static bool
-dentry_is_descendent(const struct wim_dentry *dentry,
- const struct wim_dentry *ancestor)
-{
- for (;;) {
- if (dentry == ancestor)
- return true;
- if (dentry_is_root(dentry))
- return false;
- dentry = dentry->parent;
- }
-}
-
/* Extract a dentry if it hasn't already been extracted and either
* WIMLIB_EXTRACT_FLAG_NO_STREAMS is not specified, or the dentry is a directory
* and/or has no unnamed stream. */
struct apply_args *args = arg;
int ret;
- if (dentry->is_extracted)
- return 0;
-
- if (!dentry_is_descendent(dentry, args->extract_root))
+ if (!dentry->needs_extraction)
return 0;
if (args->extract_flags & WIMLIB_EXTRACT_FLAG_NO_STREAMS &&
}
ret = args->apply_dentry(dentry, args);
if (ret == 0)
- dentry->is_extracted = 1;
+ dentry->needs_extraction = 0;
return ret;
}
struct list_head *stream_list)
{
if (++lte->out_refcnt == 1) {
- INIT_LIST_HEAD(<e->inode_list);
+ INIT_LIST_HEAD(<e->lte_dentry_list);
list_add_tail(<e->extraction_list, stream_list);
}
}
-static void
-inode_find_streams_for_extraction(struct wim_inode *inode,
- struct list_head *stream_list,
- int extract_flags)
+struct find_streams_ctx {
+ struct list_head stream_list;
+ int extract_flags;
+};
+
+static int
+dentry_find_streams_to_extract(struct wim_dentry *dentry, void *_ctx)
{
+ struct find_streams_ctx *ctx = _ctx;
+ struct wim_inode *inode = dentry->d_inode;
struct wim_lookup_table_entry *lte;
- bool inode_added = false;
+ bool dentry_added = false;
+ struct list_head *stream_list = &ctx->stream_list;
+ int extract_flags = ctx->extract_flags;
+
+ dentry->needs_extraction = 1;
lte = inode_unnamed_lte_resolved(inode);
if (lte) {
- maybe_add_stream_for_extraction(lte, stream_list);
- list_add_tail(&inode->i_lte_inode_list, <e->inode_list);
- inode_added = true;
+ if (!inode->i_visited)
+ maybe_add_stream_for_extraction(lte, stream_list);
+ list_add_tail(&dentry->tmp_list, <e->lte_dentry_list);
+ dentry_added = true;
}
/* Determine whether to include alternate data stream entries or not.
if (inode->i_ads_entries[i].stream_name_nbytes != 0) {
lte = inode->i_ads_entries[i].lte;
if (lte) {
- maybe_add_stream_for_extraction(lte,
- stream_list);
- if (!inode_added) {
- list_add_tail(&inode->i_lte_inode_list,
- <e->inode_list);
- inode_added = true;
+ if (!inode->i_visited) {
+ maybe_add_stream_for_extraction(lte,
+ stream_list);
+ }
+ if (!dentry_added) {
+ list_add_tail(&dentry->tmp_list,
+ <e->lte_dentry_list);
+ dentry_added = true;
}
}
}
}
}
-}
-
-struct find_streams_ctx {
- struct list_head stream_list;
- int extract_flags;
-};
-
-static int
-dentry_find_streams_to_extract(struct wim_dentry *dentry, void *_ctx)
-{
- struct find_streams_ctx *ctx = _ctx;
- struct wim_inode *inode = dentry->d_inode;
-
- dentry->is_extracted = 0;
- if (!inode->i_visited) {
- inode_find_streams_for_extraction(inode, &ctx->stream_list,
- ctx->extract_flags);
- inode->i_visited = 1;
- }
+ inode->i_visited = 1;
return 0;
}
}
static int
-dentry_mark_inode_unvisited(struct wim_dentry *dentry, void *_ignore)
+dentry_reset_needs_extraction(struct wim_dentry *dentry, void *_ignore)
{
+ dentry->needs_extraction = 0;
dentry->d_inode->i_visited = 0;
return 0;
}
uint64_t bytes_per_progress = args->progress.extract.total_bytes / 100;
uint64_t next_progress = bytes_per_progress;
struct wim_lookup_table_entry *lte;
- struct wim_inode *inode;
struct wim_dentry *dentry;
int ret;
/* For each distinct stream to be extracted */
list_for_each_entry(lte, stream_list, extraction_list) {
- /* For each inode that contains the stream */
- list_for_each_entry(inode, <e->inode_list, i_lte_inode_list) {
- /* For each dentry that points to the inode */
- inode_for_each_dentry(dentry, inode) {
- /* Extract the dentry if it was not already
- * extracted */
- ret = maybe_apply_dentry(dentry, args);
- if (ret)
- return ret;
- if (progress_func &&
- args->progress.extract.completed_bytes >= next_progress)
+ /* For each dentry to be extracted that is a name for an inode
+ * containing the stream */
+ list_for_each_entry(dentry, <e->lte_dentry_list, tmp_list) {
+ /* Extract the dentry if it was not already
+ * extracted */
+ ret = maybe_apply_dentry(dentry, args);
+ if (ret)
+ return ret;
+ if (progress_func &&
+ args->progress.extract.completed_bytes >= next_progress)
+ {
+ progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS,
+ &args->progress);
+ if (args->progress.extract.completed_bytes >=
+ args->progress.extract.total_bytes)
{
- progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS,
- &args->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);
- }
+ next_progress = ~0ULL;
+ } else {
+ next_progress =
+ min (args->progress.extract.completed_bytes +
+ bytes_per_progress,
+ args->progress.extract.total_bytes);
}
}
}
if (ret)
goto out_ntfs_umount;
-
/* Build a list of the streams that need to be extracted */
find_streams_for_extraction(root,
&stream_list,
if (extract_flags & WIMLIB_EXTRACT_FLAG_TO_STDOUT) {
ret = extract_dentry_to_stdout(root);
- goto out_mark_inodes_unvisited;
+ goto out_dentry_reset_needs_extraction;
}
if (progress_func) {
ret = for_dentry_in_tree(root, maybe_apply_dentry, &args);
args.extract_flags &= ~WIMLIB_EXTRACT_FLAG_NO_STREAMS;
if (ret)
- goto out_mark_inodes_unvisited;
+ goto out_dentry_reset_needs_extraction;
if (progress_func) {
progress_func(WIMLIB_PROGRESS_MSG_EXTRACT_DIR_STRUCTURE_END,
args.target_realpath = realpath(target, NULL);
if (!args.target_realpath) {
ret = WIMLIB_ERR_NOMEM;
- goto out_mark_inodes_unvisited;
+ goto out_dentry_reset_needs_extraction;
}
args.target_realpath_len = tstrlen(args.target_realpath);
}
}
out_free_target_realpath:
FREE(args.target_realpath);
-out_mark_inodes_unvisited:
- for_dentry_in_tree(root, dentry_mark_inode_unvisited, NULL);
+out_dentry_reset_needs_extraction:
+ for_dentry_in_tree(root, dentry_reset_needs_extraction, NULL);
out_ntfs_umount:
#ifdef WITH_NTFS_3G
/* Unmount the NTFS volume */
return WIMLIB_ERR_INVALID_PARAM;
#ifdef __WIN32__
- /* Wanted UNIX data on Win32? */
+ /* Wanted UNIX data on Windows? */
if (extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) {
ERROR("Extracting UNIX data is not supported on Windows");
return WIMLIB_ERR_INVALID_PARAM;
WIMLIBAPI int
wimlib_extract_files(WIMStruct *wim,
int image,
- int default_extract_flags,
const struct wimlib_extract_command *cmds,
size_t num_cmds,
+ int default_extract_flags,
WIMStruct **additional_swms,
unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
int ret;
struct wimlib_extract_command *cmds_copy;
- struct wim_lookup_table *wim_tab_save, *joined_tab;
int all_flags = 0;
default_extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
if (num_cmds == 0)
goto out;
- if (num_additional_swms) {
- ret = new_joined_lookup_table(wim, additional_swms,
- num_additional_swms,
- &joined_tab);
- if (ret)
- goto out;
- wim_tab_save = wim->lookup_table;
- wim->lookup_table = joined_tab;
- }
+ if (num_additional_swms)
+ merge_lookup_tables(wim, additional_swms, num_additional_swms);
cmds_copy = CALLOC(num_cmds, sizeof(cmds[0]));
if (!cmds_copy) {
}
FREE(cmds_copy);
out_restore_lookup_table:
- if (num_additional_swms) {
- free_lookup_table(wim->lookup_table);
- wim->lookup_table = wim_tab_save;
- }
+ if (num_additional_swms)
+ unmerge_lookup_table(wim);
out:
return ret;
}
unsigned num_additional_swms,
wimlib_progress_func_t progress_func)
{
- struct wim_lookup_table *joined_tab, *wim_tab_save;
int ret;
extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC;
if (ret)
return ret;
- if (num_additional_swms) {
- ret = new_joined_lookup_table(wim, additional_swms,
- num_additional_swms, &joined_tab);
- if (ret)
- return ret;
- wim_tab_save = wim->lookup_table;
- wim->lookup_table = joined_tab;
- }
+ if (num_additional_swms)
+ merge_lookup_tables(wim, additional_swms, num_additional_swms);
if (image == WIMLIB_ALL_IMAGES) {
- extract_flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE;
- ret = extract_all_images(wim, target, extract_flags,
+ ret = extract_all_images(wim, target,
+ extract_flags | WIMLIB_EXTRACT_FLAG_MULTI_IMAGE,
progress_func);
} else {
- extract_flags &= ~WIMLIB_EXTRACT_FLAG_MULTI_IMAGE;
ret = extract_single_image(wim, image, target, extract_flags,
progress_func);
}
lte_free_extracted_file,
NULL);
}
- if (num_additional_swms) {
- free_lookup_table(wim->lookup_table);
- wim->lookup_table = wim_tab_save;
- }
+ if (num_additional_swms)
+ unmerge_lookup_table(wim);
return ret;
}