1 /*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * Copyright (c) 2016 Martin Matuska 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_SYS_STAT_H 30 #include <sys/stat.h> 31 #endif 32 #ifdef HAVE_SYS_TYPES_H 33 #include <sys/types.h> 34 #endif 35 #if MAJOR_IN_MKDEV 36 #include <sys/mkdev.h> 37 #define HAVE_MAJOR 38 #elif MAJOR_IN_SYSMACROS 39 #include <sys/sysmacros.h> 40 #define HAVE_MAJOR 41 #endif 42 #ifdef HAVE_ERRNO_H 43 #include <errno.h> 44 #endif 45 #ifdef HAVE_LIMITS_H 46 #include <limits.h> 47 #endif 48 #ifdef HAVE_LINUX_FS_H 49 #include <linux/fs.h> /* for Linux file flags */ 50 #endif 51 /* 52 * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. 53 * As the include guards don't agree, the order of include is important. 54 */ 55 #ifdef HAVE_LINUX_EXT2_FS_H 56 #include <linux/ext2_fs.h> /* for Linux file flags */ 57 #endif 58 #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) 59 #include <ext2fs/ext2_fs.h> /* for Linux file flags */ 60 #endif 61 #include <stddef.h> 62 #include <stdio.h> 63 #ifdef HAVE_STDLIB_H 64 #include <stdlib.h> 65 #endif 66 #ifdef HAVE_STRING_H 67 #include <string.h> 68 #endif 69 #ifdef HAVE_WCHAR_H 70 #include <wchar.h> 71 #endif 72 73 #include "archive.h" 74 #include "archive_acl_private.h" 75 #include "archive_entry.h" 76 #include "archive_entry_locale.h" 77 #include "archive_private.h" 78 #include "archive_entry_private.h" 79 80 #if !defined(HAVE_MAJOR) && !defined(major) 81 /* Replacement for major/minor/makedev. */ 82 #define major(x) ((int)(0x00ff & ((x) >> 8))) 83 #define minor(x) ((int)(0xffff00ff & (x))) 84 #define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) 85 #endif 86 87 /* Play games to come up with a suitable makedev() definition. */ 88 #ifdef __QNXNTO__ 89 /* QNX. <sigh> */ 90 #include <sys/netmgr.h> 91 #define ae_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) 92 #elif defined makedev 93 /* There's a "makedev" macro. */ 94 #define ae_makedev(maj, min) makedev((maj), (min)) 95 #elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) 96 /* Windows. <sigh> */ 97 #define ae_makedev(maj, min) mkdev((maj), (min)) 98 #else 99 /* There's a "makedev" function. */ 100 #define ae_makedev(maj, min) makedev((maj), (min)) 101 #endif 102 103 /* 104 * This adjustment is needed to support the following idiom for adding 105 * 1000ns to the stored time: 106 * archive_entry_set_atime(archive_entry_atime(), 107 * archive_entry_atime_nsec() + 1000) 108 * The additional if() here compensates for ambiguity in the C standard, 109 * which permits two possible interpretations of a % b when a is negative. 110 */ 111 #define FIX_NS(t,ns) \ 112 do { \ 113 t += ns / 1000000000; \ 114 ns %= 1000000000; \ 115 if (ns < 0) { --t; ns += 1000000000; } \ 116 } while (0) 117 118 static char * ae_fflagstostr(unsigned long bitset, unsigned long bitclear); 119 static const wchar_t *ae_wcstofflags(const wchar_t *stringp, 120 unsigned long *setp, unsigned long *clrp); 121 static const char *ae_strtofflags(const char *stringp, size_t length, 122 unsigned long *setp, unsigned long *clrp); 123 124 #ifndef HAVE_WCSCPY 125 static wchar_t * wcscpy(wchar_t *s1, const wchar_t *s2) 126 { 127 wchar_t *dest = s1; 128 while ((*s1 = *s2) != L'\0') 129 ++s1, ++s2; 130 return dest; 131 } 132 #endif 133 #ifndef HAVE_WCSLEN 134 static size_t wcslen(const wchar_t *s) 135 { 136 const wchar_t *p = s; 137 while (*p != L'\0') 138 ++p; 139 return p - s; 140 } 141 #endif 142 #ifndef HAVE_WMEMCMP 143 /* Good enough for simple equality testing, but not for sorting. */ 144 #define wmemcmp(a,b,i) memcmp((a), (b), (i) * sizeof(wchar_t)) 145 #endif 146 147 /**************************************************************************** 148 * 149 * Public Interface 150 * 151 ****************************************************************************/ 152 153 struct archive_entry * 154 archive_entry_clear(struct archive_entry *entry) 155 { 156 if (entry == NULL) 157 return (NULL); 158 archive_mstring_clean(&entry->ae_fflags_text); 159 archive_mstring_clean(&entry->ae_gname); 160 archive_mstring_clean(&entry->ae_linkname); 161 archive_mstring_clean(&entry->ae_pathname); 162 archive_mstring_clean(&entry->ae_sourcepath); 163 archive_mstring_clean(&entry->ae_uname); 164 archive_entry_copy_mac_metadata(entry, NULL, 0); 165 archive_acl_clear(&entry->acl); 166 archive_entry_xattr_clear(entry); 167 archive_entry_sparse_clear(entry); 168 free(entry->stat); 169 entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED; 170 memset(entry, 0, sizeof(*entry)); 171 return entry; 172 } 173 174 struct archive_entry * 175 archive_entry_clone(struct archive_entry *entry) 176 { 177 struct archive_entry *entry2; 178 struct ae_xattr *xp; 179 struct ae_sparse *sp; 180 size_t s; 181 const void *p; 182 183 /* Allocate new structure and copy over all of the fields. */ 184 /* TODO: Should we copy the archive over? Or require a new archive 185 * as an argument? */ 186 entry2 = archive_entry_new2(entry->archive); 187 if (entry2 == NULL) 188 return (NULL); 189 entry2->ae_stat = entry->ae_stat; 190 entry2->ae_fflags_set = entry->ae_fflags_set; 191 entry2->ae_fflags_clear = entry->ae_fflags_clear; 192 193 /* TODO: XXX If clone can have a different archive, what do we do here if 194 * character sets are different? XXX */ 195 archive_mstring_copy(&entry2->ae_fflags_text, &entry->ae_fflags_text); 196 archive_mstring_copy(&entry2->ae_gname, &entry->ae_gname); 197 archive_mstring_copy(&entry2->ae_linkname, &entry->ae_linkname); 198 archive_mstring_copy(&entry2->ae_pathname, &entry->ae_pathname); 199 archive_mstring_copy(&entry2->ae_sourcepath, &entry->ae_sourcepath); 200 entry2->ae_set = entry->ae_set; 201 archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname); 202 203 /* Copy symlink type */ 204 entry2->ae_symlink_type = entry->ae_symlink_type; 205 206 /* Copy encryption status */ 207 entry2->encryption = entry->encryption; 208 209 /* Copy digests */ 210 #define copy_digest(_e2, _e, _t) \ 211 memcpy(_e2->digest._t, _e->digest._t, sizeof(_e2->digest._t)) 212 213 copy_digest(entry2, entry, md5); 214 copy_digest(entry2, entry, rmd160); 215 copy_digest(entry2, entry, sha1); 216 copy_digest(entry2, entry, sha256); 217 copy_digest(entry2, entry, sha384); 218 copy_digest(entry2, entry, sha512); 219 220 #undef copy_digest 221 222 /* Copy ACL data over. */ 223 archive_acl_copy(&entry2->acl, &entry->acl); 224 225 /* Copy Mac OS metadata. */ 226 p = archive_entry_mac_metadata(entry, &s); 227 archive_entry_copy_mac_metadata(entry2, p, s); 228 229 /* Copy xattr data over. */ 230 xp = entry->xattr_head; 231 while (xp != NULL) { 232 archive_entry_xattr_add_entry(entry2, 233 xp->name, xp->value, xp->size); 234 xp = xp->next; 235 } 236 237 /* Copy sparse data over. */ 238 sp = entry->sparse_head; 239 while (sp != NULL) { 240 archive_entry_sparse_add_entry(entry2, 241 sp->offset, sp->length); 242 sp = sp->next; 243 } 244 245 return (entry2); 246 } 247 248 void 249 archive_entry_free(struct archive_entry *entry) 250 { 251 archive_entry_clear(entry); 252 free(entry); 253 } 254 255 struct archive_entry * 256 archive_entry_new(void) 257 { 258 return archive_entry_new2(NULL); 259 } 260 261 struct archive_entry * 262 archive_entry_new2(struct archive *a) 263 { 264 struct archive_entry *entry; 265 266 entry = calloc(1, sizeof(*entry)); 267 if (entry == NULL) 268 return (NULL); 269 entry->archive = a; 270 entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED; 271 return (entry); 272 } 273 274 /* 275 * Functions for reading fields from an archive_entry. 276 */ 277 278 time_t 279 archive_entry_atime(struct archive_entry *entry) 280 { 281 return (entry->ae_stat.aest_atime); 282 } 283 284 long 285 archive_entry_atime_nsec(struct archive_entry *entry) 286 { 287 return (entry->ae_stat.aest_atime_nsec); 288 } 289 290 int 291 archive_entry_atime_is_set(struct archive_entry *entry) 292 { 293 return (entry->ae_set & AE_SET_ATIME); 294 } 295 296 time_t 297 archive_entry_birthtime(struct archive_entry *entry) 298 { 299 return (entry->ae_stat.aest_birthtime); 300 } 301 302 long 303 archive_entry_birthtime_nsec(struct archive_entry *entry) 304 { 305 return (entry->ae_stat.aest_birthtime_nsec); 306 } 307 308 int 309 archive_entry_birthtime_is_set(struct archive_entry *entry) 310 { 311 return (entry->ae_set & AE_SET_BIRTHTIME); 312 } 313 314 time_t 315 archive_entry_ctime(struct archive_entry *entry) 316 { 317 return (entry->ae_stat.aest_ctime); 318 } 319 320 int 321 archive_entry_ctime_is_set(struct archive_entry *entry) 322 { 323 return (entry->ae_set & AE_SET_CTIME); 324 } 325 326 long 327 archive_entry_ctime_nsec(struct archive_entry *entry) 328 { 329 return (entry->ae_stat.aest_ctime_nsec); 330 } 331 332 dev_t 333 archive_entry_dev(struct archive_entry *entry) 334 { 335 if (entry->ae_stat.aest_dev_is_broken_down) 336 return ae_makedev(entry->ae_stat.aest_devmajor, 337 entry->ae_stat.aest_devminor); 338 else 339 return (entry->ae_stat.aest_dev); 340 } 341 342 int 343 archive_entry_dev_is_set(struct archive_entry *entry) 344 { 345 return (entry->ae_set & AE_SET_DEV); 346 } 347 348 dev_t 349 archive_entry_devmajor(struct archive_entry *entry) 350 { 351 if (entry->ae_stat.aest_dev_is_broken_down) 352 return (entry->ae_stat.aest_devmajor); 353 else 354 return major(entry->ae_stat.aest_dev); 355 } 356 357 dev_t 358 archive_entry_devminor(struct archive_entry *entry) 359 { 360 if (entry->ae_stat.aest_dev_is_broken_down) 361 return (entry->ae_stat.aest_devminor); 362 else 363 return minor(entry->ae_stat.aest_dev); 364 } 365 366 __LA_MODE_T 367 archive_entry_filetype(struct archive_entry *entry) 368 { 369 return (AE_IFMT & entry->acl.mode); 370 } 371 372 int 373 archive_entry_filetype_is_set(struct archive_entry *entry) 374 { 375 return (entry->ae_set & AE_SET_FILETYPE); 376 } 377 378 void 379 archive_entry_fflags(struct archive_entry *entry, 380 unsigned long *set, unsigned long *clear) 381 { 382 *set = entry->ae_fflags_set; 383 *clear = entry->ae_fflags_clear; 384 } 385 386 /* 387 * Note: if text was provided, this just returns that text. If you 388 * really need the text to be rebuilt in a canonical form, set the 389 * text, ask for the bitmaps, then set the bitmaps. (Setting the 390 * bitmaps clears any stored text.) This design is deliberate: if 391 * we're editing archives, we don't want to discard flags just because 392 * they aren't supported on the current system. The bitmap<->text 393 * conversions are platform-specific (see below). 394 */ 395 const char * 396 archive_entry_fflags_text(struct archive_entry *entry) 397 { 398 const char *f; 399 char *p; 400 401 if (archive_mstring_get_mbs(entry->archive, 402 &entry->ae_fflags_text, &f) == 0) { 403 if (f != NULL) 404 return (f); 405 } else if (errno == ENOMEM) 406 __archive_errx(1, "No memory"); 407 408 if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) 409 return (NULL); 410 411 p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear); 412 if (p == NULL) 413 return (NULL); 414 415 archive_mstring_copy_mbs(&entry->ae_fflags_text, p); 416 free(p); 417 if (archive_mstring_get_mbs(entry->archive, 418 &entry->ae_fflags_text, &f) == 0) 419 return (f); 420 if (errno == ENOMEM) 421 __archive_errx(1, "No memory"); 422 return (NULL); 423 } 424 425 la_int64_t 426 archive_entry_gid(struct archive_entry *entry) 427 { 428 return (entry->ae_stat.aest_gid); 429 } 430 431 int 432 archive_entry_gid_is_set(struct archive_entry *entry) 433 { 434 return (entry->ae_set & AE_SET_GID); 435 } 436 437 const char * 438 archive_entry_gname(struct archive_entry *entry) 439 { 440 const char *p; 441 if (archive_mstring_get_mbs(entry->archive, &entry->ae_gname, &p) == 0) 442 return (p); 443 if (errno == ENOMEM) 444 __archive_errx(1, "No memory"); 445 return (NULL); 446 } 447 448 const char * 449 archive_entry_gname_utf8(struct archive_entry *entry) 450 { 451 const char *p; 452 if (archive_mstring_get_utf8(entry->archive, &entry->ae_gname, &p) == 0) 453 return (p); 454 if (errno == ENOMEM) 455 __archive_errx(1, "No memory"); 456 return (NULL); 457 } 458 459 460 const wchar_t * 461 archive_entry_gname_w(struct archive_entry *entry) 462 { 463 const wchar_t *p; 464 if (archive_mstring_get_wcs(entry->archive, &entry->ae_gname, &p) == 0) 465 return (p); 466 if (errno == ENOMEM) 467 __archive_errx(1, "No memory"); 468 return (NULL); 469 } 470 471 int 472 _archive_entry_gname_l(struct archive_entry *entry, 473 const char **p, size_t *len, struct archive_string_conv *sc) 474 { 475 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_gname, p, len, sc)); 476 } 477 478 void 479 archive_entry_set_link_to_hardlink(struct archive_entry *entry) 480 { 481 if ((entry->ae_set & AE_SET_SYMLINK) != 0) { 482 entry->ae_set &= ~AE_SET_SYMLINK; 483 } 484 entry->ae_set |= AE_SET_HARDLINK; 485 } 486 487 const char * 488 archive_entry_hardlink(struct archive_entry *entry) 489 { 490 const char *p; 491 if ((entry->ae_set & AE_SET_HARDLINK) == 0) 492 return (NULL); 493 if (archive_mstring_get_mbs( 494 entry->archive, &entry->ae_linkname, &p) == 0) 495 return (p); 496 if (errno == ENOMEM) 497 __archive_errx(1, "No memory"); 498 return (NULL); 499 } 500 501 const char * 502 archive_entry_hardlink_utf8(struct archive_entry *entry) 503 { 504 const char *p; 505 if ((entry->ae_set & AE_SET_HARDLINK) == 0) 506 return (NULL); 507 if (archive_mstring_get_utf8( 508 entry->archive, &entry->ae_linkname, &p) == 0) 509 return (p); 510 if (errno == ENOMEM) 511 __archive_errx(1, "No memory"); 512 return (NULL); 513 } 514 515 const wchar_t * 516 archive_entry_hardlink_w(struct archive_entry *entry) 517 { 518 const wchar_t *p; 519 if ((entry->ae_set & AE_SET_HARDLINK) == 0) 520 return (NULL); 521 if (archive_mstring_get_wcs( 522 entry->archive, &entry->ae_linkname, &p) == 0) 523 return (p); 524 if (errno == ENOMEM) 525 __archive_errx(1, "No memory"); 526 return (NULL); 527 } 528 529 int 530 archive_entry_hardlink_is_set(struct archive_entry *entry) 531 { 532 return (entry->ae_set & AE_SET_HARDLINK) != 0; 533 } 534 535 int 536 _archive_entry_hardlink_l(struct archive_entry *entry, 537 const char **p, size_t *len, struct archive_string_conv *sc) 538 { 539 if ((entry->ae_set & AE_SET_HARDLINK) == 0) { 540 *p = NULL; 541 *len = 0; 542 return (0); 543 } 544 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_linkname, p, len, sc)); 545 } 546 547 la_int64_t 548 archive_entry_ino(struct archive_entry *entry) 549 { 550 return (entry->ae_stat.aest_ino); 551 } 552 553 int 554 archive_entry_ino_is_set(struct archive_entry *entry) 555 { 556 return (entry->ae_set & AE_SET_INO); 557 } 558 559 la_int64_t 560 archive_entry_ino64(struct archive_entry *entry) 561 { 562 return (entry->ae_stat.aest_ino); 563 } 564 565 __LA_MODE_T 566 archive_entry_mode(struct archive_entry *entry) 567 { 568 return (entry->acl.mode); 569 } 570 571 time_t 572 archive_entry_mtime(struct archive_entry *entry) 573 { 574 return (entry->ae_stat.aest_mtime); 575 } 576 577 long 578 archive_entry_mtime_nsec(struct archive_entry *entry) 579 { 580 return (entry->ae_stat.aest_mtime_nsec); 581 } 582 583 int 584 archive_entry_mtime_is_set(struct archive_entry *entry) 585 { 586 return (entry->ae_set & AE_SET_MTIME); 587 } 588 589 unsigned int 590 archive_entry_nlink(struct archive_entry *entry) 591 { 592 return (entry->ae_stat.aest_nlink); 593 } 594 595 /* Instead, our caller could have chosen a specific encoding 596 * (archive_mstring_get_mbs, archive_mstring_get_utf8, 597 * archive_mstring_get_wcs). So we should try multiple 598 * encodings. Try mbs first because of history, even though 599 * utf8 might be better for pathname portability. 600 * Also omit wcs because of type mismatch (char * versus wchar *) 601 */ 602 const char * 603 archive_entry_pathname(struct archive_entry *entry) 604 { 605 const char *p; 606 if (archive_mstring_get_mbs( 607 entry->archive, &entry->ae_pathname, &p) == 0) 608 return (p); 609 #if HAVE_EILSEQ /*{*/ 610 if (errno == EILSEQ) { 611 if (archive_mstring_get_utf8( 612 entry->archive, &entry->ae_pathname, &p) == 0) 613 return (p); 614 } 615 #endif /*}*/ 616 if (errno == ENOMEM) 617 __archive_errx(1, "No memory"); 618 return (NULL); 619 } 620 621 const char * 622 archive_entry_pathname_utf8(struct archive_entry *entry) 623 { 624 const char *p; 625 if (archive_mstring_get_utf8( 626 entry->archive, &entry->ae_pathname, &p) == 0) 627 return (p); 628 if (errno == ENOMEM) 629 __archive_errx(1, "No memory"); 630 return (NULL); 631 } 632 633 const wchar_t * 634 archive_entry_pathname_w(struct archive_entry *entry) 635 { 636 const wchar_t *p; 637 if (archive_mstring_get_wcs( 638 entry->archive, &entry->ae_pathname, &p) == 0) 639 return (p); 640 if (errno == ENOMEM) 641 __archive_errx(1, "No memory"); 642 return (NULL); 643 } 644 645 int 646 _archive_entry_pathname_l(struct archive_entry *entry, 647 const char **p, size_t *len, struct archive_string_conv *sc) 648 { 649 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc)); 650 } 651 652 __LA_MODE_T 653 archive_entry_perm(struct archive_entry *entry) 654 { 655 return (~AE_IFMT & entry->acl.mode); 656 } 657 658 int 659 archive_entry_perm_is_set(struct archive_entry *entry) 660 { 661 return (entry->ae_set & AE_SET_PERM); 662 } 663 664 int 665 archive_entry_rdev_is_set(struct archive_entry *entry) 666 { 667 return (entry->ae_set & AE_SET_RDEV); 668 } 669 670 dev_t 671 archive_entry_rdev(struct archive_entry *entry) 672 { 673 if (archive_entry_rdev_is_set(entry)) { 674 if (entry->ae_stat.aest_rdev_is_broken_down) 675 return ae_makedev(entry->ae_stat.aest_rdevmajor, 676 entry->ae_stat.aest_rdevminor); 677 else 678 return (entry->ae_stat.aest_rdev); 679 } else { 680 return 0; 681 } 682 } 683 684 dev_t 685 archive_entry_rdevmajor(struct archive_entry *entry) 686 { 687 if (archive_entry_rdev_is_set(entry)) { 688 if (entry->ae_stat.aest_rdev_is_broken_down) 689 return (entry->ae_stat.aest_rdevmajor); 690 else 691 return major(entry->ae_stat.aest_rdev); 692 } else { 693 return 0; 694 } 695 } 696 697 dev_t 698 archive_entry_rdevminor(struct archive_entry *entry) 699 { 700 if (archive_entry_rdev_is_set(entry)) { 701 if (entry->ae_stat.aest_rdev_is_broken_down) 702 return (entry->ae_stat.aest_rdevminor); 703 else 704 return minor(entry->ae_stat.aest_rdev); 705 } else { 706 return 0; 707 } 708 } 709 710 la_int64_t 711 archive_entry_size(struct archive_entry *entry) 712 { 713 return (entry->ae_stat.aest_size); 714 } 715 716 int 717 archive_entry_size_is_set(struct archive_entry *entry) 718 { 719 return (entry->ae_set & AE_SET_SIZE); 720 } 721 722 const char * 723 archive_entry_sourcepath(struct archive_entry *entry) 724 { 725 const char *p; 726 if (archive_mstring_get_mbs( 727 entry->archive, &entry->ae_sourcepath, &p) == 0) 728 return (p); 729 if (errno == ENOMEM) 730 __archive_errx(1, "No memory"); 731 return (NULL); 732 } 733 734 const wchar_t * 735 archive_entry_sourcepath_w(struct archive_entry *entry) 736 { 737 const wchar_t *p; 738 if (archive_mstring_get_wcs( 739 entry->archive, &entry->ae_sourcepath, &p) == 0) 740 return (p); 741 return (NULL); 742 } 743 744 const char * 745 archive_entry_symlink(struct archive_entry *entry) 746 { 747 const char *p; 748 if ((entry->ae_set & AE_SET_SYMLINK) == 0) 749 return (NULL); 750 if (archive_mstring_get_mbs( 751 entry->archive, &entry->ae_linkname, &p) == 0) 752 return (p); 753 if (errno == ENOMEM) 754 __archive_errx(1, "No memory"); 755 return (NULL); 756 } 757 758 void 759 archive_entry_set_link_to_symlink(struct archive_entry *entry) 760 { 761 if ((entry->ae_set & AE_SET_HARDLINK) != 0) { 762 entry->ae_set &= ~AE_SET_HARDLINK; 763 } 764 entry->ae_set |= AE_SET_SYMLINK; 765 } 766 767 int 768 archive_entry_symlink_type(struct archive_entry *entry) 769 { 770 return (entry->ae_symlink_type); 771 } 772 773 const char * 774 archive_entry_symlink_utf8(struct archive_entry *entry) 775 { 776 const char *p; 777 if ((entry->ae_set & AE_SET_SYMLINK) == 0) 778 return (NULL); 779 if (archive_mstring_get_utf8( 780 entry->archive, &entry->ae_linkname, &p) == 0) 781 return (p); 782 if (errno == ENOMEM) 783 __archive_errx(1, "No memory"); 784 return (NULL); 785 } 786 787 const wchar_t * 788 archive_entry_symlink_w(struct archive_entry *entry) 789 { 790 const wchar_t *p; 791 if ((entry->ae_set & AE_SET_SYMLINK) == 0) 792 return (NULL); 793 if (archive_mstring_get_wcs( 794 entry->archive, &entry->ae_linkname, &p) == 0) 795 return (p); 796 if (errno == ENOMEM) 797 __archive_errx(1, "No memory"); 798 return (NULL); 799 } 800 801 int 802 _archive_entry_symlink_l(struct archive_entry *entry, 803 const char **p, size_t *len, struct archive_string_conv *sc) 804 { 805 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 806 *p = NULL; 807 *len = 0; 808 return (0); 809 } 810 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_linkname, p, len, sc)); 811 } 812 813 la_int64_t 814 archive_entry_uid(struct archive_entry *entry) 815 { 816 return (entry->ae_stat.aest_uid); 817 } 818 819 int 820 archive_entry_uid_is_set(struct archive_entry *entry) 821 { 822 return (entry->ae_set & AE_SET_UID); 823 } 824 825 const char * 826 archive_entry_uname(struct archive_entry *entry) 827 { 828 const char *p; 829 if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) 830 return (p); 831 if (errno == ENOMEM) 832 __archive_errx(1, "No memory"); 833 return (NULL); 834 } 835 836 const char * 837 archive_entry_uname_utf8(struct archive_entry *entry) 838 { 839 const char *p; 840 if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0) 841 return (p); 842 if (errno == ENOMEM) 843 __archive_errx(1, "No memory"); 844 return (NULL); 845 } 846 847 const wchar_t * 848 archive_entry_uname_w(struct archive_entry *entry) 849 { 850 const wchar_t *p; 851 if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0) 852 return (p); 853 if (errno == ENOMEM) 854 __archive_errx(1, "No memory"); 855 return (NULL); 856 } 857 858 int 859 _archive_entry_uname_l(struct archive_entry *entry, 860 const char **p, size_t *len, struct archive_string_conv *sc) 861 { 862 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc)); 863 } 864 865 int 866 archive_entry_is_data_encrypted(struct archive_entry *entry) 867 { 868 return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA); 869 } 870 871 int 872 archive_entry_is_metadata_encrypted(struct archive_entry *entry) 873 { 874 return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA); 875 } 876 877 int 878 archive_entry_is_encrypted(struct archive_entry *entry) 879 { 880 return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA)); 881 } 882 883 /* 884 * Functions to set archive_entry properties. 885 */ 886 887 void 888 archive_entry_set_filetype(struct archive_entry *entry, unsigned int type) 889 { 890 entry->stat_valid = 0; 891 entry->acl.mode &= ~AE_IFMT; 892 entry->acl.mode |= AE_IFMT & type; 893 entry->ae_set |= AE_SET_FILETYPE; 894 } 895 896 void 897 archive_entry_set_fflags(struct archive_entry *entry, 898 unsigned long set, unsigned long clear) 899 { 900 archive_mstring_clean(&entry->ae_fflags_text); 901 entry->ae_fflags_set = set; 902 entry->ae_fflags_clear = clear; 903 } 904 905 const char * 906 archive_entry_copy_fflags_text(struct archive_entry *entry, 907 const char *flags) 908 { 909 return archive_entry_copy_fflags_text_len(entry, flags, strlen(flags)); 910 } 911 912 const char * 913 archive_entry_copy_fflags_text_len(struct archive_entry *entry, 914 const char *flags, size_t flags_length) 915 { 916 archive_mstring_copy_mbs_len(&entry->ae_fflags_text, flags, flags_length); 917 return (ae_strtofflags(flags, flags_length, 918 &entry->ae_fflags_set, &entry->ae_fflags_clear)); 919 } 920 921 const wchar_t * 922 archive_entry_copy_fflags_text_w(struct archive_entry *entry, 923 const wchar_t *flags) 924 { 925 archive_mstring_copy_wcs(&entry->ae_fflags_text, flags); 926 return (ae_wcstofflags(flags, 927 &entry->ae_fflags_set, &entry->ae_fflags_clear)); 928 } 929 930 void 931 archive_entry_set_gid(struct archive_entry *entry, la_int64_t g) 932 { 933 if (g < 0) { 934 g = 0; 935 } 936 entry->stat_valid = 0; 937 entry->ae_stat.aest_gid = g; 938 entry->ae_set |= AE_SET_GID; 939 } 940 941 void 942 archive_entry_set_gname(struct archive_entry *entry, const char *name) 943 { 944 archive_mstring_copy_mbs(&entry->ae_gname, name); 945 } 946 947 void 948 archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name) 949 { 950 archive_mstring_copy_utf8(&entry->ae_gname, name); 951 } 952 953 void 954 archive_entry_copy_gname(struct archive_entry *entry, const char *name) 955 { 956 archive_mstring_copy_mbs(&entry->ae_gname, name); 957 } 958 959 void 960 archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name) 961 { 962 archive_mstring_copy_wcs(&entry->ae_gname, name); 963 } 964 965 int 966 archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name) 967 { 968 if (archive_mstring_update_utf8(entry->archive, 969 &entry->ae_gname, name) == 0) 970 return (1); 971 if (errno == ENOMEM) 972 __archive_errx(1, "No memory"); 973 return (0); 974 } 975 976 int 977 _archive_entry_copy_gname_l(struct archive_entry *entry, 978 const char *name, size_t len, struct archive_string_conv *sc) 979 { 980 return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc)); 981 } 982 983 void 984 archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino) 985 { 986 if (ino < 0) { 987 ino = 0; 988 } 989 entry->stat_valid = 0; 990 entry->ae_set |= AE_SET_INO; 991 entry->ae_stat.aest_ino = ino; 992 } 993 994 void 995 archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino) 996 { 997 if (ino < 0) { 998 ino = 0; 999 } 1000 entry->stat_valid = 0; 1001 entry->ae_set |= AE_SET_INO; 1002 entry->ae_stat.aest_ino = ino; 1003 } 1004 1005 void 1006 archive_entry_set_hardlink(struct archive_entry *entry, const char *target) 1007 { 1008 if (target == NULL) { 1009 entry->ae_set &= ~AE_SET_HARDLINK; 1010 if (entry->ae_set & AE_SET_SYMLINK) { 1011 return; 1012 } 1013 } else { 1014 entry->ae_set |= AE_SET_HARDLINK; 1015 } 1016 entry->ae_set &= ~AE_SET_SYMLINK; 1017 archive_mstring_copy_mbs(&entry->ae_linkname, target); 1018 } 1019 1020 void 1021 archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target) 1022 { 1023 if (target == NULL && (entry->ae_set & AE_SET_SYMLINK)) 1024 return; 1025 archive_mstring_copy_utf8(&entry->ae_linkname, target); 1026 if (target != NULL) 1027 entry->ae_set |= AE_SET_HARDLINK; 1028 else 1029 entry->ae_set &= ~AE_SET_HARDLINK; 1030 } 1031 1032 void 1033 archive_entry_copy_hardlink(struct archive_entry *entry, const char *target) 1034 { 1035 if (target == NULL && (entry->ae_set & AE_SET_SYMLINK)) 1036 return; 1037 archive_mstring_copy_mbs(&entry->ae_linkname, target); 1038 if (target != NULL) 1039 entry->ae_set |= AE_SET_HARDLINK; 1040 else 1041 entry->ae_set &= ~AE_SET_HARDLINK; 1042 } 1043 1044 void 1045 archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target) 1046 { 1047 if (target == NULL && (entry->ae_set & AE_SET_SYMLINK)) 1048 return; 1049 archive_mstring_copy_wcs(&entry->ae_linkname, target); 1050 if (target != NULL) 1051 entry->ae_set |= AE_SET_HARDLINK; 1052 else 1053 entry->ae_set &= ~AE_SET_HARDLINK; 1054 } 1055 1056 int 1057 archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target) 1058 { 1059 if (target == NULL && (entry->ae_set & AE_SET_SYMLINK)) 1060 return (0); 1061 if (target != NULL) 1062 entry->ae_set |= AE_SET_HARDLINK; 1063 else 1064 entry->ae_set &= ~AE_SET_HARDLINK; 1065 if (archive_mstring_update_utf8(entry->archive, 1066 &entry->ae_linkname, target) == 0) 1067 return (1); 1068 if (errno == ENOMEM) 1069 __archive_errx(1, "No memory"); 1070 return (0); 1071 } 1072 1073 int 1074 _archive_entry_copy_hardlink_l(struct archive_entry *entry, 1075 const char *target, size_t len, struct archive_string_conv *sc) 1076 { 1077 int r; 1078 1079 if (target == NULL && (entry->ae_set & AE_SET_SYMLINK)) 1080 return (0); 1081 r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname, 1082 target, len, sc); 1083 if (target != NULL && r == 0) 1084 entry->ae_set |= AE_SET_HARDLINK; 1085 else 1086 entry->ae_set &= ~AE_SET_HARDLINK; 1087 return (r); 1088 } 1089 1090 void 1091 archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) 1092 { 1093 FIX_NS(t, ns); 1094 entry->stat_valid = 0; 1095 entry->ae_set |= AE_SET_ATIME; 1096 entry->ae_stat.aest_atime = t; 1097 entry->ae_stat.aest_atime_nsec = ns; 1098 } 1099 1100 void 1101 archive_entry_unset_atime(struct archive_entry *entry) 1102 { 1103 archive_entry_set_atime(entry, 0, 0); 1104 entry->ae_set &= ~AE_SET_ATIME; 1105 } 1106 1107 void 1108 archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns) 1109 { 1110 FIX_NS(t, ns); 1111 entry->stat_valid = 0; 1112 entry->ae_set |= AE_SET_BIRTHTIME; 1113 entry->ae_stat.aest_birthtime = t; 1114 entry->ae_stat.aest_birthtime_nsec = ns; 1115 } 1116 1117 void 1118 archive_entry_unset_birthtime(struct archive_entry *entry) 1119 { 1120 archive_entry_set_birthtime(entry, 0, 0); 1121 entry->ae_set &= ~AE_SET_BIRTHTIME; 1122 } 1123 1124 void 1125 archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) 1126 { 1127 FIX_NS(t, ns); 1128 entry->stat_valid = 0; 1129 entry->ae_set |= AE_SET_CTIME; 1130 entry->ae_stat.aest_ctime = t; 1131 entry->ae_stat.aest_ctime_nsec = ns; 1132 } 1133 1134 void 1135 archive_entry_unset_ctime(struct archive_entry *entry) 1136 { 1137 archive_entry_set_ctime(entry, 0, 0); 1138 entry->ae_set &= ~AE_SET_CTIME; 1139 } 1140 1141 void 1142 archive_entry_set_dev(struct archive_entry *entry, dev_t d) 1143 { 1144 entry->stat_valid = 0; 1145 entry->ae_set |= AE_SET_DEV; 1146 entry->ae_stat.aest_dev_is_broken_down = 0; 1147 entry->ae_stat.aest_dev = d; 1148 } 1149 1150 void 1151 archive_entry_set_devmajor(struct archive_entry *entry, dev_t m) 1152 { 1153 entry->stat_valid = 0; 1154 entry->ae_set |= AE_SET_DEV; 1155 entry->ae_stat.aest_dev_is_broken_down = 1; 1156 entry->ae_stat.aest_devmajor = m; 1157 } 1158 1159 void 1160 archive_entry_set_devminor(struct archive_entry *entry, dev_t m) 1161 { 1162 entry->stat_valid = 0; 1163 entry->ae_set |= AE_SET_DEV; 1164 entry->ae_stat.aest_dev_is_broken_down = 1; 1165 entry->ae_stat.aest_devminor = m; 1166 } 1167 1168 /* Set symlink if symlink is already set, else set hardlink. */ 1169 void 1170 archive_entry_set_link(struct archive_entry *entry, const char *target) 1171 { 1172 archive_mstring_copy_mbs(&entry->ae_linkname, target); 1173 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 1174 entry->ae_set |= AE_SET_HARDLINK; 1175 } 1176 } 1177 1178 void 1179 archive_entry_set_link_utf8(struct archive_entry *entry, const char *target) 1180 { 1181 archive_mstring_copy_utf8(&entry->ae_linkname, target); 1182 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 1183 entry->ae_set |= AE_SET_HARDLINK; 1184 } 1185 } 1186 1187 /* Set symlink if symlink is already set, else set hardlink. */ 1188 void 1189 archive_entry_copy_link(struct archive_entry *entry, const char *target) 1190 { 1191 archive_mstring_copy_mbs(&entry->ae_linkname, target); 1192 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 1193 entry->ae_set |= AE_SET_HARDLINK; 1194 } 1195 } 1196 1197 /* Set symlink if symlink is already set, else set hardlink. */ 1198 void 1199 archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target) 1200 { 1201 archive_mstring_copy_wcs(&entry->ae_linkname, target); 1202 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 1203 entry->ae_set |= AE_SET_HARDLINK; 1204 } 1205 } 1206 1207 int 1208 archive_entry_update_link_utf8(struct archive_entry *entry, const char *target) 1209 { 1210 int r; 1211 r = archive_mstring_update_utf8(entry->archive, 1212 &entry->ae_linkname, target); 1213 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 1214 entry->ae_set |= AE_SET_HARDLINK; 1215 } 1216 if (r == 0) 1217 return (1); 1218 if (errno == ENOMEM) 1219 __archive_errx(1, "No memory"); 1220 return (0); 1221 } 1222 1223 int 1224 _archive_entry_copy_link_l(struct archive_entry *entry, 1225 const char *target, size_t len, struct archive_string_conv *sc) 1226 { 1227 int r; 1228 1229 r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname, 1230 target, len, sc); 1231 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 1232 entry->ae_set |= AE_SET_HARDLINK; 1233 } 1234 return (r); 1235 } 1236 1237 void 1238 archive_entry_set_mode(struct archive_entry *entry, mode_t m) 1239 { 1240 entry->stat_valid = 0; 1241 entry->acl.mode = m; 1242 entry->ae_set |= AE_SET_PERM | AE_SET_FILETYPE; 1243 } 1244 1245 void 1246 archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns) 1247 { 1248 FIX_NS(t, ns); 1249 entry->stat_valid = 0; 1250 entry->ae_set |= AE_SET_MTIME; 1251 entry->ae_stat.aest_mtime = t; 1252 entry->ae_stat.aest_mtime_nsec = ns; 1253 } 1254 1255 void 1256 archive_entry_unset_mtime(struct archive_entry *entry) 1257 { 1258 archive_entry_set_mtime(entry, 0, 0); 1259 entry->ae_set &= ~AE_SET_MTIME; 1260 } 1261 1262 void 1263 archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink) 1264 { 1265 entry->stat_valid = 0; 1266 entry->ae_stat.aest_nlink = nlink; 1267 } 1268 1269 void 1270 archive_entry_set_pathname(struct archive_entry *entry, const char *name) 1271 { 1272 archive_mstring_copy_mbs(&entry->ae_pathname, name); 1273 } 1274 1275 void 1276 archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name) 1277 { 1278 archive_mstring_copy_utf8(&entry->ae_pathname, name); 1279 } 1280 1281 void 1282 archive_entry_copy_pathname(struct archive_entry *entry, const char *name) 1283 { 1284 archive_mstring_copy_mbs(&entry->ae_pathname, name); 1285 } 1286 1287 void 1288 archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name) 1289 { 1290 archive_mstring_copy_wcs(&entry->ae_pathname, name); 1291 } 1292 1293 int 1294 archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name) 1295 { 1296 if (archive_mstring_update_utf8(entry->archive, 1297 &entry->ae_pathname, name) == 0) 1298 return (1); 1299 if (errno == ENOMEM) 1300 __archive_errx(1, "No memory"); 1301 return (0); 1302 } 1303 1304 int 1305 _archive_entry_copy_pathname_l(struct archive_entry *entry, 1306 const char *name, size_t len, struct archive_string_conv *sc) 1307 { 1308 return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname, 1309 name, len, sc)); 1310 } 1311 1312 void 1313 archive_entry_set_perm(struct archive_entry *entry, mode_t p) 1314 { 1315 entry->stat_valid = 0; 1316 entry->acl.mode &= AE_IFMT; 1317 entry->acl.mode |= ~AE_IFMT & p; 1318 entry->ae_set |= AE_SET_PERM; 1319 } 1320 1321 void 1322 archive_entry_set_rdev(struct archive_entry *entry, dev_t m) 1323 { 1324 entry->stat_valid = 0; 1325 entry->ae_stat.aest_rdev = m; 1326 entry->ae_stat.aest_rdev_is_broken_down = 0; 1327 entry->ae_stat.aest_rdevmajor = 0; 1328 entry->ae_stat.aest_rdevminor = 0; 1329 entry->ae_set |= AE_SET_RDEV; 1330 } 1331 1332 void 1333 archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m) 1334 { 1335 entry->stat_valid = 0; 1336 entry->ae_stat.aest_rdev_is_broken_down = 1; 1337 entry->ae_stat.aest_rdev = 0; 1338 entry->ae_stat.aest_rdevmajor = m; 1339 entry->ae_set |= AE_SET_RDEV; 1340 } 1341 1342 void 1343 archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) 1344 { 1345 entry->stat_valid = 0; 1346 entry->ae_stat.aest_rdev_is_broken_down = 1; 1347 entry->ae_stat.aest_rdev = 0; 1348 entry->ae_stat.aest_rdevminor = m; 1349 entry->ae_set |= AE_SET_RDEV; 1350 } 1351 1352 void 1353 archive_entry_set_size(struct archive_entry *entry, la_int64_t s) 1354 { 1355 if (s < 0) { 1356 s = 0; 1357 } 1358 entry->stat_valid = 0; 1359 entry->ae_stat.aest_size = s; 1360 entry->ae_set |= AE_SET_SIZE; 1361 } 1362 1363 void 1364 archive_entry_unset_size(struct archive_entry *entry) 1365 { 1366 archive_entry_set_size(entry, 0); 1367 entry->ae_set &= ~AE_SET_SIZE; 1368 } 1369 1370 void 1371 archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path) 1372 { 1373 archive_mstring_copy_mbs(&entry->ae_sourcepath, path); 1374 } 1375 1376 void 1377 archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path) 1378 { 1379 archive_mstring_copy_wcs(&entry->ae_sourcepath, path); 1380 } 1381 1382 void 1383 archive_entry_set_symlink(struct archive_entry *entry, const char *linkname) 1384 { 1385 if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK)) 1386 return; 1387 archive_mstring_copy_mbs(&entry->ae_linkname, linkname); 1388 entry->ae_set &= ~AE_SET_HARDLINK; 1389 if (linkname == NULL) 1390 entry->ae_set &= ~AE_SET_SYMLINK; 1391 else 1392 entry->ae_set |= AE_SET_SYMLINK; 1393 } 1394 1395 void 1396 archive_entry_set_symlink_type(struct archive_entry *entry, int type) 1397 { 1398 entry->ae_symlink_type = type; 1399 } 1400 1401 void 1402 archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname) 1403 { 1404 if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK)) 1405 return; 1406 archive_mstring_copy_utf8(&entry->ae_linkname, linkname); 1407 entry->ae_set &= ~AE_SET_HARDLINK; 1408 if (linkname == NULL) 1409 entry->ae_set &= ~AE_SET_SYMLINK; 1410 else 1411 entry->ae_set |= AE_SET_SYMLINK; 1412 } 1413 1414 void 1415 archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname) 1416 { 1417 if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK)) 1418 return; 1419 archive_mstring_copy_mbs(&entry->ae_linkname, linkname); 1420 entry->ae_set &= ~AE_SET_HARDLINK; 1421 if (linkname == NULL) 1422 entry->ae_set &= ~AE_SET_SYMLINK; 1423 else 1424 entry->ae_set |= AE_SET_SYMLINK; 1425 } 1426 1427 void 1428 archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname) 1429 { 1430 if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK)) 1431 return; 1432 archive_mstring_copy_wcs(&entry->ae_linkname, linkname); 1433 entry->ae_set &= ~AE_SET_HARDLINK; 1434 if (linkname == NULL) 1435 entry->ae_set &= ~AE_SET_SYMLINK; 1436 else 1437 entry->ae_set |= AE_SET_SYMLINK; 1438 } 1439 1440 int 1441 archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname) 1442 { 1443 if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK)) 1444 return (0); 1445 entry->ae_set &= ~AE_SET_HARDLINK; 1446 if (linkname == NULL) 1447 entry->ae_set &= ~AE_SET_SYMLINK; 1448 else 1449 entry->ae_set |= AE_SET_SYMLINK; 1450 if (archive_mstring_update_utf8(entry->archive, 1451 &entry->ae_linkname, linkname) == 0) 1452 return (1); 1453 if (errno == ENOMEM) 1454 __archive_errx(1, "No memory"); 1455 return (0); 1456 } 1457 1458 int 1459 _archive_entry_copy_symlink_l(struct archive_entry *entry, 1460 const char *linkname, size_t len, struct archive_string_conv *sc) 1461 { 1462 int r; 1463 1464 if (linkname == NULL && (entry->ae_set & AE_SET_HARDLINK)) 1465 return (0); 1466 entry->ae_set &= ~AE_SET_HARDLINK; 1467 r = archive_mstring_copy_mbs_len_l(&entry->ae_linkname, 1468 linkname, len, sc); 1469 if (linkname == NULL || r != 0) 1470 entry->ae_set &= ~AE_SET_SYMLINK; 1471 else 1472 entry->ae_set |= AE_SET_SYMLINK; 1473 return (r); 1474 } 1475 1476 void 1477 archive_entry_set_uid(struct archive_entry *entry, la_int64_t u) 1478 { 1479 if (u < 0) { 1480 u = 0; 1481 } 1482 entry->stat_valid = 0; 1483 entry->ae_stat.aest_uid = u; 1484 entry->ae_set |= AE_SET_UID; 1485 } 1486 1487 void 1488 archive_entry_set_uname(struct archive_entry *entry, const char *name) 1489 { 1490 archive_mstring_copy_mbs(&entry->ae_uname, name); 1491 } 1492 1493 void 1494 archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name) 1495 { 1496 archive_mstring_copy_utf8(&entry->ae_uname, name); 1497 } 1498 1499 void 1500 archive_entry_copy_uname(struct archive_entry *entry, const char *name) 1501 { 1502 archive_mstring_copy_mbs(&entry->ae_uname, name); 1503 } 1504 1505 void 1506 archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name) 1507 { 1508 archive_mstring_copy_wcs(&entry->ae_uname, name); 1509 } 1510 1511 int 1512 archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name) 1513 { 1514 if (archive_mstring_update_utf8(entry->archive, 1515 &entry->ae_uname, name) == 0) 1516 return (1); 1517 if (errno == ENOMEM) 1518 __archive_errx(1, "No memory"); 1519 return (0); 1520 } 1521 1522 void 1523 archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted) 1524 { 1525 if (is_encrypted) { 1526 entry->encryption |= AE_ENCRYPTION_DATA; 1527 } else { 1528 entry->encryption &= ~AE_ENCRYPTION_DATA; 1529 } 1530 } 1531 1532 void 1533 archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted) 1534 { 1535 if (is_encrypted) { 1536 entry->encryption |= AE_ENCRYPTION_METADATA; 1537 } else { 1538 entry->encryption &= ~AE_ENCRYPTION_METADATA; 1539 } 1540 } 1541 1542 int 1543 _archive_entry_copy_uname_l(struct archive_entry *entry, 1544 const char *name, size_t len, struct archive_string_conv *sc) 1545 { 1546 return (archive_mstring_copy_mbs_len_l(&entry->ae_uname, 1547 name, len, sc)); 1548 } 1549 1550 const void * 1551 archive_entry_mac_metadata(struct archive_entry *entry, size_t *s) 1552 { 1553 *s = entry->mac_metadata_size; 1554 return entry->mac_metadata; 1555 } 1556 1557 void 1558 archive_entry_copy_mac_metadata(struct archive_entry *entry, 1559 const void *p, size_t s) 1560 { 1561 free(entry->mac_metadata); 1562 if (p == NULL || s == 0) { 1563 entry->mac_metadata = NULL; 1564 entry->mac_metadata_size = 0; 1565 } else { 1566 entry->mac_metadata_size = s; 1567 entry->mac_metadata = malloc(s); 1568 if (entry->mac_metadata == NULL) 1569 abort(); 1570 memcpy(entry->mac_metadata, p, s); 1571 } 1572 } 1573 1574 /* Digest handling */ 1575 const unsigned char * 1576 archive_entry_digest(struct archive_entry *entry, int type) 1577 { 1578 switch (type) { 1579 case ARCHIVE_ENTRY_DIGEST_MD5: 1580 return entry->digest.md5; 1581 case ARCHIVE_ENTRY_DIGEST_RMD160: 1582 return entry->digest.rmd160; 1583 case ARCHIVE_ENTRY_DIGEST_SHA1: 1584 return entry->digest.sha1; 1585 case ARCHIVE_ENTRY_DIGEST_SHA256: 1586 return entry->digest.sha256; 1587 case ARCHIVE_ENTRY_DIGEST_SHA384: 1588 return entry->digest.sha384; 1589 case ARCHIVE_ENTRY_DIGEST_SHA512: 1590 return entry->digest.sha512; 1591 default: 1592 return NULL; 1593 } 1594 } 1595 1596 int 1597 archive_entry_set_digest(struct archive_entry *entry, int type, 1598 const unsigned char *digest) 1599 { 1600 #define copy_digest(_e, _t, _d)\ 1601 memcpy(_e->digest._t, _d, sizeof(_e->digest._t)) 1602 1603 switch (type) { 1604 case ARCHIVE_ENTRY_DIGEST_MD5: 1605 copy_digest(entry, md5, digest); 1606 break; 1607 case ARCHIVE_ENTRY_DIGEST_RMD160: 1608 copy_digest(entry, rmd160, digest); 1609 break; 1610 case ARCHIVE_ENTRY_DIGEST_SHA1: 1611 copy_digest(entry, sha1, digest); 1612 break; 1613 case ARCHIVE_ENTRY_DIGEST_SHA256: 1614 copy_digest(entry, sha256, digest); 1615 break; 1616 case ARCHIVE_ENTRY_DIGEST_SHA384: 1617 copy_digest(entry, sha384, digest); 1618 break; 1619 case ARCHIVE_ENTRY_DIGEST_SHA512: 1620 copy_digest(entry, sha512, digest); 1621 break; 1622 default: 1623 return ARCHIVE_WARN; 1624 } 1625 1626 return ARCHIVE_OK; 1627 #undef copy_digest 1628 } 1629 1630 /* 1631 * ACL management. The following would, of course, be a lot simpler 1632 * if: 1) the last draft of POSIX.1e were a really thorough and 1633 * complete standard that addressed the needs of ACL archiving and 2) 1634 * everyone followed it faithfully. Alas, neither is true, so the 1635 * following is a lot more complex than might seem necessary to the 1636 * uninitiated. 1637 */ 1638 1639 struct archive_acl * 1640 archive_entry_acl(struct archive_entry *entry) 1641 { 1642 return &entry->acl; 1643 } 1644 1645 void 1646 archive_entry_acl_clear(struct archive_entry *entry) 1647 { 1648 archive_acl_clear(&entry->acl); 1649 } 1650 1651 /* 1652 * Add a single ACL entry to the internal list of ACL data. 1653 */ 1654 int 1655 archive_entry_acl_add_entry(struct archive_entry *entry, 1656 int type, int permset, int tag, int id, const char *name) 1657 { 1658 return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name); 1659 } 1660 1661 /* 1662 * As above, but with a wide-character name. 1663 */ 1664 int 1665 archive_entry_acl_add_entry_w(struct archive_entry *entry, 1666 int type, int permset, int tag, int id, const wchar_t *name) 1667 { 1668 return archive_acl_add_entry_w_len(&entry->acl, 1669 type, permset, tag, id, name, wcslen(name)); 1670 } 1671 1672 /* 1673 * Return a bitmask of ACL types in an archive entry ACL list 1674 */ 1675 int 1676 archive_entry_acl_types(struct archive_entry *entry) 1677 { 1678 return (archive_acl_types(&entry->acl)); 1679 } 1680 1681 /* 1682 * Return a count of entries matching "want_type". 1683 */ 1684 int 1685 archive_entry_acl_count(struct archive_entry *entry, int want_type) 1686 { 1687 return archive_acl_count(&entry->acl, want_type); 1688 } 1689 1690 /* 1691 * Prepare for reading entries from the ACL data. Returns a count 1692 * of entries matching "want_type", or zero if there are no 1693 * non-extended ACL entries of that type. 1694 */ 1695 int 1696 archive_entry_acl_reset(struct archive_entry *entry, int want_type) 1697 { 1698 return archive_acl_reset(&entry->acl, want_type); 1699 } 1700 1701 /* 1702 * Return the next ACL entry in the list. Fake entries for the 1703 * standard permissions and include them in the returned list. 1704 */ 1705 int 1706 archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, 1707 int *permset, int *tag, int *id, const char **name) 1708 { 1709 int r; 1710 r = archive_acl_next(entry->archive, &entry->acl, want_type, type, 1711 permset, tag, id, name); 1712 if (r == ARCHIVE_FATAL && errno == ENOMEM) 1713 __archive_errx(1, "No memory"); 1714 return (r); 1715 } 1716 1717 /* 1718 * Generate a text version of the ACL. The flags parameter controls 1719 * the style of the generated ACL. 1720 */ 1721 wchar_t * 1722 archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len, 1723 int flags) 1724 { 1725 return (archive_acl_to_text_w(&entry->acl, len, flags, 1726 entry->archive)); 1727 } 1728 1729 char * 1730 archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len, 1731 int flags) 1732 { 1733 return (archive_acl_to_text_l(&entry->acl, len, flags, NULL)); 1734 } 1735 1736 char * 1737 _archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len, 1738 int flags, struct archive_string_conv *sc) 1739 { 1740 return (archive_acl_to_text_l(&entry->acl, len, flags, sc)); 1741 } 1742 1743 /* 1744 * ACL text parser. 1745 */ 1746 int 1747 archive_entry_acl_from_text_w(struct archive_entry *entry, 1748 const wchar_t *wtext, int type) 1749 { 1750 return (archive_acl_from_text_w(&entry->acl, wtext, type)); 1751 } 1752 1753 int 1754 archive_entry_acl_from_text(struct archive_entry *entry, 1755 const char *text, int type) 1756 { 1757 return (archive_acl_from_text_l(&entry->acl, text, type, NULL)); 1758 } 1759 1760 int 1761 _archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text, 1762 int type, struct archive_string_conv *sc) 1763 { 1764 return (archive_acl_from_text_l(&entry->acl, text, type, sc)); 1765 } 1766 1767 /* Deprecated */ 1768 static int 1769 archive_entry_acl_text_compat(int *flags) 1770 { 1771 if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0) 1772 return (1); 1773 1774 /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */ 1775 if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) 1776 *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID; 1777 1778 /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */ 1779 if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) 1780 *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; 1781 1782 *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA; 1783 1784 return (0); 1785 } 1786 1787 /* Deprecated */ 1788 const wchar_t * 1789 archive_entry_acl_text_w(struct archive_entry *entry, int flags) 1790 { 1791 free(entry->acl.acl_text_w); 1792 entry->acl.acl_text_w = NULL; 1793 if (archive_entry_acl_text_compat(&flags) == 0) 1794 entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl, 1795 NULL, flags, entry->archive); 1796 return (entry->acl.acl_text_w); 1797 } 1798 1799 /* Deprecated */ 1800 const char * 1801 archive_entry_acl_text(struct archive_entry *entry, int flags) 1802 { 1803 free(entry->acl.acl_text); 1804 entry->acl.acl_text = NULL; 1805 if (archive_entry_acl_text_compat(&flags) == 0) 1806 entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL, 1807 flags, NULL); 1808 1809 return (entry->acl.acl_text); 1810 } 1811 1812 /* Deprecated */ 1813 int 1814 _archive_entry_acl_text_l(struct archive_entry *entry, int flags, 1815 const char **acl_text, size_t *len, struct archive_string_conv *sc) 1816 { 1817 free(entry->acl.acl_text); 1818 entry->acl.acl_text = NULL; 1819 1820 if (archive_entry_acl_text_compat(&flags) == 0) 1821 entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, 1822 (ssize_t *)len, flags, sc); 1823 1824 *acl_text = entry->acl.acl_text; 1825 1826 return (0); 1827 } 1828 1829 /* 1830 * Following code is modified from UC Berkeley sources, and 1831 * is subject to the following copyright notice. 1832 */ 1833 1834 /*- 1835 * Copyright (c) 1993 1836 * The Regents of the University of California. All rights reserved. 1837 * 1838 * Redistribution and use in source and binary forms, with or without 1839 * modification, are permitted provided that the following conditions 1840 * are met: 1841 * 1. Redistributions of source code must retain the above copyright 1842 * notice, this list of conditions and the following disclaimer. 1843 * 2. Redistributions in binary form must reproduce the above copyright 1844 * notice, this list of conditions and the following disclaimer in the 1845 * documentation and/or other materials provided with the distribution. 1846 * 3. Neither the name of the University nor the names of its contributors 1847 * may be used to endorse or promote products derived from this software 1848 * without specific prior written permission. 1849 * 1850 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1851 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1852 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1853 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1854 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1855 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1856 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1857 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1858 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1859 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1860 * SUCH DAMAGE. 1861 */ 1862 1863 /* 1864 * Supported file flags on FreeBSD and Mac OS: 1865 * sappnd,sappend SF_APPEND 1866 * arch,archived SF_ARCHIVED 1867 * schg,schange,simmutable SF_IMMUTABLE 1868 * sunlnk,sunlink SF_NOUNLINK (FreeBSD only) 1869 * uappnd,uappend UF_APPEND 1870 * compressed UF_COMPRESSED (Mac OS only) 1871 * hidden,uhidden UF_HIDDEN 1872 * uchg,uchange,uimmutable UF_IMMUTABLE 1873 * nodump UF_NODUMP 1874 * uunlnk,uunlink UF_NOUNLINK (FreeBSD only) 1875 * offline,uoffline UF_OFFLINE (FreeBSD only) 1876 * opaque UF_OPAQUE 1877 * rdonly,urdonly,readonly UF_READONLY (FreeBSD only) 1878 * reparse,ureparse UF_REPARSE (FreeBSD only) 1879 * sparse,usparse UF_SPARSE (FreeBSD only) 1880 * system,usystem UF_SYSTEM (FreeBSD only) 1881 * 1882 * See chflags(2) for more information 1883 * 1884 * Supported file attributes on Linux: 1885 * a append only FS_APPEND_FL sappnd 1886 * A no atime updates FS_NOATIME_FL atime 1887 * c compress FS_COMPR_FL compress 1888 * C no copy on write FS_NOCOW_FL cow 1889 * d no dump FS_NODUMP_FL dump 1890 * D synchronous directory updates FS_DIRSYNC_FL dirsync 1891 * i immutable FS_IMMUTABLE_FL schg 1892 * j data journalling FS_JOURNAL_DATA_FL journal 1893 * P project hierarchy FS_PROJINHERIT_FL projinherit 1894 * s secure deletion FS_SECRM_FL securedeletion 1895 * S synchronous updates FS_SYNC_FL sync 1896 * t no tail-merging FS_NOTAIL_FL tail 1897 * T top of directory hierarchy FS_TOPDIR_FL topdir 1898 * u undeletable FS_UNRM_FL undel 1899 * 1900 * See ioctl_iflags(2) for more information 1901 * 1902 * Equivalent file flags supported on FreeBSD / Mac OS and Linux: 1903 * SF_APPEND FS_APPEND_FL sappnd 1904 * SF_IMMUTABLE FS_IMMUTABLE_FL schg 1905 * UF_NODUMP FS_NODUMP_FL nodump 1906 */ 1907 1908 static const struct flag { 1909 const char *name; 1910 const wchar_t *wname; 1911 unsigned long set; 1912 unsigned long clear; 1913 } fileflags[] = { 1914 /* Preferred (shorter) names per flag first, all prefixed by "no" */ 1915 #ifdef SF_APPEND 1916 { "nosappnd", L"nosappnd", SF_APPEND, 0}, 1917 { "nosappend", L"nosappend", SF_APPEND, 0}, 1918 #endif 1919 #if defined(FS_APPEND_FL) /* 'a' */ 1920 { "nosappnd", L"nosappnd", FS_APPEND_FL, 0}, 1921 { "nosappend", L"nosappend", FS_APPEND_FL, 0}, 1922 #elif defined(EXT2_APPEND_FL) /* 'a' */ 1923 { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0}, 1924 { "nosappend", L"nosappend", EXT2_APPEND_FL, 0}, 1925 #endif 1926 #ifdef SF_ARCHIVED 1927 { "noarch", L"noarch", SF_ARCHIVED, 0}, 1928 { "noarchived", L"noarchived", SF_ARCHIVED, 0}, 1929 #endif 1930 #ifdef SF_IMMUTABLE 1931 { "noschg", L"noschg", SF_IMMUTABLE, 0}, 1932 { "noschange", L"noschange", SF_IMMUTABLE, 0}, 1933 { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0}, 1934 #endif 1935 #if defined(FS_IMMUTABLE_FL) /* 'i' */ 1936 { "noschg", L"noschg", FS_IMMUTABLE_FL, 0}, 1937 { "noschange", L"noschange", FS_IMMUTABLE_FL, 0}, 1938 { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0}, 1939 #elif defined(EXT2_IMMUTABLE_FL) /* 'i' */ 1940 { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0}, 1941 { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0}, 1942 { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0}, 1943 #endif 1944 #ifdef SF_NOUNLINK 1945 { "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0}, 1946 { "nosunlink", L"nosunlink", SF_NOUNLINK, 0}, 1947 #endif 1948 #ifdef UF_APPEND 1949 { "nouappnd", L"nouappnd", UF_APPEND, 0}, 1950 { "nouappend", L"nouappend", UF_APPEND, 0}, 1951 #endif 1952 #ifdef UF_IMMUTABLE 1953 { "nouchg", L"nouchg", UF_IMMUTABLE, 0}, 1954 { "nouchange", L"nouchange", UF_IMMUTABLE, 0}, 1955 { "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0}, 1956 #endif 1957 #ifdef UF_NODUMP 1958 { "nodump", L"nodump", 0, UF_NODUMP}, 1959 #endif 1960 #if defined(FS_NODUMP_FL) /* 'd' */ 1961 { "nodump", L"nodump", 0, FS_NODUMP_FL}, 1962 #elif defined(EXT2_NODUMP_FL) 1963 { "nodump", L"nodump", 0, EXT2_NODUMP_FL}, 1964 #endif 1965 #ifdef UF_OPAQUE 1966 { "noopaque", L"noopaque", UF_OPAQUE, 0}, 1967 #endif 1968 #ifdef UF_NOUNLINK 1969 { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0}, 1970 { "nouunlink", L"nouunlink", UF_NOUNLINK, 0}, 1971 #endif 1972 #ifdef UF_COMPRESSED 1973 /* Mac OS */ 1974 { "nocompressed", L"nocompressed", UF_COMPRESSED, 0}, 1975 #endif 1976 #ifdef UF_HIDDEN 1977 { "nohidden", L"nohidden", UF_HIDDEN, 0}, 1978 { "nouhidden", L"nouhidden", UF_HIDDEN, 0}, 1979 #endif 1980 #ifdef FILE_ATTRIBUTE_HIDDEN 1981 { "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0}, 1982 { "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0}, 1983 #endif 1984 #ifdef UF_OFFLINE 1985 { "nooffline", L"nooffline", UF_OFFLINE, 0}, 1986 { "nouoffline", L"nouoffline", UF_OFFLINE, 0}, 1987 #endif 1988 #ifdef UF_READONLY 1989 { "nordonly", L"nordonly", UF_READONLY, 0}, 1990 { "nourdonly", L"nourdonly", UF_READONLY, 0}, 1991 { "noreadonly", L"noreadonly", UF_READONLY, 0}, 1992 #endif 1993 #ifdef FILE_ATTRIBUTE_READONLY 1994 { "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0}, 1995 { "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0}, 1996 { "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0}, 1997 #endif 1998 #ifdef UF_SPARSE 1999 { "nosparse", L"nosparse", UF_SPARSE, 0}, 2000 { "nousparse", L"nousparse", UF_SPARSE, 0}, 2001 #endif 2002 #ifdef UF_REPARSE 2003 { "noreparse", L"noreparse", UF_REPARSE, 0}, 2004 { "noureparse", L"noureparse", UF_REPARSE, 0}, 2005 #endif 2006 #ifdef UF_SYSTEM 2007 { "nosystem", L"nosystem", UF_SYSTEM, 0}, 2008 { "nousystem", L"nousystem", UF_SYSTEM, 0}, 2009 #endif 2010 #ifdef FILE_ATTRIBUTE_SYSTEM 2011 { "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0}, 2012 { "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0}, 2013 #endif 2014 #if defined(FS_UNRM_FL) /* 'u' */ 2015 { "noundel", L"noundel", FS_UNRM_FL, 0}, 2016 #elif defined(EXT2_UNRM_FL) 2017 { "noundel", L"noundel", EXT2_UNRM_FL, 0}, 2018 #endif 2019 2020 #if defined(FS_COMPR_FL) /* 'c' */ 2021 { "nocompress", L"nocompress", FS_COMPR_FL, 0}, 2022 #elif defined(EXT2_COMPR_FL) 2023 { "nocompress", L"nocompress", EXT2_COMPR_FL, 0}, 2024 #endif 2025 2026 #if defined(FS_NOATIME_FL) /* 'A' */ 2027 { "noatime", L"noatime", 0, FS_NOATIME_FL}, 2028 #elif defined(EXT2_NOATIME_FL) 2029 { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, 2030 #endif 2031 #if defined(FS_DIRSYNC_FL) /* 'D' */ 2032 { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0}, 2033 #elif defined(EXT2_DIRSYNC_FL) 2034 { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0}, 2035 #endif 2036 #if defined(FS_JOURNAL_DATA_FL) /* 'j' */ 2037 { "nojournal-data",L"nojournal-data", FS_JOURNAL_DATA_FL, 0}, 2038 { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0}, 2039 #elif defined(EXT3_JOURNAL_DATA_FL) 2040 { "nojournal-data",L"nojournal-data", EXT3_JOURNAL_DATA_FL, 0}, 2041 { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0}, 2042 #endif 2043 #if defined(FS_SECRM_FL) /* 's' */ 2044 { "nosecdel", L"nosecdel", FS_SECRM_FL, 0}, 2045 { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0}, 2046 #elif defined(EXT2_SECRM_FL) 2047 { "nosecdel", L"nosecdel", EXT2_SECRM_FL, 0}, 2048 { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0}, 2049 #endif 2050 #if defined(FS_SYNC_FL) /* 'S' */ 2051 { "nosync", L"nosync", FS_SYNC_FL, 0}, 2052 #elif defined(EXT2_SYNC_FL) 2053 { "nosync", L"nosync", EXT2_SYNC_FL, 0}, 2054 #endif 2055 #if defined(FS_NOTAIL_FL) /* 't' */ 2056 { "notail", L"notail", 0, FS_NOTAIL_FL}, 2057 #elif defined(EXT2_NOTAIL_FL) 2058 { "notail", L"notail", 0, EXT2_NOTAIL_FL}, 2059 #endif 2060 #if defined(FS_TOPDIR_FL) /* 'T' */ 2061 { "notopdir", L"notopdir", FS_TOPDIR_FL, 0}, 2062 #elif defined(EXT2_TOPDIR_FL) 2063 { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0}, 2064 #endif 2065 #ifdef FS_NOCOW_FL /* 'C' */ 2066 { "nocow", L"nocow", 0, FS_NOCOW_FL}, 2067 #endif 2068 #ifdef FS_PROJINHERIT_FL /* 'P' */ 2069 { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0}, 2070 #endif 2071 { NULL, NULL, 0, 0} 2072 }; 2073 2074 /* 2075 * fflagstostr -- 2076 * Convert file flags to a comma-separated string. If no flags 2077 * are set, return the empty string. 2078 */ 2079 static char * 2080 ae_fflagstostr(unsigned long bitset, unsigned long bitclear) 2081 { 2082 char *string, *dp; 2083 const char *sp; 2084 unsigned long bits; 2085 const struct flag *flag; 2086 size_t length; 2087 2088 bits = bitset | bitclear; 2089 length = 0; 2090 for (flag = fileflags; flag->name != NULL; flag++) 2091 if (bits & (flag->set | flag->clear)) { 2092 length += strlen(flag->name) + 1; 2093 bits &= ~(flag->set | flag->clear); 2094 } 2095 2096 if (length == 0) 2097 return (NULL); 2098 string = malloc(length); 2099 if (string == NULL) 2100 return (NULL); 2101 2102 dp = string; 2103 for (flag = fileflags; flag->name != NULL; flag++) { 2104 if (bitset & flag->set || bitclear & flag->clear) { 2105 sp = flag->name + 2; 2106 } else if (bitset & flag->clear || bitclear & flag->set) { 2107 sp = flag->name; 2108 } else 2109 continue; 2110 bitset &= ~(flag->set | flag->clear); 2111 bitclear &= ~(flag->set | flag->clear); 2112 if (dp > string) 2113 *dp++ = ','; 2114 while ((*dp++ = *sp++) != '\0') 2115 ; 2116 dp--; 2117 } 2118 2119 *dp = '\0'; 2120 return (string); 2121 } 2122 2123 /* 2124 * strtofflags -- 2125 * Take string of arguments and return file flags. This 2126 * version works a little differently than strtofflags(3). 2127 * In particular, it always tests every token, skipping any 2128 * unrecognized tokens. It returns a pointer to the first 2129 * unrecognized token, or NULL if every token was recognized. 2130 * This version is also const-correct and does not modify the 2131 * provided string. 2132 */ 2133 static const char * 2134 ae_strtofflags(const char *s, size_t l, unsigned long *setp, unsigned long *clrp) 2135 { 2136 const char *start, *end; 2137 const struct flag *flag; 2138 unsigned long set, clear; 2139 const char *failed; 2140 2141 set = clear = 0; 2142 start = s; 2143 failed = NULL; 2144 /* Find start of first token. */ 2145 while (l > 0 && (*start == '\t' || *start == ' ' || *start == ',')) { 2146 start++; 2147 l--; 2148 } 2149 while (l > 0) { 2150 size_t length; 2151 /* Locate end of token. */ 2152 end = start; 2153 while (l > 0 && *end != '\t' && 2154 *end != ' ' && *end != ',') { 2155 end++; 2156 l--; 2157 } 2158 length = end - start; 2159 for (flag = fileflags; flag->name != NULL; flag++) { 2160 size_t flag_length = strlen(flag->name); 2161 if (length == flag_length 2162 && memcmp(start, flag->name, length) == 0) { 2163 /* Matched "noXXXX", so reverse the sense. */ 2164 clear |= flag->set; 2165 set |= flag->clear; 2166 break; 2167 } else if (length == flag_length - 2 2168 && memcmp(start, flag->name + 2, length) == 0) { 2169 /* Matched "XXXX", so don't reverse. */ 2170 set |= flag->set; 2171 clear |= flag->clear; 2172 break; 2173 } 2174 } 2175 /* Ignore unknown flag names. */ 2176 if (flag->name == NULL && failed == NULL) 2177 failed = start; 2178 2179 /* Find start of next token. */ 2180 start = end; 2181 while (l > 0 && (*start == '\t' || *start == ' ' || *start == ',')) { 2182 start++; 2183 l--; 2184 } 2185 2186 } 2187 2188 if (setp) 2189 *setp = set; 2190 if (clrp) 2191 *clrp = clear; 2192 2193 /* Return location of first failure. */ 2194 return (failed); 2195 } 2196 2197 /* 2198 * wcstofflags -- 2199 * Take string of arguments and return file flags. This 2200 * version works a little differently than strtofflags(3). 2201 * In particular, it always tests every token, skipping any 2202 * unrecognized tokens. It returns a pointer to the first 2203 * unrecognized token, or NULL if every token was recognized. 2204 * This version is also const-correct and does not modify the 2205 * provided string. 2206 */ 2207 static const wchar_t * 2208 ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp) 2209 { 2210 const wchar_t *start, *end; 2211 const struct flag *flag; 2212 unsigned long set, clear; 2213 const wchar_t *failed; 2214 2215 set = clear = 0; 2216 start = s; 2217 failed = NULL; 2218 /* Find start of first token. */ 2219 while (*start == L'\t' || *start == L' ' || *start == L',') 2220 start++; 2221 while (*start != L'\0') { 2222 size_t length; 2223 /* Locate end of token. */ 2224 end = start; 2225 while (*end != L'\0' && *end != L'\t' && 2226 *end != L' ' && *end != L',') 2227 end++; 2228 length = end - start; 2229 for (flag = fileflags; flag->wname != NULL; flag++) { 2230 size_t flag_length = wcslen(flag->wname); 2231 if (length == flag_length 2232 && wmemcmp(start, flag->wname, length) == 0) { 2233 /* Matched "noXXXX", so reverse the sense. */ 2234 clear |= flag->set; 2235 set |= flag->clear; 2236 break; 2237 } else if (length == flag_length - 2 2238 && wmemcmp(start, flag->wname + 2, length) == 0) { 2239 /* Matched "XXXX", so don't reverse. */ 2240 set |= flag->set; 2241 clear |= flag->clear; 2242 break; 2243 } 2244 } 2245 /* Ignore unknown flag names. */ 2246 if (flag->wname == NULL && failed == NULL) 2247 failed = start; 2248 2249 /* Find start of next token. */ 2250 start = end; 2251 while (*start == L'\t' || *start == L' ' || *start == L',') 2252 start++; 2253 2254 } 2255 2256 if (setp) 2257 *setp = set; 2258 if (clrp) 2259 *clrp = clear; 2260 2261 /* Return location of first failure. */ 2262 return (failed); 2263 } 2264 2265 2266 #ifdef TEST 2267 #include <stdio.h> 2268 int 2269 main(int argc, char **argv) 2270 { 2271 struct archive_entry *entry = archive_entry_new(); 2272 unsigned long set, clear; 2273 const wchar_t *remainder; 2274 2275 remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,"); 2276 archive_entry_fflags(entry, &set, &clear); 2277 2278 wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder); 2279 2280 wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry)); 2281 return (0); 2282 } 2283 #endif 2284