src/mount_image.c \
src/pathlist.c \
src/paths.c \
+ src/pattern.c \
src/progress.c \
src/resource.c \
src/reference.c \
src/update_image.c \
src/util.c \
src/verify.c \
- src/wildcard.c \
src/wim.c \
src/write.c \
src/xml.c \
include/wimlib/metadata.h \
include/wimlib/pathlist.h \
include/wimlib/paths.h \
+ include/wimlib/pattern.h \
include/wimlib/progress.h \
include/wimlib/reparse.h \
include/wimlib/resource.h \
include/wimlib/unaligned.h \
include/wimlib/unix_data.h \
include/wimlib/util.h \
- include/wimlib/wildcard.h \
include/wimlib/wim.h \
include/wimlib/write.h \
include/wimlib/xml.h \
destroy_capture_config(struct capture_config *config);
extern bool
-match_pattern_list(const tchar *path, size_t path_nchars,
- const struct string_set *list);
+match_pattern_list(const tchar *path, const struct string_set *list);
extern int
-try_exclude(const tchar *full_path, size_t full_path_nchars,
- const struct capture_params *params);
+try_exclude(const tchar *full_path, const struct capture_params *params);
typedef int (*capture_tree_t)(struct wim_dentry **, const tchar *,
struct capture_params *);
--- /dev/null
+#ifndef _WIMLIB_PATTERN_H
+#define _WIMLIB_PATTERN_H
+
+#include "wimlib/types.h"
+
+struct wim_dentry;
+
+extern bool
+match_path(const tchar *path, const tchar *pattern, bool prefix_ok);
+
+extern int
+expand_path_pattern(struct wim_dentry *root, const tchar *pattern,
+ int (*consume_dentry)(struct wim_dentry *, void *),
+ void *ctx);
+
+#endif /* _WIMLIB_PATTERN_H */
+++ /dev/null
-#ifndef _WIMLIB_WILDCARD_H
-#define _WIMLIB_WILDCARD_H
-
-#include "wimlib/types.h"
-
-struct wim_dentry;
-
-#define WILDCARD_FLAG_WARN_IF_NO_MATCH 0x00000001
-#define WILDCARD_FLAG_ERROR_IF_NO_MATCH 0x00000002
-#define WILDCARD_FLAG_CASE_INSENSITIVE 0x00000004
-
-extern int
-expand_wildcard(WIMStruct *wim,
- const tchar *wildcard_path,
- int (*consume_dentry)(struct wim_dentry *, void *),
- void *consume_dentry_ctx,
- u32 flags);
-
-extern bool
-match_path(const tchar *path, size_t path_nchars,
- const tchar *wildcard, tchar path_sep, bool prefix_ok);
-
-#endif /* _WIMLIB_WILDCARD_H */
#include "wimlib/dentry.h"
#include "wimlib/error.h"
#include "wimlib/paths.h"
+#include "wimlib/pattern.h"
#include "wimlib/progress.h"
#include "wimlib/textfile.h"
-#include "wimlib/wildcard.h"
/*
* Tally a file (or directory) that has been scanned for a capture operation,
}
/*
- * Determine whether a path matches any wildcard pattern in a list.
- *
- * Special rules apply about what form @path must be in; see match_path().
+ * Determine whether @path, or any ancestor directory of @path, matches any of
+ * the patterns in @list. Path separators in @path must be WIM_PATH_SEPARATOR.
*/
bool
-match_pattern_list(const tchar *path, size_t path_nchars,
- const struct string_set *list)
+match_pattern_list(const tchar *path, const struct string_set *list)
{
for (size_t i = 0; i < list->num_strings; i++)
- if (match_path(path, path_nchars, list->strings[i],
- OS_PREFERRED_PATH_SEPARATOR, true))
+ if (match_path(path, list->strings[i], true))
return true;
return false;
}
-/*
- * Determine whether the filesystem @path should be excluded from capture, based
- * on the current capture configuration file.
- *
- * The @path must be given relative to the root of the capture, but with a
- * leading path separator. For example, if the file "in/file" is being tested
- * and the library user ran wimlib_add_image(wim, "in", ...), then the directory
- * "in" is the root of the capture and the path should be specified as "/file".
- *
- * Also, all path separators in @path must be OS_PREFERRED_PATH_SEPARATOR, there
- * cannot be trailing slashes, and there cannot be consecutive path separators.
- *
- * As a special case, the empty string will be interpreted as a single path
- * separator (which means the root of capture itself).
- */
-static bool
-should_exclude_path(const tchar *path, size_t path_nchars,
- const struct capture_config *config)
-{
- tchar dummy[2];
-
- if (!config)
- return false;
-
- if (!*path) {
- dummy[0] = OS_PREFERRED_PATH_SEPARATOR;
- dummy[1] = T('\0');
- path = dummy;
- path_nchars = 1;
- }
-
- return match_pattern_list(path, path_nchars, &config->exclusion_pats) &&
- !match_pattern_list(path, path_nchars, &config->exclusion_exception_pats);
-
-}
-
/*
* Determine if a file should be excluded from capture.
*
- * This function tests exclusions from both of the two possible sources of
- * exclusions:
+ * This function tests exclusions from both possible sources of exclusions:
*
* (1) The capture configuration file
* (2) The user-provided progress function
* appropriate value. Example for UNIX: if the capture root directory is
* "foobar/subdir", then all paths will be provided starting with
* "foobar/subdir", so params->capture_root_nchars must be set to
- * strlen("foobar/subdir") so that try_exclude() can use the appropriate suffix
- * when it calls should_exclude_path().
- *
+ * strlen("foobar/subdir") so that the appropriate path can be matched against
+ * the patterns in the exclusion list.
*
* Returns:
* < 0 if excluded
* > 0 (wimlib error code) if error
*/
int
-try_exclude(const tchar *full_path, size_t full_path_nchars,
- const struct capture_params *params)
+try_exclude(const tchar *full_path, const struct capture_params *params)
{
int ret;
- if (should_exclude_path(full_path + params->capture_root_nchars,
- full_path_nchars - params->capture_root_nchars,
- params->config))
- return -1;
+ if (params->config) {
+ const tchar *path = full_path + params->capture_root_nchars;
+ if (match_pattern_list(path, ¶ms->config->exclusion_pats) &&
+ !match_pattern_list(path, ¶ms->config->exclusion_exception_pats))
+ return -1;
+ }
if (unlikely(params->add_flags & WIMLIB_ADD_FLAG_TEST_FILE_EXCLUSION)) {
union wimlib_progress_info info;
#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"
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;
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,
.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;
struct wim_inode *inode = NULL;
ntfs_inode *ni = NULL;
- ret = try_exclude(path, path_len, params);
- if (ret < 0) /* Excluded? */
+ ret = try_exclude(path, params);
+ if (unlikely(ret < 0)) /* Excluded? */
goto out_progress;
- if (ret > 0) /* Error? */
+ if (unlikely(ret > 0)) /* Error? */
goto out;
ni = ntfs_inode_open(volume->vol, mref);
--- /dev/null
+/*
+ * pattern.c
+ *
+ * Wildcard pattern matching functions.
+ */
+
+/*
+ * Copyright (C) 2013, 2015 Eric Biggers
+ *
+ * This file is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This file is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, see http://www.gnu.org/licenses/.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <ctype.h>
+
+#include "wimlib/dentry.h"
+#include "wimlib/encoding.h"
+#include "wimlib/paths.h"
+#include "wimlib/pattern.h"
+
+static bool
+string_matches_pattern(const tchar *string, const tchar * const string_end,
+ const tchar *pattern, const tchar * const pattern_end)
+{
+ for (; string != string_end; string++, pattern++) {
+ if (pattern == pattern_end)
+ return false;
+ if (*pattern == T('*')) {
+ return string_matches_pattern(string, string_end,
+ pattern + 1, pattern_end) ||
+ string_matches_pattern(string + 1, string_end,
+ pattern, pattern_end);
+ }
+ if (*string != *pattern && *pattern != T('?') &&
+ !(default_ignore_case &&
+ totlower(*string) == totlower(*pattern)))
+ return false;
+ }
+
+ while (pattern != pattern_end && *pattern == T('*'))
+ pattern++;
+ return pattern == pattern_end;
+}
+
+/* Advance past zero or more path separators. */
+static const tchar *
+advance_to_next_component(const tchar *p)
+{
+ while (*p == WIM_PATH_SEPARATOR)
+ p++;
+ return p;
+}
+
+/* Advance past a nonempty path component. */
+static const tchar *
+advance_through_component(const tchar *p)
+{
+ do {
+ p++;
+ } while (*p && *p != WIM_PATH_SEPARATOR);
+ return p;
+}
+
+/*
+ * Determine whether a path matches a wildcard pattern.
+ *
+ * @path
+ * The null-terminated path string to match.
+ * @pattern
+ * The null-terminated wildcard pattern to match. It can contain the
+ * wildcard characters '*' (which matches zero or more characters) and '?'
+ * (which matches any single character). If there is no leading path
+ * separator, then the match is attempted with the filename component of
+ * @path only; otherwise, the match is attempted with the entire @path.
+ * @prefix_ok
+ * If %true, also allow a prefix of @path terminated by a path separator
+ * (a.k.a. an ancestor directory) to match the pattern.
+ *
+ * @path and @pattern can both contain path separators (character
+ * WIM_PATH_SEPARATOR). Leading and trailing path separators are not
+ * significant, except when determining whether to match only the filename
+ * component as noted above. The lengths of interior path separator sequences
+ * are not significant. The '*' and '?' characters act within a single path
+ * component only (they do not match path separators).
+ *
+ * Matching is done with the default case sensitivity behavior.
+ *
+ * Returns %true iff the path matched the pattern.
+ */
+bool
+match_path(const tchar *path, const tchar *pattern, bool prefix_ok)
+{
+ /* Filename only? */
+ if (*pattern != WIM_PATH_SEPARATOR)
+ path = path_basename(path);
+
+ for (;;) {
+ const tchar *path_component_end;
+ const tchar *pattern_component_end;
+
+ path = advance_to_next_component(path);
+ pattern = advance_to_next_component(pattern);
+
+ /* Is the pattern exhausted? */
+ if (!*pattern)
+ return !*path || prefix_ok;
+
+ /* Is the path exhausted (but not the pattern)? */
+ if (!*path)
+ return false;
+
+ path_component_end = advance_through_component(path);
+ pattern_component_end = advance_through_component(pattern);
+
+ /* Do the components match? */
+ if (!string_matches_pattern(path, path_component_end,
+ pattern, pattern_component_end))
+ return false;
+
+ path = path_component_end;
+ pattern = pattern_component_end;
+ }
+}
+
+/*
+ * Expand a path pattern in an in-memory tree of dentries.
+ *
+ * @root
+ * The root of the directory tree in which to expand the pattern.
+ * @pattern
+ * The path pattern to expand, which may contain the '*' and '?' wildcard
+ * characters. Path separators must be WIM_PATH_SEPARATOR. Leading and
+ * trailing path separators are ignored. The default case sensitivity
+ * behavior is used.
+ * @consume_dentry
+ * A callback function which will receive each matched directory entry.
+ * @ctx
+ * Opaque context argument for @consume_dentry.
+ *
+ * @return 0 on success; a positive error code on failure; or the first nonzero
+ * value returned by @consume_dentry.
+ */
+int
+expand_path_pattern(struct wim_dentry *root, const tchar *pattern,
+ int (*consume_dentry)(struct wim_dentry *, void *),
+ void *ctx)
+{
+ const tchar *pattern_component_end;
+ struct wim_dentry *child;
+
+ if (!root)
+ return 0;
+
+ pattern = advance_to_next_component(pattern);
+
+ /* If there are no more components, then 'root' is matched. */
+ if (!*pattern)
+ return (*consume_dentry)(root, ctx);
+
+ pattern_component_end = advance_through_component(pattern);
+
+ /* For each child dentry that matches the current pattern component,
+ * recurse with the remainder of the pattern. */
+ for_dentry_child(child, root) {
+ const tchar *name;
+ size_t name_nbytes;
+ int ret;
+
+ ret = utf16le_get_tstr(child->d_name, child->d_name_nbytes,
+ &name, &name_nbytes);
+ if (ret)
+ return ret;
+
+ if (string_matches_pattern(name, &name[name_nbytes / sizeof(tchar)],
+ pattern, pattern_component_end))
+ ret = expand_path_pattern(child, pattern_component_end,
+ consume_dentry, ctx);
+ utf16le_put_tstr(name);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
struct stat stbuf;
int stat_flags;
- ret = try_exclude(full_path, full_path_len, params);
- if (ret < 0) /* Excluded? */
+ ret = try_exclude(full_path, params);
+ if (unlikely(ret < 0)) /* Excluded? */
goto out_progress;
- if (ret > 0) /* Error? */
+ if (unlikely(ret > 0)) /* Error? */
goto out;
if (params->add_flags & (WIMLIB_ADD_FLAG_DEREFERENCE |
+++ /dev/null
-/*
- * wildcard.c
- *
- * Wildcard matching functions.
- */
-
-/*
- * Copyright (C) 2013 Eric Biggers
- *
- * This file is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option) any
- * later version.
- *
- * This file is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this file; if not, see http://www.gnu.org/licenses/.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <ctype.h>
-
-#include "wimlib/dentry.h"
-#include "wimlib/encoding.h"
-#include "wimlib/error.h"
-#include "wimlib/metadata.h"
-#include "wimlib/paths.h"
-#include "wimlib/wildcard.h"
-
-struct match_dentry_ctx {
- int (*consume_dentry)(struct wim_dentry *, void *);
- void *consume_dentry_ctx;
- size_t consume_dentry_count;
- tchar *wildcard_path;
- size_t cur_component_offset;
- size_t cur_component_len;
- bool case_insensitive;
-};
-
-static bool
-do_match_wildcard(const tchar *string, size_t string_len,
- const tchar *wildcard, size_t wildcard_len,
- bool ignore_case)
-{
- for (;;) {
- if (string_len == 0) {
- while (wildcard_len != 0 && *wildcard == T('*')) {
- wildcard++;
- wildcard_len--;
- }
- return (wildcard_len == 0);
- } else if (wildcard_len == 0) {
- return false;
- } else if (*string == *wildcard || *wildcard == T('?') ||
- (ignore_case && totlower(*string) == totlower(*wildcard)))
- {
- string++;
- string_len--;
- wildcard_len--;
- wildcard++;
- continue;
- } else if (*wildcard == T('*')) {
- return do_match_wildcard(string, string_len,
- wildcard + 1, wildcard_len - 1,
- ignore_case) ||
- do_match_wildcard(string + 1, string_len - 1,
- wildcard, wildcard_len,
- ignore_case);
- } else {
- return false;
- }
- }
-}
-
-static bool
-match_wildcard(const tchar *string, const tchar *wildcard,
- size_t wildcard_len, bool ignore_case)
-{
- return do_match_wildcard(string, tstrlen(string),
- wildcard, wildcard_len, ignore_case);
-}
-
-/*
- * Determines whether a path matches a wildcard pattern.
- *
- * @path
- * The path to match. Assumptions: All path separators must be @path_sep,
- * there cannot be consecutive path separators, there cannot be a trailing
- * path separator, and there must be exactly one leading path separator.
- *
- * @path_nchars
- * Number of characters in @path.
- *
- * @wildcard
- * The wildcard pattern to match. It can contain the wildcard characters
- * '*' and '?'. The former matches zero or more characters except
- * @path_sep, and the latter matches any character except @path_sep. All
- * path separators in the pattern must be @path_sep, and there cannot be
- * consecutive path separators, and there cannot be a trailing path
- * separator. If there is a leading path separator, the match is attempted
- * with the filename only; otherwise, the match is attempted with the whole
- * path.
- *
- * @path_sep
- * Path separator character used in @path and @wildcard.
- *
- * @prefix_ok
- * If %true, allow a prefix of @path, terminated by a path separator, to
- * match the pattern, in addition to @path itself. In other words, return
- * %true if the pattern actually matches one of the ancestor directories of
- * @path.
- *
- * Returns %true if there was a match; %false if there was not.
- */
-bool
-match_path(const tchar *path, size_t path_nchars,
- const tchar *wildcard, tchar path_sep, bool prefix_ok)
-{
- if (*wildcard != path_sep) {
- /* Pattern doesn't begin with path separator. Try to match the
- * file name only. */
- return match_wildcard(path_basename_with_len(path, path_nchars),
- wildcard, tstrlen(wildcard),
- default_ignore_case);
- } else {
- /* Pattern begins with path separator. Try to match the whole
- * path. */
- do {
- if (!*wildcard) {
- /* Path has more components than pattern */
- return prefix_ok;
- }
-
- size_t path_component_len = 0;
- size_t wildcard_component_len = 0;
-
- do {
- path_component_len++;
- } while (path[path_component_len] != path_sep &&
- path[path_component_len] != T('\0'));
- do {
- wildcard_component_len++;
- } while (wildcard[wildcard_component_len] != path_sep &&
- wildcard[wildcard_component_len] != T('\0'));
- if (!do_match_wildcard(path, path_component_len,
- wildcard, wildcard_component_len,
- default_ignore_case))
- return false;
- path += path_component_len;
- wildcard += wildcard_component_len;
- } while (*path);
-
- return (*wildcard == '\0');
- }
-}
-
-static int
-expand_wildcard_recursive(struct wim_dentry *cur_dentry,
- struct match_dentry_ctx *ctx);
-
-enum {
- WILDCARD_STATUS_DONE_FULLY,
- WILDCARD_STATUS_DONE_TRAILING_SLASHES,
- WILDCARD_STATUS_NOT_DONE,
-};
-
-static int
-wildcard_status(const tchar *wildcard)
-{
- if (*wildcard == T('\0'))
- return WILDCARD_STATUS_DONE_FULLY;
- while (*wildcard == WIM_PATH_SEPARATOR)
- wildcard++;
- if (*wildcard == T('\0'))
- return WILDCARD_STATUS_DONE_TRAILING_SLASHES;
-
- return WILDCARD_STATUS_NOT_DONE;
-}
-
-static int
-match_dentry(struct wim_dentry *cur_dentry, struct match_dentry_ctx *ctx)
-{
- const tchar *name;
- size_t name_nchars;
- int ret;
-
- if (cur_dentry->d_name_nbytes == 0)
- return 0;
-
- ret = utf16le_get_tstr(cur_dentry->d_name,
- cur_dentry->d_name_nbytes,
- &name, &name_nchars);
- if (ret)
- return ret;
- name_nchars /= sizeof(tchar);
-
- if (do_match_wildcard(name,
- name_nchars,
- &ctx->wildcard_path[ctx->cur_component_offset],
- ctx->cur_component_len,
- ctx->case_insensitive))
- {
- switch (wildcard_status(&ctx->wildcard_path[
- ctx->cur_component_offset +
- ctx->cur_component_len]))
- {
- case WILDCARD_STATUS_DONE_TRAILING_SLASHES:
- if (!dentry_is_directory(cur_dentry)) {
- ret = 0;
- break;
- }
- /* Fall through */
- case WILDCARD_STATUS_DONE_FULLY:
- ret = (*ctx->consume_dentry)(cur_dentry,
- ctx->consume_dentry_ctx);
- ctx->consume_dentry_count++;
- break;
- case WILDCARD_STATUS_NOT_DONE:
- ret = expand_wildcard_recursive(cur_dentry, ctx);
- break;
- }
- } else {
- ret = 0;
- }
-
- utf16le_put_tstr(name);
-
- return ret;
-}
-
-static int
-expand_wildcard_recursive(struct wim_dentry *cur_dentry,
- struct match_dentry_ctx *ctx)
-{
- tchar *w;
- size_t begin;
- size_t end;
- size_t len;
- size_t offset_save;
- size_t len_save;
- int ret;
- struct wim_dentry *child;
-
- w = ctx->wildcard_path;
-
- begin = ctx->cur_component_offset + ctx->cur_component_len;
- while (w[begin] == WIM_PATH_SEPARATOR)
- begin++;
-
- end = begin;
-
- while (w[end] != T('\0') && w[end] != WIM_PATH_SEPARATOR)
- end++;
-
- len = end - begin;
-
- if (len == 0)
- return 0;
-
- offset_save = ctx->cur_component_offset;
- len_save = ctx->cur_component_len;
-
- ctx->cur_component_offset = begin;
- ctx->cur_component_len = len;
-
- ret = 0;
- for_dentry_child(child, cur_dentry) {
- ret = match_dentry(child, ctx);
- if (ret)
- break;
- }
-
- ctx->cur_component_len = len_save;
- ctx->cur_component_offset = offset_save;
-
- return ret;
-}
-
-/* Expand a wildcard relative to the current WIM image.
- *
- * @wim
- * WIMStruct whose currently selected image is searched to expand the
- * wildcard.
- * @wildcard_path
- * Wildcard path to expand, which may contain the '?' and '*' characters.
- * Path separators must be WIM_PATH_SEPARATOR. Leading path separators are
- * ignored, whereas one or more trailing path separators indicate that the
- * wildcard path can only match directories (and not reparse points).
- * @consume_dentry
- * Callback function which will receive each directory entry matched by the
- * wildcard.
- * @consume_dentry_ctx
- * Argument to pass to @consume_dentry.
- * @flags
- * Zero or more of the following flags:
- *
- * WILDCARD_FLAG_WARN_IF_NO_MATCH:
- * Issue a warning if the wildcard does not match any dentries.
- *
- * WILDCARD_FLAG_ERROR_IF_NO_MATCH:
- * Issue an error and return WIMLIB_ERR_PATH_DOES_NOT_EXIST if the
- * wildcard does not match any dentries.
- *
- * WILDCARD_FLAG_CASE_INSENSITIVE:
- * Perform the matching case insensitively. Note that this may
- * cause @wildcard to match multiple dentries, even if it does not
- * contain wildcard characters.
- *
- * @return 0 on success; a positive error code on error; or the first nonzero
- * value returned by @consume_dentry.
- */
-int
-expand_wildcard(WIMStruct *wim,
- const tchar *wildcard_path,
- int (*consume_dentry)(struct wim_dentry *, void *),
- void *consume_dentry_ctx,
- u32 flags)
-{
- struct wim_dentry *root;
- int ret;
-
- root = wim_get_current_root_dentry(wim);
- if (root == NULL)
- goto no_match;
-
- struct match_dentry_ctx ctx = {
- .consume_dentry = consume_dentry,
- .consume_dentry_ctx = consume_dentry_ctx,
- .consume_dentry_count = 0,
- .wildcard_path = TSTRDUP(wildcard_path),
- .cur_component_offset = 0,
- .cur_component_len = 0,
- .case_insensitive = ((flags & WILDCARD_FLAG_CASE_INSENSITIVE) != 0),
- };
-
- if (ctx.wildcard_path == NULL)
- return WIMLIB_ERR_NOMEM;
-
- ret = expand_wildcard_recursive(root, &ctx);
- FREE(ctx.wildcard_path);
- if (ret == 0 && ctx.consume_dentry_count == 0)
- goto no_match;
- return ret;
-
-no_match:
- ret = 0;
- if (flags & WILDCARD_FLAG_WARN_IF_NO_MATCH)
- WARNING("No matches for wildcard path \"%"TS"\"", wildcard_path);
-
- if (flags & WILDCARD_FLAG_ERROR_IF_NO_MATCH) {
- ERROR("No matches for wildcard path \"%"TS"\"", wildcard_path);
- ret = WIMLIB_ERR_PATH_DOES_NOT_EXIST;
- }
- return ret;
-}
#include "wimlib/error.h"
#include "wimlib/metadata.h"
#include "wimlib/paths.h"
+#include "wimlib/pattern.h"
#include "wimlib/reparse.h"
#include "wimlib/textfile.h"
#include "wimlib/xml.h"
-#include "wimlib/wildcard.h"
#include "wimlib/wimboot.h"
struct win32_apply_ctx {
return 0;
}
-/* Returns %true if the specified absolute path to a file in the WIM image
- * matches a pattern in [PrepopulateList] of WimBootCompress.ini. Otherwise
- * returns %false. */
-static bool
-in_prepopulate_list(const wchar_t *path, size_t path_nchars,
- const struct win32_apply_ctx *ctx)
-{
- const struct string_set *pats = ctx->wimboot.prepopulate_pats;
-
- if (!pats || !pats->num_strings)
- return false;
-
- return match_pattern_list(path, path_nchars, pats);
-}
-
/* Returns %true if the specified absolute path to a file in the WIM image can
* be subject to external backing when extracted. Otherwise returns %false. */
static bool
-can_externally_back_path(const wchar_t *path, size_t path_nchars,
- const struct win32_apply_ctx *ctx)
+can_externally_back_path(const wchar_t *path, const struct win32_apply_ctx *ctx)
{
- if (in_prepopulate_list(path, path_nchars, ctx))
+ /* Does the path match a pattern given in the [PrepopulateList] section
+ * of WimBootCompress.ini? */
+ if (ctx->wimboot.prepopulate_pats &&
+ match_pattern_list(path, ctx->wimboot.prepopulate_pats))
return false;
/* Since we attempt to modify the SYSTEM registry after it's extracted
* However, a WIM that wasn't specifically captured in "WIMBoot mode"
* may contain SYSTEM.* files. So to make things "just work", hard-code
* the pattern. */
- if (match_path(path, path_nchars, L"\\Windows\\System32\\config\\SYSTEM*",
- OS_PREFERRED_PATH_SEPARATOR, false))
+ if (match_path(path, L"\\Windows\\System32\\config\\SYSTEM*", false))
return false;
return true;
if (ret)
return ret;
- if (!can_externally_back_path(dentry->d_full_path,
- wcslen(dentry->d_full_path), ctx))
- {
+ if (!can_externally_back_path(dentry->d_full_path, ctx)) {
if (excluded_dentry_ret)
*excluded_dentry_ret = dentry;
return WIM_BACKING_EXCLUDED;
ACCESS_MASK requestedPerms;
u64 sort_key;
- ret = try_exclude(full_path, full_path_nchars, params);
- if (ret < 0) /* Excluded? */
+ ret = try_exclude(full_path, params);
+ if (unlikely(ret < 0)) /* Excluded? */
goto out_progress;
- if (ret > 0) /* Error? */
+ if (unlikely(ret > 0)) /* Error? */
goto out;
/* Open the file. */