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: src/usr.bin/cpio/matching.c,v 1.2 2008/06/21 02:20:20 kientzle Exp $");
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 /* Exclusions take priority */
160 for (match
= matching
->exclusions
; match
!= NULL
; match
= match
->next
){
161 if (match_exclusion(match
, pathname
))
165 /* Then check for inclusions */
167 for (match
= matching
->inclusions
; match
!= NULL
; match
= match
->next
){
168 if (match_inclusion(match
, pathname
)) {
170 * If this pattern has never been matched,
173 if (match
->matches
== 0) {
175 matching
->inclusions_unmatched_count
--;
179 * Otherwise, remember the match but keep checking
180 * in case we can tick off an unmatched pattern.
186 * We didn't find a pattern that had never been matched, but
187 * we did find a match, so count it and exit.
189 if (matched
!= NULL
) {
194 /* If there were inclusions, default is to exclude. */
195 if (matching
->inclusions
!= NULL
)
198 /* No explicit inclusions, default is to match. */
203 * This is a little odd, but it matches the default behavior of
204 * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar'
208 match_exclusion(struct match
*match
, const char *pathname
)
210 return (lafe_pathmatch(match
->pattern
,
212 PATHMATCH_NO_ANCHOR_START
| PATHMATCH_NO_ANCHOR_END
));
216 * Again, mimic gtar: inclusions are always anchored (have to match
217 * the beginning of the path) even though exclusions are not anchored.
220 match_inclusion(struct match
*match
, const char *pathname
)
223 return (lafe_pathmatch(match
->pattern
, pathname
, 0));
225 return (lafe_pathmatch(match
->pattern
, pathname
, PATHMATCH_NO_ANCHOR_END
));
230 lafe_cleanup_exclusions(struct lafe_matching
**matching
)
234 if (*matching
== NULL
)
237 for (p
= (*matching
)->inclusions
; p
!= NULL
; ) {
243 for (p
= (*matching
)->exclusions
; p
!= NULL
; ) {
254 initialize_matching(struct lafe_matching
**matching
)
256 *matching
= calloc(sizeof(**matching
), 1);
257 if (*matching
== NULL
)
258 lafe_errc(1, errno
, "No memory");
262 lafe_unmatched_inclusions(struct lafe_matching
*matching
)
265 if (matching
== NULL
)
267 return (matching
->inclusions_unmatched_count
);
271 lafe_unmatched_inclusions_warn(struct lafe_matching
*matching
, const char *msg
)
275 if (matching
== NULL
)
278 for (p
= matching
->inclusions
; p
!= NULL
; p
= p
->next
) {
280 lafe_warnc(0, "%s: %s", p
->pattern
, msg
);
283 return (matching
->inclusions_unmatched_count
);