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