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