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