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$"); 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 /* Instead, our caller could have chosen a specific encoding 572 * (archive_mstring_get_mbs, archive_mstring_get_utf8, 573 * archive_mstring_get_wcs). So we should try multiple 574 * encodings. Try mbs first because of history, even though 575 * utf8 might be better for pathname portability. 576 * Also omit wcs because of type mismatch (char * versus wchar *) 577 */ 578 const char * 579 archive_entry_pathname(struct archive_entry *entry) 580 { 581 const char *p; 582 if (archive_mstring_get_mbs( 583 entry->archive, &entry->ae_pathname, &p) == 0) 584 return (p); 585 #if HAVE_EILSEQ /*{*/ 586 if (errno == EILSEQ) { 587 if (archive_mstring_get_utf8( 588 entry->archive, &entry->ae_pathname, &p) == 0) 589 return (p); 590 } 591 #endif /*}*/ 592 if (errno == ENOMEM) 593 __archive_errx(1, "No memory"); 594 return (NULL); 595 } 596 597 const char * 598 archive_entry_pathname_utf8(struct archive_entry *entry) 599 { 600 const char *p; 601 if (archive_mstring_get_utf8( 602 entry->archive, &entry->ae_pathname, &p) == 0) 603 return (p); 604 if (errno == ENOMEM) 605 __archive_errx(1, "No memory"); 606 return (NULL); 607 } 608 609 const wchar_t * 610 archive_entry_pathname_w(struct archive_entry *entry) 611 { 612 const wchar_t *p; 613 if (archive_mstring_get_wcs( 614 entry->archive, &entry->ae_pathname, &p) == 0) 615 return (p); 616 if (errno == ENOMEM) 617 __archive_errx(1, "No memory"); 618 return (NULL); 619 } 620 621 int 622 _archive_entry_pathname_l(struct archive_entry *entry, 623 const char **p, size_t *len, struct archive_string_conv *sc) 624 { 625 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_pathname, p, len, sc)); 626 } 627 628 __LA_MODE_T 629 archive_entry_perm(struct archive_entry *entry) 630 { 631 return (~AE_IFMT & entry->acl.mode); 632 } 633 634 dev_t 635 archive_entry_rdev(struct archive_entry *entry) 636 { 637 if (entry->ae_stat.aest_rdev_is_broken_down) 638 return ae_makedev(entry->ae_stat.aest_rdevmajor, 639 entry->ae_stat.aest_rdevminor); 640 else 641 return (entry->ae_stat.aest_rdev); 642 } 643 644 dev_t 645 archive_entry_rdevmajor(struct archive_entry *entry) 646 { 647 if (entry->ae_stat.aest_rdev_is_broken_down) 648 return (entry->ae_stat.aest_rdevmajor); 649 else 650 return major(entry->ae_stat.aest_rdev); 651 } 652 653 dev_t 654 archive_entry_rdevminor(struct archive_entry *entry) 655 { 656 if (entry->ae_stat.aest_rdev_is_broken_down) 657 return (entry->ae_stat.aest_rdevminor); 658 else 659 return minor(entry->ae_stat.aest_rdev); 660 } 661 662 la_int64_t 663 archive_entry_size(struct archive_entry *entry) 664 { 665 return (entry->ae_stat.aest_size); 666 } 667 668 int 669 archive_entry_size_is_set(struct archive_entry *entry) 670 { 671 return (entry->ae_set & AE_SET_SIZE); 672 } 673 674 const char * 675 archive_entry_sourcepath(struct archive_entry *entry) 676 { 677 const char *p; 678 if (archive_mstring_get_mbs( 679 entry->archive, &entry->ae_sourcepath, &p) == 0) 680 return (p); 681 if (errno == ENOMEM) 682 __archive_errx(1, "No memory"); 683 return (NULL); 684 } 685 686 const wchar_t * 687 archive_entry_sourcepath_w(struct archive_entry *entry) 688 { 689 const wchar_t *p; 690 if (archive_mstring_get_wcs( 691 entry->archive, &entry->ae_sourcepath, &p) == 0) 692 return (p); 693 return (NULL); 694 } 695 696 const char * 697 archive_entry_symlink(struct archive_entry *entry) 698 { 699 const char *p; 700 if ((entry->ae_set & AE_SET_SYMLINK) == 0) 701 return (NULL); 702 if (archive_mstring_get_mbs( 703 entry->archive, &entry->ae_symlink, &p) == 0) 704 return (p); 705 if (errno == ENOMEM) 706 __archive_errx(1, "No memory"); 707 return (NULL); 708 } 709 710 int 711 archive_entry_symlink_type(struct archive_entry *entry) 712 { 713 return (entry->ae_symlink_type); 714 } 715 716 const char * 717 archive_entry_symlink_utf8(struct archive_entry *entry) 718 { 719 const char *p; 720 if ((entry->ae_set & AE_SET_SYMLINK) == 0) 721 return (NULL); 722 if (archive_mstring_get_utf8( 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 const wchar_t * 731 archive_entry_symlink_w(struct archive_entry *entry) 732 { 733 const wchar_t *p; 734 if ((entry->ae_set & AE_SET_SYMLINK) == 0) 735 return (NULL); 736 if (archive_mstring_get_wcs( 737 entry->archive, &entry->ae_symlink, &p) == 0) 738 return (p); 739 if (errno == ENOMEM) 740 __archive_errx(1, "No memory"); 741 return (NULL); 742 } 743 744 int 745 _archive_entry_symlink_l(struct archive_entry *entry, 746 const char **p, size_t *len, struct archive_string_conv *sc) 747 { 748 if ((entry->ae_set & AE_SET_SYMLINK) == 0) { 749 *p = NULL; 750 *len = 0; 751 return (0); 752 } 753 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_symlink, p, len, sc)); 754 } 755 756 la_int64_t 757 archive_entry_uid(struct archive_entry *entry) 758 { 759 return (entry->ae_stat.aest_uid); 760 } 761 762 const char * 763 archive_entry_uname(struct archive_entry *entry) 764 { 765 const char *p; 766 if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) 767 return (p); 768 if (errno == ENOMEM) 769 __archive_errx(1, "No memory"); 770 return (NULL); 771 } 772 773 const char * 774 archive_entry_uname_utf8(struct archive_entry *entry) 775 { 776 const char *p; 777 if (archive_mstring_get_utf8(entry->archive, &entry->ae_uname, &p) == 0) 778 return (p); 779 if (errno == ENOMEM) 780 __archive_errx(1, "No memory"); 781 return (NULL); 782 } 783 784 const wchar_t * 785 archive_entry_uname_w(struct archive_entry *entry) 786 { 787 const wchar_t *p; 788 if (archive_mstring_get_wcs(entry->archive, &entry->ae_uname, &p) == 0) 789 return (p); 790 if (errno == ENOMEM) 791 __archive_errx(1, "No memory"); 792 return (NULL); 793 } 794 795 int 796 _archive_entry_uname_l(struct archive_entry *entry, 797 const char **p, size_t *len, struct archive_string_conv *sc) 798 { 799 return (archive_mstring_get_mbs_l(entry->archive, &entry->ae_uname, p, len, sc)); 800 } 801 802 int 803 archive_entry_is_data_encrypted(struct archive_entry *entry) 804 { 805 return ((entry->encryption & AE_ENCRYPTION_DATA) == AE_ENCRYPTION_DATA); 806 } 807 808 int 809 archive_entry_is_metadata_encrypted(struct archive_entry *entry) 810 { 811 return ((entry->encryption & AE_ENCRYPTION_METADATA) == AE_ENCRYPTION_METADATA); 812 } 813 814 int 815 archive_entry_is_encrypted(struct archive_entry *entry) 816 { 817 return (entry->encryption & (AE_ENCRYPTION_DATA|AE_ENCRYPTION_METADATA)); 818 } 819 820 /* 821 * Functions to set archive_entry properties. 822 */ 823 824 void 825 archive_entry_set_filetype(struct archive_entry *entry, unsigned int type) 826 { 827 entry->stat_valid = 0; 828 entry->acl.mode &= ~AE_IFMT; 829 entry->acl.mode |= AE_IFMT & type; 830 } 831 832 void 833 archive_entry_set_fflags(struct archive_entry *entry, 834 unsigned long set, unsigned long clear) 835 { 836 archive_mstring_clean(&entry->ae_fflags_text); 837 entry->ae_fflags_set = set; 838 entry->ae_fflags_clear = clear; 839 } 840 841 const char * 842 archive_entry_copy_fflags_text(struct archive_entry *entry, 843 const char *flags) 844 { 845 archive_mstring_copy_mbs(&entry->ae_fflags_text, flags); 846 return (ae_strtofflags(flags, 847 &entry->ae_fflags_set, &entry->ae_fflags_clear)); 848 } 849 850 const wchar_t * 851 archive_entry_copy_fflags_text_w(struct archive_entry *entry, 852 const wchar_t *flags) 853 { 854 archive_mstring_copy_wcs(&entry->ae_fflags_text, flags); 855 return (ae_wcstofflags(flags, 856 &entry->ae_fflags_set, &entry->ae_fflags_clear)); 857 } 858 859 void 860 archive_entry_set_gid(struct archive_entry *entry, la_int64_t g) 861 { 862 entry->stat_valid = 0; 863 entry->ae_stat.aest_gid = g; 864 } 865 866 void 867 archive_entry_set_gname(struct archive_entry *entry, const char *name) 868 { 869 archive_mstring_copy_mbs(&entry->ae_gname, name); 870 } 871 872 void 873 archive_entry_set_gname_utf8(struct archive_entry *entry, const char *name) 874 { 875 archive_mstring_copy_utf8(&entry->ae_gname, name); 876 } 877 878 void 879 archive_entry_copy_gname(struct archive_entry *entry, const char *name) 880 { 881 archive_mstring_copy_mbs(&entry->ae_gname, name); 882 } 883 884 void 885 archive_entry_copy_gname_w(struct archive_entry *entry, const wchar_t *name) 886 { 887 archive_mstring_copy_wcs(&entry->ae_gname, name); 888 } 889 890 int 891 archive_entry_update_gname_utf8(struct archive_entry *entry, const char *name) 892 { 893 if (archive_mstring_update_utf8(entry->archive, 894 &entry->ae_gname, name) == 0) 895 return (1); 896 if (errno == ENOMEM) 897 __archive_errx(1, "No memory"); 898 return (0); 899 } 900 901 int 902 _archive_entry_copy_gname_l(struct archive_entry *entry, 903 const char *name, size_t len, struct archive_string_conv *sc) 904 { 905 return (archive_mstring_copy_mbs_len_l(&entry->ae_gname, name, len, sc)); 906 } 907 908 void 909 archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino) 910 { 911 entry->stat_valid = 0; 912 entry->ae_set |= AE_SET_INO; 913 entry->ae_stat.aest_ino = ino; 914 } 915 916 void 917 archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino) 918 { 919 entry->stat_valid = 0; 920 entry->ae_set |= AE_SET_INO; 921 entry->ae_stat.aest_ino = ino; 922 } 923 924 void 925 archive_entry_set_hardlink(struct archive_entry *entry, const char *target) 926 { 927 archive_mstring_copy_mbs(&entry->ae_hardlink, target); 928 if (target != NULL) 929 entry->ae_set |= AE_SET_HARDLINK; 930 else 931 entry->ae_set &= ~AE_SET_HARDLINK; 932 } 933 934 void 935 archive_entry_set_hardlink_utf8(struct archive_entry *entry, const char *target) 936 { 937 archive_mstring_copy_utf8(&entry->ae_hardlink, target); 938 if (target != NULL) 939 entry->ae_set |= AE_SET_HARDLINK; 940 else 941 entry->ae_set &= ~AE_SET_HARDLINK; 942 } 943 944 void 945 archive_entry_copy_hardlink(struct archive_entry *entry, const char *target) 946 { 947 archive_mstring_copy_mbs(&entry->ae_hardlink, target); 948 if (target != NULL) 949 entry->ae_set |= AE_SET_HARDLINK; 950 else 951 entry->ae_set &= ~AE_SET_HARDLINK; 952 } 953 954 void 955 archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target) 956 { 957 archive_mstring_copy_wcs(&entry->ae_hardlink, target); 958 if (target != NULL) 959 entry->ae_set |= AE_SET_HARDLINK; 960 else 961 entry->ae_set &= ~AE_SET_HARDLINK; 962 } 963 964 int 965 archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target) 966 { 967 if (target != NULL) 968 entry->ae_set |= AE_SET_HARDLINK; 969 else 970 entry->ae_set &= ~AE_SET_HARDLINK; 971 if (archive_mstring_update_utf8(entry->archive, 972 &entry->ae_hardlink, target) == 0) 973 return (1); 974 if (errno == ENOMEM) 975 __archive_errx(1, "No memory"); 976 return (0); 977 } 978 979 int 980 _archive_entry_copy_hardlink_l(struct archive_entry *entry, 981 const char *target, size_t len, struct archive_string_conv *sc) 982 { 983 int r; 984 985 r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, 986 target, len, sc); 987 if (target != NULL && r == 0) 988 entry->ae_set |= AE_SET_HARDLINK; 989 else 990 entry->ae_set &= ~AE_SET_HARDLINK; 991 return (r); 992 } 993 994 void 995 archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) 996 { 997 FIX_NS(t, ns); 998 entry->stat_valid = 0; 999 entry->ae_set |= AE_SET_ATIME; 1000 entry->ae_stat.aest_atime = t; 1001 entry->ae_stat.aest_atime_nsec = ns; 1002 } 1003 1004 void 1005 archive_entry_unset_atime(struct archive_entry *entry) 1006 { 1007 archive_entry_set_atime(entry, 0, 0); 1008 entry->ae_set &= ~AE_SET_ATIME; 1009 } 1010 1011 void 1012 archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns) 1013 { 1014 FIX_NS(t, ns); 1015 entry->stat_valid = 0; 1016 entry->ae_set |= AE_SET_BIRTHTIME; 1017 entry->ae_stat.aest_birthtime = t; 1018 entry->ae_stat.aest_birthtime_nsec = ns; 1019 } 1020 1021 void 1022 archive_entry_unset_birthtime(struct archive_entry *entry) 1023 { 1024 archive_entry_set_birthtime(entry, 0, 0); 1025 entry->ae_set &= ~AE_SET_BIRTHTIME; 1026 } 1027 1028 void 1029 archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns) 1030 { 1031 FIX_NS(t, ns); 1032 entry->stat_valid = 0; 1033 entry->ae_set |= AE_SET_CTIME; 1034 entry->ae_stat.aest_ctime = t; 1035 entry->ae_stat.aest_ctime_nsec = ns; 1036 } 1037 1038 void 1039 archive_entry_unset_ctime(struct archive_entry *entry) 1040 { 1041 archive_entry_set_ctime(entry, 0, 0); 1042 entry->ae_set &= ~AE_SET_CTIME; 1043 } 1044 1045 void 1046 archive_entry_set_dev(struct archive_entry *entry, dev_t d) 1047 { 1048 entry->stat_valid = 0; 1049 entry->ae_set |= AE_SET_DEV; 1050 entry->ae_stat.aest_dev_is_broken_down = 0; 1051 entry->ae_stat.aest_dev = d; 1052 } 1053 1054 void 1055 archive_entry_set_devmajor(struct archive_entry *entry, dev_t m) 1056 { 1057 entry->stat_valid = 0; 1058 entry->ae_set |= AE_SET_DEV; 1059 entry->ae_stat.aest_dev_is_broken_down = 1; 1060 entry->ae_stat.aest_devmajor = m; 1061 } 1062 1063 void 1064 archive_entry_set_devminor(struct archive_entry *entry, dev_t m) 1065 { 1066 entry->stat_valid = 0; 1067 entry->ae_set |= AE_SET_DEV; 1068 entry->ae_stat.aest_dev_is_broken_down = 1; 1069 entry->ae_stat.aest_devminor = m; 1070 } 1071 1072 /* Set symlink if symlink is already set, else set hardlink. */ 1073 void 1074 archive_entry_set_link(struct archive_entry *entry, const char *target) 1075 { 1076 if (entry->ae_set & AE_SET_SYMLINK) 1077 archive_mstring_copy_mbs(&entry->ae_symlink, target); 1078 else 1079 archive_mstring_copy_mbs(&entry->ae_hardlink, target); 1080 } 1081 1082 void 1083 archive_entry_set_link_utf8(struct archive_entry *entry, const char *target) 1084 { 1085 if (entry->ae_set & AE_SET_SYMLINK) 1086 archive_mstring_copy_utf8(&entry->ae_symlink, target); 1087 else 1088 archive_mstring_copy_utf8(&entry->ae_hardlink, target); 1089 } 1090 1091 /* Set symlink if symlink is already set, else set hardlink. */ 1092 void 1093 archive_entry_copy_link(struct archive_entry *entry, const char *target) 1094 { 1095 if (entry->ae_set & AE_SET_SYMLINK) 1096 archive_mstring_copy_mbs(&entry->ae_symlink, target); 1097 else 1098 archive_mstring_copy_mbs(&entry->ae_hardlink, target); 1099 } 1100 1101 /* Set symlink if symlink is already set, else set hardlink. */ 1102 void 1103 archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target) 1104 { 1105 if (entry->ae_set & AE_SET_SYMLINK) 1106 archive_mstring_copy_wcs(&entry->ae_symlink, target); 1107 else 1108 archive_mstring_copy_wcs(&entry->ae_hardlink, target); 1109 } 1110 1111 int 1112 archive_entry_update_link_utf8(struct archive_entry *entry, const char *target) 1113 { 1114 int r; 1115 if (entry->ae_set & AE_SET_SYMLINK) 1116 r = archive_mstring_update_utf8(entry->archive, 1117 &entry->ae_symlink, target); 1118 else 1119 r = archive_mstring_update_utf8(entry->archive, 1120 &entry->ae_hardlink, target); 1121 if (r == 0) 1122 return (1); 1123 if (errno == ENOMEM) 1124 __archive_errx(1, "No memory"); 1125 return (0); 1126 } 1127 1128 int 1129 _archive_entry_copy_link_l(struct archive_entry *entry, 1130 const char *target, size_t len, struct archive_string_conv *sc) 1131 { 1132 int r; 1133 1134 if (entry->ae_set & AE_SET_SYMLINK) 1135 r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, 1136 target, len, sc); 1137 else 1138 r = archive_mstring_copy_mbs_len_l(&entry->ae_hardlink, 1139 target, len, sc); 1140 return (r); 1141 } 1142 1143 void 1144 archive_entry_set_mode(struct archive_entry *entry, mode_t m) 1145 { 1146 entry->stat_valid = 0; 1147 entry->acl.mode = m; 1148 } 1149 1150 void 1151 archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns) 1152 { 1153 FIX_NS(t, ns); 1154 entry->stat_valid = 0; 1155 entry->ae_set |= AE_SET_MTIME; 1156 entry->ae_stat.aest_mtime = t; 1157 entry->ae_stat.aest_mtime_nsec = ns; 1158 } 1159 1160 void 1161 archive_entry_unset_mtime(struct archive_entry *entry) 1162 { 1163 archive_entry_set_mtime(entry, 0, 0); 1164 entry->ae_set &= ~AE_SET_MTIME; 1165 } 1166 1167 void 1168 archive_entry_set_nlink(struct archive_entry *entry, unsigned int nlink) 1169 { 1170 entry->stat_valid = 0; 1171 entry->ae_stat.aest_nlink = nlink; 1172 } 1173 1174 void 1175 archive_entry_set_pathname(struct archive_entry *entry, const char *name) 1176 { 1177 archive_mstring_copy_mbs(&entry->ae_pathname, name); 1178 } 1179 1180 void 1181 archive_entry_set_pathname_utf8(struct archive_entry *entry, const char *name) 1182 { 1183 archive_mstring_copy_utf8(&entry->ae_pathname, name); 1184 } 1185 1186 void 1187 archive_entry_copy_pathname(struct archive_entry *entry, const char *name) 1188 { 1189 archive_mstring_copy_mbs(&entry->ae_pathname, name); 1190 } 1191 1192 void 1193 archive_entry_copy_pathname_w(struct archive_entry *entry, const wchar_t *name) 1194 { 1195 archive_mstring_copy_wcs(&entry->ae_pathname, name); 1196 } 1197 1198 int 1199 archive_entry_update_pathname_utf8(struct archive_entry *entry, const char *name) 1200 { 1201 if (archive_mstring_update_utf8(entry->archive, 1202 &entry->ae_pathname, name) == 0) 1203 return (1); 1204 if (errno == ENOMEM) 1205 __archive_errx(1, "No memory"); 1206 return (0); 1207 } 1208 1209 int 1210 _archive_entry_copy_pathname_l(struct archive_entry *entry, 1211 const char *name, size_t len, struct archive_string_conv *sc) 1212 { 1213 return (archive_mstring_copy_mbs_len_l(&entry->ae_pathname, 1214 name, len, sc)); 1215 } 1216 1217 void 1218 archive_entry_set_perm(struct archive_entry *entry, mode_t p) 1219 { 1220 entry->stat_valid = 0; 1221 entry->acl.mode &= AE_IFMT; 1222 entry->acl.mode |= ~AE_IFMT & p; 1223 } 1224 1225 void 1226 archive_entry_set_rdev(struct archive_entry *entry, dev_t m) 1227 { 1228 entry->stat_valid = 0; 1229 entry->ae_stat.aest_rdev = m; 1230 entry->ae_stat.aest_rdev_is_broken_down = 0; 1231 } 1232 1233 void 1234 archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m) 1235 { 1236 entry->stat_valid = 0; 1237 entry->ae_stat.aest_rdev_is_broken_down = 1; 1238 entry->ae_stat.aest_rdevmajor = m; 1239 } 1240 1241 void 1242 archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m) 1243 { 1244 entry->stat_valid = 0; 1245 entry->ae_stat.aest_rdev_is_broken_down = 1; 1246 entry->ae_stat.aest_rdevminor = m; 1247 } 1248 1249 void 1250 archive_entry_set_size(struct archive_entry *entry, la_int64_t s) 1251 { 1252 entry->stat_valid = 0; 1253 entry->ae_stat.aest_size = s; 1254 entry->ae_set |= AE_SET_SIZE; 1255 } 1256 1257 void 1258 archive_entry_unset_size(struct archive_entry *entry) 1259 { 1260 archive_entry_set_size(entry, 0); 1261 entry->ae_set &= ~AE_SET_SIZE; 1262 } 1263 1264 void 1265 archive_entry_copy_sourcepath(struct archive_entry *entry, const char *path) 1266 { 1267 archive_mstring_copy_mbs(&entry->ae_sourcepath, path); 1268 } 1269 1270 void 1271 archive_entry_copy_sourcepath_w(struct archive_entry *entry, const wchar_t *path) 1272 { 1273 archive_mstring_copy_wcs(&entry->ae_sourcepath, path); 1274 } 1275 1276 void 1277 archive_entry_set_symlink(struct archive_entry *entry, const char *linkname) 1278 { 1279 archive_mstring_copy_mbs(&entry->ae_symlink, linkname); 1280 if (linkname != NULL) 1281 entry->ae_set |= AE_SET_SYMLINK; 1282 else 1283 entry->ae_set &= ~AE_SET_SYMLINK; 1284 } 1285 1286 void 1287 archive_entry_set_symlink_type(struct archive_entry *entry, int type) 1288 { 1289 entry->ae_symlink_type = type; 1290 } 1291 1292 void 1293 archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname) 1294 { 1295 archive_mstring_copy_utf8(&entry->ae_symlink, linkname); 1296 if (linkname != NULL) 1297 entry->ae_set |= AE_SET_SYMLINK; 1298 else 1299 entry->ae_set &= ~AE_SET_SYMLINK; 1300 } 1301 1302 void 1303 archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname) 1304 { 1305 archive_mstring_copy_mbs(&entry->ae_symlink, linkname); 1306 if (linkname != NULL) 1307 entry->ae_set |= AE_SET_SYMLINK; 1308 else 1309 entry->ae_set &= ~AE_SET_SYMLINK; 1310 } 1311 1312 void 1313 archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linkname) 1314 { 1315 archive_mstring_copy_wcs(&entry->ae_symlink, linkname); 1316 if (linkname != NULL) 1317 entry->ae_set |= AE_SET_SYMLINK; 1318 else 1319 entry->ae_set &= ~AE_SET_SYMLINK; 1320 } 1321 1322 int 1323 archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname) 1324 { 1325 if (linkname != NULL) 1326 entry->ae_set |= AE_SET_SYMLINK; 1327 else 1328 entry->ae_set &= ~AE_SET_SYMLINK; 1329 if (archive_mstring_update_utf8(entry->archive, 1330 &entry->ae_symlink, linkname) == 0) 1331 return (1); 1332 if (errno == ENOMEM) 1333 __archive_errx(1, "No memory"); 1334 return (0); 1335 } 1336 1337 int 1338 _archive_entry_copy_symlink_l(struct archive_entry *entry, 1339 const char *linkname, size_t len, struct archive_string_conv *sc) 1340 { 1341 int r; 1342 1343 r = archive_mstring_copy_mbs_len_l(&entry->ae_symlink, 1344 linkname, len, sc); 1345 if (linkname != NULL && r == 0) 1346 entry->ae_set |= AE_SET_SYMLINK; 1347 else 1348 entry->ae_set &= ~AE_SET_SYMLINK; 1349 return (r); 1350 } 1351 1352 void 1353 archive_entry_set_uid(struct archive_entry *entry, la_int64_t u) 1354 { 1355 entry->stat_valid = 0; 1356 entry->ae_stat.aest_uid = u; 1357 } 1358 1359 void 1360 archive_entry_set_uname(struct archive_entry *entry, const char *name) 1361 { 1362 archive_mstring_copy_mbs(&entry->ae_uname, name); 1363 } 1364 1365 void 1366 archive_entry_set_uname_utf8(struct archive_entry *entry, const char *name) 1367 { 1368 archive_mstring_copy_utf8(&entry->ae_uname, name); 1369 } 1370 1371 void 1372 archive_entry_copy_uname(struct archive_entry *entry, const char *name) 1373 { 1374 archive_mstring_copy_mbs(&entry->ae_uname, name); 1375 } 1376 1377 void 1378 archive_entry_copy_uname_w(struct archive_entry *entry, const wchar_t *name) 1379 { 1380 archive_mstring_copy_wcs(&entry->ae_uname, name); 1381 } 1382 1383 int 1384 archive_entry_update_uname_utf8(struct archive_entry *entry, const char *name) 1385 { 1386 if (archive_mstring_update_utf8(entry->archive, 1387 &entry->ae_uname, name) == 0) 1388 return (1); 1389 if (errno == ENOMEM) 1390 __archive_errx(1, "No memory"); 1391 return (0); 1392 } 1393 1394 void 1395 archive_entry_set_is_data_encrypted(struct archive_entry *entry, char is_encrypted) 1396 { 1397 if (is_encrypted) { 1398 entry->encryption |= AE_ENCRYPTION_DATA; 1399 } else { 1400 entry->encryption &= ~AE_ENCRYPTION_DATA; 1401 } 1402 } 1403 1404 void 1405 archive_entry_set_is_metadata_encrypted(struct archive_entry *entry, char is_encrypted) 1406 { 1407 if (is_encrypted) { 1408 entry->encryption |= AE_ENCRYPTION_METADATA; 1409 } else { 1410 entry->encryption &= ~AE_ENCRYPTION_METADATA; 1411 } 1412 } 1413 1414 int 1415 _archive_entry_copy_uname_l(struct archive_entry *entry, 1416 const char *name, size_t len, struct archive_string_conv *sc) 1417 { 1418 return (archive_mstring_copy_mbs_len_l(&entry->ae_uname, 1419 name, len, sc)); 1420 } 1421 1422 const void * 1423 archive_entry_mac_metadata(struct archive_entry *entry, size_t *s) 1424 { 1425 *s = entry->mac_metadata_size; 1426 return entry->mac_metadata; 1427 } 1428 1429 void 1430 archive_entry_copy_mac_metadata(struct archive_entry *entry, 1431 const void *p, size_t s) 1432 { 1433 free(entry->mac_metadata); 1434 if (p == NULL || s == 0) { 1435 entry->mac_metadata = NULL; 1436 entry->mac_metadata_size = 0; 1437 } else { 1438 entry->mac_metadata_size = s; 1439 entry->mac_metadata = malloc(s); 1440 if (entry->mac_metadata == NULL) 1441 abort(); 1442 memcpy(entry->mac_metadata, p, s); 1443 } 1444 } 1445 1446 /* Digest handling */ 1447 const unsigned char * 1448 archive_entry_digest(struct archive_entry *entry, int type) 1449 { 1450 switch (type) { 1451 case ARCHIVE_ENTRY_DIGEST_MD5: 1452 return entry->digest.md5; 1453 case ARCHIVE_ENTRY_DIGEST_RMD160: 1454 return entry->digest.rmd160; 1455 case ARCHIVE_ENTRY_DIGEST_SHA1: 1456 return entry->digest.sha1; 1457 case ARCHIVE_ENTRY_DIGEST_SHA256: 1458 return entry->digest.sha256; 1459 case ARCHIVE_ENTRY_DIGEST_SHA384: 1460 return entry->digest.sha384; 1461 case ARCHIVE_ENTRY_DIGEST_SHA512: 1462 return entry->digest.sha512; 1463 default: 1464 return NULL; 1465 } 1466 } 1467 1468 int 1469 archive_entry_set_digest(struct archive_entry *entry, int type, 1470 const unsigned char *digest) 1471 { 1472 #define copy_digest(_e, _t, _d)\ 1473 memcpy(_e->digest._t, _d, sizeof(_e->digest._t)) 1474 1475 switch (type) { 1476 case ARCHIVE_ENTRY_DIGEST_MD5: 1477 copy_digest(entry, md5, digest); 1478 break; 1479 case ARCHIVE_ENTRY_DIGEST_RMD160: 1480 copy_digest(entry, rmd160, digest); 1481 break; 1482 case ARCHIVE_ENTRY_DIGEST_SHA1: 1483 copy_digest(entry, sha1, digest); 1484 break; 1485 case ARCHIVE_ENTRY_DIGEST_SHA256: 1486 copy_digest(entry, sha256, digest); 1487 break; 1488 case ARCHIVE_ENTRY_DIGEST_SHA384: 1489 copy_digest(entry, sha384, digest); 1490 break; 1491 case ARCHIVE_ENTRY_DIGEST_SHA512: 1492 copy_digest(entry, sha512, digest); 1493 break; 1494 default: 1495 return ARCHIVE_WARN; 1496 } 1497 1498 return ARCHIVE_OK; 1499 #undef copy_digest 1500 } 1501 1502 /* 1503 * ACL management. The following would, of course, be a lot simpler 1504 * if: 1) the last draft of POSIX.1e were a really thorough and 1505 * complete standard that addressed the needs of ACL archiving and 2) 1506 * everyone followed it faithfully. Alas, neither is true, so the 1507 * following is a lot more complex than might seem necessary to the 1508 * uninitiated. 1509 */ 1510 1511 struct archive_acl * 1512 archive_entry_acl(struct archive_entry *entry) 1513 { 1514 return &entry->acl; 1515 } 1516 1517 void 1518 archive_entry_acl_clear(struct archive_entry *entry) 1519 { 1520 archive_acl_clear(&entry->acl); 1521 } 1522 1523 /* 1524 * Add a single ACL entry to the internal list of ACL data. 1525 */ 1526 int 1527 archive_entry_acl_add_entry(struct archive_entry *entry, 1528 int type, int permset, int tag, int id, const char *name) 1529 { 1530 return archive_acl_add_entry(&entry->acl, type, permset, tag, id, name); 1531 } 1532 1533 /* 1534 * As above, but with a wide-character name. 1535 */ 1536 int 1537 archive_entry_acl_add_entry_w(struct archive_entry *entry, 1538 int type, int permset, int tag, int id, const wchar_t *name) 1539 { 1540 return archive_acl_add_entry_w_len(&entry->acl, 1541 type, permset, tag, id, name, wcslen(name)); 1542 } 1543 1544 /* 1545 * Return a bitmask of ACL types in an archive entry ACL list 1546 */ 1547 int 1548 archive_entry_acl_types(struct archive_entry *entry) 1549 { 1550 return (archive_acl_types(&entry->acl)); 1551 } 1552 1553 /* 1554 * Return a count of entries matching "want_type". 1555 */ 1556 int 1557 archive_entry_acl_count(struct archive_entry *entry, int want_type) 1558 { 1559 return archive_acl_count(&entry->acl, want_type); 1560 } 1561 1562 /* 1563 * Prepare for reading entries from the ACL data. Returns a count 1564 * of entries matching "want_type", or zero if there are no 1565 * non-extended ACL entries of that type. 1566 */ 1567 int 1568 archive_entry_acl_reset(struct archive_entry *entry, int want_type) 1569 { 1570 return archive_acl_reset(&entry->acl, want_type); 1571 } 1572 1573 /* 1574 * Return the next ACL entry in the list. Fake entries for the 1575 * standard permissions and include them in the returned list. 1576 */ 1577 int 1578 archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type, 1579 int *permset, int *tag, int *id, const char **name) 1580 { 1581 int r; 1582 r = archive_acl_next(entry->archive, &entry->acl, want_type, type, 1583 permset, tag, id, name); 1584 if (r == ARCHIVE_FATAL && errno == ENOMEM) 1585 __archive_errx(1, "No memory"); 1586 return (r); 1587 } 1588 1589 /* 1590 * Generate a text version of the ACL. The flags parameter controls 1591 * the style of the generated ACL. 1592 */ 1593 wchar_t * 1594 archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len, 1595 int flags) 1596 { 1597 return (archive_acl_to_text_w(&entry->acl, len, flags, 1598 entry->archive)); 1599 } 1600 1601 char * 1602 archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len, 1603 int flags) 1604 { 1605 return (archive_acl_to_text_l(&entry->acl, len, flags, NULL)); 1606 } 1607 1608 char * 1609 _archive_entry_acl_to_text_l(struct archive_entry *entry, ssize_t *len, 1610 int flags, struct archive_string_conv *sc) 1611 { 1612 return (archive_acl_to_text_l(&entry->acl, len, flags, sc)); 1613 } 1614 1615 /* 1616 * ACL text parser. 1617 */ 1618 int 1619 archive_entry_acl_from_text_w(struct archive_entry *entry, 1620 const wchar_t *wtext, int type) 1621 { 1622 return (archive_acl_from_text_w(&entry->acl, wtext, type)); 1623 } 1624 1625 int 1626 archive_entry_acl_from_text(struct archive_entry *entry, 1627 const char *text, int type) 1628 { 1629 return (archive_acl_from_text_l(&entry->acl, text, type, NULL)); 1630 } 1631 1632 int 1633 _archive_entry_acl_from_text_l(struct archive_entry *entry, const char *text, 1634 int type, struct archive_string_conv *sc) 1635 { 1636 return (archive_acl_from_text_l(&entry->acl, text, type, sc)); 1637 } 1638 1639 /* Deprecated */ 1640 static int 1641 archive_entry_acl_text_compat(int *flags) 1642 { 1643 if ((*flags & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) == 0) 1644 return (1); 1645 1646 /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID */ 1647 if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID) != 0) 1648 *flags |= ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID; 1649 1650 /* ABI compat with old ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT */ 1651 if ((*flags & OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT) != 0) 1652 *flags |= ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT; 1653 1654 *flags |= ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA; 1655 1656 return (0); 1657 } 1658 1659 /* Deprecated */ 1660 const wchar_t * 1661 archive_entry_acl_text_w(struct archive_entry *entry, int flags) 1662 { 1663 free(entry->acl.acl_text_w); 1664 entry->acl.acl_text_w = NULL; 1665 if (archive_entry_acl_text_compat(&flags) == 0) 1666 entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl, 1667 NULL, flags, entry->archive); 1668 return (entry->acl.acl_text_w); 1669 } 1670 1671 /* Deprecated */ 1672 const char * 1673 archive_entry_acl_text(struct archive_entry *entry, int flags) 1674 { 1675 free(entry->acl.acl_text); 1676 entry->acl.acl_text = NULL; 1677 if (archive_entry_acl_text_compat(&flags) == 0) 1678 entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL, 1679 flags, NULL); 1680 1681 return (entry->acl.acl_text); 1682 } 1683 1684 /* Deprecated */ 1685 int 1686 _archive_entry_acl_text_l(struct archive_entry *entry, int flags, 1687 const char **acl_text, size_t *len, struct archive_string_conv *sc) 1688 { 1689 free(entry->acl.acl_text); 1690 entry->acl.acl_text = NULL; 1691 1692 if (archive_entry_acl_text_compat(&flags) == 0) 1693 entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, 1694 (ssize_t *)len, flags, sc); 1695 1696 *acl_text = entry->acl.acl_text; 1697 1698 return (0); 1699 } 1700 1701 /* 1702 * Following code is modified from UC Berkeley sources, and 1703 * is subject to the following copyright notice. 1704 */ 1705 1706 /*- 1707 * Copyright (c) 1993 1708 * The Regents of the University of California. All rights reserved. 1709 * 1710 * Redistribution and use in source and binary forms, with or without 1711 * modification, are permitted provided that the following conditions 1712 * are met: 1713 * 1. Redistributions of source code must retain the above copyright 1714 * notice, this list of conditions and the following disclaimer. 1715 * 2. Redistributions in binary form must reproduce the above copyright 1716 * notice, this list of conditions and the following disclaimer in the 1717 * documentation and/or other materials provided with the distribution. 1718 * 3. Neither the name of the University nor the names of its contributors 1719 * may be used to endorse or promote products derived from this software 1720 * without specific prior written permission. 1721 * 1722 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1723 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1724 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1725 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1726 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1727 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1728 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1729 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1730 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1731 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1732 * SUCH DAMAGE. 1733 */ 1734 1735 /* 1736 * Supported file flags on FreeBSD and Mac OS: 1737 * sappnd,sappend SF_APPEND 1738 * arch,archived SF_ARCHIVED 1739 * schg,schange,simmutable SF_IMMUTABLE 1740 * sunlnk,sunlink SF_NOUNLINK (FreeBSD only) 1741 * uappnd,uappend UF_APPEND 1742 * compressed UF_COMPRESSED (Mac OS only) 1743 * hidden,uhidden UF_HIDDEN 1744 * uchg,uchange,uimmutable UF_IMMUTABLE 1745 * nodump UF_NODUMP 1746 * uunlnk,uunlink UF_NOUNLINK (FreeBSD only) 1747 * offline,uoffline UF_OFFLINE (FreeBSD only) 1748 * opaque UF_OPAQUE 1749 * rdonly,urdonly,readonly UF_READONLY (FreeBSD only) 1750 * reparse,ureparse UF_REPARSE (FreeBSD only) 1751 * sparse,usparse UF_SPARSE (FreeBSD only) 1752 * system,usystem UF_SYSTEM (FreeBSD only) 1753 * 1754 * See chflags(2) for more information 1755 * 1756 * Supported file attributes on Linux: 1757 * a append only FS_APPEND_FL sappnd 1758 * A no atime updates FS_NOATIME_FL atime 1759 * c compress FS_COMPR_FL compress 1760 * C no copy on write FS_NOCOW_FL cow 1761 * d no dump FS_NODUMP_FL dump 1762 * D synchronous directory updates FS_DIRSYNC_FL dirsync 1763 * i immutable FS_IMMUTABLE_FL schg 1764 * j data journalling FS_JOURNAL_DATA_FL journal 1765 * P project hierarchy FS_PROJINHERIT_FL projinherit 1766 * s secure deletion FS_SECRM_FL securedeletion 1767 * S synchronous updates FS_SYNC_FL sync 1768 * t no tail-merging FS_NOTAIL_FL tail 1769 * T top of directory hierarchy FS_TOPDIR_FL topdir 1770 * u undeletable FS_UNRM_FL undel 1771 * 1772 * See ioctl_iflags(2) for more information 1773 * 1774 * Equivalent file flags supported on FreeBSD / Mac OS and Linux: 1775 * SF_APPEND FS_APPEND_FL sappnd 1776 * SF_IMMUTABLE FS_IMMUTABLE_FL schg 1777 * UF_NODUMP FS_NODUMP_FL nodump 1778 */ 1779 1780 static const struct flag { 1781 const char *name; 1782 const wchar_t *wname; 1783 unsigned long set; 1784 unsigned long clear; 1785 } fileflags[] = { 1786 /* Preferred (shorter) names per flag first, all prefixed by "no" */ 1787 #ifdef SF_APPEND 1788 { "nosappnd", L"nosappnd", SF_APPEND, 0}, 1789 { "nosappend", L"nosappend", SF_APPEND, 0}, 1790 #endif 1791 #if defined(FS_APPEND_FL) /* 'a' */ 1792 { "nosappnd", L"nosappnd", FS_APPEND_FL, 0}, 1793 { "nosappend", L"nosappend", FS_APPEND_FL, 0}, 1794 #elif defined(EXT2_APPEND_FL) /* 'a' */ 1795 { "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0}, 1796 { "nosappend", L"nosappend", EXT2_APPEND_FL, 0}, 1797 #endif 1798 #ifdef SF_ARCHIVED 1799 { "noarch", L"noarch", SF_ARCHIVED, 0}, 1800 { "noarchived", L"noarchived", SF_ARCHIVED, 0}, 1801 #endif 1802 #ifdef SF_IMMUTABLE 1803 { "noschg", L"noschg", SF_IMMUTABLE, 0}, 1804 { "noschange", L"noschange", SF_IMMUTABLE, 0}, 1805 { "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0}, 1806 #endif 1807 #if defined(FS_IMMUTABLE_FL) /* 'i' */ 1808 { "noschg", L"noschg", FS_IMMUTABLE_FL, 0}, 1809 { "noschange", L"noschange", FS_IMMUTABLE_FL, 0}, 1810 { "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0}, 1811 #elif defined(EXT2_IMMUTABLE_FL) /* 'i' */ 1812 { "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0}, 1813 { "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0}, 1814 { "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0}, 1815 #endif 1816 #ifdef SF_NOUNLINK 1817 { "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0}, 1818 { "nosunlink", L"nosunlink", SF_NOUNLINK, 0}, 1819 #endif 1820 #ifdef UF_APPEND 1821 { "nouappnd", L"nouappnd", UF_APPEND, 0}, 1822 { "nouappend", L"nouappend", UF_APPEND, 0}, 1823 #endif 1824 #ifdef UF_IMMUTABLE 1825 { "nouchg", L"nouchg", UF_IMMUTABLE, 0}, 1826 { "nouchange", L"nouchange", UF_IMMUTABLE, 0}, 1827 { "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0}, 1828 #endif 1829 #ifdef UF_NODUMP 1830 { "nodump", L"nodump", 0, UF_NODUMP}, 1831 #endif 1832 #if defined(FS_NODUMP_FL) /* 'd' */ 1833 { "nodump", L"nodump", 0, FS_NODUMP_FL}, 1834 #elif defined(EXT2_NODUMP_FL) 1835 { "nodump", L"nodump", 0, EXT2_NODUMP_FL}, 1836 #endif 1837 #ifdef UF_OPAQUE 1838 { "noopaque", L"noopaque", UF_OPAQUE, 0}, 1839 #endif 1840 #ifdef UF_NOUNLINK 1841 { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0}, 1842 { "nouunlink", L"nouunlink", UF_NOUNLINK, 0}, 1843 #endif 1844 #ifdef UF_COMPRESSED 1845 /* Mac OS */ 1846 { "nocompressed", L"nocompressed", UF_COMPRESSED, 0}, 1847 #endif 1848 #ifdef UF_HIDDEN 1849 { "nohidden", L"nohidden", UF_HIDDEN, 0}, 1850 { "nouhidden", L"nouhidden", UF_HIDDEN, 0}, 1851 #endif 1852 #ifdef FILE_ATTRIBUTE_HIDDEN 1853 { "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0}, 1854 { "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0}, 1855 #endif 1856 #ifdef UF_OFFLINE 1857 { "nooffline", L"nooffline", UF_OFFLINE, 0}, 1858 { "nouoffline", L"nouoffline", UF_OFFLINE, 0}, 1859 #endif 1860 #ifdef UF_READONLY 1861 { "nordonly", L"nordonly", UF_READONLY, 0}, 1862 { "nourdonly", L"nourdonly", UF_READONLY, 0}, 1863 { "noreadonly", L"noreadonly", UF_READONLY, 0}, 1864 #endif 1865 #ifdef FILE_ATTRIBUTE_READONLY 1866 { "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0}, 1867 { "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0}, 1868 { "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0}, 1869 #endif 1870 #ifdef UF_SPARSE 1871 { "nosparse", L"nosparse", UF_SPARSE, 0}, 1872 { "nousparse", L"nousparse", UF_SPARSE, 0}, 1873 #endif 1874 #ifdef UF_REPARSE 1875 { "noreparse", L"noreparse", UF_REPARSE, 0}, 1876 { "noureparse", L"noureparse", UF_REPARSE, 0}, 1877 #endif 1878 #ifdef UF_SYSTEM 1879 { "nosystem", L"nosystem", UF_SYSTEM, 0}, 1880 { "nousystem", L"nousystem", UF_SYSTEM, 0}, 1881 #endif 1882 #ifdef FILE_ATTRIBUTE_SYSTEM 1883 { "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0}, 1884 { "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0}, 1885 #endif 1886 #if defined(FS_UNRM_FL) /* 'u' */ 1887 { "noundel", L"noundel", FS_UNRM_FL, 0}, 1888 #elif defined(EXT2_UNRM_FL) 1889 { "noundel", L"noundel", EXT2_UNRM_FL, 0}, 1890 #endif 1891 1892 #if defined(FS_COMPR_FL) /* 'c' */ 1893 { "nocompress", L"nocompress", FS_COMPR_FL, 0}, 1894 #elif defined(EXT2_COMPR_FL) 1895 { "nocompress", L"nocompress", EXT2_COMPR_FL, 0}, 1896 #endif 1897 1898 #if defined(FS_NOATIME_FL) /* 'A' */ 1899 { "noatime", L"noatime", 0, FS_NOATIME_FL}, 1900 #elif defined(EXT2_NOATIME_FL) 1901 { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, 1902 #endif 1903 #if defined(FS_DIRSYNC_FL) /* 'D' */ 1904 { "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0}, 1905 #elif defined(EXT2_DIRSYNC_FL) 1906 { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0}, 1907 #endif 1908 #if defined(FS_JOURNAL_DATA_FL) /* 'j' */ 1909 { "nojournal-data",L"nojournal-data", FS_JOURNAL_DATA_FL, 0}, 1910 { "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0}, 1911 #elif defined(EXT3_JOURNAL_DATA_FL) 1912 { "nojournal-data",L"nojournal-data", EXT3_JOURNAL_DATA_FL, 0}, 1913 { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0}, 1914 #endif 1915 #if defined(FS_SECRM_FL) /* 's' */ 1916 { "nosecdel", L"nosecdel", FS_SECRM_FL, 0}, 1917 { "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0}, 1918 #elif defined(EXT2_SECRM_FL) 1919 { "nosecdel", L"nosecdel", EXT2_SECRM_FL, 0}, 1920 { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0}, 1921 #endif 1922 #if defined(FS_SYNC_FL) /* 'S' */ 1923 { "nosync", L"nosync", FS_SYNC_FL, 0}, 1924 #elif defined(EXT2_SYNC_FL) 1925 { "nosync", L"nosync", EXT2_SYNC_FL, 0}, 1926 #endif 1927 #if defined(FS_NOTAIL_FL) /* 't' */ 1928 { "notail", L"notail", 0, FS_NOTAIL_FL}, 1929 #elif defined(EXT2_NOTAIL_FL) 1930 { "notail", L"notail", 0, EXT2_NOTAIL_FL}, 1931 #endif 1932 #if defined(FS_TOPDIR_FL) /* 'T' */ 1933 { "notopdir", L"notopdir", FS_TOPDIR_FL, 0}, 1934 #elif defined(EXT2_TOPDIR_FL) 1935 { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0}, 1936 #endif 1937 #ifdef FS_NOCOW_FL /* 'C' */ 1938 { "nocow", L"nocow", 0, FS_NOCOW_FL}, 1939 #endif 1940 #ifdef FS_PROJINHERIT_FL /* 'P' */ 1941 { "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0}, 1942 #endif 1943 { NULL, NULL, 0, 0} 1944 }; 1945 1946 /* 1947 * fflagstostr -- 1948 * Convert file flags to a comma-separated string. If no flags 1949 * are set, return the empty string. 1950 */ 1951 static char * 1952 ae_fflagstostr(unsigned long bitset, unsigned long bitclear) 1953 { 1954 char *string, *dp; 1955 const char *sp; 1956 unsigned long bits; 1957 const struct flag *flag; 1958 size_t length; 1959 1960 bits = bitset | bitclear; 1961 length = 0; 1962 for (flag = fileflags; flag->name != NULL; flag++) 1963 if (bits & (flag->set | flag->clear)) { 1964 length += strlen(flag->name) + 1; 1965 bits &= ~(flag->set | flag->clear); 1966 } 1967 1968 if (length == 0) 1969 return (NULL); 1970 string = (char *)malloc(length); 1971 if (string == NULL) 1972 return (NULL); 1973 1974 dp = string; 1975 for (flag = fileflags; flag->name != NULL; flag++) { 1976 if (bitset & flag->set || bitclear & flag->clear) { 1977 sp = flag->name + 2; 1978 } else if (bitset & flag->clear || bitclear & flag->set) { 1979 sp = flag->name; 1980 } else 1981 continue; 1982 bitset &= ~(flag->set | flag->clear); 1983 bitclear &= ~(flag->set | flag->clear); 1984 if (dp > string) 1985 *dp++ = ','; 1986 while ((*dp++ = *sp++) != '\0') 1987 ; 1988 dp--; 1989 } 1990 1991 *dp = '\0'; 1992 return (string); 1993 } 1994 1995 /* 1996 * strtofflags -- 1997 * Take string of arguments and return file flags. This 1998 * version works a little differently than strtofflags(3). 1999 * In particular, it always tests every token, skipping any 2000 * unrecognized tokens. It returns a pointer to the first 2001 * unrecognized token, or NULL if every token was recognized. 2002 * This version is also const-correct and does not modify the 2003 * provided string. 2004 */ 2005 static const char * 2006 ae_strtofflags(const char *s, unsigned long *setp, unsigned long *clrp) 2007 { 2008 const char *start, *end; 2009 const struct flag *flag; 2010 unsigned long set, clear; 2011 const char *failed; 2012 2013 set = clear = 0; 2014 start = s; 2015 failed = NULL; 2016 /* Find start of first token. */ 2017 while (*start == '\t' || *start == ' ' || *start == ',') 2018 start++; 2019 while (*start != '\0') { 2020 size_t length; 2021 /* Locate end of token. */ 2022 end = start; 2023 while (*end != '\0' && *end != '\t' && 2024 *end != ' ' && *end != ',') 2025 end++; 2026 length = end - start; 2027 for (flag = fileflags; flag->name != NULL; flag++) { 2028 size_t flag_length = strlen(flag->name); 2029 if (length == flag_length 2030 && memcmp(start, flag->name, length) == 0) { 2031 /* Matched "noXXXX", so reverse the sense. */ 2032 clear |= flag->set; 2033 set |= flag->clear; 2034 break; 2035 } else if (length == flag_length - 2 2036 && memcmp(start, flag->name + 2, length) == 0) { 2037 /* Matched "XXXX", so don't reverse. */ 2038 set |= flag->set; 2039 clear |= flag->clear; 2040 break; 2041 } 2042 } 2043 /* Ignore unknown flag names. */ 2044 if (flag->name == NULL && failed == NULL) 2045 failed = start; 2046 2047 /* Find start of next token. */ 2048 start = end; 2049 while (*start == '\t' || *start == ' ' || *start == ',') 2050 start++; 2051 2052 } 2053 2054 if (setp) 2055 *setp = set; 2056 if (clrp) 2057 *clrp = clear; 2058 2059 /* Return location of first failure. */ 2060 return (failed); 2061 } 2062 2063 /* 2064 * wcstofflags -- 2065 * Take string of arguments and return file flags. This 2066 * version works a little differently than strtofflags(3). 2067 * In particular, it always tests every token, skipping any 2068 * unrecognized tokens. It returns a pointer to the first 2069 * unrecognized token, or NULL if every token was recognized. 2070 * This version is also const-correct and does not modify the 2071 * provided string. 2072 */ 2073 static const wchar_t * 2074 ae_wcstofflags(const wchar_t *s, unsigned long *setp, unsigned long *clrp) 2075 { 2076 const wchar_t *start, *end; 2077 const struct flag *flag; 2078 unsigned long set, clear; 2079 const wchar_t *failed; 2080 2081 set = clear = 0; 2082 start = s; 2083 failed = NULL; 2084 /* Find start of first token. */ 2085 while (*start == L'\t' || *start == L' ' || *start == L',') 2086 start++; 2087 while (*start != L'\0') { 2088 size_t length; 2089 /* Locate end of token. */ 2090 end = start; 2091 while (*end != L'\0' && *end != L'\t' && 2092 *end != L' ' && *end != L',') 2093 end++; 2094 length = end - start; 2095 for (flag = fileflags; flag->wname != NULL; flag++) { 2096 size_t flag_length = wcslen(flag->wname); 2097 if (length == flag_length 2098 && wmemcmp(start, flag->wname, length) == 0) { 2099 /* Matched "noXXXX", so reverse the sense. */ 2100 clear |= flag->set; 2101 set |= flag->clear; 2102 break; 2103 } else if (length == flag_length - 2 2104 && wmemcmp(start, flag->wname + 2, length) == 0) { 2105 /* Matched "XXXX", so don't reverse. */ 2106 set |= flag->set; 2107 clear |= flag->clear; 2108 break; 2109 } 2110 } 2111 /* Ignore unknown flag names. */ 2112 if (flag->wname == NULL && failed == NULL) 2113 failed = start; 2114 2115 /* Find start of next token. */ 2116 start = end; 2117 while (*start == L'\t' || *start == L' ' || *start == L',') 2118 start++; 2119 2120 } 2121 2122 if (setp) 2123 *setp = set; 2124 if (clrp) 2125 *clrp = clear; 2126 2127 /* Return location of first failure. */ 2128 return (failed); 2129 } 2130 2131 2132 #ifdef TEST 2133 #include <stdio.h> 2134 int 2135 main(int argc, char **argv) 2136 { 2137 struct archive_entry *entry = archive_entry_new(); 2138 unsigned long set, clear; 2139 const wchar_t *remainder; 2140 2141 remainder = archive_entry_copy_fflags_text_w(entry, L"nosappnd dump archive,,,,,,,"); 2142 archive_entry_fflags(entry, &set, &clear); 2143 2144 wprintf(L"set=0x%lX clear=0x%lX remainder='%ls'\n", set, clear, remainder); 2145 2146 wprintf(L"new flags='%s'\n", archive_entry_fflags_text(entry)); 2147 return (0); 2148 } 2149 #endif 2150