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