archive_match.c revision 248616
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	(void)rb_ops_wcs;
1380	pathname = archive_entry_pathname(entry);
1381	if (pathname == NULL) {
1382		free(f);
1383		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1384		return (ARCHIVE_FAILED);
1385	}
1386	archive_mstring_copy_mbs(&(f->pathname), pathname);
1387	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1388#endif
1389	f->flag = flag;
1390	f->mtime_sec = archive_entry_mtime(entry);
1391	f->mtime_nsec = archive_entry_mtime_nsec(entry);
1392	f->ctime_sec = archive_entry_ctime(entry);
1393	f->ctime_nsec = archive_entry_ctime_nsec(entry);
1394	r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
1395	if (!r) {
1396		struct match_file *f2;
1397
1398		/* Get the duplicated file. */
1399		f2 = (struct match_file *)__archive_rb_tree_find_node(
1400			&(a->exclusion_tree), pathname);
1401
1402		/*
1403		 * We always overwrite comparison condision.
1404		 * If you do not want to overwrite it, you should not
1405		 * call archive_match_exclude_entry(). We cannot know
1406		 * what behavior you really expect since overwriting
1407		 * condition might be different with the flag.
1408		 */
1409		if (f2 != NULL) {
1410			f2->flag = f->flag;
1411			f2->mtime_sec = f->mtime_sec;
1412			f2->mtime_nsec = f->mtime_nsec;
1413			f2->ctime_sec = f->ctime_sec;
1414			f2->ctime_nsec = f->ctime_nsec;
1415		}
1416		/* Release the duplicated file. */
1417		archive_mstring_clean(&(f->pathname));
1418		free(f);
1419		return (ARCHIVE_OK);
1420	}
1421	entry_list_add(&(a->exclusion_entry_list), f);
1422	a->setflag |= TIME_IS_SET;
1423	return (ARCHIVE_OK);
1424}
1425
1426/*
1427 * Test if entry is excluded by its timestamp.
1428 */
1429static int
1430time_excluded(struct archive_match *a, struct archive_entry *entry)
1431{
1432	struct match_file *f;
1433	const void *pathname;
1434	time_t sec;
1435	long nsec;
1436
1437	/*
1438	 * If this file/dir is excluded by a time comparison, skip it.
1439	 */
1440	if (a->newer_ctime_filter) {
1441		/* If ctime is not set, use mtime instead. */
1442		if (archive_entry_ctime_is_set(entry))
1443			sec = archive_entry_ctime(entry);
1444		else
1445			sec = archive_entry_mtime(entry);
1446		if (sec < a->newer_ctime_sec)
1447			return (1); /* Too old, skip it. */
1448		if (sec == a->newer_ctime_sec) {
1449			if (archive_entry_ctime_is_set(entry))
1450				nsec = archive_entry_ctime_nsec(entry);
1451			else
1452				nsec = archive_entry_mtime_nsec(entry);
1453			if (nsec < a->newer_ctime_nsec)
1454				return (1); /* Too old, skip it. */
1455			if (nsec == a->newer_ctime_nsec &&
1456			    (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
1457			      == 0)
1458				return (1); /* Equal, skip it. */
1459		}
1460	}
1461	if (a->older_ctime_filter) {
1462		/* If ctime is not set, use mtime instead. */
1463		if (archive_entry_ctime_is_set(entry))
1464			sec = archive_entry_ctime(entry);
1465		else
1466			sec = archive_entry_mtime(entry);
1467		if (sec > a->older_ctime_sec)
1468			return (1); /* Too new, skip it. */
1469		if (sec == a->older_ctime_sec) {
1470			if (archive_entry_ctime_is_set(entry))
1471				nsec = archive_entry_ctime_nsec(entry);
1472			else
1473				nsec = archive_entry_mtime_nsec(entry);
1474			if (nsec > a->older_ctime_nsec)
1475				return (1); /* Too new, skip it. */
1476			if (nsec == a->older_ctime_nsec &&
1477			    (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
1478			      == 0)
1479				return (1); /* Eeual, skip it. */
1480		}
1481	}
1482	if (a->newer_mtime_filter) {
1483		sec = archive_entry_mtime(entry);
1484		if (sec < a->newer_mtime_sec)
1485			return (1); /* Too old, skip it. */
1486		if (sec == a->newer_mtime_sec) {
1487			nsec = archive_entry_mtime_nsec(entry);
1488			if (nsec < a->newer_mtime_nsec)
1489				return (1); /* Too old, skip it. */
1490			if (nsec == a->newer_mtime_nsec &&
1491			    (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
1492			       == 0)
1493				return (1); /* Equal, skip it. */
1494		}
1495	}
1496	if (a->older_mtime_filter) {
1497		sec = archive_entry_mtime(entry);
1498		if (sec > a->older_mtime_sec)
1499			return (1); /* Too new, skip it. */
1500		nsec = archive_entry_mtime_nsec(entry);
1501		if (sec == a->older_mtime_sec) {
1502			if (nsec > a->older_mtime_nsec)
1503				return (1); /* Too new, skip it. */
1504			if (nsec == a->older_mtime_nsec &&
1505			    (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
1506			       == 0)
1507				return (1); /* Equal, skip it. */
1508		}
1509	}
1510
1511	/* If there is no excluson list, include the file. */
1512	if (a->exclusion_entry_list.count == 0)
1513		return (0);
1514
1515#if defined(_WIN32) && !defined(__CYGWIN__)
1516	pathname = archive_entry_pathname_w(entry);
1517	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1518#else
1519	(void)rb_ops_wcs;
1520	pathname = archive_entry_pathname(entry);
1521	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1522#endif
1523	if (pathname == NULL)
1524		return (0);
1525
1526	f = (struct match_file *)__archive_rb_tree_find_node(
1527		&(a->exclusion_tree), pathname);
1528	/* If the file wasn't rejected, include it. */
1529	if (f == NULL)
1530		return (0);
1531
1532	if (f->flag & ARCHIVE_MATCH_CTIME) {
1533		sec = archive_entry_ctime(entry);
1534		if (f->ctime_sec > sec) {
1535			if (f->flag & ARCHIVE_MATCH_OLDER)
1536				return (1);
1537		} else if (f->ctime_sec < sec) {
1538			if (f->flag & ARCHIVE_MATCH_NEWER)
1539				return (1);
1540		} else {
1541			nsec = archive_entry_ctime_nsec(entry);
1542			if (f->ctime_nsec > nsec) {
1543				if (f->flag & ARCHIVE_MATCH_OLDER)
1544					return (1);
1545			} else if (f->ctime_nsec < nsec) {
1546				if (f->flag & ARCHIVE_MATCH_NEWER)
1547					return (1);
1548			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1549				return (1);
1550		}
1551	}
1552	if (f->flag & ARCHIVE_MATCH_MTIME) {
1553		sec = archive_entry_mtime(entry);
1554		if (f->mtime_sec > sec) {
1555			if (f->flag & ARCHIVE_MATCH_OLDER)
1556				return (1);
1557		} else if (f->mtime_sec < sec) {
1558			if (f->flag & ARCHIVE_MATCH_NEWER)
1559				return (1);
1560		} else {
1561			nsec = archive_entry_mtime_nsec(entry);
1562			if (f->mtime_nsec > nsec) {
1563				if (f->flag & ARCHIVE_MATCH_OLDER)
1564					return (1);
1565			} else if (f->mtime_nsec < nsec) {
1566				if (f->flag & ARCHIVE_MATCH_NEWER)
1567					return (1);
1568			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1569				return (1);
1570		}
1571	}
1572	return (0);
1573}
1574
1575/*
1576 * Utility functions to manage inclusion owners
1577 */
1578
1579int
1580archive_match_include_uid(struct archive *_a, int64_t uid)
1581{
1582	struct archive_match *a;
1583
1584	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1585	    ARCHIVE_STATE_NEW, "archive_match_include_uid");
1586	a = (struct archive_match *)_a;
1587	return (add_owner_id(a, &(a->inclusion_uids), uid));
1588}
1589
1590int
1591archive_match_include_gid(struct archive *_a, int64_t gid)
1592{
1593	struct archive_match *a;
1594
1595	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1596	    ARCHIVE_STATE_NEW, "archive_match_include_gid");
1597	a = (struct archive_match *)_a;
1598	return (add_owner_id(a, &(a->inclusion_gids), gid));
1599}
1600
1601int
1602archive_match_include_uname(struct archive *_a, const char *uname)
1603{
1604	struct archive_match *a;
1605
1606	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1607	    ARCHIVE_STATE_NEW, "archive_match_include_uname");
1608	a = (struct archive_match *)_a;
1609	return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
1610}
1611
1612int
1613archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
1614{
1615	struct archive_match *a;
1616
1617	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1618	    ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
1619	a = (struct archive_match *)_a;
1620	return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
1621}
1622
1623int
1624archive_match_include_gname(struct archive *_a, const char *gname)
1625{
1626	struct archive_match *a;
1627
1628	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1629	    ARCHIVE_STATE_NEW, "archive_match_include_gname");
1630	a = (struct archive_match *)_a;
1631	return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
1632}
1633
1634int
1635archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
1636{
1637	struct archive_match *a;
1638
1639	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1640	    ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
1641	a = (struct archive_match *)_a;
1642	return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
1643}
1644
1645/*
1646 * Test function for owner(uid, gid, uname, gname).
1647 *
1648 * Returns 1 if archive entry is excluded.
1649 * Returns 0 if archive entry is not excluded.
1650 * Returns <0 if something error happened.
1651 */
1652int
1653archive_match_owner_excluded(struct archive *_a,
1654    struct archive_entry *entry)
1655{
1656	struct archive_match *a;
1657
1658	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1659	    ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
1660
1661	a = (struct archive_match *)_a;
1662	if (entry == NULL) {
1663		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1664		return (ARCHIVE_FAILED);
1665	}
1666
1667	/* If we don't have inclusion id set at all, the entry is always
1668	 * not excluded. */
1669	if ((a->setflag & ID_IS_SET) == 0)
1670		return (0);
1671	return (owner_excluded(a, entry));
1672}
1673
1674static int
1675add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
1676{
1677	unsigned i;
1678
1679	if (ids->count + 1 >= ids->size) {
1680		void *p;
1681
1682		if (ids->size == 0)
1683			ids->size = 8;
1684		else
1685			ids->size *= 2;
1686		p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
1687		if (p == NULL)
1688			return (error_nomem(a));
1689		ids->ids = (int64_t *)p;
1690	}
1691
1692	/* Find an insert point. */
1693	for (i = 0; i < ids->count; i++) {
1694		if (ids->ids[i] >= id)
1695			break;
1696	}
1697
1698	/* Add oowner id. */
1699	if (i == ids->count)
1700		ids->ids[ids->count++] = id;
1701	else if (ids->ids[i] != id) {
1702		memmove(&(ids->ids[i+1]), &(ids->ids[i]),
1703		    (ids->count - i) * sizeof(ids->ids[0]));
1704		ids->ids[i] = id;
1705		ids->count++;
1706	}
1707	a->setflag |= ID_IS_SET;
1708	return (ARCHIVE_OK);
1709}
1710
1711static int
1712match_owner_id(struct id_array *ids, int64_t id)
1713{
1714	unsigned b, m, t;
1715
1716	t = 0;
1717	b = (unsigned)ids->count;
1718	while (t < b) {
1719		m = (t + b)>>1;
1720		if (ids->ids[m] == id)
1721			return (1);
1722		if (ids->ids[m] < id)
1723			t = m + 1;
1724		else
1725			b = m;
1726	}
1727	return (0);
1728}
1729
1730static int
1731add_owner_name(struct archive_match *a, struct match_list *list,
1732    int mbs, const void *name)
1733{
1734	struct match *match;
1735
1736	match = calloc(1, sizeof(*match));
1737	if (match == NULL)
1738		return (error_nomem(a));
1739	if (mbs)
1740		archive_mstring_copy_mbs(&(match->pattern), name);
1741	else
1742		archive_mstring_copy_wcs(&(match->pattern), name);
1743	match_list_add(list, match);
1744	a->setflag |= ID_IS_SET;
1745	return (ARCHIVE_OK);
1746}
1747
1748#if !defined(_WIN32) || defined(__CYGWIN__)
1749static int
1750match_owner_name_mbs(struct archive_match *a, struct match_list *list,
1751    const char *name)
1752{
1753	struct match *m;
1754	const char *p;
1755
1756	if (name == NULL || *name == '\0')
1757		return (0);
1758	for (m = list->first; m; m = m->next) {
1759		if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
1760		    < 0 && errno == ENOMEM)
1761			return (error_nomem(a));
1762		if (p != NULL && strcmp(p, name) == 0) {
1763			m->matches++;
1764			return (1);
1765		}
1766	}
1767	return (0);
1768}
1769#else
1770static int
1771match_owner_name_wcs(struct archive_match *a, struct match_list *list,
1772    const wchar_t *name)
1773{
1774	struct match *m;
1775	const wchar_t *p;
1776
1777	if (name == NULL || *name == L'\0')
1778		return (0);
1779	for (m = list->first; m; m = m->next) {
1780		if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
1781		    < 0 && errno == ENOMEM)
1782			return (error_nomem(a));
1783		if (p != NULL && wcscmp(p, name) == 0) {
1784			m->matches++;
1785			return (1);
1786		}
1787	}
1788	return (0);
1789}
1790#endif
1791
1792/*
1793 * Test if entry is excluded by uid, gid, uname or gname.
1794 */
1795static int
1796owner_excluded(struct archive_match *a, struct archive_entry *entry)
1797{
1798	int r;
1799
1800	if (a->inclusion_uids.count) {
1801		if (!match_owner_id(&(a->inclusion_uids),
1802		    archive_entry_uid(entry)))
1803			return (1);
1804	}
1805
1806	if (a->inclusion_gids.count) {
1807		if (!match_owner_id(&(a->inclusion_gids),
1808		    archive_entry_gid(entry)))
1809			return (1);
1810	}
1811
1812	if (a->inclusion_unames.count) {
1813#if defined(_WIN32) && !defined(__CYGWIN__)
1814		r = match_owner_name_wcs(a, &(a->inclusion_unames),
1815			archive_entry_uname_w(entry));
1816#else
1817		r = match_owner_name_mbs(a, &(a->inclusion_unames),
1818			archive_entry_uname(entry));
1819#endif
1820		if (!r)
1821			return (1);
1822		else if (r < 0)
1823			return (r);
1824	}
1825
1826	if (a->inclusion_gnames.count) {
1827#if defined(_WIN32) && !defined(__CYGWIN__)
1828		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
1829			archive_entry_gname_w(entry));
1830#else
1831		r = match_owner_name_mbs(a, &(a->inclusion_gnames),
1832			archive_entry_gname(entry));
1833#endif
1834		if (!r)
1835			return (1);
1836		else if (r < 0)
1837			return (r);
1838	}
1839	return (0);
1840}
1841
1842