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