X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fextract.c;h=b1f62b1268ddf02434829bccd416bdd133724c35;hb=93843920ce69aaac7414ea2eaaac54b85f6f5584;hp=ee82be2bf1e5df21f1adb86c97d60e81b63ec620;hpb=013617d583c028b1741bfc05c22e7a626b394174;p=wimlib diff --git a/src/extract.c b/src/extract.c index ee82be2b..b1f62b12 100644 --- a/src/extract.c +++ b/src/extract.c @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2012, 2013 Eric Biggers + * Copyright (C) 2012, 2013, 2014 Eric Biggers * * This file is part of wimlib, a library for working with WIM files. * @@ -26,9 +26,9 @@ /* * This file provides the API functions wimlib_extract_image(), - * wimlib_extract_image_from_pipe(), wimlib_extract_files(), - * wimlib_extract_paths(), and wimlib_extract_pathlist(). Internally, all end - * up calling do_wimlib_extract_paths() and extract_trees(). + * wimlib_extract_image_from_pipe(), wimlib_extract_paths(), and + * wimlib_extract_pathlist(). Internally, all end up calling + * do_wimlib_extract_paths() and extract_trees(). * * Although wimlib supports multiple extraction modes/backends (NTFS-3g, UNIX, * Win32), this file does not itself have code to extract files or directories @@ -68,8 +68,7 @@ #define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000 #define WIMLIB_EXTRACT_FLAG_FROM_PIPE 0x40000000 -#define WIMLIB_EXTRACT_FLAG_FILEMODE 0x20000000 -#define WIMLIB_EXTRACT_FLAG_IMAGEMODE 0x10000000 +#define WIMLIB_EXTRACT_FLAG_IMAGEMODE 0x20000000 /* Keep in sync with wimlib.h */ #define WIMLIB_EXTRACT_MASK_PUBLIC \ @@ -94,7 +93,8 @@ WIMLIB_EXTRACT_FLAG_GLOB_PATHS | \ WIMLIB_EXTRACT_FLAG_STRICT_GLOB | \ WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES | \ - WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE) + WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE | \ + WIMLIB_EXTRACT_FLAG_WIMBOOT) static bool dentry_in_list(const struct wim_dentry *dentry) @@ -494,7 +494,8 @@ extract_streams(const tchar *path, struct apply_ctx *ctx, } } else { ret = ctx->ops->extract_unnamed_stream( - file_spec, lte, ctx); + file_spec, lte, ctx, + dentry); if (ret) goto error; } @@ -1658,17 +1659,11 @@ dentry_reset_extraction_list_node(struct wim_dentry *dentry) dentry->extraction_list = (struct list_head){NULL, NULL}; } -static void -dentry_delete_from_list(struct wim_dentry *dentry) +static int +dentry_delete_from_list(struct wim_dentry *dentry, void *_ignore) { list_del(&dentry->extraction_list); dentry_reset_extraction_list_node(dentry); -} - -static int -do_dentry_delete_from_list(struct wim_dentry *dentry, void *_ignore) -{ - dentry_delete_from_list(dentry); return 0; } @@ -1795,8 +1790,8 @@ dentry_calculate_extraction_name(struct wim_dentry *dentry, if (!ctx->ops->supports_case_sensitive_filenames) { struct wim_dentry *other; - list_for_each_entry(other, &dentry->case_insensitive_conflict_list, - case_insensitive_conflict_list) + list_for_each_entry(other, &dentry->d_ci_conflict_list, + d_ci_conflict_list) { if (dentry_in_list(other)) { if (ctx->extract_flags & @@ -1885,7 +1880,7 @@ out_replace: return 0; skip_dentry: - for_dentry_in_tree(dentry, do_dentry_delete_from_list, NULL); + for_dentry_in_tree(dentry, dentry_delete_from_list, NULL); return 0; } @@ -1907,8 +1902,8 @@ dentry_list_calculate_extraction_names(struct list_head *dentry_list, struct list_head *prev, *cur; /* Can't use list_for_each_entry() because a call to - * dentry_calculate_extraction_name() may the current dentry and its - * children from the list. */ + * dentry_calculate_extraction_name() may delete the current dentry and + * its children from the list. */ prev = dentry_list; for (;;) { @@ -2440,21 +2435,7 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees, ctx.progress.extract.target = target; } - if (extract_flags & WIMLIB_EXTRACT_FLAG_FILEMODE) { - /* Called from wimlib_extract_files(). There should be only 1 - * tree, and directory structure should not be preserved. */ - wimlib_assert(num_trees == 1); - wimlib_assert(extract_flags & - WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE); - ret = calculate_dentry_full_path(trees[0]); - if (ret) - return ret; - ctx.progress.extract.extract_root_wim_source_path = trees[0]->_full_path; - ctx.target_dentry = trees[0]; - } else { - ctx.progress.extract.extract_root_wim_source_path = T(""); - ctx.target_dentry = wim_root_dentry(wim); - } + ctx.target_dentry = wim_root_dentry(wim); /* Note: ctx.target_dentry represents the dentry that gets extracted to * @target. There may be none, in which case it gets set to the image * root and never matches any of the dentries actually being extracted. @@ -2490,7 +2471,7 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees, * volume. */ ret = ctx.ops->start_extract(target, &ctx); if (ret) - return ret; + goto out_destroy_dentry_list; /* Get and check the features required to extract the dentries. */ dentry_list_get_features(&dentry_list, &required_features); @@ -2506,12 +2487,12 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees, * can't be extracted due to naming problems. */ ret = dentry_list_calculate_extraction_names(&dentry_list, &ctx); if (ret) - goto out_destroy_dentry_list; + goto out_finish_or_abort_extract; /* Build list of streams to extract. */ ret = dentry_list_resolve_streams(&dentry_list, &ctx); if (ret) - goto out_destroy_dentry_list; + goto out_finish_or_abort_extract; INIT_LIST_HEAD(&ctx.stream_list); ret = dentry_list_ref_streams(&dentry_list, &ctx); if (ret) @@ -2548,6 +2529,18 @@ extract_trees(WIMStruct *wim, struct wim_dentry **trees, size_t num_trees, goto out_destroy_stream_list; } ctx.realtarget_nchars = tstrlen(ctx.realtarget); + #ifdef __WIN32__ + /* Strip trailing slashes. If we don't do this, we may create a + * path with multiple consecutive backslashes, which for some + * reason causes Windows to report that the file cannot be found. + */ + while (ctx.realtarget_nchars >= 2 + && ctx.realtarget[ctx.realtarget_nchars - 1] == L'\\' + && ctx.realtarget[ctx.realtarget_nchars - 2] != L':') + { + ctx.realtarget[--ctx.realtarget_nchars] = L'\0'; + } + #endif } if (progress_func) { @@ -2677,8 +2670,6 @@ out_free_realtarget: out_destroy_stream_list: if (!(ctx.extract_flags & WIMLIB_EXTRACT_FLAG_FILE_ORDER)) destroy_stream_list(&ctx.stream_list); -out_destroy_dentry_list: - destroy_dentry_list(&dentry_list); out_finish_or_abort_extract: if (ret) { if (ctx.ops->abort_extract) @@ -2687,6 +2678,8 @@ out_finish_or_abort_extract: if (ctx.ops->finish_extract) ret = ctx.ops->finish_extract(&ctx); } +out_destroy_dentry_list: + destroy_dentry_list(&dentry_list); return ret; } @@ -2750,6 +2743,13 @@ check_extract_flags(const WIMStruct *wim, int *extract_flags_p) } #endif +#ifndef __WIN32__ + if (extract_flags & WIMLIB_EXTRACT_FLAG_WIMBOOT) { + ERROR("WIMBoot extraction is only supported on Windows!"); + return WIMLIB_ERR_UNSUPPORTED; + } +#endif + if ((extract_flags & (WIMLIB_EXTRACT_FLAG_RPFIX | WIMLIB_EXTRACT_FLAG_NORPFIX | WIMLIB_EXTRACT_FLAG_IMAGEMODE)) == @@ -2855,8 +2855,7 @@ do_wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target, return ret; if ((extract_flags & (WIMLIB_EXTRACT_FLAG_NTFS | - WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE | - WIMLIB_EXTRACT_FLAG_FILEMODE)) == + WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE)) == (WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE)) { ret = mkdir_if_needed(target); @@ -2937,7 +2936,7 @@ extract_single_image(WIMStruct *wim, int image, const tchar *target, int extract_flags, wimlib_progress_func_t progress_func) { - const tchar *path = T(""); + const tchar *path = WIMLIB_WIM_ROOT_PATH; extract_flags |= WIMLIB_EXTRACT_FLAG_IMAGEMODE; return do_wimlib_extract_paths(wim, image, target, &path, 1, extract_flags, progress_func); @@ -3046,67 +3045,6 @@ do_wimlib_extract_image(WIMStruct *wim, * Extraction API * ****************************************************************************/ -/* Note: new code should use wimlib_extract_paths() instead of - * wimlib_extract_files() if possible. */ -WIMLIBAPI int -wimlib_extract_files(WIMStruct *wim, int image, - const struct wimlib_extract_command *cmds, size_t num_cmds, - int default_extract_flags, - wimlib_progress_func_t progress_func) -{ - int all_flags = 0; - int link_flags; - int ret; - - if (num_cmds == 0) - return 0; - - default_extract_flags |= WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE; - - for (size_t i = 0; i < num_cmds; i++) { - int cmd_flags = (cmds[i].extract_flags | - default_extract_flags); - - if (cmd_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC) - return WIMLIB_ERR_INVALID_PARAM; - - int cmd_link_flags = (cmd_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | - WIMLIB_EXTRACT_FLAG_HARDLINK)); - if (i == 0) { - link_flags = cmd_link_flags; - } else { - if (cmd_link_flags != link_flags) { - ERROR("The same symlink or hardlink extraction mode " - "must be set on all extraction commands!"); - return WIMLIB_ERR_INVALID_PARAM; - } - } - all_flags |= cmd_flags; - } - if (all_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS) { - ERROR("Glob paths not supported for wimlib_extract_files(). " - "Use wimlib_extract_paths() instead."); - return WIMLIB_ERR_INVALID_PARAM; - } - - for (size_t i = 0; i < num_cmds; i++) { - int extract_flags = (cmds[i].extract_flags | - default_extract_flags); - const tchar *target = cmds[i].fs_dest_path; - const tchar *wim_source_path = cmds[i].wim_source_path; - - ret = do_wimlib_extract_paths(wim, image, target, - &wim_source_path, 1, - extract_flags | WIMLIB_EXTRACT_FLAG_FILEMODE, - progress_func); - if (ret) - break; - } - - clear_lte_extracted_file(wim, all_flags); - return ret; -} - WIMLIBAPI int wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target, const tchar * const *paths, size_t num_paths,