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