xref: /freebsd/contrib/libarchive/libarchive/archive_match.c (revision bd66c1b43e33540205dbc1187c2f2a15c58b57ba)
1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * Copyright (c) 2012 Michihiro NAKAJIMA
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "archive_platform.h"
28 
29 #ifdef HAVE_ERRNO_H
30 #include <errno.h>
31 #endif
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h>
34 #endif
35 #ifdef HAVE_STRING_H
36 #include <string.h>
37 #endif
38 
39 #include "archive.h"
40 #include "archive_private.h"
41 #include "archive_entry.h"
42 #include "archive_getdate.h"
43 #include "archive_pathmatch.h"
44 #include "archive_rb.h"
45 #include "archive_string.h"
46 
47 struct match {
48 	struct match		*next;
49 	int			 matched;
50 	struct archive_mstring	 pattern;
51 };
52 
53 struct match_list {
54 	struct match		*first;
55 	struct match		**last;
56 	int			 count;
57 	int			 unmatched_count;
58 	struct match		*unmatched_next;
59 	int			 unmatched_eof;
60 };
61 
62 struct match_file {
63 	struct archive_rb_node	 node;
64 	struct match_file	*next;
65 	struct archive_mstring	 pathname;
66 	int			 flag;
67 	time_t			 mtime_sec;
68 	long			 mtime_nsec;
69 	time_t			 ctime_sec;
70 	long			 ctime_nsec;
71 };
72 
73 struct entry_list {
74 	struct match_file	*first;
75 	struct match_file	**last;
76 	int			 count;
77 };
78 
79 struct id_array {
80 	size_t			 size;/* Allocated size */
81 	size_t			 count;
82 	int64_t			*ids;
83 };
84 
85 #define PATTERN_IS_SET		1
86 #define TIME_IS_SET		2
87 #define ID_IS_SET		4
88 
89 struct archive_match {
90 	struct archive		 archive;
91 
92 	/* exclusion/inclusion set flag. */
93 	int			 setflag;
94 
95 	/* Recursively include directory content? */
96 	int			 recursive_include;
97 
98 	/*
99 	 * Matching filename patterns.
100 	 */
101 	struct match_list	 exclusions;
102 	struct match_list	 inclusions;
103 
104 	/*
105 	 * Matching time stamps.
106 	 */
107 	time_t			 now;
108 	int			 newer_mtime_filter;
109 	time_t			 newer_mtime_sec;
110 	long			 newer_mtime_nsec;
111 	int			 newer_ctime_filter;
112 	time_t			 newer_ctime_sec;
113 	long			 newer_ctime_nsec;
114 	int			 older_mtime_filter;
115 	time_t			 older_mtime_sec;
116 	long			 older_mtime_nsec;
117 	int			 older_ctime_filter;
118 	time_t			 older_ctime_sec;
119 	long			 older_ctime_nsec;
120 	/*
121 	 * Matching time stamps with its filename.
122 	 */
123 	struct archive_rb_tree	 exclusion_tree;
124 	struct entry_list 	 exclusion_entry_list;
125 
126 	/*
127 	 * Matching file owners.
128 	 */
129 	struct id_array 	 inclusion_uids;
130 	struct id_array 	 inclusion_gids;
131 	struct match_list	 inclusion_unames;
132 	struct match_list	 inclusion_gnames;
133 };
134 
135 static int	add_pattern_from_file(struct archive_match *,
136 		    struct match_list *, int, const void *, int);
137 static int	add_entry(struct archive_match *, int,
138 		    struct archive_entry *);
139 static int	add_owner_id(struct archive_match *, struct id_array *,
140 		    int64_t);
141 static int	add_owner_name(struct archive_match *, struct match_list *,
142 		    int, const void *);
143 static int	add_pattern_mbs(struct archive_match *, struct match_list *,
144 		    const char *);
145 static int	add_pattern_wcs(struct archive_match *, struct match_list *,
146 		    const wchar_t *);
147 static int	cmp_key_mbs(const struct archive_rb_node *, const void *);
148 static int	cmp_key_wcs(const struct archive_rb_node *, const void *);
149 static int	cmp_node_mbs(const struct archive_rb_node *,
150 		    const struct archive_rb_node *);
151 static int	cmp_node_wcs(const struct archive_rb_node *,
152 		    const struct archive_rb_node *);
153 static void	entry_list_add(struct entry_list *, struct match_file *);
154 static void	entry_list_free(struct entry_list *);
155 static void	entry_list_init(struct entry_list *);
156 static int	error_nomem(struct archive_match *);
157 static void	match_list_add(struct match_list *, struct match *);
158 static void	match_list_free(struct match_list *);
159 static void	match_list_init(struct match_list *);
160 static int	match_list_unmatched_inclusions_next(struct archive_match *,
161 		    struct match_list *, int, const void **);
162 static int	match_owner_id(struct id_array *, int64_t);
163 #if !defined(_WIN32) || defined(__CYGWIN__)
164 static int	match_owner_name_mbs(struct archive_match *,
165 		    struct match_list *, const char *);
166 #else
167 static int	match_owner_name_wcs(struct archive_match *,
168 		    struct match_list *, const wchar_t *);
169 #endif
170 static int	match_path_exclusion(struct archive_match *,
171 		    struct match *, int, const void *);
172 static int	match_path_inclusion(struct archive_match *,
173 		    struct match *, int, const void *);
174 static int	owner_excluded(struct archive_match *,
175 		    struct archive_entry *);
176 static int	path_excluded(struct archive_match *, int, const void *);
177 static int	set_timefilter(struct archive_match *, int, time_t, long,
178 		    time_t, long);
179 static int	set_timefilter_pathname_mbs(struct archive_match *,
180 		    int, const char *);
181 static int	set_timefilter_pathname_wcs(struct archive_match *,
182 		    int, const wchar_t *);
183 static int	set_timefilter_date(struct archive_match *, int, const char *);
184 static int	set_timefilter_date_w(struct archive_match *, int,
185 		    const wchar_t *);
186 static int	time_excluded(struct archive_match *,
187 		    struct archive_entry *);
188 static int	validate_time_flag(struct archive *, int, const char *);
189 
190 #define get_date __archive_get_date
191 
192 static const struct archive_rb_tree_ops rb_ops_mbs = {
193 	cmp_node_mbs, cmp_key_mbs
194 };
195 
196 static const struct archive_rb_tree_ops rb_ops_wcs = {
197 	cmp_node_wcs, cmp_key_wcs
198 };
199 
200 /*
201  * The matching logic here needs to be re-thought.  I started out to
202  * try to mimic gtar's matching logic, but it's not entirely
203  * consistent.  In particular 'tar -t' and 'tar -x' interpret patterns
204  * on the command line as anchored, but --exclude doesn't.
205  */
206 
207 static int
error_nomem(struct archive_match * a)208 error_nomem(struct archive_match *a)
209 {
210 	archive_set_error(&(a->archive), ENOMEM, "No memory");
211 	a->archive.state = ARCHIVE_STATE_FATAL;
212 	return (ARCHIVE_FATAL);
213 }
214 
215 /*
216  * Create an ARCHIVE_MATCH object.
217  */
218 struct archive *
archive_match_new(void)219 archive_match_new(void)
220 {
221 	struct archive_match *a;
222 
223 	a = calloc(1, sizeof(*a));
224 	if (a == NULL)
225 		return (NULL);
226 	a->archive.magic = ARCHIVE_MATCH_MAGIC;
227 	a->archive.state = ARCHIVE_STATE_NEW;
228 	a->recursive_include = 1;
229 	match_list_init(&(a->inclusions));
230 	match_list_init(&(a->exclusions));
231 	__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
232 	entry_list_init(&(a->exclusion_entry_list));
233 	match_list_init(&(a->inclusion_unames));
234 	match_list_init(&(a->inclusion_gnames));
235 	time(&a->now);
236 	return (&(a->archive));
237 }
238 
239 /*
240  * Free an ARCHIVE_MATCH object.
241  */
242 int
archive_match_free(struct archive * _a)243 archive_match_free(struct archive *_a)
244 {
245 	struct archive_match *a;
246 
247 	if (_a == NULL)
248 		return (ARCHIVE_OK);
249 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
250 	    ARCHIVE_STATE_ANY | ARCHIVE_STATE_FATAL, "archive_match_free");
251 	a = (struct archive_match *)_a;
252 	match_list_free(&(a->inclusions));
253 	match_list_free(&(a->exclusions));
254 	entry_list_free(&(a->exclusion_entry_list));
255 	free(a->inclusion_uids.ids);
256 	free(a->inclusion_gids.ids);
257 	match_list_free(&(a->inclusion_unames));
258 	match_list_free(&(a->inclusion_gnames));
259 	free(a);
260 	return (ARCHIVE_OK);
261 }
262 
263 /*
264  * Convenience function to perform all exclusion tests.
265  *
266  * Returns 1 if archive entry is excluded.
267  * Returns 0 if archive entry is not excluded.
268  * Returns <0 if something error happened.
269  */
270 int
archive_match_excluded(struct archive * _a,struct archive_entry * entry)271 archive_match_excluded(struct archive *_a, struct archive_entry *entry)
272 {
273 	struct archive_match *a;
274 	int r;
275 
276 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
277 	    ARCHIVE_STATE_NEW, "archive_match_excluded_ae");
278 
279 	a = (struct archive_match *)_a;
280 	if (entry == NULL) {
281 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
282 		return (ARCHIVE_FAILED);
283 	}
284 
285 	r = 0;
286 	if (a->setflag & PATTERN_IS_SET) {
287 #if defined(_WIN32) && !defined(__CYGWIN__)
288 		r = path_excluded(a, 0, archive_entry_pathname_w(entry));
289 #else
290 		r = path_excluded(a, 1, archive_entry_pathname(entry));
291 #endif
292 		if (r != 0)
293 			return (r);
294 	}
295 
296 	if (a->setflag & TIME_IS_SET) {
297 		r = time_excluded(a, entry);
298 		if (r != 0)
299 			return (r);
300 	}
301 
302 	if (a->setflag & ID_IS_SET)
303 		r = owner_excluded(a, entry);
304 	return (r);
305 }
306 
307 /*
308  * Utility functions to manage exclusion/inclusion patterns
309  */
310 
311 int
archive_match_exclude_pattern(struct archive * _a,const char * pattern)312 archive_match_exclude_pattern(struct archive *_a, const char *pattern)
313 {
314 	struct archive_match *a;
315 	int r;
316 
317 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
318 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern");
319 	a = (struct archive_match *)_a;
320 
321 	if (pattern == NULL || *pattern == '\0') {
322 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
323 		return (ARCHIVE_FAILED);
324 	}
325 	if ((r = add_pattern_mbs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
326 		return (r);
327 	return (ARCHIVE_OK);
328 }
329 
330 int
archive_match_exclude_pattern_w(struct archive * _a,const wchar_t * pattern)331 archive_match_exclude_pattern_w(struct archive *_a, const wchar_t *pattern)
332 {
333 	struct archive_match *a;
334 	int r;
335 
336 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
337 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_w");
338 	a = (struct archive_match *)_a;
339 
340 	if (pattern == NULL || *pattern == L'\0') {
341 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
342 		return (ARCHIVE_FAILED);
343 	}
344 	if ((r = add_pattern_wcs(a, &(a->exclusions), pattern)) != ARCHIVE_OK)
345 		return (r);
346 	return (ARCHIVE_OK);
347 }
348 
349 int
archive_match_exclude_pattern_from_file(struct archive * _a,const char * pathname,int nullSeparator)350 archive_match_exclude_pattern_from_file(struct archive *_a,
351     const char *pathname, int nullSeparator)
352 {
353 	struct archive_match *a;
354 
355 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
356 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file");
357 	a = (struct archive_match *)_a;
358 
359 	return add_pattern_from_file(a, &(a->exclusions), 1, pathname,
360 		nullSeparator);
361 }
362 
363 int
archive_match_exclude_pattern_from_file_w(struct archive * _a,const wchar_t * pathname,int nullSeparator)364 archive_match_exclude_pattern_from_file_w(struct archive *_a,
365     const wchar_t *pathname, int nullSeparator)
366 {
367 	struct archive_match *a;
368 
369 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
370 	    ARCHIVE_STATE_NEW, "archive_match_exclude_pattern_from_file_w");
371 	a = (struct archive_match *)_a;
372 
373 	return add_pattern_from_file(a, &(a->exclusions), 0, pathname,
374 		nullSeparator);
375 }
376 
377 int
archive_match_include_pattern(struct archive * _a,const char * pattern)378 archive_match_include_pattern(struct archive *_a, const char *pattern)
379 {
380 	struct archive_match *a;
381 	int r;
382 
383 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
384 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern");
385 	a = (struct archive_match *)_a;
386 
387 	if (pattern == NULL || *pattern == '\0') {
388 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
389 		return (ARCHIVE_FAILED);
390 	}
391 	if ((r = add_pattern_mbs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
392 		return (r);
393 	return (ARCHIVE_OK);
394 }
395 
396 int
archive_match_include_pattern_w(struct archive * _a,const wchar_t * pattern)397 archive_match_include_pattern_w(struct archive *_a, const wchar_t *pattern)
398 {
399 	struct archive_match *a;
400 	int r;
401 
402 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
403 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_w");
404 	a = (struct archive_match *)_a;
405 
406 	if (pattern == NULL || *pattern == L'\0') {
407 		archive_set_error(&(a->archive), EINVAL, "pattern is empty");
408 		return (ARCHIVE_FAILED);
409 	}
410 	if ((r = add_pattern_wcs(a, &(a->inclusions), pattern)) != ARCHIVE_OK)
411 		return (r);
412 	return (ARCHIVE_OK);
413 }
414 
415 int
archive_match_include_pattern_from_file(struct archive * _a,const char * pathname,int nullSeparator)416 archive_match_include_pattern_from_file(struct archive *_a,
417     const char *pathname, int nullSeparator)
418 {
419 	struct archive_match *a;
420 
421 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
422 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file");
423 	a = (struct archive_match *)_a;
424 
425 	return add_pattern_from_file(a, &(a->inclusions), 1, pathname,
426 		nullSeparator);
427 }
428 
429 int
archive_match_include_pattern_from_file_w(struct archive * _a,const wchar_t * pathname,int nullSeparator)430 archive_match_include_pattern_from_file_w(struct archive *_a,
431     const wchar_t *pathname, int nullSeparator)
432 {
433 	struct archive_match *a;
434 
435 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
436 	    ARCHIVE_STATE_NEW, "archive_match_include_pattern_from_file_w");
437 	a = (struct archive_match *)_a;
438 
439 	return add_pattern_from_file(a, &(a->inclusions), 0, pathname,
440 		nullSeparator);
441 }
442 
443 /*
444  * Test functions for pathname patterns.
445  *
446  * Returns 1 if archive entry is excluded.
447  * Returns 0 if archive entry is not excluded.
448  * Returns <0 if something error happened.
449  */
450 int
archive_match_path_excluded(struct archive * _a,struct archive_entry * entry)451 archive_match_path_excluded(struct archive *_a,
452     struct archive_entry *entry)
453 {
454 	struct archive_match *a;
455 
456 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
457 	    ARCHIVE_STATE_NEW, "archive_match_path_excluded");
458 
459 	a = (struct archive_match *)_a;
460 	if (entry == NULL) {
461 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
462 		return (ARCHIVE_FAILED);
463 	}
464 
465 	/* If we don't have exclusion/inclusion pattern set at all,
466 	 * the entry is always not excluded. */
467 	if ((a->setflag & PATTERN_IS_SET) == 0)
468 		return (0);
469 #if defined(_WIN32) && !defined(__CYGWIN__)
470 	return (path_excluded(a, 0, archive_entry_pathname_w(entry)));
471 #else
472 	return (path_excluded(a, 1, archive_entry_pathname(entry)));
473 #endif
474 }
475 
476 /*
477  * When recursive inclusion of directory content is enabled,
478  * an inclusion pattern that matches a directory will also
479  * include everything beneath that directory. Enabled by default.
480  *
481  * For compatibility with GNU tar, exclusion patterns always
482  * match if a subset of the full patch matches (i.e., they are
483  * are not rooted at the beginning of the path) and thus there
484  * is no corresponding non-recursive exclusion mode.
485  */
486 int
archive_match_set_inclusion_recursion(struct archive * _a,int enabled)487 archive_match_set_inclusion_recursion(struct archive *_a, int enabled)
488 {
489 	struct archive_match *a;
490 
491 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
492 	    ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion");
493 	a = (struct archive_match *)_a;
494 	a->recursive_include = enabled;
495 	return (ARCHIVE_OK);
496 }
497 
498 /*
499  * Utility functions to get statistic information for inclusion patterns.
500  */
501 int
archive_match_path_unmatched_inclusions(struct archive * _a)502 archive_match_path_unmatched_inclusions(struct archive *_a)
503 {
504 	struct archive_match *a;
505 
506 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
507 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
508 	a = (struct archive_match *)_a;
509 
510 	return (a->inclusions.unmatched_count);
511 }
512 
513 int
archive_match_path_unmatched_inclusions_next(struct archive * _a,const char ** _p)514 archive_match_path_unmatched_inclusions_next(struct archive *_a,
515     const char **_p)
516 {
517 	struct archive_match *a;
518 	const void *v;
519 	int r;
520 
521 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
522 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next");
523 	a = (struct archive_match *)_a;
524 
525 	r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 1, &v);
526 	*_p = (const char *)v;
527 	return (r);
528 }
529 
530 int
archive_match_path_unmatched_inclusions_next_w(struct archive * _a,const wchar_t ** _p)531 archive_match_path_unmatched_inclusions_next_w(struct archive *_a,
532     const wchar_t **_p)
533 {
534 	struct archive_match *a;
535 	const void *v;
536 	int r;
537 
538 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
539 	    ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions_next_w");
540 	a = (struct archive_match *)_a;
541 
542 	r = match_list_unmatched_inclusions_next(a, &(a->inclusions), 0, &v);
543 	*_p = (const wchar_t *)v;
544 	return (r);
545 }
546 
547 /*
548  * Add inclusion/exclusion patterns.
549  */
550 static int
add_pattern_mbs(struct archive_match * a,struct match_list * list,const char * pattern)551 add_pattern_mbs(struct archive_match *a, struct match_list *list,
552     const char *pattern)
553 {
554 	struct match *match;
555 	size_t len;
556 
557 	match = calloc(1, sizeof(*match));
558 	if (match == NULL)
559 		return (error_nomem(a));
560 	/* Both "foo/" and "foo" should match "foo/bar". */
561 	len = strlen(pattern);
562 	if (len && pattern[len - 1] == '/')
563 		--len;
564 	archive_mstring_copy_mbs_len(&(match->pattern), pattern, len);
565 	match_list_add(list, match);
566 	a->setflag |= PATTERN_IS_SET;
567 	return (ARCHIVE_OK);
568 }
569 
570 static int
add_pattern_wcs(struct archive_match * a,struct match_list * list,const wchar_t * pattern)571 add_pattern_wcs(struct archive_match *a, struct match_list *list,
572     const wchar_t *pattern)
573 {
574 	struct match *match;
575 	size_t len;
576 
577 	match = calloc(1, sizeof(*match));
578 	if (match == NULL)
579 		return (error_nomem(a));
580 	/* Both "foo/" and "foo" should match "foo/bar". */
581 	len = wcslen(pattern);
582 	if (len && pattern[len - 1] == L'/')
583 		--len;
584 	archive_mstring_copy_wcs_len(&(match->pattern), pattern, len);
585 	match_list_add(list, match);
586 	a->setflag |= PATTERN_IS_SET;
587 	return (ARCHIVE_OK);
588 }
589 
590 static int
add_pattern_from_file(struct archive_match * a,struct match_list * mlist,int mbs,const void * pathname,int nullSeparator)591 add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
592     int mbs, const void *pathname, int nullSeparator)
593 {
594 	struct archive *ar;
595 	struct archive_entry *ae;
596 	struct archive_string as;
597 	const void *buff;
598 	size_t size;
599 	int64_t offset;
600 	int r;
601 
602 	ar = archive_read_new();
603 	if (ar == NULL) {
604 		archive_set_error(&(a->archive), ENOMEM, "No memory");
605 		return (ARCHIVE_FATAL);
606 	}
607 	r = archive_read_support_format_raw(ar);
608 	if (r == ARCHIVE_OK)
609 		r = archive_read_support_format_empty(ar);
610 	if (r != ARCHIVE_OK) {
611 		archive_copy_error(&(a->archive), ar);
612 		archive_read_free(ar);
613 		return (r);
614 	}
615 	if (mbs)
616 		r = archive_read_open_filename(ar, pathname, 512*20);
617 	else
618 		r = archive_read_open_filename_w(ar, pathname, 512*20);
619 	if (r != ARCHIVE_OK) {
620 		archive_copy_error(&(a->archive), ar);
621 		archive_read_free(ar);
622 		return (r);
623 	}
624 	r = archive_read_next_header(ar, &ae);
625 	if (r != ARCHIVE_OK) {
626 		archive_read_free(ar);
627 		if (r == ARCHIVE_EOF) {
628 			return (ARCHIVE_OK);
629 		} else {
630 			archive_copy_error(&(a->archive), ar);
631 			return (r);
632 		}
633 	}
634 
635 	archive_string_init(&as);
636 
637 	while ((r = archive_read_data_block(ar, &buff, &size, &offset))
638 	    == ARCHIVE_OK) {
639 		const char *b = (const char *)buff;
640 
641 		while (size) {
642 			const char *s = (const char *)b;
643 			size_t length = 0;
644 			int found_separator = 0;
645 
646 			while (length < size) {
647 				if (nullSeparator) {
648 					if (*b == '\0') {
649 						found_separator = 1;
650 						break;
651 					}
652 				} else {
653 			            	if (*b == 0x0d || *b == 0x0a) {
654 						found_separator = 1;
655 						break;
656 					}
657 				}
658 				b++;
659 				length++;
660 			}
661 			if (!found_separator) {
662 				archive_strncat(&as, s, length);
663 				/* Read next data block. */
664 				break;
665 			}
666 			b++;
667 			size -= length + 1;
668 			archive_strncat(&as, s, length);
669 
670 			/* If the line is not empty, add the pattern. */
671 			if (archive_strlen(&as) > 0) {
672 				/* Add pattern. */
673 				r = add_pattern_mbs(a, mlist, as.s);
674 				if (r != ARCHIVE_OK) {
675 					archive_read_free(ar);
676 					archive_string_free(&as);
677 					return (r);
678 				}
679 				archive_string_empty(&as);
680 			}
681 		}
682 	}
683 
684 	/* If an error occurred, report it immediately. */
685 	if (r < ARCHIVE_OK) {
686 		archive_copy_error(&(a->archive), ar);
687 		archive_read_free(ar);
688 		archive_string_free(&as);
689 		return (r);
690 	}
691 
692 	/* If the line is not empty, add the pattern. */
693 	if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
694 		/* Add pattern. */
695 		r = add_pattern_mbs(a, mlist, as.s);
696 		if (r != ARCHIVE_OK) {
697 			archive_read_free(ar);
698 			archive_string_free(&as);
699 			return (r);
700 		}
701 	}
702 	archive_read_free(ar);
703 	archive_string_free(&as);
704 	return (ARCHIVE_OK);
705 }
706 
707 /*
708  * Test if pathname is excluded by inclusion/exclusion patterns.
709  */
710 static int
path_excluded(struct archive_match * a,int mbs,const void * pathname)711 path_excluded(struct archive_match *a, int mbs, const void *pathname)
712 {
713 	struct match *match;
714 	struct match *matched;
715 	int r;
716 
717 	if (a == NULL)
718 		return (0);
719 
720 	/* Mark off any unmatched inclusions. */
721 	/* In particular, if a filename does appear in the archive and
722 	 * is explicitly included and excluded, then we don't report
723 	 * it as missing even though we don't extract it.
724 	 */
725 	matched = NULL;
726 	for (match = a->inclusions.first; match != NULL;
727 	    match = match->next){
728 		if (!match->matched &&
729 		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
730 			if (r < 0)
731 				return (r);
732 			a->inclusions.unmatched_count--;
733 			match->matched = 1;
734 			matched = match;
735 		}
736 	}
737 
738 	/* Exclusions take priority */
739 	for (match = a->exclusions.first; match != NULL;
740 	    match = match->next){
741 		r = match_path_exclusion(a, match, mbs, pathname);
742 		if (r)
743 			return (r);
744 	}
745 
746 	/* It's not excluded and we found an inclusion above, so it's
747 	 * included. */
748 	if (matched != NULL)
749 		return (0);
750 
751 
752 	/* We didn't find an unmatched inclusion, check the remaining ones. */
753 	for (match = a->inclusions.first; match != NULL;
754 	    match = match->next){
755 		/* We looked at previously-unmatched inclusions already. */
756 		if (match->matched &&
757 		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
758 			if (r < 0)
759 				return (r);
760 			return (0);
761 		}
762 	}
763 
764 	/* If there were inclusions, default is to exclude. */
765 	if (a->inclusions.first != NULL)
766 	    return (1);
767 
768 	/* No explicit inclusions, default is to match. */
769 	return (0);
770 }
771 
772 /*
773  * This is a little odd, but it matches the default behavior of
774  * gtar.  In particular, 'a*b' will match 'foo/a1111/222b/bar'
775  *
776  */
777 static int
match_path_exclusion(struct archive_match * a,struct match * m,int mbs,const void * pn)778 match_path_exclusion(struct archive_match *a, struct match *m,
779     int mbs, const void *pn)
780 {
781 	int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
782 	int r;
783 
784 	if (mbs) {
785 		const char *p;
786 		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
787 		if (r == 0)
788 			return (archive_pathmatch(p, (const char *)pn, flag));
789 	} else {
790 		const wchar_t *p;
791 		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
792 		if (r == 0)
793 			return (archive_pathmatch_w(p, (const wchar_t *)pn,
794 				flag));
795 	}
796 	if (errno == ENOMEM)
797 		return (error_nomem(a));
798 	return (0);
799 }
800 
801 /*
802  * Again, mimic gtar:  inclusions are always anchored (have to match
803  * the beginning of the path) even though exclusions are not anchored.
804  */
805 static int
match_path_inclusion(struct archive_match * a,struct match * m,int mbs,const void * pn)806 match_path_inclusion(struct archive_match *a, struct match *m,
807     int mbs, const void *pn)
808 {
809 	/* Recursive operation requires only a prefix match. */
810 	int flag = a->recursive_include ?
811 		PATHMATCH_NO_ANCHOR_END :
812 		0;
813 	int r;
814 
815 	if (mbs) {
816 		const char *p;
817 		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
818 		if (r == 0)
819 			return (archive_pathmatch(p, (const char *)pn, flag));
820 	} else {
821 		const wchar_t *p;
822 		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
823 		if (r == 0)
824 			return (archive_pathmatch_w(p, (const wchar_t *)pn,
825 				flag));
826 	}
827 	if (errno == ENOMEM)
828 		return (error_nomem(a));
829 	return (0);
830 }
831 
832 static void
match_list_init(struct match_list * list)833 match_list_init(struct match_list *list)
834 {
835 	list->first = NULL;
836 	list->last = &(list->first);
837 	list->count = 0;
838 }
839 
840 static void
match_list_free(struct match_list * list)841 match_list_free(struct match_list *list)
842 {
843 	struct match *p, *q;
844 
845 	for (p = list->first; p != NULL; ) {
846 		q = p;
847 		p = p->next;
848 		archive_mstring_clean(&(q->pattern));
849 		free(q);
850 	}
851 }
852 
853 static void
match_list_add(struct match_list * list,struct match * m)854 match_list_add(struct match_list *list, struct match *m)
855 {
856 	*list->last = m;
857 	list->last = &(m->next);
858 	list->count++;
859 	list->unmatched_count++;
860 }
861 
862 static int
match_list_unmatched_inclusions_next(struct archive_match * a,struct match_list * list,int mbs,const void ** vp)863 match_list_unmatched_inclusions_next(struct archive_match *a,
864     struct match_list *list, int mbs, const void **vp)
865 {
866 	struct match *m;
867 
868 	*vp = NULL;
869 	if (list->unmatched_eof) {
870 		list->unmatched_eof = 0;
871 		return (ARCHIVE_EOF);
872 	}
873 	if (list->unmatched_next == NULL) {
874 		if (list->unmatched_count == 0)
875 			return (ARCHIVE_EOF);
876 		list->unmatched_next = list->first;
877 	}
878 
879 	for (m = list->unmatched_next; m != NULL; m = m->next) {
880 		int r;
881 
882 		if (m->matched)
883 			continue;
884 		if (mbs) {
885 			const char *p;
886 			r = archive_mstring_get_mbs(&(a->archive),
887 				&(m->pattern), &p);
888 			if (r < 0 && errno == ENOMEM)
889 				return (error_nomem(a));
890 			if (p == NULL)
891 				p = "";
892 			*vp = p;
893 		} else {
894 			const wchar_t *p;
895 			r = archive_mstring_get_wcs(&(a->archive),
896 				&(m->pattern), &p);
897 			if (r < 0 && errno == ENOMEM)
898 				return (error_nomem(a));
899 			if (p == NULL)
900 				p = L"";
901 			*vp = p;
902 		}
903 		list->unmatched_next = m->next;
904 		if (list->unmatched_next == NULL)
905 			/* To return EOF next time. */
906 			list->unmatched_eof = 1;
907 		return (ARCHIVE_OK);
908 	}
909 	list->unmatched_next = NULL;
910 	return (ARCHIVE_EOF);
911 }
912 
913 /*
914  * Utility functions to manage inclusion timestamps.
915  */
916 int
archive_match_include_time(struct archive * _a,int flag,time_t sec,long nsec)917 archive_match_include_time(struct archive *_a, int flag, time_t sec,
918     long nsec)
919 {
920 	int r;
921 
922 	r = validate_time_flag(_a, flag, "archive_match_include_time");
923 	if (r != ARCHIVE_OK)
924 		return (r);
925 	return set_timefilter((struct archive_match *)_a, flag,
926 			sec, nsec, sec, nsec);
927 }
928 
929 int
archive_match_include_date(struct archive * _a,int flag,const char * datestr)930 archive_match_include_date(struct archive *_a, int flag,
931     const char *datestr)
932 {
933 	int r;
934 
935 	r = validate_time_flag(_a, flag, "archive_match_include_date");
936 	if (r != ARCHIVE_OK)
937 		return (r);
938 	return set_timefilter_date((struct archive_match *)_a, flag, datestr);
939 }
940 
941 int
archive_match_include_date_w(struct archive * _a,int flag,const wchar_t * datestr)942 archive_match_include_date_w(struct archive *_a, int flag,
943     const wchar_t *datestr)
944 {
945 	int r;
946 
947 	r = validate_time_flag(_a, flag, "archive_match_include_date_w");
948 	if (r != ARCHIVE_OK)
949 		return (r);
950 
951 	return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
952 }
953 
954 int
archive_match_include_file_time(struct archive * _a,int flag,const char * pathname)955 archive_match_include_file_time(struct archive *_a, int flag,
956     const char *pathname)
957 {
958 	int r;
959 
960 	r = validate_time_flag(_a, flag, "archive_match_include_file_time");
961 	if (r != ARCHIVE_OK)
962 		return (r);
963 	return set_timefilter_pathname_mbs((struct archive_match *)_a,
964 			flag, pathname);
965 }
966 
967 int
archive_match_include_file_time_w(struct archive * _a,int flag,const wchar_t * pathname)968 archive_match_include_file_time_w(struct archive *_a, int flag,
969     const wchar_t *pathname)
970 {
971 	int r;
972 
973 	r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
974 	if (r != ARCHIVE_OK)
975 		return (r);
976 	return set_timefilter_pathname_wcs((struct archive_match *)_a,
977 			flag, pathname);
978 }
979 
980 int
archive_match_exclude_entry(struct archive * _a,int flag,struct archive_entry * entry)981 archive_match_exclude_entry(struct archive *_a, int flag,
982     struct archive_entry *entry)
983 {
984 	struct archive_match *a;
985 	int r;
986 
987 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
988 	    ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
989 	a = (struct archive_match *)_a;
990 
991 	if (entry == NULL) {
992 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
993 		return (ARCHIVE_FAILED);
994 	}
995 	r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
996 	if (r != ARCHIVE_OK)
997 		return (r);
998 	return (add_entry(a, flag, entry));
999 }
1000 
1001 /*
1002  * Test function for time stamps.
1003  *
1004  * Returns 1 if archive entry is excluded.
1005  * Returns 0 if archive entry is not excluded.
1006  * Returns <0 if something error happened.
1007  */
1008 int
archive_match_time_excluded(struct archive * _a,struct archive_entry * entry)1009 archive_match_time_excluded(struct archive *_a,
1010     struct archive_entry *entry)
1011 {
1012 	struct archive_match *a;
1013 
1014 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1015 	    ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
1016 
1017 	a = (struct archive_match *)_a;
1018 	if (entry == NULL) {
1019 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1020 		return (ARCHIVE_FAILED);
1021 	}
1022 
1023 	/* If we don't have inclusion time set at all, the entry is always
1024 	 * not excluded. */
1025 	if ((a->setflag & TIME_IS_SET) == 0)
1026 		return (0);
1027 	return (time_excluded(a, entry));
1028 }
1029 
1030 static int
validate_time_flag(struct archive * _a,int flag,const char * _fn)1031 validate_time_flag(struct archive *_a, int flag, const char *_fn)
1032 {
1033 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1034 	    ARCHIVE_STATE_NEW, _fn);
1035 
1036 	/* Check a type of time. */
1037 	if (flag &
1038 	   ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
1039 		archive_set_error(_a, EINVAL, "Invalid time flag");
1040 		return (ARCHIVE_FAILED);
1041 	}
1042 	if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
1043 		archive_set_error(_a, EINVAL, "No time flag");
1044 		return (ARCHIVE_FAILED);
1045 	}
1046 
1047 	/* Check a type of comparison. */
1048 	if (flag &
1049 	   ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1050 			| ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
1051 		archive_set_error(_a, EINVAL, "Invalid comparison flag");
1052 		return (ARCHIVE_FAILED);
1053 	}
1054 	if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1055 	    | ARCHIVE_MATCH_EQUAL)) == 0) {
1056 		archive_set_error(_a, EINVAL, "No comparison flag");
1057 		return (ARCHIVE_FAILED);
1058 	}
1059 
1060 	return (ARCHIVE_OK);
1061 }
1062 
1063 #define JUST_EQUAL(t) (((t) &  (ARCHIVE_MATCH_EQUAL |\
1064 	ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
1065 static int
set_timefilter(struct archive_match * a,int timetype,time_t mtime_sec,long mtime_nsec,time_t ctime_sec,long ctime_nsec)1066 set_timefilter(struct archive_match *a, int timetype,
1067     time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
1068 {
1069 	if (timetype & ARCHIVE_MATCH_MTIME) {
1070 		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1071 			a->newer_mtime_filter = timetype;
1072 			a->newer_mtime_sec = mtime_sec;
1073 			a->newer_mtime_nsec = mtime_nsec;
1074 			a->setflag |= TIME_IS_SET;
1075 		}
1076 		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1077 			a->older_mtime_filter = timetype;
1078 			a->older_mtime_sec = mtime_sec;
1079 			a->older_mtime_nsec = mtime_nsec;
1080 			a->setflag |= TIME_IS_SET;
1081 		}
1082 	}
1083 	if (timetype & ARCHIVE_MATCH_CTIME) {
1084 		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1085 			a->newer_ctime_filter = timetype;
1086 			a->newer_ctime_sec = ctime_sec;
1087 			a->newer_ctime_nsec = ctime_nsec;
1088 			a->setflag |= TIME_IS_SET;
1089 		}
1090 		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1091 			a->older_ctime_filter = timetype;
1092 			a->older_ctime_sec = ctime_sec;
1093 			a->older_ctime_nsec = ctime_nsec;
1094 			a->setflag |= TIME_IS_SET;
1095 		}
1096 	}
1097 	return (ARCHIVE_OK);
1098 }
1099 
1100 static int
set_timefilter_date(struct archive_match * a,int timetype,const char * datestr)1101 set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
1102 {
1103 	time_t t;
1104 
1105 	if (datestr == NULL || *datestr == '\0') {
1106 		archive_set_error(&(a->archive), EINVAL, "date is empty");
1107 		return (ARCHIVE_FAILED);
1108 	}
1109 	t = get_date(a->now, datestr);
1110 	if (t == (time_t)-1) {
1111 		archive_set_error(&(a->archive), EINVAL, "invalid date string");
1112 		return (ARCHIVE_FAILED);
1113 	}
1114 	return set_timefilter(a, timetype, t, 0, t, 0);
1115 }
1116 
1117 static int
set_timefilter_date_w(struct archive_match * a,int timetype,const wchar_t * datestr)1118 set_timefilter_date_w(struct archive_match *a, int timetype,
1119     const wchar_t *datestr)
1120 {
1121 	struct archive_string as;
1122 	time_t t;
1123 
1124 	if (datestr == NULL || *datestr == L'\0') {
1125 		archive_set_error(&(a->archive), EINVAL, "date is empty");
1126 		return (ARCHIVE_FAILED);
1127 	}
1128 
1129 	archive_string_init(&as);
1130 	if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
1131 		archive_string_free(&as);
1132 		if (errno == ENOMEM)
1133 			return (error_nomem(a));
1134 		archive_set_error(&(a->archive), -1,
1135 		    "Failed to convert WCS to MBS");
1136 		return (ARCHIVE_FAILED);
1137 	}
1138 	t = get_date(a->now, as.s);
1139 	archive_string_free(&as);
1140 	if (t == (time_t)-1) {
1141 		archive_set_error(&(a->archive), EINVAL, "invalid date string");
1142 		return (ARCHIVE_FAILED);
1143 	}
1144 	return set_timefilter(a, timetype, t, 0, t, 0);
1145 }
1146 
1147 #if defined(_WIN32) && !defined(__CYGWIN__)
1148 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1149 static int
set_timefilter_find_data(struct archive_match * a,int timetype,DWORD ftLastWriteTime_dwHighDateTime,DWORD ftLastWriteTime_dwLowDateTime,DWORD ftCreationTime_dwHighDateTime,DWORD ftCreationTime_dwLowDateTime)1150 set_timefilter_find_data(struct archive_match *a, int timetype,
1151     DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
1152     DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
1153 {
1154 	ULARGE_INTEGER utc;
1155 	time_t ctime_sec, mtime_sec;
1156 	long ctime_ns, mtime_ns;
1157 
1158 	utc.HighPart = ftCreationTime_dwHighDateTime;
1159 	utc.LowPart = ftCreationTime_dwLowDateTime;
1160 	if (utc.QuadPart >= EPOC_TIME) {
1161 		utc.QuadPart -= EPOC_TIME;
1162 		ctime_sec = (time_t)(utc.QuadPart / 10000000);
1163 		ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
1164 	} else {
1165 		ctime_sec = 0;
1166 		ctime_ns = 0;
1167 	}
1168 	utc.HighPart = ftLastWriteTime_dwHighDateTime;
1169 	utc.LowPart = ftLastWriteTime_dwLowDateTime;
1170 	if (utc.QuadPart >= EPOC_TIME) {
1171 		utc.QuadPart -= EPOC_TIME;
1172 		mtime_sec = (time_t)(utc.QuadPart / 10000000);
1173 		mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
1174 	} else {
1175 		mtime_sec = 0;
1176 		mtime_ns = 0;
1177 	}
1178 	return set_timefilter(a, timetype,
1179 			mtime_sec, mtime_ns, ctime_sec, ctime_ns);
1180 }
1181 
1182 static int
set_timefilter_pathname_mbs(struct archive_match * a,int timetype,const char * path)1183 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1184     const char *path)
1185 {
1186 	/* NOTE: stat() on Windows cannot handle nano seconds. */
1187 	HANDLE h;
1188 	WIN32_FIND_DATAA d;
1189 
1190 	if (path == NULL || *path == '\0') {
1191 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1192 		return (ARCHIVE_FAILED);
1193 	}
1194 	h = FindFirstFileA(path, &d);
1195 	if (h == INVALID_HANDLE_VALUE) {
1196 		la_dosmaperr(GetLastError());
1197 		archive_set_error(&(a->archive), errno,
1198 		    "Failed to FindFirstFileA");
1199 		return (ARCHIVE_FAILED);
1200 	}
1201 	FindClose(h);
1202 	return set_timefilter_find_data(a, timetype,
1203 	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1204 	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1205 }
1206 
1207 static int
set_timefilter_pathname_wcs(struct archive_match * a,int timetype,const wchar_t * path)1208 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1209     const wchar_t *path)
1210 {
1211 	HANDLE h;
1212 	WIN32_FIND_DATAW d;
1213 
1214 	if (path == NULL || *path == L'\0') {
1215 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1216 		return (ARCHIVE_FAILED);
1217 	}
1218 	h = FindFirstFileW(path, &d);
1219 	if (h == INVALID_HANDLE_VALUE) {
1220 		la_dosmaperr(GetLastError());
1221 		archive_set_error(&(a->archive), errno,
1222 		    "Failed to FindFirstFile");
1223 		return (ARCHIVE_FAILED);
1224 	}
1225 	FindClose(h);
1226 	return set_timefilter_find_data(a, timetype,
1227 	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1228 	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1229 }
1230 
1231 #else /* _WIN32 && !__CYGWIN__ */
1232 
1233 static int
set_timefilter_stat(struct archive_match * a,int timetype,struct stat * st)1234 set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
1235 {
1236 	struct archive_entry *ae;
1237 	time_t ctime_sec, mtime_sec;
1238 	long ctime_ns, mtime_ns;
1239 
1240 	ae = archive_entry_new();
1241 	if (ae == NULL)
1242 		return (error_nomem(a));
1243 	archive_entry_copy_stat(ae, st);
1244 	ctime_sec = archive_entry_ctime(ae);
1245 	ctime_ns = archive_entry_ctime_nsec(ae);
1246 	mtime_sec = archive_entry_mtime(ae);
1247 	mtime_ns = archive_entry_mtime_nsec(ae);
1248 	archive_entry_free(ae);
1249 	return set_timefilter(a, timetype, mtime_sec, mtime_ns,
1250 			ctime_sec, ctime_ns);
1251 }
1252 
1253 static int
set_timefilter_pathname_mbs(struct archive_match * a,int timetype,const char * path)1254 set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1255     const char *path)
1256 {
1257 	struct stat st;
1258 
1259 	if (path == NULL || *path == '\0') {
1260 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1261 		return (ARCHIVE_FAILED);
1262 	}
1263 	if (la_stat(path, &st) != 0) {
1264 		archive_set_error(&(a->archive), errno, "Failed to stat()");
1265 		return (ARCHIVE_FAILED);
1266 	}
1267 	return (set_timefilter_stat(a, timetype, &st));
1268 }
1269 
1270 static int
set_timefilter_pathname_wcs(struct archive_match * a,int timetype,const wchar_t * path)1271 set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1272     const wchar_t *path)
1273 {
1274 	struct archive_string as;
1275 	int r;
1276 
1277 	if (path == NULL || *path == L'\0') {
1278 		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1279 		return (ARCHIVE_FAILED);
1280 	}
1281 
1282 	/* Convert WCS filename to MBS filename. */
1283 	archive_string_init(&as);
1284 	if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
1285 		archive_string_free(&as);
1286 		if (errno == ENOMEM)
1287 			return (error_nomem(a));
1288 		archive_set_error(&(a->archive), -1,
1289 		    "Failed to convert WCS to MBS");
1290 		return (ARCHIVE_FAILED);
1291 	}
1292 
1293 	r = set_timefilter_pathname_mbs(a, timetype, as.s);
1294 	archive_string_free(&as);
1295 
1296 	return (r);
1297 }
1298 #endif /* _WIN32 && !__CYGWIN__ */
1299 
1300 /*
1301  * Call back functions for archive_rb.
1302  */
1303 static int
cmp_node_mbs(const struct archive_rb_node * n1,const struct archive_rb_node * n2)1304 cmp_node_mbs(const struct archive_rb_node *n1,
1305     const struct archive_rb_node *n2)
1306 {
1307 	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1308 	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1309 	const char *p1, *p2;
1310 
1311 	archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
1312 	archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
1313 	if (p1 == NULL)
1314 		return (1);
1315 	if (p2 == NULL)
1316 		return (-1);
1317 	return (strcmp(p1, p2));
1318 }
1319 
1320 static int
cmp_key_mbs(const struct archive_rb_node * n,const void * key)1321 cmp_key_mbs(const struct archive_rb_node *n, const void *key)
1322 {
1323 	struct match_file *f = (struct match_file *)(uintptr_t)n;
1324 	const char *p;
1325 
1326 	archive_mstring_get_mbs(NULL, &(f->pathname), &p);
1327 	if (p == NULL)
1328 		return (-1);
1329 	return (strcmp(p, (const char *)key));
1330 }
1331 
1332 static int
cmp_node_wcs(const struct archive_rb_node * n1,const struct archive_rb_node * n2)1333 cmp_node_wcs(const struct archive_rb_node *n1,
1334     const struct archive_rb_node *n2)
1335 {
1336 	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1337 	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1338 	const wchar_t *p1, *p2;
1339 
1340 	archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
1341 	archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
1342 	if (p1 == NULL)
1343 		return (1);
1344 	if (p2 == NULL)
1345 		return (-1);
1346 	return (wcscmp(p1, p2));
1347 }
1348 
1349 static int
cmp_key_wcs(const struct archive_rb_node * n,const void * key)1350 cmp_key_wcs(const struct archive_rb_node *n, const void *key)
1351 {
1352 	struct match_file *f = (struct match_file *)(uintptr_t)n;
1353 	const wchar_t *p;
1354 
1355 	archive_mstring_get_wcs(NULL, &(f->pathname), &p);
1356 	if (p == NULL)
1357 		return (-1);
1358 	return (wcscmp(p, (const wchar_t *)key));
1359 }
1360 
1361 static void
entry_list_init(struct entry_list * list)1362 entry_list_init(struct entry_list *list)
1363 {
1364 	list->first = NULL;
1365 	list->last = &(list->first);
1366 	list->count = 0;
1367 }
1368 
1369 static void
entry_list_free(struct entry_list * list)1370 entry_list_free(struct entry_list *list)
1371 {
1372 	struct match_file *p, *q;
1373 
1374 	for (p = list->first; p != NULL; ) {
1375 		q = p;
1376 		p = p->next;
1377 		archive_mstring_clean(&(q->pathname));
1378 		free(q);
1379 	}
1380 }
1381 
1382 static void
entry_list_add(struct entry_list * list,struct match_file * file)1383 entry_list_add(struct entry_list *list, struct match_file *file)
1384 {
1385 	*list->last = file;
1386 	list->last = &(file->next);
1387 	list->count++;
1388 }
1389 
1390 static int
add_entry(struct archive_match * a,int flag,struct archive_entry * entry)1391 add_entry(struct archive_match *a, int flag,
1392     struct archive_entry *entry)
1393 {
1394 	struct match_file *f;
1395 	const void *pathname;
1396 	int r;
1397 
1398 	f = calloc(1, sizeof(*f));
1399 	if (f == NULL)
1400 		return (error_nomem(a));
1401 
1402 #if defined(_WIN32) && !defined(__CYGWIN__)
1403 	pathname = archive_entry_pathname_w(entry);
1404 	if (pathname == NULL) {
1405 		free(f);
1406 		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1407 		return (ARCHIVE_FAILED);
1408 	}
1409 	archive_mstring_copy_wcs(&(f->pathname), pathname);
1410 	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1411 #else
1412 	(void)rb_ops_wcs;
1413 	pathname = archive_entry_pathname(entry);
1414 	if (pathname == NULL) {
1415 		free(f);
1416 		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1417 		return (ARCHIVE_FAILED);
1418 	}
1419 	archive_mstring_copy_mbs(&(f->pathname), pathname);
1420 	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1421 #endif
1422 	f->flag = flag;
1423 	f->mtime_sec = archive_entry_mtime(entry);
1424 	f->mtime_nsec = archive_entry_mtime_nsec(entry);
1425 	f->ctime_sec = archive_entry_ctime(entry);
1426 	f->ctime_nsec = archive_entry_ctime_nsec(entry);
1427 	r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
1428 	if (!r) {
1429 		struct match_file *f2;
1430 
1431 		/* Get the duplicated file. */
1432 		f2 = (struct match_file *)__archive_rb_tree_find_node(
1433 			&(a->exclusion_tree), pathname);
1434 
1435 		/*
1436 		 * We always overwrite comparison condition.
1437 		 * If you do not want to overwrite it, you should not
1438 		 * call archive_match_exclude_entry(). We cannot know
1439 		 * what behavior you really expect since overwriting
1440 		 * condition might be different with the flag.
1441 		 */
1442 		if (f2 != NULL) {
1443 			f2->flag = f->flag;
1444 			f2->mtime_sec = f->mtime_sec;
1445 			f2->mtime_nsec = f->mtime_nsec;
1446 			f2->ctime_sec = f->ctime_sec;
1447 			f2->ctime_nsec = f->ctime_nsec;
1448 		}
1449 		/* Release the duplicated file. */
1450 		archive_mstring_clean(&(f->pathname));
1451 		free(f);
1452 		return (ARCHIVE_OK);
1453 	}
1454 	entry_list_add(&(a->exclusion_entry_list), f);
1455 	a->setflag |= TIME_IS_SET;
1456 	return (ARCHIVE_OK);
1457 }
1458 
1459 /*
1460  * Test if entry is excluded by its timestamp.
1461  */
1462 static int
time_excluded(struct archive_match * a,struct archive_entry * entry)1463 time_excluded(struct archive_match *a, struct archive_entry *entry)
1464 {
1465 	struct match_file *f;
1466 	const void *pathname;
1467 	time_t sec;
1468 	long nsec;
1469 
1470 	/*
1471 	 * If this file/dir is excluded by a time comparison, skip it.
1472 	 */
1473 	if (a->newer_ctime_filter) {
1474 		/* If ctime is not set, use mtime instead. */
1475 		if (archive_entry_ctime_is_set(entry))
1476 			sec = archive_entry_ctime(entry);
1477 		else
1478 			sec = archive_entry_mtime(entry);
1479 		if (sec < a->newer_ctime_sec)
1480 			return (1); /* Too old, skip it. */
1481 		if (sec == a->newer_ctime_sec) {
1482 			if (archive_entry_ctime_is_set(entry))
1483 				nsec = archive_entry_ctime_nsec(entry);
1484 			else
1485 				nsec = archive_entry_mtime_nsec(entry);
1486 			if (nsec < a->newer_ctime_nsec)
1487 				return (1); /* Too old, skip it. */
1488 			if (nsec == a->newer_ctime_nsec &&
1489 			    (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
1490 			      == 0)
1491 				return (1); /* Equal, skip it. */
1492 		}
1493 	}
1494 	if (a->older_ctime_filter) {
1495 		/* If ctime is not set, use mtime instead. */
1496 		if (archive_entry_ctime_is_set(entry))
1497 			sec = archive_entry_ctime(entry);
1498 		else
1499 			sec = archive_entry_mtime(entry);
1500 		if (sec > a->older_ctime_sec)
1501 			return (1); /* Too new, skip it. */
1502 		if (sec == a->older_ctime_sec) {
1503 			if (archive_entry_ctime_is_set(entry))
1504 				nsec = archive_entry_ctime_nsec(entry);
1505 			else
1506 				nsec = archive_entry_mtime_nsec(entry);
1507 			if (nsec > a->older_ctime_nsec)
1508 				return (1); /* Too new, skip it. */
1509 			if (nsec == a->older_ctime_nsec &&
1510 			    (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
1511 			      == 0)
1512 				return (1); /* Equal, skip it. */
1513 		}
1514 	}
1515 	if (a->newer_mtime_filter) {
1516 		sec = archive_entry_mtime(entry);
1517 		if (sec < a->newer_mtime_sec)
1518 			return (1); /* Too old, skip it. */
1519 		if (sec == a->newer_mtime_sec) {
1520 			nsec = archive_entry_mtime_nsec(entry);
1521 			if (nsec < a->newer_mtime_nsec)
1522 				return (1); /* Too old, skip it. */
1523 			if (nsec == a->newer_mtime_nsec &&
1524 			    (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
1525 			       == 0)
1526 				return (1); /* Equal, skip it. */
1527 		}
1528 	}
1529 	if (a->older_mtime_filter) {
1530 		sec = archive_entry_mtime(entry);
1531 		if (sec > a->older_mtime_sec)
1532 			return (1); /* Too new, skip it. */
1533 		nsec = archive_entry_mtime_nsec(entry);
1534 		if (sec == a->older_mtime_sec) {
1535 			if (nsec > a->older_mtime_nsec)
1536 				return (1); /* Too new, skip it. */
1537 			if (nsec == a->older_mtime_nsec &&
1538 			    (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
1539 			       == 0)
1540 				return (1); /* Equal, skip it. */
1541 		}
1542 	}
1543 
1544 	/* If there is no exclusion list, include the file. */
1545 	if (a->exclusion_entry_list.count == 0)
1546 		return (0);
1547 
1548 #if defined(_WIN32) && !defined(__CYGWIN__)
1549 	pathname = archive_entry_pathname_w(entry);
1550 	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1551 #else
1552 	(void)rb_ops_wcs;
1553 	pathname = archive_entry_pathname(entry);
1554 	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1555 #endif
1556 	if (pathname == NULL)
1557 		return (0);
1558 
1559 	f = (struct match_file *)__archive_rb_tree_find_node(
1560 		&(a->exclusion_tree), pathname);
1561 	/* If the file wasn't rejected, include it. */
1562 	if (f == NULL)
1563 		return (0);
1564 
1565 	if (f->flag & ARCHIVE_MATCH_CTIME) {
1566 		sec = archive_entry_ctime(entry);
1567 		if (f->ctime_sec > sec) {
1568 			if (f->flag & ARCHIVE_MATCH_OLDER)
1569 				return (1);
1570 		} else if (f->ctime_sec < sec) {
1571 			if (f->flag & ARCHIVE_MATCH_NEWER)
1572 				return (1);
1573 		} else {
1574 			nsec = archive_entry_ctime_nsec(entry);
1575 			if (f->ctime_nsec > nsec) {
1576 				if (f->flag & ARCHIVE_MATCH_OLDER)
1577 					return (1);
1578 			} else if (f->ctime_nsec < nsec) {
1579 				if (f->flag & ARCHIVE_MATCH_NEWER)
1580 					return (1);
1581 			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1582 				return (1);
1583 		}
1584 	}
1585 	if (f->flag & ARCHIVE_MATCH_MTIME) {
1586 		sec = archive_entry_mtime(entry);
1587 		if (f->mtime_sec > sec) {
1588 			if (f->flag & ARCHIVE_MATCH_OLDER)
1589 				return (1);
1590 		} else if (f->mtime_sec < sec) {
1591 			if (f->flag & ARCHIVE_MATCH_NEWER)
1592 				return (1);
1593 		} else {
1594 			nsec = archive_entry_mtime_nsec(entry);
1595 			if (f->mtime_nsec > nsec) {
1596 				if (f->flag & ARCHIVE_MATCH_OLDER)
1597 					return (1);
1598 			} else if (f->mtime_nsec < nsec) {
1599 				if (f->flag & ARCHIVE_MATCH_NEWER)
1600 					return (1);
1601 			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1602 				return (1);
1603 		}
1604 	}
1605 	return (0);
1606 }
1607 
1608 /*
1609  * Utility functions to manage inclusion owners
1610  */
1611 
1612 int
archive_match_include_uid(struct archive * _a,la_int64_t uid)1613 archive_match_include_uid(struct archive *_a, la_int64_t uid)
1614 {
1615 	struct archive_match *a;
1616 
1617 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1618 	    ARCHIVE_STATE_NEW, "archive_match_include_uid");
1619 	a = (struct archive_match *)_a;
1620 	return (add_owner_id(a, &(a->inclusion_uids), uid));
1621 }
1622 
1623 int
archive_match_include_gid(struct archive * _a,la_int64_t gid)1624 archive_match_include_gid(struct archive *_a, la_int64_t gid)
1625 {
1626 	struct archive_match *a;
1627 
1628 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1629 	    ARCHIVE_STATE_NEW, "archive_match_include_gid");
1630 	a = (struct archive_match *)_a;
1631 	return (add_owner_id(a, &(a->inclusion_gids), gid));
1632 }
1633 
1634 int
archive_match_include_uname(struct archive * _a,const char * uname)1635 archive_match_include_uname(struct archive *_a, const char *uname)
1636 {
1637 	struct archive_match *a;
1638 
1639 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1640 	    ARCHIVE_STATE_NEW, "archive_match_include_uname");
1641 	a = (struct archive_match *)_a;
1642 	return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
1643 }
1644 
1645 int
archive_match_include_uname_w(struct archive * _a,const wchar_t * uname)1646 archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
1647 {
1648 	struct archive_match *a;
1649 
1650 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1651 	    ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
1652 	a = (struct archive_match *)_a;
1653 	return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
1654 }
1655 
1656 int
archive_match_include_gname(struct archive * _a,const char * gname)1657 archive_match_include_gname(struct archive *_a, const char *gname)
1658 {
1659 	struct archive_match *a;
1660 
1661 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1662 	    ARCHIVE_STATE_NEW, "archive_match_include_gname");
1663 	a = (struct archive_match *)_a;
1664 	return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
1665 }
1666 
1667 int
archive_match_include_gname_w(struct archive * _a,const wchar_t * gname)1668 archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
1669 {
1670 	struct archive_match *a;
1671 
1672 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1673 	    ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
1674 	a = (struct archive_match *)_a;
1675 	return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
1676 }
1677 
1678 /*
1679  * Test function for owner(uid, gid, uname, gname).
1680  *
1681  * Returns 1 if archive entry is excluded.
1682  * Returns 0 if archive entry is not excluded.
1683  * Returns <0 if something error happened.
1684  */
1685 int
archive_match_owner_excluded(struct archive * _a,struct archive_entry * entry)1686 archive_match_owner_excluded(struct archive *_a,
1687     struct archive_entry *entry)
1688 {
1689 	struct archive_match *a;
1690 
1691 	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1692 	    ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
1693 
1694 	a = (struct archive_match *)_a;
1695 	if (entry == NULL) {
1696 		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1697 		return (ARCHIVE_FAILED);
1698 	}
1699 
1700 	/* If we don't have inclusion id set at all, the entry is always
1701 	 * not excluded. */
1702 	if ((a->setflag & ID_IS_SET) == 0)
1703 		return (0);
1704 	return (owner_excluded(a, entry));
1705 }
1706 
1707 static int
add_owner_id(struct archive_match * a,struct id_array * ids,int64_t id)1708 add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
1709 {
1710 	unsigned i;
1711 
1712 	if (ids->count + 1 >= ids->size) {
1713 		void *p;
1714 
1715 		if (ids->size == 0)
1716 			ids->size = 8;
1717 		else
1718 			ids->size *= 2;
1719 		p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
1720 		if (p == NULL)
1721 			return (error_nomem(a));
1722 		ids->ids = (int64_t *)p;
1723 	}
1724 
1725 	/* Find an insert point. */
1726 	for (i = 0; i < ids->count; i++) {
1727 		if (ids->ids[i] >= id)
1728 			break;
1729 	}
1730 
1731 	/* Add owner id. */
1732 	if (i == ids->count)
1733 		ids->ids[ids->count++] = id;
1734 	else if (ids->ids[i] != id) {
1735 		memmove(&(ids->ids[i+1]), &(ids->ids[i]),
1736 		    (ids->count - i) * sizeof(ids->ids[0]));
1737 		ids->ids[i] = id;
1738 		ids->count++;
1739 	}
1740 	a->setflag |= ID_IS_SET;
1741 	return (ARCHIVE_OK);
1742 }
1743 
1744 static int
match_owner_id(struct id_array * ids,int64_t id)1745 match_owner_id(struct id_array *ids, int64_t id)
1746 {
1747 	unsigned b, m, t;
1748 
1749 	t = 0;
1750 	b = (unsigned)ids->count;
1751 	while (t < b) {
1752 		m = (t + b)>>1;
1753 		if (ids->ids[m] == id)
1754 			return (1);
1755 		if (ids->ids[m] < id)
1756 			t = m + 1;
1757 		else
1758 			b = m;
1759 	}
1760 	return (0);
1761 }
1762 
1763 static int
add_owner_name(struct archive_match * a,struct match_list * list,int mbs,const void * name)1764 add_owner_name(struct archive_match *a, struct match_list *list,
1765     int mbs, const void *name)
1766 {
1767 	struct match *match;
1768 
1769 	match = calloc(1, sizeof(*match));
1770 	if (match == NULL)
1771 		return (error_nomem(a));
1772 	if (mbs)
1773 		archive_mstring_copy_mbs(&(match->pattern), name);
1774 	else
1775 		archive_mstring_copy_wcs(&(match->pattern), name);
1776 	match_list_add(list, match);
1777 	a->setflag |= ID_IS_SET;
1778 	return (ARCHIVE_OK);
1779 }
1780 
1781 #if !defined(_WIN32) || defined(__CYGWIN__)
1782 static int
match_owner_name_mbs(struct archive_match * a,struct match_list * list,const char * name)1783 match_owner_name_mbs(struct archive_match *a, struct match_list *list,
1784     const char *name)
1785 {
1786 	struct match *m;
1787 	const char *p;
1788 
1789 	if (name == NULL || *name == '\0')
1790 		return (0);
1791 	for (m = list->first; m; m = m->next) {
1792 		if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
1793 		    < 0 && errno == ENOMEM)
1794 			return (error_nomem(a));
1795 		if (p != NULL && strcmp(p, name) == 0) {
1796 			m->matched = 1;
1797 			return (1);
1798 		}
1799 	}
1800 	return (0);
1801 }
1802 #else
1803 static int
match_owner_name_wcs(struct archive_match * a,struct match_list * list,const wchar_t * name)1804 match_owner_name_wcs(struct archive_match *a, struct match_list *list,
1805     const wchar_t *name)
1806 {
1807 	struct match *m;
1808 	const wchar_t *p;
1809 
1810 	if (name == NULL || *name == L'\0')
1811 		return (0);
1812 	for (m = list->first; m; m = m->next) {
1813 		if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
1814 		    < 0 && errno == ENOMEM)
1815 			return (error_nomem(a));
1816 		if (p != NULL && wcscmp(p, name) == 0) {
1817 			m->matched = 1;
1818 			return (1);
1819 		}
1820 	}
1821 	return (0);
1822 }
1823 #endif
1824 
1825 /*
1826  * Test if entry is excluded by uid, gid, uname or gname.
1827  */
1828 static int
owner_excluded(struct archive_match * a,struct archive_entry * entry)1829 owner_excluded(struct archive_match *a, struct archive_entry *entry)
1830 {
1831 	int r;
1832 
1833 	if (a->inclusion_uids.count) {
1834 		if (!match_owner_id(&(a->inclusion_uids),
1835 		    archive_entry_uid(entry)))
1836 			return (1);
1837 	}
1838 
1839 	if (a->inclusion_gids.count) {
1840 		if (!match_owner_id(&(a->inclusion_gids),
1841 		    archive_entry_gid(entry)))
1842 			return (1);
1843 	}
1844 
1845 	if (a->inclusion_unames.count) {
1846 #if defined(_WIN32) && !defined(__CYGWIN__)
1847 		r = match_owner_name_wcs(a, &(a->inclusion_unames),
1848 			archive_entry_uname_w(entry));
1849 #else
1850 		r = match_owner_name_mbs(a, &(a->inclusion_unames),
1851 			archive_entry_uname(entry));
1852 #endif
1853 		if (!r)
1854 			return (1);
1855 		else if (r < 0)
1856 			return (r);
1857 	}
1858 
1859 	if (a->inclusion_gnames.count) {
1860 #if defined(_WIN32) && !defined(__CYGWIN__)
1861 		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
1862 			archive_entry_gname_w(entry));
1863 #else
1864 		r = match_owner_name_mbs(a, &(a->inclusion_gnames),
1865 			archive_entry_gname(entry));
1866 #endif
1867 		if (!r)
1868 			return (1);
1869 		else if (r < 0)
1870 			return (r);
1871 	}
1872 	return (0);
1873 }
1874 
1875