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