X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fextract.c;h=a087a76d48adbfad43409e8fe75d038c09906c1a;hb=c5ca51d282da984a92074acdc8977ed580e8cdd5;hp=235d504c47a49832a44deac9b9184cae206c8200;hpb=dc9916cb5419320b2c570af2b81e92f3d26b6e4f;p=wimlib diff --git a/src/extract.c b/src/extract.c index 235d504c..a087a76d 100644 --- a/src/extract.c +++ b/src/extract.c @@ -53,7 +53,6 @@ #include "wimlib/reparse.h" #include "wimlib/resource.h" #include "wimlib/security.h" -#include "wimlib/swm.h" #ifdef __WIN32__ # include "wimlib/win32.h" /* for realpath() equivalent */ #endif @@ -1119,6 +1118,11 @@ hardlink: return 0; } +/* This is a wrapper around do_dentry_extract_skeleton() that handles building + * the path, doing short name reordering. This is also idempotent; dentries + * already processed have skeleton_extracted set and no action is taken. See + * apply_operations.requires_short_name_reordering for more details about short + * name reordering. */ static int dentry_extract_skeleton(struct wim_dentry *dentry, void *_ctx) { @@ -1128,32 +1132,18 @@ dentry_extract_skeleton(struct wim_dentry *dentry, void *_ctx) struct wim_dentry *other_dentry; int ret; - /* Here we may re-order the extraction of multiple names (hard links) - * for the same file in the same directory in order to ensure the short - * (DOS) name is set correctly. A short name is always associated with - * exactly one long name, and at least on NTFS, only one long name for a - * file can have a short name associated with it. (More specifically, - * there can be unlimited names in the POSIX namespace, but only one - * name can be in the Win32+DOS namespace, or one name in the Win32 - * namespace with a corresponding name in the DOS namespace.) To ensure - * the short name of a file is associated with the correct long name in - * a directory, we extract the long name with a corresponding short name - * before any additional names. This can affect NTFS-3g extraction - * (which uses ntfs_set_ntfs_dos_name(), which doesn't allow specifying - * the long name to associate with a short name) and may affect Win32 - * extraction as well (which uses SetFileShortName()). */ - if (dentry->skeleton_extracted) return 0; + orig_dentry = NULL; if (ctx->supported_features.short_names + && ctx->ops->requires_short_name_reordering && !dentry_has_short_name(dentry) && !dentry->d_inode->i_dos_name_extracted) { inode_for_each_dentry(other_dentry, dentry->d_inode) { if (dentry_has_short_name(other_dentry) - && !other_dentry->skeleton_extracted - && other_dentry->parent == dentry->parent) + && !other_dentry->skeleton_extracted) { DEBUG("Creating %"TS" before %"TS" " "to guarantee correct DOS name extraction", @@ -1183,6 +1173,14 @@ again: return 0; } +static int +dentry_extract_dir_skeleton(struct wim_dentry *dentry, void *_ctx) +{ + if (dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) + return dentry_extract_skeleton(dentry, _ctx); + return 0; +} + /* Create a file or directory, then immediately extract all streams. This * assumes that WIMLIB_EXTRACT_FLAG_SEQUENTIAL is not specified, since the WIM * may not be read sequentially by this function. */ @@ -1428,7 +1426,7 @@ extract_streams_from_pipe(struct apply_ctx *ctx) if ((found_lte->resource_location != RESOURCE_NONEXISTENT) && !(found_lte->resource_entry.flags & WIM_RESHDR_FLAG_METADATA) - && (needed_lte = __lookup_resource(lookup_table, found_lte->hash)) + && (needed_lte = lookup_resource(lookup_table, found_lte->hash)) && (needed_lte->out_refcnt)) { copy_resource_entry(&needed_lte->resource_entry, @@ -1803,20 +1801,13 @@ dentry_tally_features(struct wim_dentry *dentry, void *_features) return 0; } -static int -dentry_clear_inode_visited(struct wim_dentry *dentry, void *_ignore) -{ - dentry->d_inode->i_visited = 0; - return 0; -} - /* Tally the features necessary to extract a dentry tree. */ static void dentry_tree_get_features(struct wim_dentry *root, struct wim_features *features) { memset(features, 0, sizeof(struct wim_features)); for_dentry_in_tree(root, dentry_tally_features, features); - for_dentry_in_tree(root, dentry_clear_inode_visited, NULL); + dentry_tree_clear_inode_visited(root); } static u32 @@ -2322,6 +2313,13 @@ extract_tree(WIMStruct *wim, const tchar *wim_source_path, const tchar *target, ctx.realtarget_nchars = tstrlen(ctx.realtarget); } + if (ctx.ops->requires_short_name_reordering) { + ret = for_dentry_in_tree(root, dentry_extract_dir_skeleton, + &ctx); + if (ret) + goto out_free_realtarget; + } + /* Finally, the important part: extract the tree of files. */ if (extract_flags & (WIMLIB_EXTRACT_FLAG_SEQUENTIAL | WIMLIB_EXTRACT_FLAG_FROM_PIPE)) { @@ -2562,8 +2560,6 @@ wimlib_extract_files(WIMStruct *wim, 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; @@ -2572,21 +2568,12 @@ wimlib_extract_files(WIMStruct *wim, default_extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC; - ret = verify_swm_set(wim, additional_swms, num_additional_swms); - if (ret) - goto out; - if (num_cmds == 0) - goto out; - - if (num_additional_swms) - merge_lookup_tables(wim, additional_swms, num_additional_swms); + return 0; cmds_copy = CALLOC(num_cmds, sizeof(cmds[0])); - if (!cmds_copy) { - ret = WIMLIB_ERR_NOMEM; - goto out_restore_lookup_table; - } + if (!cmds_copy) + return WIMLIB_ERR_NOMEM; for (size_t i = 0; i < num_cmds; i++) { cmds_copy[i].extract_flags = (default_extract_flags | @@ -2623,10 +2610,6 @@ out_free_cmds_copy: FREE(cmds_copy[i].fs_dest_path); } FREE(cmds_copy); -out_restore_lookup_table: - if (num_additional_swms) - unmerge_lookup_table(wim); -out: return ret; } @@ -2747,24 +2730,10 @@ do_wimlib_extract_image(WIMStruct *wim, int image, const tchar *target, int extract_flags, - WIMStruct **additional_swms, - unsigned num_additional_swms, wimlib_progress_func_t progress_func) { int ret; - if (extract_flags & WIMLIB_EXTRACT_FLAG_FROM_PIPE) { - wimlib_assert(wim->hdr.part_number == 1); - wimlib_assert(num_additional_swms == 0); - } else { - ret = verify_swm_set(wim, additional_swms, num_additional_swms); - if (ret) - return ret; - - if (num_additional_swms) - merge_lookup_tables(wim, additional_swms, num_additional_swms); - } - if (image == WIMLIB_ALL_IMAGES) { ret = extract_all_images(wim, target, extract_flags, progress_func); @@ -2780,8 +2749,6 @@ do_wimlib_extract_image(WIMStruct *wim, lte_free_extracted_file, NULL); } - if (num_additional_swms) - unmerge_lookup_table(wim); return ret; } @@ -2935,7 +2902,7 @@ wimlib_extract_image_from_pipe(int pipe_fd, const tchar *image_num_or_name, /* Extract the image. */ extract_flags |= WIMLIB_EXTRACT_FLAG_FROM_PIPE; ret = do_wimlib_extract_image(pwm, image, target, - extract_flags, NULL, 0, progress_func); + extract_flags, progress_func); /* Clean up and return. */ out_wimlib_free: wimlib_free(pwm); @@ -2948,12 +2915,9 @@ wimlib_extract_image(WIMStruct *wim, int image, const tchar *target, int extract_flags, - WIMStruct **additional_swms, - unsigned num_additional_swms, wimlib_progress_func_t progress_func) { extract_flags &= WIMLIB_EXTRACT_MASK_PUBLIC; return do_wimlib_extract_image(wim, image, target, extract_flags, - additional_swms, num_additional_swms, progress_func); }