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