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_pattern(const tchar *pat, tchar **canonical_pat_ret)
35 if (pat[0] != T('/') && pat[0] != T('\\') &&
36 pat[0] != T('\0') && pat[1] == T(':'))
38 /* Pattern begins with drive letter */
39 if (pat[2] != T('/') && pat[2] != T('\\')) {
40 /* Something like c:file, which is actually a path
41 * relative to the current working directory on the c:
42 * drive. We require paths with drive letters to be
44 ERROR("Invalid path \"%"TS"\"; paths including drive letters "
45 "must be absolute!", pat);
46 ERROR("Maybe try \"%"TC":/%"TS"\"?",
48 return WIMLIB_ERR_INVALID_CAPTURE_CONFIG;
51 WARNING("Pattern \"%"TS"\" starts with a drive letter, which is "
52 "being removed.", pat);
53 /* Strip the drive letter */
56 canonical_pat = canonicalize_fs_path(pat);
58 return WIMLIB_ERR_NOMEM;
59 *canonical_pat_ret = canonical_pat;
64 copy_and_canonicalize_pattern_list(const struct wimlib_pattern_list *list,
65 struct wimlib_pattern_list *copy)
69 copy->pats = CALLOC(list->num_pats, sizeof(list->pats[0]));
71 return WIMLIB_ERR_NOMEM;
72 copy->num_pats = list->num_pats;
73 for (size_t i = 0; i < list->num_pats; i++) {
74 ret = canonicalize_pattern(list->pats[i], ©->pats[i]);
82 copy_and_canonicalize_capture_config(const struct wimlib_capture_config *config,
83 struct wimlib_capture_config **config_copy_ret)
85 struct wimlib_capture_config *config_copy;
88 config_copy = CALLOC(1, sizeof(struct wimlib_capture_config));
90 ret = WIMLIB_ERR_NOMEM;
91 goto out_free_capture_config;
93 ret = copy_and_canonicalize_pattern_list(&config->exclusion_pats,
94 &config_copy->exclusion_pats);
96 goto out_free_capture_config;
97 ret = copy_and_canonicalize_pattern_list(&config->exclusion_exception_pats,
98 &config_copy->exclusion_exception_pats);
100 goto out_free_capture_config;
101 *config_copy_ret = config_copy;
103 out_free_capture_config:
104 free_capture_config(config_copy);
110 destroy_pattern_list(struct wimlib_pattern_list *list)
112 for (size_t i = 0; i < list->num_pats; i++)
118 free_capture_config(struct wimlib_capture_config *config)
121 destroy_pattern_list(&config->exclusion_pats);
122 destroy_pattern_list(&config->exclusion_exception_pats);
128 match_pattern(const tchar *path,
129 const tchar *path_basename,
130 const struct wimlib_pattern_list *list)
132 for (size_t i = 0; i < list->num_pats; i++) {
134 const tchar *pat = list->pats[i];
137 if (*pat == T('/')) {
138 /* Absolute path from root of capture */
141 if (tstrchr(pat, T('/')))
142 /* Relative path from root of capture */
145 /* A file name pattern */
146 string = path_basename;
149 /* Warning: on Windows native builds, fnmatch() calls the
150 * replacement function in win32.c. */
151 if (fnmatch(pat, string, FNM_PATHNAME | FNM_NOESCAPE
157 DEBUG("\"%"TS"\" matches the pattern \"%"TS"\"",
161 DEBUG2("\"%"TS"\" does not match the pattern \"%"TS"\"",
168 /* Return true if the image capture configuration file indicates we should
169 * exclude the filename @path from capture.
171 * If @exclude_prefix is %true, the part of the path up and including the name
172 * of the directory being captured is not included in the path for matching
173 * purposes. This allows, for example, a pattern like /hiberfil.sys to match a
174 * file /mnt/windows7/hiberfil.sys if we are capturing the /mnt/windows7
178 exclude_path(const tchar *path, size_t path_len,
179 const struct wimlib_capture_config *config, bool exclude_prefix)
181 const tchar *basename = path_basename_with_len(path, path_len);
182 if (exclude_prefix) {
183 wimlib_assert(path_len >= config->_prefix_num_tchars);
184 if (!tmemcmp(config->_prefix, path, config->_prefix_num_tchars) &&
185 path[config->_prefix_num_tchars] == T('/'))
187 path += config->_prefix_num_tchars;
190 return match_pattern(path, basename, &config->exclusion_pats) &&
191 !match_pattern(path, basename, &config->exclusion_exception_pats);