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