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