gdb - Local mods (compile)
[dragonfly.git] / contrib / libarchive / libarchive / archive_match.c
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
47 struct match {
48         struct match            *next;
49         int                      matches;
50         struct archive_mstring   pattern;
51 };
52
53 struct match_list {
54         struct match            *first;
55         struct match            **last;
56         int                      count;
57         int                      unmatched_count;
58         struct match            *unmatched_next;
59         int                      unmatched_eof;
60 };
61
62 struct match_file {
63         struct archive_rb_node   node;
64         struct match_file       *next;
65         struct archive_mstring   pathname;
66         int                      flag;
67         time_t                   mtime_sec;
68         long                     mtime_nsec;
69         time_t                   ctime_sec;
70         long                     ctime_nsec;
71 };
72
73 struct entry_list {
74         struct match_file       *first;
75         struct match_file       **last;
76         int                      count;
77 };
78
79 struct id_array {
80         size_t                   size;/* Allocated size */
81         size_t                   count;
82         int64_t                 *ids;
83 };
84
85 #define PATTERN_IS_SET          1
86 #define TIME_IS_SET             2
87 #define ID_IS_SET               4
88
89 struct archive_match {
90         struct archive           archive;
91
92         /* exclusion/inclusion set flag. */
93         int                      setflag;
94
95         /*
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
132 static int      add_pattern_from_file(struct archive_match *,
133                     struct match_list *, int, const void *, int);
134 static int      add_entry(struct archive_match *, int,
135                     struct archive_entry *);
136 static int      add_owner_id(struct archive_match *, struct id_array *,
137                     int64_t);
138 static int      add_owner_name(struct archive_match *, struct match_list *,
139                     int, const void *);
140 static int      add_pattern_mbs(struct archive_match *, struct match_list *,
141                     const char *);
142 static int      add_pattern_wcs(struct archive_match *, struct match_list *,
143                     const wchar_t *);
144 static int      cmp_key_mbs(const struct archive_rb_node *, const void *);
145 static int      cmp_key_wcs(const struct archive_rb_node *, const void *);
146 static int      cmp_node_mbs(const struct archive_rb_node *,
147                     const struct archive_rb_node *);
148 static int      cmp_node_wcs(const struct archive_rb_node *,
149                     const struct archive_rb_node *);
150 static void     entry_list_add(struct entry_list *, struct match_file *);
151 static void     entry_list_free(struct entry_list *);
152 static void     entry_list_init(struct entry_list *);
153 static int      error_nomem(struct archive_match *);
154 static void     match_list_add(struct match_list *, struct match *);
155 static void     match_list_free(struct match_list *);
156 static void     match_list_init(struct match_list *);
157 static int      match_list_unmatched_inclusions_next(struct archive_match *,
158                     struct match_list *, int, const void **);
159 static int      match_owner_id(struct id_array *, int64_t);
160 #if !defined(_WIN32) || defined(__CYGWIN__)
161 static int      match_owner_name_mbs(struct archive_match *,
162                     struct match_list *, const char *);
163 #else
164 static int      match_owner_name_wcs(struct archive_match *,
165                     struct match_list *, const wchar_t *);
166 #endif
167 static int      match_path_exclusion(struct archive_match *,
168                     struct match *, int, const void *);
169 static int      match_path_inclusion(struct archive_match *,
170                     struct match *, int, const void *);
171 static int      owner_excluded(struct archive_match *,
172                     struct archive_entry *);
173 static int      path_excluded(struct archive_match *, int, const void *);
174 static int      set_timefilter(struct archive_match *, int, time_t, long,
175                     time_t, long);
176 static int      set_timefilter_pathname_mbs(struct archive_match *,
177                     int, const char *);
178 static int      set_timefilter_pathname_wcs(struct archive_match *,
179                     int, const wchar_t *);
180 static int      set_timefilter_date(struct archive_match *, int, const char *);
181 static int      set_timefilter_date_w(struct archive_match *, int,
182                     const wchar_t *);
183 static int      time_excluded(struct archive_match *,
184                     struct archive_entry *);
185 static int      validate_time_flag(struct archive *, int, const char *);
186
187 time_t __archive_get_date(time_t now, const char *);
188 #define get_date __archive_get_date
189
190 static const struct archive_rb_tree_ops rb_ops_mbs = {
191         cmp_node_mbs, cmp_key_mbs
192 };
193
194 static 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
205 static int
206 error_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  */
216 struct archive *
217 archive_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  */
239 int
240 archive_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  */
267 int
268 archive_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
308 int
309 archive_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
327 int
328 archive_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
346 int
347 archive_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
360 int
361 archive_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
374 int
375 archive_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
393 int
394 archive_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
412 int
413 archive_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
426 int
427 archive_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  */
447 int
448 archive_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  */
476 int
477 archive_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
488 int
489 archive_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
505 int
506 archive_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  */
525 static int
526 add_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
545 static int
546 add_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
565 static int
566 add_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  */
679 static int
680 path_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  */
747 static int
748 match_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  */
775 static int
776 match_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
799 static void
800 match_list_init(struct match_list *list)
801 {
802         list->first = NULL;
803         list->last = &(list->first);
804         list->count = 0;
805 }
806
807 static void
808 match_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
820 static void
821 match_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
829 static int
830 match_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  */
883 int
884 archive_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
896 int
897 archive_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
908 int
909 archive_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
921 int
922 archive_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
934 int
935 archive_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
947 int
948 archive_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  */
975 int
976 archive_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
997 static int
998 validate_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)
1032 static int
1033 set_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
1067 static int
1068 set_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
1084 static int
1085 set_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)
1116 static int
1117 set_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
1149 static int
1150 set_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
1174 static int
1175 set_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
1200 static int
1201 set_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
1220 static int
1221 set_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
1237 static int
1238 set_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  */
1270 static int
1271 cmp_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         
1287 static int
1288 cmp_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
1299 static int
1300 cmp_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         
1316 static int
1317 cmp_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
1328 static void
1329 entry_list_init(struct entry_list *list)
1330 {
1331         list->first = NULL;
1332         list->last = &(list->first);
1333         list->count = 0;
1334 }
1335
1336 static void
1337 entry_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
1349 static void
1350 entry_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
1357 static int
1358 add_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  */
1429 static int
1430 time_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
1579 int
1580 archive_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
1590 int
1591 archive_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
1601 int
1602 archive_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
1612 int
1613 archive_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
1623 int
1624 archive_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
1634 int
1635 archive_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  */
1652 int
1653 archive_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
1674 static int
1675 add_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
1711 static int
1712 match_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
1730 static int
1731 add_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__)
1749 static int
1750 match_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
1770 static int
1771 match_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  */
1795 static int
1796 owner_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