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