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