archive_match.c revision 313570
189080Stmm/*-
289080Stmm * Copyright (c) 2003-2007 Tim Kientzle
389080Stmm * Copyright (c) 2012 Michihiro NAKAJIMA
489080Stmm * All rights reserved.
589080Stmm *
689080Stmm * Redistribution and use in source and binary forms, with or without
789080Stmm * modification, are permitted provided that the following conditions
889080Stmm * are met:
989080Stmm * 1. Redistributions of source code must retain the above copyright
1089080Stmm *    notice, this list of conditions and the following disclaimer.
1189080Stmm * 2. Redistributions in binary form must reproduce the above copyright
1289080Stmm *    notice, this list of conditions and the following disclaimer in the
1389080Stmm *    documentation and/or other materials provided with the distribution.
1489080Stmm *
1589080Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
1689080Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1789080Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1889080Stmm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
1989080Stmm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2089080Stmm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2189080Stmm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2289080Stmm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2389080Stmm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2489080Stmm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2589080Stmm */
2689080Stmm
2789080Stmm#include "archive_platform.h"
2889080Stmm__FBSDID("$FreeBSD$");
2989080Stmm
3089080Stmm#ifdef HAVE_ERRNO_H
3189080Stmm#include <errno.h>
3289080Stmm#endif
3389080Stmm#ifdef HAVE_STDLIB_H
3491163Sjake#include <stdlib.h>
3591163Sjake#endif
3691617Sjake#ifdef HAVE_STRING_H
3791617Sjake#include <string.h>
3891163Sjake#endif
3991163Sjake
4091163Sjake#include "archive.h"
4191617Sjake#include "archive_private.h"
4291617Sjake#include "archive_entry.h"
4391617Sjake#include "archive_getdate.h"
4491617Sjake#include "archive_pathmatch.h"
4591617Sjake#include "archive_rb.h"
4691617Sjake#include "archive_string.h"
4791617Sjake
4891617Sjakestruct match {
4991617Sjake	struct match		*next;
5089080Stmm	int			 matches;
51	struct archive_mstring	 pattern;
52};
53
54struct match_list {
55	struct match		*first;
56	struct match		**last;
57	int			 count;
58	int			 unmatched_count;
59	struct match		*unmatched_next;
60	int			 unmatched_eof;
61};
62
63struct match_file {
64	struct archive_rb_node	 node;
65	struct match_file	*next;
66	struct archive_mstring	 pathname;
67	int			 flag;
68	time_t			 mtime_sec;
69	long			 mtime_nsec;
70	time_t			 ctime_sec;
71	long			 ctime_nsec;
72};
73
74struct entry_list {
75	struct match_file	*first;
76	struct match_file	**last;
77	int			 count;
78};
79
80struct id_array {
81	size_t			 size;/* Allocated size */
82	size_t			 count;
83	int64_t			*ids;
84};
85
86#define PATTERN_IS_SET		1
87#define TIME_IS_SET		2
88#define ID_IS_SET		4
89
90struct archive_match {
91	struct archive		 archive;
92
93	/* exclusion/inclusion set flag. */
94	int			 setflag;
95
96	/*
97	 * Matching filename patterns.
98	 */
99	struct match_list	 exclusions;
100	struct match_list	 inclusions;
101
102	/*
103	 * Matching time stamps.
104	 */
105	time_t			 now;
106	int			 newer_mtime_filter;
107	time_t			 newer_mtime_sec;
108	long			 newer_mtime_nsec;
109	int			 newer_ctime_filter;
110	time_t			 newer_ctime_sec;
111	long			 newer_ctime_nsec;
112	int			 older_mtime_filter;
113	time_t			 older_mtime_sec;
114	long			 older_mtime_nsec;
115	int			 older_ctime_filter;
116	time_t			 older_ctime_sec;
117	long			 older_ctime_nsec;
118	/*
119	 * Matching time stamps with its filename.
120	 */
121	struct archive_rb_tree	 exclusion_tree;
122	struct entry_list 	 exclusion_entry_list;
123
124	/*
125	 * Matching file owners.
126	 */
127	struct id_array 	 inclusion_uids;
128	struct id_array 	 inclusion_gids;
129	struct match_list	 inclusion_unames;
130	struct match_list	 inclusion_gnames;
131};
132
133static int	add_pattern_from_file(struct archive_match *,
134		    struct match_list *, int, const void *, int);
135static int	add_entry(struct archive_match *, int,
136		    struct archive_entry *);
137static int	add_owner_id(struct archive_match *, struct id_array *,
138		    int64_t);
139static int	add_owner_name(struct archive_match *, struct match_list *,
140		    int, const void *);
141static int	add_pattern_mbs(struct archive_match *, struct match_list *,
142		    const char *);
143static int	add_pattern_wcs(struct archive_match *, struct match_list *,
144		    const wchar_t *);
145static int	cmp_key_mbs(const struct archive_rb_node *, const void *);
146static int	cmp_key_wcs(const struct archive_rb_node *, const void *);
147static int	cmp_node_mbs(const struct archive_rb_node *,
148		    const struct archive_rb_node *);
149static int	cmp_node_wcs(const struct archive_rb_node *,
150		    const struct archive_rb_node *);
151static void	entry_list_add(struct entry_list *, struct match_file *);
152static void	entry_list_free(struct entry_list *);
153static void	entry_list_init(struct entry_list *);
154static int	error_nomem(struct archive_match *);
155static void	match_list_add(struct match_list *, struct match *);
156static void	match_list_free(struct match_list *);
157static void	match_list_init(struct match_list *);
158static int	match_list_unmatched_inclusions_next(struct archive_match *,
159		    struct match_list *, int, const void **);
160static int	match_owner_id(struct id_array *, int64_t);
161#if !defined(_WIN32) || defined(__CYGWIN__)
162static int	match_owner_name_mbs(struct archive_match *,
163		    struct match_list *, const char *);
164#else
165static int	match_owner_name_wcs(struct archive_match *,
166		    struct match_list *, const wchar_t *);
167#endif
168static int	match_path_exclusion(struct archive_match *,
169		    struct match *, int, const void *);
170static int	match_path_inclusion(struct archive_match *,
171		    struct match *, int, const void *);
172static int	owner_excluded(struct archive_match *,
173		    struct archive_entry *);
174static int	path_excluded(struct archive_match *, int, const void *);
175static int	set_timefilter(struct archive_match *, int, time_t, long,
176		    time_t, long);
177static int	set_timefilter_pathname_mbs(struct archive_match *,
178		    int, const char *);
179static int	set_timefilter_pathname_wcs(struct archive_match *,
180		    int, const wchar_t *);
181static int	set_timefilter_date(struct archive_match *, int, const char *);
182static int	set_timefilter_date_w(struct archive_match *, int,
183		    const wchar_t *);
184static int	time_excluded(struct archive_match *,
185		    struct archive_entry *);
186static int	validate_time_flag(struct archive *, int, const char *);
187
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 * Utility 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	r = archive_read_support_format_empty(ar);
584	if (r != ARCHIVE_OK) {
585		archive_copy_error(&(a->archive), ar);
586		archive_read_free(ar);
587		return (r);
588	}
589	if (mbs)
590		r = archive_read_open_filename(ar, pathname, 512*20);
591	else
592		r = archive_read_open_filename_w(ar, pathname, 512*20);
593	if (r != ARCHIVE_OK) {
594		archive_copy_error(&(a->archive), ar);
595		archive_read_free(ar);
596		return (r);
597	}
598	r = archive_read_next_header(ar, &ae);
599	if (r != ARCHIVE_OK) {
600		archive_read_free(ar);
601		if (r == ARCHIVE_EOF) {
602			return (ARCHIVE_OK);
603		} else {
604			archive_copy_error(&(a->archive), ar);
605			return (r);
606		}
607	}
608
609	archive_string_init(&as);
610
611	while ((r = archive_read_data_block(ar, &buff, &size, &offset))
612	    == ARCHIVE_OK) {
613		const char *b = (const char *)buff;
614
615		while (size) {
616			const char *s = (const char *)b;
617			size_t length = 0;
618			int found_separator = 0;
619
620			while (length < size) {
621				if (nullSeparator) {
622					if (*b == '\0') {
623						found_separator = 1;
624						break;
625					}
626				} else {
627			            	if (*b == 0x0d || *b == 0x0a) {
628						found_separator = 1;
629						break;
630					}
631				}
632				b++;
633				length++;
634			}
635			if (!found_separator) {
636				archive_strncat(&as, s, length);
637				/* Read next data block. */
638				break;
639			}
640			b++;
641			size -= length + 1;
642			archive_strncat(&as, s, length);
643
644			/* If the line is not empty, add the pattern. */
645			if (archive_strlen(&as) > 0) {
646				/* Add pattern. */
647				r = add_pattern_mbs(a, mlist, as.s);
648				if (r != ARCHIVE_OK) {
649					archive_read_free(ar);
650					archive_string_free(&as);
651					return (r);
652				}
653				archive_string_empty(&as);
654			}
655		}
656	}
657
658	/* If an error occurred, report it immediately. */
659	if (r < ARCHIVE_OK) {
660		archive_copy_error(&(a->archive), ar);
661		archive_read_free(ar);
662		archive_string_free(&as);
663		return (r);
664	}
665
666	/* If the line is not empty, add the pattern. */
667	if (r == ARCHIVE_EOF && archive_strlen(&as) > 0) {
668		/* Add pattern. */
669		r = add_pattern_mbs(a, mlist, as.s);
670		if (r != ARCHIVE_OK) {
671			archive_read_free(ar);
672			archive_string_free(&as);
673			return (r);
674		}
675	}
676	archive_read_free(ar);
677	archive_string_free(&as);
678	return (ARCHIVE_OK);
679}
680
681/*
682 * Test if pathname is excluded by inclusion/exclusion patterns.
683 */
684static int
685path_excluded(struct archive_match *a, int mbs, const void *pathname)
686{
687	struct match *match;
688	struct match *matched;
689	int r;
690
691	if (a == NULL)
692		return (0);
693
694	/* Mark off any unmatched inclusions. */
695	/* In particular, if a filename does appear in the archive and
696	 * is explicitly included and excluded, then we don't report
697	 * it as missing even though we don't extract it.
698	 */
699	matched = NULL;
700	for (match = a->inclusions.first; match != NULL;
701	    match = match->next){
702		if (match->matches == 0 &&
703		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
704			if (r < 0)
705				return (r);
706			a->inclusions.unmatched_count--;
707			match->matches++;
708			matched = match;
709		}
710	}
711
712	/* Exclusions take priority */
713	for (match = a->exclusions.first; match != NULL;
714	    match = match->next){
715		r = match_path_exclusion(a, match, mbs, pathname);
716		if (r)
717			return (r);
718	}
719
720	/* It's not excluded and we found an inclusion above, so it's
721	 * included. */
722	if (matched != NULL)
723		return (0);
724
725
726	/* We didn't find an unmatched inclusion, check the remaining ones. */
727	for (match = a->inclusions.first; match != NULL;
728	    match = match->next){
729		/* We looked at previously-unmatched inclusions already. */
730		if (match->matches > 0 &&
731		    (r = match_path_inclusion(a, match, mbs, pathname)) != 0) {
732			if (r < 0)
733				return (r);
734			match->matches++;
735			return (0);
736		}
737	}
738
739	/* If there were inclusions, default is to exclude. */
740	if (a->inclusions.first != NULL)
741	    return (1);
742
743	/* No explicit inclusions, default is to match. */
744	return (0);
745}
746
747/*
748 * This is a little odd, but it matches the default behavior of
749 * gtar.  In particular, 'a*b' will match 'foo/a1111/222b/bar'
750 *
751 */
752static int
753match_path_exclusion(struct archive_match *a, struct match *m,
754    int mbs, const void *pn)
755{
756	int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END;
757	int r;
758
759	if (mbs) {
760		const char *p;
761		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
762		if (r == 0)
763			return (archive_pathmatch(p, (const char *)pn, flag));
764	} else {
765		const wchar_t *p;
766		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
767		if (r == 0)
768			return (archive_pathmatch_w(p, (const wchar_t *)pn,
769				flag));
770	}
771	if (errno == ENOMEM)
772		return (error_nomem(a));
773	return (0);
774}
775
776/*
777 * Again, mimic gtar:  inclusions are always anchored (have to match
778 * the beginning of the path) even though exclusions are not anchored.
779 */
780static int
781match_path_inclusion(struct archive_match *a, struct match *m,
782    int mbs, const void *pn)
783{
784	int flag = PATHMATCH_NO_ANCHOR_END;
785	int r;
786
787	if (mbs) {
788		const char *p;
789		r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p);
790		if (r == 0)
791			return (archive_pathmatch(p, (const char *)pn, flag));
792	} else {
793		const wchar_t *p;
794		r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p);
795		if (r == 0)
796			return (archive_pathmatch_w(p, (const wchar_t *)pn,
797				flag));
798	}
799	if (errno == ENOMEM)
800		return (error_nomem(a));
801	return (0);
802}
803
804static void
805match_list_init(struct match_list *list)
806{
807	list->first = NULL;
808	list->last = &(list->first);
809	list->count = 0;
810}
811
812static void
813match_list_free(struct match_list *list)
814{
815	struct match *p, *q;
816
817	for (p = list->first; p != NULL; ) {
818		q = p;
819		p = p->next;
820		archive_mstring_clean(&(q->pattern));
821		free(q);
822	}
823}
824
825static void
826match_list_add(struct match_list *list, struct match *m)
827{
828	*list->last = m;
829	list->last = &(m->next);
830	list->count++;
831	list->unmatched_count++;
832}
833
834static int
835match_list_unmatched_inclusions_next(struct archive_match *a,
836    struct match_list *list, int mbs, const void **vp)
837{
838	struct match *m;
839
840	*vp = NULL;
841	if (list->unmatched_eof) {
842		list->unmatched_eof = 0;
843		return (ARCHIVE_EOF);
844	}
845	if (list->unmatched_next == NULL) {
846		if (list->unmatched_count == 0)
847			return (ARCHIVE_EOF);
848		list->unmatched_next = list->first;
849	}
850
851	for (m = list->unmatched_next; m != NULL; m = m->next) {
852		int r;
853
854		if (m->matches)
855			continue;
856		if (mbs) {
857			const char *p;
858			r = archive_mstring_get_mbs(&(a->archive),
859				&(m->pattern), &p);
860			if (r < 0 && errno == ENOMEM)
861				return (error_nomem(a));
862			if (p == NULL)
863				p = "";
864			*vp = p;
865		} else {
866			const wchar_t *p;
867			r = archive_mstring_get_wcs(&(a->archive),
868				&(m->pattern), &p);
869			if (r < 0 && errno == ENOMEM)
870				return (error_nomem(a));
871			if (p == NULL)
872				p = L"";
873			*vp = p;
874		}
875		list->unmatched_next = m->next;
876		if (list->unmatched_next == NULL)
877			/* To return EOF next time. */
878			list->unmatched_eof = 1;
879		return (ARCHIVE_OK);
880	}
881	list->unmatched_next = NULL;
882	return (ARCHIVE_EOF);
883}
884
885/*
886 * Utility functions to manage inclusion timestamps.
887 */
888int
889archive_match_include_time(struct archive *_a, int flag, time_t sec,
890    long nsec)
891{
892	int r;
893
894	r = validate_time_flag(_a, flag, "archive_match_include_time");
895	if (r != ARCHIVE_OK)
896		return (r);
897	return set_timefilter((struct archive_match *)_a, flag,
898			sec, nsec, sec, nsec);
899}
900
901int
902archive_match_include_date(struct archive *_a, int flag,
903    const char *datestr)
904{
905	int r;
906
907	r = validate_time_flag(_a, flag, "archive_match_include_date");
908	if (r != ARCHIVE_OK)
909		return (r);
910	return set_timefilter_date((struct archive_match *)_a, flag, datestr);
911}
912
913int
914archive_match_include_date_w(struct archive *_a, int flag,
915    const wchar_t *datestr)
916{
917	int r;
918
919	r = validate_time_flag(_a, flag, "archive_match_include_date_w");
920	if (r != ARCHIVE_OK)
921		return (r);
922
923	return set_timefilter_date_w((struct archive_match *)_a, flag, datestr);
924}
925
926int
927archive_match_include_file_time(struct archive *_a, int flag,
928    const char *pathname)
929{
930	int r;
931
932	r = validate_time_flag(_a, flag, "archive_match_include_file_time");
933	if (r != ARCHIVE_OK)
934		return (r);
935	return set_timefilter_pathname_mbs((struct archive_match *)_a,
936			flag, pathname);
937}
938
939int
940archive_match_include_file_time_w(struct archive *_a, int flag,
941    const wchar_t *pathname)
942{
943	int r;
944
945	r = validate_time_flag(_a, flag, "archive_match_include_file_time_w");
946	if (r != ARCHIVE_OK)
947		return (r);
948	return set_timefilter_pathname_wcs((struct archive_match *)_a,
949			flag, pathname);
950}
951
952int
953archive_match_exclude_entry(struct archive *_a, int flag,
954    struct archive_entry *entry)
955{
956	struct archive_match *a;
957	int r;
958
959	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
960	    ARCHIVE_STATE_NEW, "archive_match_time_include_entry");
961	a = (struct archive_match *)_a;
962
963	if (entry == NULL) {
964		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
965		return (ARCHIVE_FAILED);
966	}
967	r = validate_time_flag(_a, flag, "archive_match_exclude_entry");
968	if (r != ARCHIVE_OK)
969		return (r);
970	return (add_entry(a, flag, entry));
971}
972
973/*
974 * Test function for time stamps.
975 *
976 * Returns 1 if archive entry is excluded.
977 * Returns 0 if archive entry is not excluded.
978 * Returns <0 if something error happened.
979 */
980int
981archive_match_time_excluded(struct archive *_a,
982    struct archive_entry *entry)
983{
984	struct archive_match *a;
985
986	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
987	    ARCHIVE_STATE_NEW, "archive_match_time_excluded_ae");
988
989	a = (struct archive_match *)_a;
990	if (entry == NULL) {
991		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
992		return (ARCHIVE_FAILED);
993	}
994
995	/* If we don't have inclusion time set at all, the entry is always
996	 * not excluded. */
997	if ((a->setflag & TIME_IS_SET) == 0)
998		return (0);
999	return (time_excluded(a, entry));
1000}
1001
1002static int
1003validate_time_flag(struct archive *_a, int flag, const char *_fn)
1004{
1005	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1006	    ARCHIVE_STATE_NEW, _fn);
1007
1008	/* Check a type of time. */
1009	if (flag &
1010	   ((~(ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) & 0xff00)) {
1011		archive_set_error(_a, EINVAL, "Invalid time flag");
1012		return (ARCHIVE_FAILED);
1013	}
1014	if ((flag & (ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_CTIME)) == 0) {
1015		archive_set_error(_a, EINVAL, "No time flag");
1016		return (ARCHIVE_FAILED);
1017	}
1018
1019	/* Check a type of comparison. */
1020	if (flag &
1021	   ((~(ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1022			| ARCHIVE_MATCH_EQUAL)) & 0x00ff)) {
1023		archive_set_error(_a, EINVAL, "Invalid comparison flag");
1024		return (ARCHIVE_FAILED);
1025	}
1026	if ((flag & (ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER
1027	    | ARCHIVE_MATCH_EQUAL)) == 0) {
1028		archive_set_error(_a, EINVAL, "No comparison flag");
1029		return (ARCHIVE_FAILED);
1030	}
1031
1032	return (ARCHIVE_OK);
1033}
1034
1035#define JUST_EQUAL(t) (((t) &  (ARCHIVE_MATCH_EQUAL |\
1036	ARCHIVE_MATCH_NEWER | ARCHIVE_MATCH_OLDER)) == ARCHIVE_MATCH_EQUAL)
1037static int
1038set_timefilter(struct archive_match *a, int timetype,
1039    time_t mtime_sec, long mtime_nsec, time_t ctime_sec, long ctime_nsec)
1040{
1041	if (timetype & ARCHIVE_MATCH_MTIME) {
1042		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1043			a->newer_mtime_filter = timetype;
1044			a->newer_mtime_sec = mtime_sec;
1045			a->newer_mtime_nsec = mtime_nsec;
1046			a->setflag |= TIME_IS_SET;
1047		}
1048		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1049			a->older_mtime_filter = timetype;
1050			a->older_mtime_sec = mtime_sec;
1051			a->older_mtime_nsec = mtime_nsec;
1052			a->setflag |= TIME_IS_SET;
1053		}
1054	}
1055	if (timetype & ARCHIVE_MATCH_CTIME) {
1056		if ((timetype & ARCHIVE_MATCH_NEWER) || JUST_EQUAL(timetype)) {
1057			a->newer_ctime_filter = timetype;
1058			a->newer_ctime_sec = ctime_sec;
1059			a->newer_ctime_nsec = ctime_nsec;
1060			a->setflag |= TIME_IS_SET;
1061		}
1062		if ((timetype & ARCHIVE_MATCH_OLDER) || JUST_EQUAL(timetype)) {
1063			a->older_ctime_filter = timetype;
1064			a->older_ctime_sec = ctime_sec;
1065			a->older_ctime_nsec = ctime_nsec;
1066			a->setflag |= TIME_IS_SET;
1067		}
1068	}
1069	return (ARCHIVE_OK);
1070}
1071
1072static int
1073set_timefilter_date(struct archive_match *a, int timetype, const char *datestr)
1074{
1075	time_t t;
1076
1077	if (datestr == NULL || *datestr == '\0') {
1078		archive_set_error(&(a->archive), EINVAL, "date is empty");
1079		return (ARCHIVE_FAILED);
1080	}
1081	t = get_date(a->now, datestr);
1082	if (t == (time_t)-1) {
1083		archive_set_error(&(a->archive), EINVAL, "invalid date string");
1084		return (ARCHIVE_FAILED);
1085	}
1086	return set_timefilter(a, timetype, t, 0, t, 0);
1087}
1088
1089static int
1090set_timefilter_date_w(struct archive_match *a, int timetype,
1091    const wchar_t *datestr)
1092{
1093	struct archive_string as;
1094	time_t t;
1095
1096	if (datestr == NULL || *datestr == L'\0') {
1097		archive_set_error(&(a->archive), EINVAL, "date is empty");
1098		return (ARCHIVE_FAILED);
1099	}
1100
1101	archive_string_init(&as);
1102	if (archive_string_append_from_wcs(&as, datestr, wcslen(datestr)) < 0) {
1103		archive_string_free(&as);
1104		if (errno == ENOMEM)
1105			return (error_nomem(a));
1106		archive_set_error(&(a->archive), -1,
1107		    "Failed to convert WCS to MBS");
1108		return (ARCHIVE_FAILED);
1109	}
1110	t = get_date(a->now, as.s);
1111	archive_string_free(&as);
1112	if (t == (time_t)-1) {
1113		archive_set_error(&(a->archive), EINVAL, "invalid date string");
1114		return (ARCHIVE_FAILED);
1115	}
1116	return set_timefilter(a, timetype, t, 0, t, 0);
1117}
1118
1119#if defined(_WIN32) && !defined(__CYGWIN__)
1120#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1121static int
1122set_timefilter_find_data(struct archive_match *a, int timetype,
1123    DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
1124    DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
1125{
1126	ULARGE_INTEGER utc;
1127	time_t ctime_sec, mtime_sec;
1128	long ctime_ns, mtime_ns;
1129
1130	utc.HighPart = ftCreationTime_dwHighDateTime;
1131	utc.LowPart = ftCreationTime_dwLowDateTime;
1132	if (utc.QuadPart >= EPOC_TIME) {
1133		utc.QuadPart -= EPOC_TIME;
1134		ctime_sec = (time_t)(utc.QuadPart / 10000000);
1135		ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
1136	} else {
1137		ctime_sec = 0;
1138		ctime_ns = 0;
1139	}
1140	utc.HighPart = ftLastWriteTime_dwHighDateTime;
1141	utc.LowPart = ftLastWriteTime_dwLowDateTime;
1142	if (utc.QuadPart >= EPOC_TIME) {
1143		utc.QuadPart -= EPOC_TIME;
1144		mtime_sec = (time_t)(utc.QuadPart / 10000000);
1145		mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
1146	} else {
1147		mtime_sec = 0;
1148		mtime_ns = 0;
1149	}
1150	return set_timefilter(a, timetype,
1151			mtime_sec, mtime_ns, ctime_sec, ctime_ns);
1152}
1153
1154static int
1155set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1156    const char *path)
1157{
1158	/* NOTE: stat() on Windows cannot handle nano seconds. */
1159	HANDLE h;
1160	WIN32_FIND_DATAA d;
1161
1162	if (path == NULL || *path == '\0') {
1163		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1164		return (ARCHIVE_FAILED);
1165	}
1166	h = FindFirstFileA(path, &d);
1167	if (h == INVALID_HANDLE_VALUE) {
1168		la_dosmaperr(GetLastError());
1169		archive_set_error(&(a->archive), errno,
1170		    "Failed to FindFirstFileA");
1171		return (ARCHIVE_FAILED);
1172	}
1173	FindClose(h);
1174	return set_timefilter_find_data(a, timetype,
1175	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1176	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1177}
1178
1179static int
1180set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1181    const wchar_t *path)
1182{
1183	HANDLE h;
1184	WIN32_FIND_DATAW d;
1185
1186	if (path == NULL || *path == L'\0') {
1187		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1188		return (ARCHIVE_FAILED);
1189	}
1190	h = FindFirstFileW(path, &d);
1191	if (h == INVALID_HANDLE_VALUE) {
1192		la_dosmaperr(GetLastError());
1193		archive_set_error(&(a->archive), errno,
1194		    "Failed to FindFirstFile");
1195		return (ARCHIVE_FAILED);
1196	}
1197	FindClose(h);
1198	return set_timefilter_find_data(a, timetype,
1199	    d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
1200	    d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
1201}
1202
1203#else /* _WIN32 && !__CYGWIN__ */
1204
1205static int
1206set_timefilter_stat(struct archive_match *a, int timetype, struct stat *st)
1207{
1208	struct archive_entry *ae;
1209	time_t ctime_sec, mtime_sec;
1210	long ctime_ns, mtime_ns;
1211
1212	ae = archive_entry_new();
1213	if (ae == NULL)
1214		return (error_nomem(a));
1215	archive_entry_copy_stat(ae, st);
1216	ctime_sec = archive_entry_ctime(ae);
1217	ctime_ns = archive_entry_ctime_nsec(ae);
1218	mtime_sec = archive_entry_mtime(ae);
1219	mtime_ns = archive_entry_mtime_nsec(ae);
1220	archive_entry_free(ae);
1221	return set_timefilter(a, timetype, mtime_sec, mtime_ns,
1222			ctime_sec, ctime_ns);
1223}
1224
1225static int
1226set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
1227    const char *path)
1228{
1229	struct stat st;
1230
1231	if (path == NULL || *path == '\0') {
1232		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1233		return (ARCHIVE_FAILED);
1234	}
1235	if (stat(path, &st) != 0) {
1236		archive_set_error(&(a->archive), errno, "Failed to stat()");
1237		return (ARCHIVE_FAILED);
1238	}
1239	return (set_timefilter_stat(a, timetype, &st));
1240}
1241
1242static int
1243set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
1244    const wchar_t *path)
1245{
1246	struct archive_string as;
1247	int r;
1248
1249	if (path == NULL || *path == L'\0') {
1250		archive_set_error(&(a->archive), EINVAL, "pathname is empty");
1251		return (ARCHIVE_FAILED);
1252	}
1253
1254	/* Convert WCS filename to MBS filename. */
1255	archive_string_init(&as);
1256	if (archive_string_append_from_wcs(&as, path, wcslen(path)) < 0) {
1257		archive_string_free(&as);
1258		if (errno == ENOMEM)
1259			return (error_nomem(a));
1260		archive_set_error(&(a->archive), -1,
1261		    "Failed to convert WCS to MBS");
1262		return (ARCHIVE_FAILED);
1263	}
1264
1265	r = set_timefilter_pathname_mbs(a, timetype, as.s);
1266	archive_string_free(&as);
1267
1268	return (r);
1269}
1270#endif /* _WIN32 && !__CYGWIN__ */
1271
1272/*
1273 * Call back functions for archive_rb.
1274 */
1275static int
1276cmp_node_mbs(const struct archive_rb_node *n1,
1277    const struct archive_rb_node *n2)
1278{
1279	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1280	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1281	const char *p1, *p2;
1282
1283	archive_mstring_get_mbs(NULL, &(f1->pathname), &p1);
1284	archive_mstring_get_mbs(NULL, &(f2->pathname), &p2);
1285	if (p1 == NULL)
1286		return (1);
1287	if (p2 == NULL)
1288		return (-1);
1289	return (strcmp(p1, p2));
1290}
1291
1292static int
1293cmp_key_mbs(const struct archive_rb_node *n, const void *key)
1294{
1295	struct match_file *f = (struct match_file *)(uintptr_t)n;
1296	const char *p;
1297
1298	archive_mstring_get_mbs(NULL, &(f->pathname), &p);
1299	if (p == NULL)
1300		return (-1);
1301	return (strcmp(p, (const char *)key));
1302}
1303
1304static int
1305cmp_node_wcs(const struct archive_rb_node *n1,
1306    const struct archive_rb_node *n2)
1307{
1308	struct match_file *f1 = (struct match_file *)(uintptr_t)n1;
1309	struct match_file *f2 = (struct match_file *)(uintptr_t)n2;
1310	const wchar_t *p1, *p2;
1311
1312	archive_mstring_get_wcs(NULL, &(f1->pathname), &p1);
1313	archive_mstring_get_wcs(NULL, &(f2->pathname), &p2);
1314	if (p1 == NULL)
1315		return (1);
1316	if (p2 == NULL)
1317		return (-1);
1318	return (wcscmp(p1, p2));
1319}
1320
1321static int
1322cmp_key_wcs(const struct archive_rb_node *n, const void *key)
1323{
1324	struct match_file *f = (struct match_file *)(uintptr_t)n;
1325	const wchar_t *p;
1326
1327	archive_mstring_get_wcs(NULL, &(f->pathname), &p);
1328	if (p == NULL)
1329		return (-1);
1330	return (wcscmp(p, (const wchar_t *)key));
1331}
1332
1333static void
1334entry_list_init(struct entry_list *list)
1335{
1336	list->first = NULL;
1337	list->last = &(list->first);
1338	list->count = 0;
1339}
1340
1341static void
1342entry_list_free(struct entry_list *list)
1343{
1344	struct match_file *p, *q;
1345
1346	for (p = list->first; p != NULL; ) {
1347		q = p;
1348		p = p->next;
1349		archive_mstring_clean(&(q->pathname));
1350		free(q);
1351	}
1352}
1353
1354static void
1355entry_list_add(struct entry_list *list, struct match_file *file)
1356{
1357	*list->last = file;
1358	list->last = &(file->next);
1359	list->count++;
1360}
1361
1362static int
1363add_entry(struct archive_match *a, int flag,
1364    struct archive_entry *entry)
1365{
1366	struct match_file *f;
1367	const void *pathname;
1368	int r;
1369
1370	f = calloc(1, sizeof(*f));
1371	if (f == NULL)
1372		return (error_nomem(a));
1373
1374#if defined(_WIN32) && !defined(__CYGWIN__)
1375	pathname = archive_entry_pathname_w(entry);
1376	if (pathname == NULL) {
1377		free(f);
1378		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1379		return (ARCHIVE_FAILED);
1380	}
1381	archive_mstring_copy_wcs(&(f->pathname), pathname);
1382	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1383#else
1384	(void)rb_ops_wcs;
1385	pathname = archive_entry_pathname(entry);
1386	if (pathname == NULL) {
1387		free(f);
1388		archive_set_error(&(a->archive), EINVAL, "pathname is NULL");
1389		return (ARCHIVE_FAILED);
1390	}
1391	archive_mstring_copy_mbs(&(f->pathname), pathname);
1392	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1393#endif
1394	f->flag = flag;
1395	f->mtime_sec = archive_entry_mtime(entry);
1396	f->mtime_nsec = archive_entry_mtime_nsec(entry);
1397	f->ctime_sec = archive_entry_ctime(entry);
1398	f->ctime_nsec = archive_entry_ctime_nsec(entry);
1399	r = __archive_rb_tree_insert_node(&(a->exclusion_tree), &(f->node));
1400	if (!r) {
1401		struct match_file *f2;
1402
1403		/* Get the duplicated file. */
1404		f2 = (struct match_file *)__archive_rb_tree_find_node(
1405			&(a->exclusion_tree), pathname);
1406
1407		/*
1408		 * We always overwrite comparison condition.
1409		 * If you do not want to overwrite it, you should not
1410		 * call archive_match_exclude_entry(). We cannot know
1411		 * what behavior you really expect since overwriting
1412		 * condition might be different with the flag.
1413		 */
1414		if (f2 != NULL) {
1415			f2->flag = f->flag;
1416			f2->mtime_sec = f->mtime_sec;
1417			f2->mtime_nsec = f->mtime_nsec;
1418			f2->ctime_sec = f->ctime_sec;
1419			f2->ctime_nsec = f->ctime_nsec;
1420		}
1421		/* Release the duplicated file. */
1422		archive_mstring_clean(&(f->pathname));
1423		free(f);
1424		return (ARCHIVE_OK);
1425	}
1426	entry_list_add(&(a->exclusion_entry_list), f);
1427	a->setflag |= TIME_IS_SET;
1428	return (ARCHIVE_OK);
1429}
1430
1431/*
1432 * Test if entry is excluded by its timestamp.
1433 */
1434static int
1435time_excluded(struct archive_match *a, struct archive_entry *entry)
1436{
1437	struct match_file *f;
1438	const void *pathname;
1439	time_t sec;
1440	long nsec;
1441
1442	/*
1443	 * If this file/dir is excluded by a time comparison, skip it.
1444	 */
1445	if (a->newer_ctime_filter) {
1446		/* If ctime is not set, use mtime instead. */
1447		if (archive_entry_ctime_is_set(entry))
1448			sec = archive_entry_ctime(entry);
1449		else
1450			sec = archive_entry_mtime(entry);
1451		if (sec < a->newer_ctime_sec)
1452			return (1); /* Too old, skip it. */
1453		if (sec == a->newer_ctime_sec) {
1454			if (archive_entry_ctime_is_set(entry))
1455				nsec = archive_entry_ctime_nsec(entry);
1456			else
1457				nsec = archive_entry_mtime_nsec(entry);
1458			if (nsec < a->newer_ctime_nsec)
1459				return (1); /* Too old, skip it. */
1460			if (nsec == a->newer_ctime_nsec &&
1461			    (a->newer_ctime_filter & ARCHIVE_MATCH_EQUAL)
1462			      == 0)
1463				return (1); /* Equal, skip it. */
1464		}
1465	}
1466	if (a->older_ctime_filter) {
1467		/* If ctime is not set, use mtime instead. */
1468		if (archive_entry_ctime_is_set(entry))
1469			sec = archive_entry_ctime(entry);
1470		else
1471			sec = archive_entry_mtime(entry);
1472		if (sec > a->older_ctime_sec)
1473			return (1); /* Too new, skip it. */
1474		if (sec == a->older_ctime_sec) {
1475			if (archive_entry_ctime_is_set(entry))
1476				nsec = archive_entry_ctime_nsec(entry);
1477			else
1478				nsec = archive_entry_mtime_nsec(entry);
1479			if (nsec > a->older_ctime_nsec)
1480				return (1); /* Too new, skip it. */
1481			if (nsec == a->older_ctime_nsec &&
1482			    (a->older_ctime_filter & ARCHIVE_MATCH_EQUAL)
1483			      == 0)
1484				return (1); /* Equal, skip it. */
1485		}
1486	}
1487	if (a->newer_mtime_filter) {
1488		sec = archive_entry_mtime(entry);
1489		if (sec < a->newer_mtime_sec)
1490			return (1); /* Too old, skip it. */
1491		if (sec == a->newer_mtime_sec) {
1492			nsec = archive_entry_mtime_nsec(entry);
1493			if (nsec < a->newer_mtime_nsec)
1494				return (1); /* Too old, skip it. */
1495			if (nsec == a->newer_mtime_nsec &&
1496			    (a->newer_mtime_filter & ARCHIVE_MATCH_EQUAL)
1497			       == 0)
1498				return (1); /* Equal, skip it. */
1499		}
1500	}
1501	if (a->older_mtime_filter) {
1502		sec = archive_entry_mtime(entry);
1503		if (sec > a->older_mtime_sec)
1504			return (1); /* Too new, skip it. */
1505		nsec = archive_entry_mtime_nsec(entry);
1506		if (sec == a->older_mtime_sec) {
1507			if (nsec > a->older_mtime_nsec)
1508				return (1); /* Too new, skip it. */
1509			if (nsec == a->older_mtime_nsec &&
1510			    (a->older_mtime_filter & ARCHIVE_MATCH_EQUAL)
1511			       == 0)
1512				return (1); /* Equal, skip it. */
1513		}
1514	}
1515
1516	/* If there is no exclusion list, include the file. */
1517	if (a->exclusion_entry_list.count == 0)
1518		return (0);
1519
1520#if defined(_WIN32) && !defined(__CYGWIN__)
1521	pathname = archive_entry_pathname_w(entry);
1522	a->exclusion_tree.rbt_ops = &rb_ops_wcs;
1523#else
1524	(void)rb_ops_wcs;
1525	pathname = archive_entry_pathname(entry);
1526	a->exclusion_tree.rbt_ops = &rb_ops_mbs;
1527#endif
1528	if (pathname == NULL)
1529		return (0);
1530
1531	f = (struct match_file *)__archive_rb_tree_find_node(
1532		&(a->exclusion_tree), pathname);
1533	/* If the file wasn't rejected, include it. */
1534	if (f == NULL)
1535		return (0);
1536
1537	if (f->flag & ARCHIVE_MATCH_CTIME) {
1538		sec = archive_entry_ctime(entry);
1539		if (f->ctime_sec > sec) {
1540			if (f->flag & ARCHIVE_MATCH_OLDER)
1541				return (1);
1542		} else if (f->ctime_sec < sec) {
1543			if (f->flag & ARCHIVE_MATCH_NEWER)
1544				return (1);
1545		} else {
1546			nsec = archive_entry_ctime_nsec(entry);
1547			if (f->ctime_nsec > nsec) {
1548				if (f->flag & ARCHIVE_MATCH_OLDER)
1549					return (1);
1550			} else if (f->ctime_nsec < nsec) {
1551				if (f->flag & ARCHIVE_MATCH_NEWER)
1552					return (1);
1553			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1554				return (1);
1555		}
1556	}
1557	if (f->flag & ARCHIVE_MATCH_MTIME) {
1558		sec = archive_entry_mtime(entry);
1559		if (f->mtime_sec > sec) {
1560			if (f->flag & ARCHIVE_MATCH_OLDER)
1561				return (1);
1562		} else if (f->mtime_sec < sec) {
1563			if (f->flag & ARCHIVE_MATCH_NEWER)
1564				return (1);
1565		} else {
1566			nsec = archive_entry_mtime_nsec(entry);
1567			if (f->mtime_nsec > nsec) {
1568				if (f->flag & ARCHIVE_MATCH_OLDER)
1569					return (1);
1570			} else if (f->mtime_nsec < nsec) {
1571				if (f->flag & ARCHIVE_MATCH_NEWER)
1572					return (1);
1573			} else if (f->flag & ARCHIVE_MATCH_EQUAL)
1574				return (1);
1575		}
1576	}
1577	return (0);
1578}
1579
1580/*
1581 * Utility functions to manage inclusion owners
1582 */
1583
1584int
1585archive_match_include_uid(struct archive *_a, int64_t uid)
1586{
1587	struct archive_match *a;
1588
1589	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1590	    ARCHIVE_STATE_NEW, "archive_match_include_uid");
1591	a = (struct archive_match *)_a;
1592	return (add_owner_id(a, &(a->inclusion_uids), uid));
1593}
1594
1595int
1596archive_match_include_gid(struct archive *_a, int64_t gid)
1597{
1598	struct archive_match *a;
1599
1600	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1601	    ARCHIVE_STATE_NEW, "archive_match_include_gid");
1602	a = (struct archive_match *)_a;
1603	return (add_owner_id(a, &(a->inclusion_gids), gid));
1604}
1605
1606int
1607archive_match_include_uname(struct archive *_a, const char *uname)
1608{
1609	struct archive_match *a;
1610
1611	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1612	    ARCHIVE_STATE_NEW, "archive_match_include_uname");
1613	a = (struct archive_match *)_a;
1614	return (add_owner_name(a, &(a->inclusion_unames), 1, uname));
1615}
1616
1617int
1618archive_match_include_uname_w(struct archive *_a, const wchar_t *uname)
1619{
1620	struct archive_match *a;
1621
1622	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1623	    ARCHIVE_STATE_NEW, "archive_match_include_uname_w");
1624	a = (struct archive_match *)_a;
1625	return (add_owner_name(a, &(a->inclusion_unames), 0, uname));
1626}
1627
1628int
1629archive_match_include_gname(struct archive *_a, const char *gname)
1630{
1631	struct archive_match *a;
1632
1633	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1634	    ARCHIVE_STATE_NEW, "archive_match_include_gname");
1635	a = (struct archive_match *)_a;
1636	return (add_owner_name(a, &(a->inclusion_gnames), 1, gname));
1637}
1638
1639int
1640archive_match_include_gname_w(struct archive *_a, const wchar_t *gname)
1641{
1642	struct archive_match *a;
1643
1644	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1645	    ARCHIVE_STATE_NEW, "archive_match_include_gname_w");
1646	a = (struct archive_match *)_a;
1647	return (add_owner_name(a, &(a->inclusion_gnames), 0, gname));
1648}
1649
1650/*
1651 * Test function for owner(uid, gid, uname, gname).
1652 *
1653 * Returns 1 if archive entry is excluded.
1654 * Returns 0 if archive entry is not excluded.
1655 * Returns <0 if something error happened.
1656 */
1657int
1658archive_match_owner_excluded(struct archive *_a,
1659    struct archive_entry *entry)
1660{
1661	struct archive_match *a;
1662
1663	archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
1664	    ARCHIVE_STATE_NEW, "archive_match_id_excluded_ae");
1665
1666	a = (struct archive_match *)_a;
1667	if (entry == NULL) {
1668		archive_set_error(&(a->archive), EINVAL, "entry is NULL");
1669		return (ARCHIVE_FAILED);
1670	}
1671
1672	/* If we don't have inclusion id set at all, the entry is always
1673	 * not excluded. */
1674	if ((a->setflag & ID_IS_SET) == 0)
1675		return (0);
1676	return (owner_excluded(a, entry));
1677}
1678
1679static int
1680add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
1681{
1682	unsigned i;
1683
1684	if (ids->count + 1 >= ids->size) {
1685		void *p;
1686
1687		if (ids->size == 0)
1688			ids->size = 8;
1689		else
1690			ids->size *= 2;
1691		p = realloc(ids->ids, sizeof(*ids->ids) * ids->size);
1692		if (p == NULL)
1693			return (error_nomem(a));
1694		ids->ids = (int64_t *)p;
1695	}
1696
1697	/* Find an insert point. */
1698	for (i = 0; i < ids->count; i++) {
1699		if (ids->ids[i] >= id)
1700			break;
1701	}
1702
1703	/* Add owner id. */
1704	if (i == ids->count)
1705		ids->ids[ids->count++] = id;
1706	else if (ids->ids[i] != id) {
1707		memmove(&(ids->ids[i+1]), &(ids->ids[i]),
1708		    (ids->count - i) * sizeof(ids->ids[0]));
1709		ids->ids[i] = id;
1710		ids->count++;
1711	}
1712	a->setflag |= ID_IS_SET;
1713	return (ARCHIVE_OK);
1714}
1715
1716static int
1717match_owner_id(struct id_array *ids, int64_t id)
1718{
1719	unsigned b, m, t;
1720
1721	t = 0;
1722	b = (unsigned)ids->count;
1723	while (t < b) {
1724		m = (t + b)>>1;
1725		if (ids->ids[m] == id)
1726			return (1);
1727		if (ids->ids[m] < id)
1728			t = m + 1;
1729		else
1730			b = m;
1731	}
1732	return (0);
1733}
1734
1735static int
1736add_owner_name(struct archive_match *a, struct match_list *list,
1737    int mbs, const void *name)
1738{
1739	struct match *match;
1740
1741	match = calloc(1, sizeof(*match));
1742	if (match == NULL)
1743		return (error_nomem(a));
1744	if (mbs)
1745		archive_mstring_copy_mbs(&(match->pattern), name);
1746	else
1747		archive_mstring_copy_wcs(&(match->pattern), name);
1748	match_list_add(list, match);
1749	a->setflag |= ID_IS_SET;
1750	return (ARCHIVE_OK);
1751}
1752
1753#if !defined(_WIN32) || defined(__CYGWIN__)
1754static int
1755match_owner_name_mbs(struct archive_match *a, struct match_list *list,
1756    const char *name)
1757{
1758	struct match *m;
1759	const char *p;
1760
1761	if (name == NULL || *name == '\0')
1762		return (0);
1763	for (m = list->first; m; m = m->next) {
1764		if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p)
1765		    < 0 && errno == ENOMEM)
1766			return (error_nomem(a));
1767		if (p != NULL && strcmp(p, name) == 0) {
1768			m->matches++;
1769			return (1);
1770		}
1771	}
1772	return (0);
1773}
1774#else
1775static int
1776match_owner_name_wcs(struct archive_match *a, struct match_list *list,
1777    const wchar_t *name)
1778{
1779	struct match *m;
1780	const wchar_t *p;
1781
1782	if (name == NULL || *name == L'\0')
1783		return (0);
1784	for (m = list->first; m; m = m->next) {
1785		if (archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p)
1786		    < 0 && errno == ENOMEM)
1787			return (error_nomem(a));
1788		if (p != NULL && wcscmp(p, name) == 0) {
1789			m->matches++;
1790			return (1);
1791		}
1792	}
1793	return (0);
1794}
1795#endif
1796
1797/*
1798 * Test if entry is excluded by uid, gid, uname or gname.
1799 */
1800static int
1801owner_excluded(struct archive_match *a, struct archive_entry *entry)
1802{
1803	int r;
1804
1805	if (a->inclusion_uids.count) {
1806		if (!match_owner_id(&(a->inclusion_uids),
1807		    archive_entry_uid(entry)))
1808			return (1);
1809	}
1810
1811	if (a->inclusion_gids.count) {
1812		if (!match_owner_id(&(a->inclusion_gids),
1813		    archive_entry_gid(entry)))
1814			return (1);
1815	}
1816
1817	if (a->inclusion_unames.count) {
1818#if defined(_WIN32) && !defined(__CYGWIN__)
1819		r = match_owner_name_wcs(a, &(a->inclusion_unames),
1820			archive_entry_uname_w(entry));
1821#else
1822		r = match_owner_name_mbs(a, &(a->inclusion_unames),
1823			archive_entry_uname(entry));
1824#endif
1825		if (!r)
1826			return (1);
1827		else if (r < 0)
1828			return (r);
1829	}
1830
1831	if (a->inclusion_gnames.count) {
1832#if defined(_WIN32) && !defined(__CYGWIN__)
1833		r = match_owner_name_wcs(a, &(a->inclusion_gnames),
1834			archive_entry_gname_w(entry));
1835#else
1836		r = match_owner_name_mbs(a, &(a->inclusion_gnames),
1837			archive_entry_gname(entry));
1838#endif
1839		if (!r)
1840			return (1);
1841		else if (r < 0)
1842			return (r);
1843	}
1844	return (0);
1845}
1846
1847