2 * Copyright (C) 2013 Eric Biggers
4 * This file is part of wimlib, a library for working with WIM files.
6 * wimlib is free software; you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 3 of the License, or (at your option)
11 * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public License
17 * along with wimlib; if not, see http://www.gnu.org/licenses/.
20 #include "wimlib_internal.h"
31 canonicalize_pat(tchar **pat_p)
35 /* Turn all backslashes in the pattern into forward slashes. */
38 if (*pat != T('/') && *pat != T('\0') && *(pat + 1) == T(':')) {
39 /* Pattern begins with drive letter */
40 if (*(pat + 2) != T('/')) {
41 /* Something like c:file, which is actually a path
42 * relative to the current working directory on the c:
43 * drive. We require paths with drive letters to be
45 ERROR("Invalid path \"%"TS"\"; paths including drive letters "
46 "must be absolute!", pat);
47 ERROR("Maybe try \"%"TC":/%"TS"\"?",
49 return WIMLIB_ERR_INVALID_CAPTURE_CONFIG;
52 WARNING("Pattern \"%"TS"\" starts with a drive letter, which is "
53 "being removed.", pat);
54 /* Strip the drive letter */
62 canonicalize_pat_list(struct wimlib_pattern_list *pat_list)
65 for (size_t i = 0; i < pat_list->num_pats; i++) {
66 ret = canonicalize_pat(&pat_list->pats[i]);
74 canonicalize_capture_config(struct wimlib_capture_config *config)
76 int ret = canonicalize_pat_list(&config->exclusion_pats);
79 return canonicalize_pat_list(&config->exclusion_exception_pats);
83 copy_pattern_list(struct wimlib_pattern_list *copy,
84 const struct wimlib_pattern_list *list)
86 copy->pats = CALLOC(list->num_pats, sizeof(list->pats[0]));
89 copy->num_pats = list->num_pats;
90 for (size_t i = 0; i < list->num_pats; i++) {
91 copy->pats[i] = TSTRDUP(list->pats[i]);
98 struct wimlib_capture_config *
99 copy_capture_config(const struct wimlib_capture_config *config)
101 struct wimlib_capture_config *copy;
103 copy = CALLOC(1, sizeof(struct wimlib_capture_config));
106 if (!copy_pattern_list(©->exclusion_pats, &config->exclusion_pats))
108 if (!copy_pattern_list(©->exclusion_exception_pats,
109 &config->exclusion_exception_pats))
113 free_capture_config(copy);
120 destroy_pattern_list(struct wimlib_pattern_list *list)
122 for (size_t i = 0; i < list->num_pats; i++)
128 free_capture_config(struct wimlib_capture_config *config)
131 destroy_pattern_list(&config->exclusion_pats);
132 destroy_pattern_list(&config->exclusion_exception_pats);
138 match_pattern(const tchar *path,
139 const tchar *path_basename,
140 const struct wimlib_pattern_list *list)
142 for (size_t i = 0; i < list->num_pats; i++) {
144 const tchar *pat = list->pats[i];
147 if (*pat == T('/')) {
148 /* Absolute path from root of capture */
151 if (tstrchr(pat, T('/')))
152 /* Relative path from root of capture */
155 /* A file name pattern */
156 string = path_basename;
159 /* Warning: on Windows native builds, fnmatch() calls the
160 * replacement function in win32.c. */
161 if (fnmatch(pat, string, FNM_PATHNAME | FNM_NOESCAPE
167 DEBUG("\"%"TS"\" matches the pattern \"%"TS"\"",
171 DEBUG2("\"%"TS"\" does not match the pattern \"%"TS"\"",
178 /* Return true if the image capture configuration file indicates we should
179 * exclude the filename @path from capture.
181 * If @exclude_prefix is %true, the part of the path up and including the name
182 * of the directory being captured is not included in the path for matching
183 * purposes. This allows, for example, a pattern like /hiberfil.sys to match a
184 * file /mnt/windows7/hiberfil.sys if we are capturing the /mnt/windows7
188 exclude_path(const tchar *path, size_t path_len,
189 const struct wimlib_capture_config *config, bool exclude_prefix)
191 const tchar *basename = path_basename_with_len(path, path_len);
192 if (exclude_prefix) {
193 wimlib_assert(path_len >= config->_prefix_num_tchars);
194 if (!tmemcmp(config->_prefix, path, config->_prefix_num_tchars) &&
195 path[config->_prefix_num_tchars] == T('/'))
197 path += config->_prefix_num_tchars;
200 return match_pattern(path, basename, &config->exclusion_pats) &&
201 !match_pattern(path, basename, &config->exclusion_exception_pats);