X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fextract.c;h=706282e00306dc73e465cca403c9268758cd95e0;hp=c794620d590c170c222d79fe233f8dd7e118140c;hb=9b53e465be528eb95ede2c464e603f5d79873794;hpb=aac0f095b5ed1273f91d87009f3b551eedcee085 diff --git a/src/extract.c b/src/extract.c index c794620d..706282e0 100644 --- a/src/extract.c +++ b/src/extract.c @@ -54,11 +54,11 @@ #include "wimlib/metadata.h" #include "wimlib/pathlist.h" #include "wimlib/paths.h" +#include "wimlib/pattern.h" #include "wimlib/reparse.h" #include "wimlib/resource.h" #include "wimlib/security.h" #include "wimlib/unix_data.h" -#include "wimlib/wildcard.h" #include "wimlib/wim.h" #include "wimlib/win32.h" /* for realpath() equivalent */ #include "wimlib/xml.h" @@ -341,30 +341,9 @@ extract_chunk_wrapper(const void *chunk, size_t size, void *_ctx) if (ret) return ret; - if (progress->extract.completed_bytes >= - progress->extract.total_bytes) - { - ctx->next_progress = UINT64_MAX; - } else { - /* Send new message as soon as another 1/128 of the - * total has been extracted. (Arbitrary number.) */ - ctx->next_progress = - progress->extract.completed_bytes + - progress->extract.total_bytes / 128; - - /* ... Unless that would be more than 5000000 bytes, in - * which case send the next after the next 5000000 - * bytes. (Another arbitrary number.) */ - if (progress->extract.completed_bytes + 5000000 < - ctx->next_progress) - ctx->next_progress = - progress->extract.completed_bytes + 5000000; - - /* ... But always send a message as soon as we're - * completely done. */ - if (progress->extract.total_bytes < ctx->next_progress) - ctx->next_progress = progress->extract.total_bytes; - } + set_next_progress(progress->extract.completed_bytes, + progress->extract.total_bytes, + &ctx->next_progress); } if (unlikely(filedes_valid(&ctx->tmpfile_fd))) { @@ -522,14 +501,14 @@ remove_duplicate_trees(struct wim_dentry **trees, size_t num_trees) { size_t i, j = 0; for (i = 0; i < num_trees; i++) { - if (!trees[i]->tmp_flag) { + if (!trees[i]->d_tmp_flag) { /* Found distinct dentry. */ - trees[i]->tmp_flag = 1; + trees[i]->d_tmp_flag = 1; trees[j++] = trees[i]; } } for (i = 0; i < j; i++) - trees[i]->tmp_flag = 0; + trees[i]->d_tmp_flag = 0; return j; } @@ -543,23 +522,23 @@ remove_contained_trees(struct wim_dentry **trees, size_t num_trees) { size_t i, j = 0; for (i = 0; i < num_trees; i++) - trees[i]->tmp_flag = 1; + trees[i]->d_tmp_flag = 1; for (i = 0; i < num_trees; i++) { struct wim_dentry *d = trees[i]; while (!dentry_is_root(d)) { d = d->d_parent; - if (d->tmp_flag) + if (d->d_tmp_flag) goto tree_contained; } trees[j++] = trees[i]; continue; tree_contained: - trees[i]->tmp_flag = 0; + trees[i]->d_tmp_flag = 0; } for (i = 0; i < j; i++) - trees[i]->tmp_flag = 0; + trees[i]->d_tmp_flag = 0; return j; } @@ -580,8 +559,10 @@ dentry_reset_extraction_list_node(struct wim_dentry *dentry) static int dentry_delete_from_list(struct wim_dentry *dentry, void *_ignore) { - list_del(&dentry->d_extraction_list_node); - dentry_reset_extraction_list_node(dentry); + if (will_extract_dentry(dentry)) { + list_del(&dentry->d_extraction_list_node); + dentry_reset_extraction_list_node(dentry); + } return 0; } @@ -643,7 +624,7 @@ destroy_dentry_list(struct list_head *dentry_list) dentry_reset_extraction_list_node(dentry); inode->i_visited = 0; inode->i_can_externally_back = 0; - if ((void *)dentry->d_extraction_name != (void *)dentry->file_name) + if ((void *)dentry->d_extraction_name != (void *)dentry->d_name) FREE(dentry->d_extraction_name); dentry->d_extraction_name = NULL; dentry->d_extraction_name_nchars = 0; @@ -694,16 +675,6 @@ file_name_valid(utf16lechar *name, size_t num_chars, bool fix) } } -#ifdef __WIN32__ - if (name[num_chars - 1] == cpu_to_le16(' ') || - name[num_chars - 1] == cpu_to_le16('.')) - { - if (fix) - name[num_chars - 1] = replacement_char; - else - return false; - } -#endif return true; } @@ -718,8 +689,8 @@ dentry_calculate_extraction_name(struct wim_dentry *dentry, #ifdef WITH_NTFS_3G if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) { - dentry->d_extraction_name = dentry->file_name; - dentry->d_extraction_name_nchars = dentry->file_name_nbytes / + dentry->d_extraction_name = dentry->d_name; + dentry->d_extraction_name_nchars = dentry->d_name_nbytes / sizeof(utf16lechar); return 0; } @@ -752,12 +723,13 @@ dentry_calculate_extraction_name(struct wim_dentry *dentry, } } - if (file_name_valid(dentry->file_name, dentry->file_name_nbytes / 2, false)) { - ret = utf16le_get_tstr(dentry->file_name, - dentry->file_name_nbytes, + if (file_name_valid(dentry->d_name, dentry->d_name_nbytes / 2, false)) { + size_t nbytes = 0; + ret = utf16le_get_tstr(dentry->d_name, + dentry->d_name_nbytes, (const tchar **)&dentry->d_extraction_name, - &dentry->d_extraction_name_nchars); - dentry->d_extraction_name_nchars /= sizeof(tchar); + &nbytes); + dentry->d_extraction_name_nchars = nbytes / sizeof(tchar); return ret; } else { if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES) @@ -777,16 +749,16 @@ dentry_calculate_extraction_name(struct wim_dentry *dentry, out_replace: { - utf16lechar utf16_name_copy[dentry->file_name_nbytes / 2]; + utf16lechar utf16_name_copy[dentry->d_name_nbytes / 2]; - memcpy(utf16_name_copy, dentry->file_name, dentry->file_name_nbytes); - file_name_valid(utf16_name_copy, dentry->file_name_nbytes / 2, true); + memcpy(utf16_name_copy, dentry->d_name, dentry->d_name_nbytes); + file_name_valid(utf16_name_copy, dentry->d_name_nbytes / 2, true); const tchar *tchar_name; size_t tchar_nchars; ret = utf16le_get_tstr(utf16_name_copy, - dentry->file_name_nbytes, + dentry->d_name_nbytes, &tchar_name, &tchar_nchars); if (ret) return ret; @@ -1080,18 +1052,14 @@ static void dentry_list_build_inode_alias_lists(struct list_head *dentry_list) { struct wim_dentry *dentry; - struct wim_inode *inode; + + list_for_each_entry(dentry, dentry_list, d_extraction_list_node) + dentry->d_inode->i_first_extraction_alias = NULL; list_for_each_entry(dentry, dentry_list, d_extraction_list_node) { - inode = dentry->d_inode; - if (!inode->i_visited) - INIT_LIST_HEAD(&inode->i_extraction_aliases); - list_add_tail(&dentry->d_extraction_alias_node, - &inode->i_extraction_aliases); - inode->i_visited = 1; + dentry->d_next_extraction_alias = dentry->d_inode->i_first_extraction_alias; + dentry->d_inode->i_first_extraction_alias = dentry; } - list_for_each_entry(dentry, dentry_list, d_extraction_list_node) - dentry->d_inode->i_visited = 0; } static void @@ -1526,22 +1494,6 @@ check_extract_flags(const WIMStruct *wim, int *extract_flags_p) return 0; } -static u32 -get_wildcard_flags(int extract_flags) -{ - u32 wildcard_flags = 0; - - if (extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_GLOB) - wildcard_flags |= WILDCARD_FLAG_ERROR_IF_NO_MATCH; - else - wildcard_flags |= WILDCARD_FLAG_WARN_IF_NO_MATCH; - - if (default_ignore_case) - wildcard_flags |= WILDCARD_FLAG_CASE_INSENSITIVE; - - return wildcard_flags; -} - struct append_dentry_ctx { struct wim_dentry **dentries; size_t num_dentries; @@ -1570,6 +1522,31 @@ append_dentry_cb(struct wim_dentry *dentry, void *_ctx) return 0; } +/* Append dentries matched by a path which can contain wildcard characters. */ +static int +append_matched_dentries(WIMStruct *wim, const tchar *orig_pattern, + int extract_flags, struct append_dentry_ctx *ctx) +{ + const size_t count_before = ctx->num_dentries; + tchar *pattern; + int ret; + + pattern = canonicalize_wim_path(orig_pattern); + if (!pattern) + return WIMLIB_ERR_NOMEM; + ret = expand_path_pattern(wim_get_current_root_dentry(wim), pattern, + append_dentry_cb, ctx); + FREE(pattern); + if (ret || ctx->num_dentries > count_before) + return ret; + if (extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_GLOB) { + ERROR("No matches for path pattern \"%"TS"\"", orig_pattern); + return WIMLIB_ERR_PATH_DOES_NOT_EXIST; + } + WARNING("No matches for path pattern \"%"TS"\"", orig_pattern); + return 0; +} + static int do_wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target, const tchar * const *paths, size_t num_paths, @@ -1612,20 +1589,10 @@ do_wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target, .num_alloc_dentries = 0, }; - u32 wildcard_flags = get_wildcard_flags(extract_flags); - for (size_t i = 0; i < num_paths; i++) { - tchar *path = canonicalize_wim_path(paths[i]); - if (path == NULL) { - ret = WIMLIB_ERR_NOMEM; - trees = append_dentry_ctx.dentries; - goto out_free_trees; - } - ret = expand_wildcard(wim, path, - append_dentry_cb, - &append_dentry_ctx, - wildcard_flags); - FREE(path); + ret = append_matched_dentries(wim, paths[i], + extract_flags, + &append_dentry_ctx); if (ret) { trees = append_dentry_ctx.dentries; goto out_free_trees;