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