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 47struct match { 48 struct match *next; 49 int matched; 50 struct archive_mstring pattern; 51}; 52 53struct 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 62struct 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 73struct entry_list { 74 struct match_file *first; 75 struct match_file **last; 76 int count; 77}; 78 79struct 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 89struct 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 135static int add_pattern_from_file(struct archive_match *, 136 struct match_list *, int, const void *, int); 137static int add_entry(struct archive_match *, int, 138 struct archive_entry *); 139static int add_owner_id(struct archive_match *, struct id_array *, 140 int64_t); 141static int add_owner_name(struct archive_match *, struct match_list *, 142 int, const void *); 143static int add_pattern_mbs(struct archive_match *, struct match_list *, 144 const char *); 145static int add_pattern_wcs(struct archive_match *, struct match_list *, 146 const wchar_t *); 147static int cmp_key_mbs(const struct archive_rb_node *, const void *); 148static int cmp_key_wcs(const struct archive_rb_node *, const void *); 149static int cmp_node_mbs(const struct archive_rb_node *, 150 const struct archive_rb_node *); 151static int cmp_node_wcs(const struct archive_rb_node *, 152 const struct archive_rb_node *); 153static void entry_list_add(struct entry_list *, struct match_file *); 154static void entry_list_free(struct entry_list *); 155static void entry_list_init(struct entry_list *); 156static int error_nomem(struct archive_match *); 157static void match_list_add(struct match_list *, struct match *); 158static void match_list_free(struct match_list *); 159static void match_list_init(struct match_list *); 160static int match_list_unmatched_inclusions_next(struct archive_match *, 161 struct match_list *, int, const void **); 162static int match_owner_id(struct id_array *, int64_t); 163#if !defined(_WIN32) || defined(__CYGWIN__) 164static int match_owner_name_mbs(struct archive_match *, 165 struct match_list *, const char *); 166#else 167static int match_owner_name_wcs(struct archive_match *, 168 struct match_list *, const wchar_t *); 169#endif 170static int match_path_exclusion(struct archive_match *, 171 struct match *, int, const void *); 172static int match_path_inclusion(struct archive_match *, 173 struct match *, int, const void *); 174static int owner_excluded(struct archive_match *, 175 struct archive_entry *); 176static int path_excluded(struct archive_match *, int, const void *); 177static int set_timefilter(struct archive_match *, int, time_t, long, 178 time_t, long); 179static int set_timefilter_pathname_mbs(struct archive_match *, 180 int, const char *); 181static int set_timefilter_pathname_wcs(struct archive_match *, 182 int, const wchar_t *); 183static int set_timefilter_date(struct archive_match *, int, const char *); 184static int set_timefilter_date_w(struct archive_match *, int, 185 const wchar_t *); 186static int time_excluded(struct archive_match *, 187 struct archive_entry *); 188static int validate_time_flag(struct archive *, int, const char *); 189 190#define get_date __archive_get_date 191 192static const struct archive_rb_tree_ops rb_ops_mbs = { 193 cmp_node_mbs, cmp_key_mbs 194}; 195 196static 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 207static int 208error_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 */ 218struct archive * 219archive_match_new(void) 220{ 221 struct archive_match *a; 222 223 a = (struct archive_match *)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 */ 242int 243archive_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 */ 270int 271archive_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 311int 312archive_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 330int 331archive_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 349int 350archive_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 363int 364archive_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 377int 378archive_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 396int 397archive_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 415int 416archive_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 429int 430archive_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 */ 450int 451archive_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 */ 486int 487archive_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 */ 501int 502archive_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 513int 514archive_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 530int 531archive_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 */ 550static int 551add_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 570static int 571add_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 590static int 591add_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 */ 710static int 711path_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 */ 777static int 778match_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 */ 805static int 806match_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 832static void 833match_list_init(struct match_list *list) 834{ 835 list->first = NULL; 836 list->last = &(list->first); 837 list->count = 0; 838} 839 840static void 841match_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 853static void 854match_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 862static int 863match_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 */ 916int 917archive_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 929int 930archive_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 941int 942archive_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 954int 955archive_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 967int 968archive_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 980int 981archive_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 */ 1008int 1009archive_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 1030static int 1031validate_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) 1065static int 1066set_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 1100static int 1101set_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 1117static int 1118set_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) 1149static int 1150set_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 1182static int 1183set_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 1207static int 1208set_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 1233static int 1234set_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 1253static int 1254set_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 1270static int 1271set_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 */ 1303static int 1304cmp_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 1320static int 1321cmp_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 1332static int 1333cmp_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 1349static int 1350cmp_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 1361static void 1362entry_list_init(struct entry_list *list) 1363{ 1364 list->first = NULL; 1365 list->last = &(list->first); 1366 list->count = 0; 1367} 1368 1369static void 1370entry_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 1382static void 1383entry_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 1390static int 1391add_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 */ 1462static int 1463time_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 1612int 1613archive_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 1623int 1624archive_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 1634int 1635archive_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 1645int 1646archive_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 1656int 1657archive_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 1667int 1668archive_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 */ 1685int 1686archive_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 1707static int 1708add_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 1744static int 1745match_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 1763static int 1764add_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__) 1782static int 1783match_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 1803static int 1804match_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 */ 1828static int 1829owner_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