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