2 * Copyright (c) 2003-2007 Tim Kientzle
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "lafe_platform.h"
27 __FBSDID("$FreeBSD$");
40 #include "line_reader.h"
42 #include "pathmatch.h"
50 struct lafe_matching {
51 struct match *exclusions;
53 struct match *inclusions;
55 int inclusions_unmatched_count;
58 static void add_pattern(struct match **list, const char *pattern);
59 static void initialize_matching(struct lafe_matching **);
60 static int match_exclusion(struct match *, const char *pathname);
61 static int match_inclusion(struct match *, const char *pathname);
64 * The matching logic here needs to be re-thought. I started out to
65 * try to mimic gtar's matching logic, but it's not entirely
66 * consistent. In particular 'tar -t' and 'tar -x' interpret patterns
67 * on the command line as anchored, but --exclude doesn't.
71 * Utility functions to manage exclusion/inclusion patterns
75 lafe_exclude(struct lafe_matching **matching, const char *pattern)
78 if (*matching == NULL)
79 initialize_matching(matching);
80 add_pattern(&((*matching)->exclusions), pattern);
81 (*matching)->exclusions_count++;
86 lafe_exclude_from_file(struct lafe_matching **matching, const char *pathname)
88 struct lafe_line_reader *lr;
92 lr = lafe_line_reader(pathname, 0);
93 while ((p = lafe_line_reader_next(lr)) != NULL) {
94 if (lafe_exclude(matching, p) != 0)
97 lafe_line_reader_free(lr);
102 lafe_include(struct lafe_matching **matching, const char *pattern)
105 if (*matching == NULL)
106 initialize_matching(matching);
107 add_pattern(&((*matching)->inclusions), pattern);
108 (*matching)->inclusions_count++;
109 (*matching)->inclusions_unmatched_count++;
114 lafe_include_from_file(struct lafe_matching **matching, const char *pathname,
117 struct lafe_line_reader *lr;
121 lr = lafe_line_reader(pathname, nullSeparator);
122 while ((p = lafe_line_reader_next(lr)) != NULL) {
123 if (lafe_include(matching, p) != 0)
126 lafe_line_reader_free(lr);
131 add_pattern(struct match **list, const char *pattern)
136 len = strlen(pattern);
137 match = malloc(sizeof(*match) + len + 1);
139 lafe_errc(1, errno, "Out of memory");
140 strcpy(match->pattern, pattern);
141 /* Both "foo/" and "foo" should match "foo/bar". */
142 if (len && match->pattern[len - 1] == '/')
143 match->pattern[strlen(match->pattern)-1] = '\0';
151 lafe_excluded(struct lafe_matching *matching, const char *pathname)
154 struct match *matched;
156 if (matching == NULL)
159 /* Mark off any unmatched inclusions. */
160 /* In particular, if a filename does appear in the archive and
161 * is explicitly included and excluded, then we don't report
162 * it as missing even though we don't extract it.
165 for (match = matching->inclusions; match != NULL; match = match->next){
166 if (match->matches == 0
167 && match_inclusion(match, pathname)) {
168 matching->inclusions_unmatched_count--;
174 /* Exclusions take priority */
175 for (match = matching->exclusions; match != NULL; match = match->next){
176 if (match_exclusion(match, pathname))
180 /* It's not excluded and we found an inclusion above, so it's included. */
185 /* We didn't find an unmatched inclusion, check the remaining ones. */
186 for (match = matching->inclusions; match != NULL; match = match->next){
187 /* We looked at previously-unmatched inclusions already. */
188 if (match->matches > 0
189 && match_inclusion(match, pathname)) {
195 /* If there were inclusions, default is to exclude. */
196 if (matching->inclusions != NULL)
199 /* No explicit inclusions, default is to match. */
204 * This is a little odd, but it matches the default behavior of
205 * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
209 match_exclusion(struct match *match, const char *pathname)
211 return (lafe_pathmatch(match->pattern,
213 PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END));
217 * Again, mimic gtar: inclusions are always anchored (have to match
218 * the beginning of the path) even though exclusions are not anchored.
221 match_inclusion(struct match *match, const char *pathname)
223 return (lafe_pathmatch(match->pattern, pathname, PATHMATCH_NO_ANCHOR_END));
227 lafe_cleanup_exclusions(struct lafe_matching **matching)
231 if (*matching == NULL)
234 for (p = (*matching)->inclusions; p != NULL; ) {
240 for (p = (*matching)->exclusions; p != NULL; ) {
251 initialize_matching(struct lafe_matching **matching)
253 *matching = calloc(sizeof(**matching), 1);
254 if (*matching == NULL)
255 lafe_errc(1, errno, "No memory");
259 lafe_unmatched_inclusions(struct lafe_matching *matching)
262 if (matching == NULL)
264 return (matching->inclusions_unmatched_count);
268 lafe_unmatched_inclusions_warn(struct lafe_matching *matching, const char *msg)
272 if (matching == NULL)
275 for (p = matching->inclusions; p != NULL; p = p->next) {
277 lafe_warnc(0, "%s: %s", p->pattern, msg);
280 return (matching->inclusions_unmatched_count);