1/*- 2 * Copyright (c) 2009 Michihiro NAKAJIMA 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#include "archive_platform.h" 26__FBSDID("$FreeBSD$"); 27 28#ifdef HAVE_ERRNO_H 29#include <errno.h> 30#endif 31#ifdef HAVE_STDLIB_H 32#include <stdlib.h> 33#endif 34#if HAVE_LIBXML_XMLREADER_H 35#include <libxml/xmlreader.h> 36#elif HAVE_BSDXML_H 37#include <bsdxml.h> 38#elif HAVE_EXPAT_H 39#include <expat.h> 40#endif 41#ifdef HAVE_BZLIB_H 42#include <bzlib.h> 43#endif 44#if HAVE_LZMA_H 45#include <lzma.h> 46#elif HAVE_LZMADEC_H 47#include <lzmadec.h> 48#endif 49#ifdef HAVE_ZLIB_H 50#include <zlib.h> 51#endif 52 53#include "archive.h" 54#include "archive_endian.h" 55#include "archive_entry.h" 56#include "archive_hash.h" 57#include "archive_private.h" 58#include "archive_read_private.h" 59 60#if (!defined(HAVE_LIBXML_XMLREADER_H) && \ 61 !defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\ 62 !defined(HAVE_ZLIB_H) || \ 63 !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1) 64/* 65 * xar needs several external libraries. 66 * o libxml2 or expat --- XML parser 67 * o openssl or MD5/SHA1 hash function 68 * o zlib 69 * o bzlib2 (option) 70 * o liblzma (option) 71 */ 72int 73archive_read_support_format_xar(struct archive *_a) 74{ 75 struct archive_read *a = (struct archive_read *)_a; 76 77 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 78 "Xar not supported on this platform"); 79 return (ARCHIVE_WARN); 80} 81 82#else /* Support xar format */ 83 84//#define DEBUG 1 85//#define DEBUG_PRINT_TOC 1 86#if DEBUG_PRINT_TOC 87#define PRINT_TOC(d, outbytes) do { \ 88 unsigned char *x = (unsigned char *)(uintptr_t)d; \ 89 unsigned char c = x[outbytes-1]; \ 90 x[outbytes - 1] = 0; \ 91 fprintf(stderr, "%s", x); \ 92 fprintf(stderr, "%c", c); \ 93 x[outbytes - 1] = c; \ 94} while (0) 95#else 96#define PRINT_TOC(d, outbytes) 97#endif 98 99#define HEADER_MAGIC 0x78617221 100#define HEADER_SIZE 28 101#define HEADER_VERSION 1 102#define CKSUM_NONE 0 103#define CKSUM_SHA1 1 104#define CKSUM_MD5 2 105 106#define MD5_SIZE 16 107#define SHA1_SIZE 20 108#define MAX_SUM_SIZE 20 109 110enum enctype { 111 NONE, 112 GZIP, 113 BZIP2, 114 LZMA, 115 XZ, 116}; 117 118struct chksumval { 119 int alg; 120 size_t len; 121 unsigned char val[MAX_SUM_SIZE]; 122}; 123 124struct chksumwork { 125 int alg; 126#ifdef ARCHIVE_HAS_MD5 127 archive_md5_ctx md5ctx; 128#endif 129#ifdef ARCHIVE_HAS_SHA1 130 archive_sha1_ctx sha1ctx; 131#endif 132}; 133 134struct xattr { 135 struct xattr *next; 136 struct archive_string name; 137 uint64_t id; 138 uint64_t length; 139 uint64_t offset; 140 uint64_t size; 141 enum enctype encoding; 142 struct chksumval a_sum; 143 struct chksumval e_sum; 144 struct archive_string fstype; 145}; 146 147struct xar_file { 148 struct xar_file *next; 149 struct xar_file *hdnext; 150 struct xar_file *parent; 151 int subdirs; 152 153 unsigned int has; 154#define HAS_DATA 0x00001 155#define HAS_PATHNAME 0x00002 156#define HAS_SYMLINK 0x00004 157#define HAS_TIME 0x00008 158#define HAS_UID 0x00010 159#define HAS_GID 0x00020 160#define HAS_MODE 0x00040 161#define HAS_TYPE 0x00080 162#define HAS_DEV 0x00100 163#define HAS_DEVMAJOR 0x00200 164#define HAS_DEVMINOR 0x00400 165#define HAS_INO 0x00800 166#define HAS_FFLAGS 0x01000 167#define HAS_XATTR 0x02000 168#define HAS_ACL 0x04000 169 170 uint64_t id; 171 uint64_t length; 172 uint64_t offset; 173 uint64_t size; 174 enum enctype encoding; 175 struct chksumval a_sum; 176 struct chksumval e_sum; 177 struct archive_string pathname; 178 struct archive_string symlink; 179 time_t ctime; 180 time_t mtime; 181 time_t atime; 182 struct archive_string uname; 183 uid_t uid; 184 struct archive_string gname; 185 gid_t gid; 186 mode_t mode; 187 dev_t dev; 188 dev_t devmajor; 189 dev_t devminor; 190 int64_t ino64; 191 struct archive_string fflags_text; 192 unsigned int link; 193 unsigned int nlink; 194 struct archive_string hardlink; 195 struct xattr *xattr_list; 196}; 197 198struct hdlink { 199 struct hdlink *next; 200 201 unsigned int id; 202 int cnt; 203 struct xar_file *files; 204}; 205 206struct heap_queue { 207 struct xar_file **files; 208 int allocated; 209 int used; 210}; 211 212enum xmlstatus { 213 INIT, 214 XAR, 215 TOC, 216 TOC_CREATION_TIME, 217 TOC_CHECKSUM, 218 TOC_CHECKSUM_OFFSET, 219 TOC_CHECKSUM_SIZE, 220 TOC_FILE, 221 FILE_DATA, 222 FILE_DATA_LENGTH, 223 FILE_DATA_OFFSET, 224 FILE_DATA_SIZE, 225 FILE_DATA_ENCODING, 226 FILE_DATA_A_CHECKSUM, 227 FILE_DATA_E_CHECKSUM, 228 FILE_DATA_CONTENT, 229 FILE_EA, 230 FILE_EA_LENGTH, 231 FILE_EA_OFFSET, 232 FILE_EA_SIZE, 233 FILE_EA_ENCODING, 234 FILE_EA_A_CHECKSUM, 235 FILE_EA_E_CHECKSUM, 236 FILE_EA_NAME, 237 FILE_EA_FSTYPE, 238 FILE_CTIME, 239 FILE_MTIME, 240 FILE_ATIME, 241 FILE_GROUP, 242 FILE_GID, 243 FILE_USER, 244 FILE_UID, 245 FILE_MODE, 246 FILE_DEVICE, 247 FILE_DEVICE_MAJOR, 248 FILE_DEVICE_MINOR, 249 FILE_DEVICENO, 250 FILE_INODE, 251 FILE_LINK, 252 FILE_TYPE, 253 FILE_NAME, 254 FILE_ACL, 255 FILE_ACL_DEFAULT, 256 FILE_ACL_ACCESS, 257 FILE_ACL_APPLEEXTENDED, 258 /* BSD file flags. */ 259 FILE_FLAGS, 260 FILE_FLAGS_USER_NODUMP, 261 FILE_FLAGS_USER_IMMUTABLE, 262 FILE_FLAGS_USER_APPEND, 263 FILE_FLAGS_USER_OPAQUE, 264 FILE_FLAGS_USER_NOUNLINK, 265 FILE_FLAGS_SYS_ARCHIVED, 266 FILE_FLAGS_SYS_IMMUTABLE, 267 FILE_FLAGS_SYS_APPEND, 268 FILE_FLAGS_SYS_NOUNLINK, 269 FILE_FLAGS_SYS_SNAPSHOT, 270 /* Linux file flags. */ 271 FILE_EXT2, 272 FILE_EXT2_SecureDeletion, 273 FILE_EXT2_Undelete, 274 FILE_EXT2_Compress, 275 FILE_EXT2_Synchronous, 276 FILE_EXT2_Immutable, 277 FILE_EXT2_AppendOnly, 278 FILE_EXT2_NoDump, 279 FILE_EXT2_NoAtime, 280 FILE_EXT2_CompDirty, 281 FILE_EXT2_CompBlock, 282 FILE_EXT2_NoCompBlock, 283 FILE_EXT2_CompError, 284 FILE_EXT2_BTree, 285 FILE_EXT2_HashIndexed, 286 FILE_EXT2_iMagic, 287 FILE_EXT2_Journaled, 288 FILE_EXT2_NoTail, 289 FILE_EXT2_DirSync, 290 FILE_EXT2_TopDir, 291 FILE_EXT2_Reserved, 292 UNKNOWN, 293}; 294 295struct unknown_tag { 296 struct unknown_tag *next; 297 struct archive_string name; 298}; 299 300struct xar { 301 uint64_t offset; /* Current position in the file. */ 302 int64_t total; 303 uint64_t h_base; 304 int end_of_file; 305 unsigned char buff[1024*32]; 306 307 enum xmlstatus xmlsts; 308 enum xmlstatus xmlsts_unknown; 309 struct unknown_tag *unknowntags; 310 int base64text; 311 312 /* 313 * TOC 314 */ 315 uint64_t toc_remaining; 316 uint64_t toc_total; 317 uint64_t toc_chksum_offset; 318 uint64_t toc_chksum_size; 319 320 /* 321 * For Decoding data. 322 */ 323 enum enctype rd_encoding; 324 z_stream stream; 325 int stream_valid; 326#ifdef HAVE_BZLIB_H 327 bz_stream bzstream; 328 int bzstream_valid; 329#endif 330#if HAVE_LZMA_H && HAVE_LIBLZMA 331 lzma_stream lzstream; 332 int lzstream_valid; 333#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC 334 lzmadec_stream lzstream; 335 int lzstream_valid; 336#endif 337 /* 338 * For Checksum data. 339 */ 340 struct chksumwork a_sumwrk; 341 struct chksumwork e_sumwrk; 342 343 struct xar_file *file; /* current reading file. */ 344 struct xattr *xattr; /* current reading extended attribute. */ 345 struct heap_queue file_queue; 346 struct xar_file *hdlink_orgs; 347 struct hdlink *hdlink_list; 348 349 int entry_init; 350 uint64_t entry_total; 351 uint64_t entry_remaining; 352 uint64_t entry_size; 353 enum enctype entry_encoding; 354 struct chksumval entry_a_sum; 355 struct chksumval entry_e_sum; 356}; 357 358struct xmlattr { 359 struct xmlattr *next; 360 char *name; 361 char *value; 362}; 363 364struct xmlattr_list { 365 struct xmlattr *first; 366 struct xmlattr **last; 367}; 368 369static int xar_bid(struct archive_read *); 370static int xar_read_header(struct archive_read *, 371 struct archive_entry *); 372static int xar_read_data(struct archive_read *, 373 const void **, size_t *, off_t *); 374static int xar_read_data_skip(struct archive_read *); 375static int xar_cleanup(struct archive_read *); 376static int move_reading_point(struct archive_read *, uint64_t); 377static int rd_contents_init(struct archive_read *, 378 enum enctype, int, int); 379static int rd_contents(struct archive_read *, const void **, 380 size_t *, size_t *, uint64_t); 381static uint64_t atol10(const char *, size_t); 382static int64_t atol8(const char *, size_t); 383static size_t atohex(unsigned char *, size_t, const char *, size_t); 384static time_t parse_time(const char *p, size_t n); 385static void heap_add_entry(struct heap_queue *, struct xar_file *); 386static struct xar_file *heap_get_entry(struct heap_queue *); 387static void add_link(struct xar *, struct xar_file *); 388static void checksum_init(struct archive_read *, int, int); 389static void checksum_update(struct archive_read *, const void *, 390 size_t, const void *, size_t); 391static int checksum_final(struct archive_read *, const void *, 392 size_t, const void *, size_t); 393static int decompression_init(struct archive_read *, enum enctype); 394static int decompress(struct archive_read *, const void **, 395 size_t *, const void *, size_t *); 396static int decompression_cleanup(struct archive_read *); 397static void xmlattr_cleanup(struct xmlattr_list *); 398static void file_new(struct xar *, struct xmlattr_list *); 399static void file_free(struct xar_file *); 400static void xattr_new(struct xar *, struct xmlattr_list *); 401static void xattr_free(struct xattr *); 402static int getencoding(struct xmlattr_list *); 403static int getsumalgorithm(struct xmlattr_list *); 404static void unknowntag_start(struct xar *, const char *); 405static void unknowntag_end(struct xar *, const char *); 406static void xml_start(void *, const char *, struct xmlattr_list *); 407static void xml_end(void *, const char *); 408static void xml_data(void *, const char *, int); 409static int xml_parse_file_flags(struct xar *, const char *); 410static int xml_parse_file_ext2(struct xar *, const char *); 411#if defined(HAVE_LIBXML_XMLREADER_H) 412static int xml2_xmlattr_setup(struct xmlattr_list *, xmlTextReaderPtr); 413static int xml2_read_cb(void *, char *, int); 414static int xml2_close_cb(void *); 415static void xml2_error_hdr(void *, const char *, xmlParserSeverities, 416 xmlTextReaderLocatorPtr); 417static int xml2_read_toc(struct archive_read *); 418#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) 419static void expat_xmlattr_setup(struct xmlattr_list *, const XML_Char **); 420static void expat_start_cb(void *, const XML_Char *, const XML_Char **); 421static void expat_end_cb(void *, const XML_Char *); 422static void expat_data_cb(void *, const XML_Char *, int); 423static int expat_read_toc(struct archive_read *); 424#endif 425 426int 427archive_read_support_format_xar(struct archive *_a) 428{ 429 struct xar *xar; 430 struct archive_read *a = (struct archive_read *)_a; 431 int r; 432 433 xar = (struct xar *)calloc(1, sizeof(*xar)); 434 if (xar == NULL) { 435 archive_set_error(&a->archive, ENOMEM, 436 "Can't allocate xar data"); 437 return (ARCHIVE_FATAL); 438 } 439 440 r = __archive_read_register_format(a, 441 xar, 442 "xar", 443 xar_bid, 444 NULL, 445 xar_read_header, 446 xar_read_data, 447 xar_read_data_skip, 448 xar_cleanup); 449 if (r != ARCHIVE_OK) 450 free(xar); 451 return (r); 452} 453 454static int 455xar_bid(struct archive_read *a) 456{ 457 const unsigned char *b; 458 int bid; 459 460 b = __archive_read_ahead(a, HEADER_SIZE, NULL); 461 if (b == NULL) 462 return (-1); 463 464 bid = 0; 465 /* 466 * Verify magic code 467 */ 468 if (archive_be32dec(b) != HEADER_MAGIC) 469 return (0); 470 bid += 32; 471 /* 472 * Verify header size 473 */ 474 if (archive_be16dec(b+4) != HEADER_SIZE) 475 return (0); 476 bid += 16; 477 /* 478 * Verify header version 479 */ 480 if (archive_be16dec(b+6) != HEADER_VERSION) 481 return (0); 482 bid += 16; 483 /* 484 * Verify type of checksum 485 */ 486 switch (archive_be32dec(b+24)) { 487 case CKSUM_NONE: 488 case CKSUM_SHA1: 489 case CKSUM_MD5: 490 bid += 32; 491 break; 492 default: 493 return (0); 494 } 495 496 return (bid); 497} 498 499static int 500read_toc(struct archive_read *a) 501{ 502 struct xar *xar; 503 struct xar_file *file; 504 const unsigned char *b; 505 uint64_t toc_compressed_size; 506 uint64_t toc_uncompressed_size; 507 uint32_t toc_chksum_alg; 508 ssize_t bytes; 509 int r; 510 511 xar = (struct xar *)(a->format->data); 512 513 /* 514 * Read xar header. 515 */ 516 b = __archive_read_ahead(a, HEADER_SIZE, &bytes); 517 if (bytes < 0) 518 return ((int)bytes); 519 if (bytes < HEADER_SIZE) { 520 archive_set_error(&a->archive, 521 ARCHIVE_ERRNO_FILE_FORMAT, 522 "Truncated archive header"); 523 return (ARCHIVE_FATAL); 524 } 525 526 if (archive_be32dec(b) != HEADER_MAGIC) { 527 archive_set_error(&a->archive, 528 ARCHIVE_ERRNO_FILE_FORMAT, 529 "Invalid header magic"); 530 return (ARCHIVE_FATAL); 531 } 532 if (archive_be16dec(b+6) != HEADER_VERSION) { 533 archive_set_error(&a->archive, 534 ARCHIVE_ERRNO_FILE_FORMAT, 535 "Unsupported header version(%d)", 536 archive_be16dec(b+6)); 537 return (ARCHIVE_FATAL); 538 } 539 toc_compressed_size = archive_be64dec(b+8); 540 xar->toc_remaining = toc_compressed_size; 541 toc_uncompressed_size = archive_be64dec(b+16); 542 toc_chksum_alg = archive_be32dec(b+24); 543 __archive_read_consume(a, HEADER_SIZE); 544 xar->offset += HEADER_SIZE; 545 xar->toc_total = 0; 546 547 /* 548 * Read TOC(Table of Contents). 549 */ 550 /* Initialize reading contents. */ 551 r = move_reading_point(a, HEADER_SIZE); 552 if (r != ARCHIVE_OK) 553 return (r); 554 r = rd_contents_init(a, GZIP, toc_chksum_alg, CKSUM_NONE); 555 if (r != ARCHIVE_OK) 556 return (r); 557 558#ifdef HAVE_LIBXML_XMLREADER_H 559 r = xml2_read_toc(a); 560#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) 561 r = expat_read_toc(a); 562#endif 563 if (r != ARCHIVE_OK) 564 return (r); 565 566 /* Set 'The HEAP' base. */ 567 xar->h_base = xar->offset; 568 if (xar->toc_total != toc_uncompressed_size) { 569 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 570 "TOC uncompressed size error"); 571 return (ARCHIVE_FATAL); 572 } 573 574 /* 575 * Checksum TOC 576 */ 577 if (toc_chksum_alg != CKSUM_NONE) { 578 r = move_reading_point(a, xar->toc_chksum_offset); 579 if (r != ARCHIVE_OK) 580 return (r); 581 b = __archive_read_ahead(a, xar->toc_chksum_size, &bytes); 582 if (bytes < 0) 583 return ((int)bytes); 584 if ((uint64_t)bytes < xar->toc_chksum_size) { 585 archive_set_error(&a->archive, 586 ARCHIVE_ERRNO_FILE_FORMAT, 587 "Truncated archive file"); 588 return (ARCHIVE_FATAL); 589 } 590 r = checksum_final(a, b, xar->toc_chksum_size, NULL, 0); 591 __archive_read_consume(a, xar->toc_chksum_size); 592 xar->offset += xar->toc_chksum_size; 593 if (r != ARCHIVE_OK) 594 return (ARCHIVE_FATAL); 595 } 596 597 /* 598 * Connect hardlinked files. 599 */ 600 for (file = xar->hdlink_orgs; file != NULL; file = file->hdnext) { 601 struct hdlink **hdlink; 602 603 for (hdlink = &(xar->hdlink_list); *hdlink != NULL; 604 hdlink = &((*hdlink)->next)) { 605 if ((*hdlink)->id == file->id) { 606 struct hdlink *hltmp; 607 struct xar_file *f2; 608 int nlink = (*hdlink)->cnt + 1; 609 610 file->nlink = nlink; 611 for (f2 = (*hdlink)->files; f2 != NULL; 612 f2 = f2->hdnext) { 613 f2->nlink = nlink; 614 archive_string_copy( 615 &(f2->hardlink), &(file->pathname)); 616 } 617 /* Remove resolved files from hdlist_list. */ 618 hltmp = *hdlink; 619 *hdlink = hltmp->next; 620 free(hltmp); 621 break; 622 } 623 } 624 } 625 a->archive.archive_format = ARCHIVE_FORMAT_XAR; 626 a->archive.archive_format_name = "xar"; 627 628 return (ARCHIVE_OK); 629} 630 631static int 632xar_read_header(struct archive_read *a, struct archive_entry *entry) 633{ 634 struct xar *xar; 635 struct xar_file *file; 636 struct xattr *xattr; 637 int r; 638 639 xar = (struct xar *)(a->format->data); 640 641 if (xar->offset == 0) { 642 /* Read TOC. */ 643 r = read_toc(a); 644 if (r != ARCHIVE_OK) 645 return (r); 646 } 647 648 for (;;) { 649 file = xar->file = heap_get_entry(&(xar->file_queue)); 650 if (file == NULL) { 651 xar->end_of_file = 1; 652 return (ARCHIVE_EOF); 653 } 654 if ((file->mode & AE_IFMT) != AE_IFDIR) 655 break; 656 if (file->has != (HAS_PATHNAME | HAS_TYPE)) 657 break; 658 /* 659 * If a file type is a directory and it does not have 660 * any metadata, do not export. 661 */ 662 file_free(file); 663 } 664 archive_entry_set_atime(entry, file->atime, 0); 665 archive_entry_set_ctime(entry, file->ctime, 0); 666 archive_entry_set_mtime(entry, file->mtime, 0); 667 archive_entry_set_gid(entry, file->gid); 668 if (file->gname.length > 0) 669 archive_entry_update_gname_utf8(entry, file->gname.s); 670 archive_entry_set_uid(entry, file->uid); 671 if (file->uname.length > 0) 672 archive_entry_update_uname_utf8(entry, file->uname.s); 673 archive_entry_set_mode(entry, file->mode); 674 archive_entry_update_pathname_utf8(entry, file->pathname.s); 675 if (file->symlink.length > 0) 676 archive_entry_update_symlink_utf8(entry, file->symlink.s); 677 /* Set proper nlink. */ 678 if ((file->mode & AE_IFMT) == AE_IFDIR) 679 archive_entry_set_nlink(entry, file->subdirs + 2); 680 else 681 archive_entry_set_nlink(entry, file->nlink); 682 archive_entry_set_size(entry, file->size); 683 if (archive_strlen(&(file->hardlink)) > 0) 684 archive_entry_update_hardlink_utf8(entry, 685 file->hardlink.s); 686 archive_entry_set_ino64(entry, file->ino64); 687 if (file->has & HAS_DEV) 688 archive_entry_set_dev(entry, file->dev); 689 if (file->has & HAS_DEVMAJOR) 690 archive_entry_set_devmajor(entry, file->devmajor); 691 if (file->has & HAS_DEVMINOR) 692 archive_entry_set_devminor(entry, file->devminor); 693 if (archive_strlen(&(file->fflags_text)) > 0) 694 archive_entry_copy_fflags_text(entry, file->fflags_text.s); 695 696 xar->entry_init = 1; 697 xar->entry_total = 0; 698 xar->entry_remaining = file->length; 699 xar->entry_size = file->size; 700 xar->entry_encoding = file->encoding; 701 xar->entry_a_sum = file->a_sum; 702 xar->entry_e_sum = file->e_sum; 703 /* 704 * Read extended attributes. 705 */ 706 r = ARCHIVE_OK; 707 xattr = file->xattr_list; 708 while (xattr != NULL) { 709 const void *d; 710 size_t outbytes, used; 711 712 r = move_reading_point(a, xattr->offset); 713 if (r != ARCHIVE_OK) 714 break; 715 r = rd_contents_init(a, xattr->encoding, 716 xattr->a_sum.alg, xattr->e_sum.alg); 717 if (r != ARCHIVE_OK) 718 break; 719 d = NULL; 720 r = rd_contents(a, &d, &outbytes, &used, xattr->length); 721 if (r != ARCHIVE_OK) 722 break; 723 if (outbytes != xattr->size) { 724 archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, 725 "Decompressed size error"); 726 r = ARCHIVE_FATAL; 727 break; 728 } 729 r = checksum_final(a, 730 xattr->a_sum.val, xattr->a_sum.len, 731 xattr->e_sum.val, xattr->e_sum.len); 732 if (r != ARCHIVE_OK) 733 break; 734 archive_entry_xattr_add_entry(entry, 735 xattr->name.s, d, outbytes); 736 xattr = xattr->next; 737 } 738 if (r != ARCHIVE_OK) { 739 file_free(file); 740 return (r); 741 } 742 743 if (xar->entry_remaining > 0) 744 /* Move reading point to the beginning of current 745 * file contents. */ 746 r = move_reading_point(a, file->offset); 747 else 748 r = ARCHIVE_OK; 749 750 file_free(file); 751 return (r); 752} 753 754static int 755xar_read_data(struct archive_read *a, 756 const void **buff, size_t *size, off_t *offset) 757{ 758 struct xar *xar; 759 size_t used; 760 int r; 761 762 xar = (struct xar *)(a->format->data); 763 if (xar->end_of_file || xar->entry_remaining <= 0) { 764 r = ARCHIVE_EOF; 765 goto abort_read_data; 766 } 767 768 if (xar->entry_init) { 769 r = rd_contents_init(a, xar->entry_encoding, 770 xar->entry_a_sum.alg, xar->entry_e_sum.alg); 771 if (r != ARCHIVE_OK) { 772 xar->entry_remaining = 0; 773 return (r); 774 } 775 xar->entry_init = 0; 776 } 777 778 *buff = NULL; 779 r = rd_contents(a, buff, size, &used, xar->entry_remaining); 780 if (r != ARCHIVE_OK) 781 goto abort_read_data; 782 783 *offset = xar->entry_total; 784 xar->entry_total += *size; 785 xar->total += *size; 786 xar->offset += used; 787 xar->entry_remaining -= used; 788 __archive_read_consume(a, used); 789 790 if (xar->entry_remaining == 0) { 791 if (xar->entry_total != xar->entry_size) { 792 archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, 793 "Decompressed size error"); 794 r = ARCHIVE_FATAL; 795 goto abort_read_data; 796 } 797 r = checksum_final(a, 798 xar->entry_a_sum.val, xar->entry_a_sum.len, 799 xar->entry_e_sum.val, xar->entry_e_sum.len); 800 if (r != ARCHIVE_OK) 801 goto abort_read_data; 802 } 803 804 return (ARCHIVE_OK); 805abort_read_data: 806 *buff = NULL; 807 *size = 0; 808 *offset = xar->total; 809 return (r); 810} 811 812static int 813xar_read_data_skip(struct archive_read *a) 814{ 815 struct xar *xar; 816 int64_t bytes_skipped; 817 818 xar = (struct xar *)(a->format->data); 819 if (xar->end_of_file) 820 return (ARCHIVE_EOF); 821 bytes_skipped = __archive_read_skip(a, xar->entry_remaining); 822 if (bytes_skipped < 0) 823 return (ARCHIVE_FATAL); 824 xar->offset += bytes_skipped; 825 return (ARCHIVE_OK); 826} 827 828static int 829xar_cleanup(struct archive_read *a) 830{ 831 struct xar *xar; 832 struct hdlink *hdlink; 833 int i; 834 int r; 835 836 xar = (struct xar *)(a->format->data); 837 r = decompression_cleanup(a); 838 hdlink = xar->hdlink_list; 839 while (hdlink != NULL) { 840 struct hdlink *next = hdlink->next; 841 842 free(hdlink); 843 hdlink = next; 844 } 845 for (i = 0; i < xar->file_queue.used; i++) 846 file_free(xar->file_queue.files[i]); 847 while (xar->unknowntags != NULL) { 848 struct unknown_tag *tag; 849 850 tag = xar->unknowntags; 851 xar->unknowntags = tag->next; 852 archive_string_free(&(tag->name)); 853 free(tag); 854 } 855 free(xar); 856 a->format->data = NULL; 857 return (r); 858} 859 860static int 861move_reading_point(struct archive_read *a, uint64_t offset) 862{ 863 struct xar *xar; 864 865 xar = (struct xar *)(a->format->data); 866 if (xar->offset - xar->h_base != offset) { 867 /* Seek forward to the start of file contents. */ 868 int64_t step; 869 870 step = offset - (xar->offset - xar->h_base); 871 if (step > 0) { 872 step = __archive_read_skip(a, step); 873 if (step < 0) 874 return ((int)step); 875 xar->offset += step; 876 } else { 877 archive_set_error(&(a->archive), 878 ARCHIVE_ERRNO_MISC, 879 "Cannot seek."); 880 return (ARCHIVE_FAILED); 881 } 882 } 883 return (ARCHIVE_OK); 884} 885 886static int 887rd_contents_init(struct archive_read *a, enum enctype encoding, 888 int a_sum_alg, int e_sum_alg) 889{ 890 int r; 891 892 /* Init decompress library. */ 893 if ((r = decompression_init(a, encoding)) != ARCHIVE_OK) 894 return (r); 895 /* Init checksum library. */ 896 checksum_init(a, a_sum_alg, e_sum_alg); 897 return (ARCHIVE_OK); 898} 899 900static int 901rd_contents(struct archive_read *a, const void **buff, size_t *size, 902 size_t *used, uint64_t remaining) 903{ 904 const unsigned char *b; 905 ssize_t bytes; 906 907 /* Get whatever bytes are immediately available. */ 908 b = __archive_read_ahead(a, 1, &bytes); 909 if (bytes < 0) 910 return ((int)bytes); 911 if (bytes == 0) { 912 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 913 "Truncated archive file"); 914 return (ARCHIVE_FATAL); 915 } 916 if ((uint64_t)bytes > remaining) 917 bytes = (ssize_t)remaining; 918 919 /* 920 * Decompress contents of file. 921 */ 922 *used = bytes; 923 if (decompress(a, buff, size, b, used) != ARCHIVE_OK) 924 return (ARCHIVE_FATAL); 925 926 /* 927 * Update checksum of a compressed data and a extracted data. 928 */ 929 checksum_update(a, b, *used, *buff, *size); 930 931 return (ARCHIVE_OK); 932} 933 934/* 935 * Note that this implementation does not (and should not!) obey 936 * locale settings; you cannot simply substitute strtol here, since 937 * it does obey locale. 938 */ 939 940static uint64_t 941atol10(const char *p, size_t char_cnt) 942{ 943 uint64_t l; 944 int digit; 945 946 l = 0; 947 digit = *p - '0'; 948 while (digit >= 0 && digit < 10 && char_cnt-- > 0) { 949 l = (l * 10) + digit; 950 digit = *++p - '0'; 951 } 952 return (l); 953} 954 955static int64_t 956atol8(const char *p, size_t char_cnt) 957{ 958 int64_t l; 959 int digit; 960 961 l = 0; 962 while (char_cnt-- > 0) { 963 if (*p >= '0' && *p <= '7') 964 digit = *p - '0'; 965 else 966 break; 967 p++; 968 l <<= 3; 969 l |= digit; 970 } 971 return (l); 972} 973 974static size_t 975atohex(unsigned char *b, size_t bsize, const char *p, size_t psize) 976{ 977 size_t fbsize = bsize; 978 979 while (bsize && psize > 1) { 980 unsigned char x; 981 982 if (p[0] >= 'a' && p[0] <= 'z') 983 x = (p[0] - 'a' + 0x0a) << 4; 984 else if (p[0] >= 'A' && p[0] <= 'Z') 985 x = (p[0] - 'A' + 0x0a) << 4; 986 else if (p[0] >= '0' && p[0] <= '9') 987 x = (p[0] - '0') << 4; 988 else 989 return (-1); 990 if (p[1] >= 'a' && p[1] <= 'z') 991 x |= p[1] - 'a' + 0x0a; 992 else if (p[1] >= 'A' && p[1] <= 'Z') 993 x |= p[1] - 'A' + 0x0a; 994 else if (p[1] >= '0' && p[1] <= '9') 995 x |= p[1] - '0'; 996 else 997 return (-1); 998 999 *b++ = x; 1000 bsize--; 1001 p += 2; 1002 psize -= 2; 1003 } 1004 return (fbsize - bsize); 1005} 1006 1007static time_t 1008time_from_tm(struct tm *t) 1009{ 1010#if HAVE_TIMEGM 1011 /* Use platform timegm() if available. */ 1012 return (timegm(t)); 1013#else 1014 /* Else use direct calculation using POSIX assumptions. */ 1015 /* First, fix up tm_yday based on the year/month/day. */ 1016 mktime(t); 1017 /* Then we can compute timegm() from first principles. */ 1018 return (t->tm_sec + t->tm_min * 60 + t->tm_hour * 3600 1019 + t->tm_yday * 86400 + (t->tm_year - 70) * 31536000 1020 + ((t->tm_year - 69) / 4) * 86400 - 1021 ((t->tm_year - 1) / 100) * 86400 1022 + ((t->tm_year + 299) / 400) * 86400); 1023#endif 1024} 1025 1026static time_t 1027parse_time(const char *p, size_t n) 1028{ 1029 struct tm tm; 1030 time_t t = 0; 1031 int64_t data; 1032 1033 memset(&tm, 0, sizeof(tm)); 1034 if (n != 20) 1035 return (t); 1036 data = atol10(p, 4); 1037 if (data < 1900) 1038 return (t); 1039 tm.tm_year = (int)data - 1900; 1040 p += 4; 1041 if (*p++ != '-') 1042 return (t); 1043 data = atol10(p, 2); 1044 if (data < 1 || data > 12) 1045 return (t); 1046 tm.tm_mon = (int)data -1; 1047 p += 2; 1048 if (*p++ != '-') 1049 return (t); 1050 data = atol10(p, 2); 1051 if (data < 1 || data > 31) 1052 return (t); 1053 tm.tm_mday = (int)data; 1054 p += 2; 1055 if (*p++ != 'T') 1056 return (t); 1057 data = atol10(p, 2); 1058 if (data < 0 || data > 23) 1059 return (t); 1060 tm.tm_hour = (int)data; 1061 p += 2; 1062 if (*p++ != ':') 1063 return (t); 1064 data = atol10(p, 2); 1065 if (data < 0 || data > 59) 1066 return (t); 1067 tm.tm_min = (int)data; 1068 p += 2; 1069 if (*p++ != ':') 1070 return (t); 1071 data = atol10(p, 2); 1072 if (data < 0 || data > 60) 1073 return (t); 1074 tm.tm_sec = (int)data; 1075#if 0 1076 p += 2; 1077 if (*p != 'Z') 1078 return (t); 1079#endif 1080 1081 t = time_from_tm(&tm); 1082 1083 return (t); 1084} 1085 1086static void 1087heap_add_entry(struct heap_queue *heap, struct xar_file *file) 1088{ 1089 uint64_t file_id, parent_id; 1090 int hole, parent; 1091 1092 /* Expand our pending files list as necessary. */ 1093 if (heap->used >= heap->allocated) { 1094 struct xar_file **new_pending_files; 1095 int new_size = heap->allocated * 2; 1096 1097 if (heap->allocated < 1024) 1098 new_size = 1024; 1099 /* Overflow might keep us from growing the list. */ 1100 if (new_size <= heap->allocated) 1101 __archive_errx(1, "Out of memory"); 1102 new_pending_files = (struct xar_file **) 1103 malloc(new_size * sizeof(new_pending_files[0])); 1104 if (new_pending_files == NULL) 1105 __archive_errx(1, "Out of memory"); 1106 memcpy(new_pending_files, heap->files, 1107 heap->allocated * sizeof(new_pending_files[0])); 1108 if (heap->files != NULL) 1109 free(heap->files); 1110 heap->files = new_pending_files; 1111 heap->allocated = new_size; 1112 } 1113 1114 file_id = file->id; 1115 1116 /* 1117 * Start with hole at end, walk it up tree to find insertion point. 1118 */ 1119 hole = heap->used++; 1120 while (hole > 0) { 1121 parent = (hole - 1)/2; 1122 parent_id = heap->files[parent]->id; 1123 if (file_id >= parent_id) { 1124 heap->files[hole] = file; 1125 return; 1126 } 1127 // Move parent into hole <==> move hole up tree. 1128 heap->files[hole] = heap->files[parent]; 1129 hole = parent; 1130 } 1131 heap->files[0] = file; 1132} 1133 1134static struct xar_file * 1135heap_get_entry(struct heap_queue *heap) 1136{ 1137 uint64_t a_id, b_id, c_id; 1138 int a, b, c; 1139 struct xar_file *r, *tmp; 1140 1141 if (heap->used < 1) 1142 return (NULL); 1143 1144 /* 1145 * The first file in the list is the earliest; we'll return this. 1146 */ 1147 r = heap->files[0]; 1148 1149 /* 1150 * Move the last item in the heap to the root of the tree 1151 */ 1152 heap->files[0] = heap->files[--(heap->used)]; 1153 1154 /* 1155 * Rebalance the heap. 1156 */ 1157 a = 0; // Starting element and its heap key 1158 a_id = heap->files[a]->id; 1159 for (;;) { 1160 b = a + a + 1; // First child 1161 if (b >= heap->used) 1162 return (r); 1163 b_id = heap->files[b]->id; 1164 c = b + 1; // Use second child if it is smaller. 1165 if (c < heap->used) { 1166 c_id = heap->files[c]->id; 1167 if (c_id < b_id) { 1168 b = c; 1169 b_id = c_id; 1170 } 1171 } 1172 if (a_id <= b_id) 1173 return (r); 1174 tmp = heap->files[a]; 1175 heap->files[a] = heap->files[b]; 1176 heap->files[b] = tmp; 1177 a = b; 1178 } 1179} 1180 1181static void 1182add_link(struct xar *xar, struct xar_file *file) 1183{ 1184 struct hdlink *hdlink; 1185 1186 for (hdlink = xar->hdlink_list; hdlink != NULL; hdlink = hdlink->next) { 1187 if (hdlink->id == file->link) { 1188 file->hdnext = hdlink->files; 1189 hdlink->cnt++; 1190 hdlink->files = file; 1191 return; 1192 } 1193 } 1194 hdlink = malloc(sizeof(*hdlink)); 1195 if (hdlink == NULL) 1196 __archive_errx(1, "No memory for add_link()"); 1197 file->hdnext = NULL; 1198 hdlink->id = file->link; 1199 hdlink->cnt = 1; 1200 hdlink->files = file; 1201 hdlink->next = xar->hdlink_list; 1202 xar->hdlink_list = hdlink; 1203} 1204 1205static void 1206_checksum_init(struct chksumwork *sumwrk, int sum_alg) 1207{ 1208 sumwrk->alg = sum_alg; 1209 switch (sum_alg) { 1210 case CKSUM_NONE: 1211 break; 1212 case CKSUM_SHA1: 1213 archive_sha1_init(&(sumwrk->sha1ctx)); 1214 break; 1215 case CKSUM_MD5: 1216 archive_md5_init(&(sumwrk->md5ctx)); 1217 break; 1218 } 1219} 1220 1221static void 1222_checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size) 1223{ 1224 1225 switch (sumwrk->alg) { 1226 case CKSUM_NONE: 1227 break; 1228 case CKSUM_SHA1: 1229 archive_sha1_update(&(sumwrk->sha1ctx), buff, size); 1230 break; 1231 case CKSUM_MD5: 1232 archive_md5_update(&(sumwrk->md5ctx), buff, size); 1233 break; 1234 } 1235} 1236 1237static int 1238_checksum_final(struct chksumwork *sumwrk, const void *val, size_t len) 1239{ 1240 unsigned char sum[MAX_SUM_SIZE]; 1241 int r = ARCHIVE_OK; 1242 1243 switch (sumwrk->alg) { 1244 case CKSUM_NONE: 1245 break; 1246 case CKSUM_SHA1: 1247 archive_sha1_final(&(sumwrk->sha1ctx), sum); 1248 if (len != SHA1_SIZE || 1249 memcmp(val, sum, SHA1_SIZE) != 0) 1250 r = ARCHIVE_FAILED; 1251 break; 1252 case CKSUM_MD5: 1253 archive_md5_final(&(sumwrk->md5ctx), sum); 1254 if (len != MD5_SIZE || 1255 memcmp(val, sum, MD5_SIZE) != 0) 1256 r = ARCHIVE_FAILED; 1257 break; 1258 } 1259 return (r); 1260} 1261 1262static void 1263checksum_init(struct archive_read *a, int a_sum_alg, int e_sum_alg) 1264{ 1265 struct xar *xar; 1266 1267 xar = (struct xar *)(a->format->data); 1268 _checksum_init(&(xar->a_sumwrk), a_sum_alg); 1269 _checksum_init(&(xar->e_sumwrk), e_sum_alg); 1270} 1271 1272static void 1273checksum_update(struct archive_read *a, const void *abuff, size_t asize, 1274 const void *ebuff, size_t esize) 1275{ 1276 struct xar *xar; 1277 1278 xar = (struct xar *)(a->format->data); 1279 _checksum_update(&(xar->a_sumwrk), abuff, asize); 1280 _checksum_update(&(xar->e_sumwrk), ebuff, esize); 1281} 1282 1283static int 1284checksum_final(struct archive_read *a, const void *a_sum_val, 1285 size_t a_sum_len, const void *e_sum_val, size_t e_sum_len) 1286{ 1287 struct xar *xar; 1288 int r; 1289 1290 xar = (struct xar *)(a->format->data); 1291 r = _checksum_final(&(xar->a_sumwrk), a_sum_val, a_sum_len); 1292 if (r == ARCHIVE_OK) 1293 r = _checksum_final(&(xar->e_sumwrk), e_sum_val, e_sum_len); 1294 if (r != ARCHIVE_OK) 1295 archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, 1296 "Sumcheck error"); 1297 return (r); 1298} 1299 1300static int 1301decompression_init(struct archive_read *a, enum enctype encoding) 1302{ 1303 struct xar *xar; 1304 const char *detail; 1305 int r; 1306 1307 xar = (struct xar *)(a->format->data); 1308 xar->rd_encoding = encoding; 1309 switch (encoding) { 1310 case NONE: 1311 break; 1312 case GZIP: 1313 if (xar->stream_valid) 1314 r = inflateReset(&(xar->stream)); 1315 else 1316 r = inflateInit(&(xar->stream)); 1317 if (r != Z_OK) { 1318 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1319 "Couldn't initialize zlib stream."); 1320 return (ARCHIVE_FATAL); 1321 } 1322 xar->stream_valid = 1; 1323 xar->stream.total_in = 0; 1324 xar->stream.total_out = 0; 1325 break; 1326#ifdef HAVE_BZLIB_H 1327 case BZIP2: 1328 if (xar->bzstream_valid) { 1329 BZ2_bzDecompressEnd(&(xar->bzstream)); 1330 xar->bzstream_valid = 0; 1331 } 1332 r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 0); 1333 if (r == BZ_MEM_ERROR) 1334 r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 1); 1335 if (r != BZ_OK) { 1336 int err = ARCHIVE_ERRNO_MISC; 1337 detail = NULL; 1338 switch (r) { 1339 case BZ_PARAM_ERROR: 1340 detail = "invalid setup parameter"; 1341 break; 1342 case BZ_MEM_ERROR: 1343 err = ENOMEM; 1344 detail = "out of memory"; 1345 break; 1346 case BZ_CONFIG_ERROR: 1347 detail = "mis-compiled library"; 1348 break; 1349 } 1350 archive_set_error(&a->archive, err, 1351 "Internal error initializing decompressor: %s", 1352 detail == NULL ? "??" : detail); 1353 xar->bzstream_valid = 0; 1354 return (ARCHIVE_FATAL); 1355 } 1356 xar->bzstream_valid = 1; 1357 xar->bzstream.total_in_lo32 = 0; 1358 xar->bzstream.total_in_hi32 = 0; 1359 xar->bzstream.total_out_lo32 = 0; 1360 xar->bzstream.total_out_hi32 = 0; 1361 break; 1362#endif 1363#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1364 case XZ: 1365 case LZMA: 1366 if (xar->lzstream_valid) { 1367 lzma_end(&(xar->lzstream)); 1368 xar->lzstream_valid = 0; 1369 } 1370 if (xar->entry_encoding == XZ) 1371 r = lzma_stream_decoder(&(xar->lzstream), 1372 (1U << 30),/* memlimit */ 1373 LZMA_CONCATENATED); 1374 else 1375 r = lzma_alone_decoder(&(xar->lzstream), 1376 (1U << 30));/* memlimit */ 1377 if (r != LZMA_OK) { 1378 switch (r) { 1379 case LZMA_MEM_ERROR: 1380 archive_set_error(&a->archive, 1381 ENOMEM, 1382 "Internal error initializing " 1383 "compression library: " 1384 "Cannot allocate memory"); 1385 break; 1386 case LZMA_OPTIONS_ERROR: 1387 archive_set_error(&a->archive, 1388 ARCHIVE_ERRNO_MISC, 1389 "Internal error initializing " 1390 "compression library: " 1391 "Invalid or unsupported options"); 1392 break; 1393 default: 1394 archive_set_error(&a->archive, 1395 ARCHIVE_ERRNO_MISC, 1396 "Internal error initializing " 1397 "lzma library"); 1398 break; 1399 } 1400 return (ARCHIVE_FATAL); 1401 } 1402 xar->lzstream_valid = 1; 1403 xar->lzstream.total_in = 0; 1404 xar->lzstream.total_out = 0; 1405 break; 1406#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) 1407 case LZMA: 1408 if (xar->lzstream_valid) 1409 lzmadec_end(&(xar->lzstream)); 1410 r = lzmadec_init(&(xar->lzstream)); 1411 if (r != LZMADEC_OK) { 1412 switch (r) { 1413 case LZMADEC_HEADER_ERROR: 1414 archive_set_error(&a->archive, 1415 ARCHIVE_ERRNO_MISC, 1416 "Internal error initializing " 1417 "compression library: " 1418 "invalid header"); 1419 break; 1420 case LZMADEC_MEM_ERROR: 1421 archive_set_error(&a->archive, 1422 ENOMEM, 1423 "Internal error initializing " 1424 "compression library: " 1425 "out of memory"); 1426 break; 1427 } 1428 return (ARCHIVE_FATAL); 1429 } 1430 xar->lzstream_valid = 1; 1431 xar->lzstream.total_in = 0; 1432 xar->lzstream.total_out = 0; 1433 break; 1434#endif 1435 /* 1436 * Unsupported compression. 1437 */ 1438 default: 1439#ifndef HAVE_BZLIB_H 1440 case BZIP2: 1441#endif 1442#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) 1443#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) 1444 case LZMA: 1445#endif 1446 case XZ: 1447#endif 1448 switch (xar->entry_encoding) { 1449 case BZIP2: detail = "bzip2"; break; 1450 case LZMA: detail = "lzma"; break; 1451 case XZ: detail = "xz"; break; 1452 default: detail = "??"; break; 1453 } 1454 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1455 "%s compression not supported on this platform", 1456 detail); 1457 return (ARCHIVE_FAILED); 1458 } 1459 return (ARCHIVE_OK); 1460} 1461 1462static int 1463decompress(struct archive_read *a, const void **buff, size_t *outbytes, 1464 const void *b, size_t *used) 1465{ 1466 struct xar *xar; 1467 void *outbuff; 1468 size_t avail_in, avail_out; 1469 int r; 1470 1471 xar = (struct xar *)(a->format->data); 1472 avail_in = *used; 1473 outbuff = (void *)(uintptr_t)*buff; 1474 if (outbuff == NULL) { 1475 outbuff = xar->buff; 1476 *buff = outbuff; 1477 avail_out = sizeof(xar->buff); 1478 } else 1479 avail_out = *outbytes; 1480 switch (xar->rd_encoding) { 1481 case GZIP: 1482 xar->stream.next_in = (Bytef *)(uintptr_t)b; 1483 xar->stream.avail_in = avail_in; 1484 xar->stream.next_out = (unsigned char *)outbuff; 1485 xar->stream.avail_out = avail_out; 1486 r = inflate(&(xar->stream), 0); 1487 switch (r) { 1488 case Z_OK: /* Decompressor made some progress.*/ 1489 case Z_STREAM_END: /* Found end of stream. */ 1490 break; 1491 default: 1492 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1493 "File decompression failed (%d)", r); 1494 return (ARCHIVE_FATAL); 1495 } 1496 *used = avail_in - xar->stream.avail_in; 1497 *outbytes = avail_out - xar->stream.avail_out; 1498 break; 1499#ifdef HAVE_BZLIB_H 1500 case BZIP2: 1501 xar->bzstream.next_in = (char *)(uintptr_t)b; 1502 xar->bzstream.avail_in = avail_in; 1503 xar->bzstream.next_out = (char *)outbuff; 1504 xar->bzstream.avail_out = avail_out; 1505 r = BZ2_bzDecompress(&(xar->bzstream)); 1506 switch (r) { 1507 case BZ_STREAM_END: /* Found end of stream. */ 1508 switch (BZ2_bzDecompressEnd(&(xar->bzstream))) { 1509 case BZ_OK: 1510 break; 1511 default: 1512 archive_set_error(&(a->archive), 1513 ARCHIVE_ERRNO_MISC, 1514 "Failed to clean up decompressor"); 1515 return (ARCHIVE_FATAL); 1516 } 1517 xar->bzstream_valid = 0; 1518 /* FALLTHROUGH */ 1519 case BZ_OK: /* Decompressor made some progress. */ 1520 break; 1521 default: 1522 archive_set_error(&(a->archive), 1523 ARCHIVE_ERRNO_MISC, 1524 "bzip decompression failed"); 1525 return (ARCHIVE_FATAL); 1526 } 1527 *used = avail_in - xar->bzstream.avail_in; 1528 *outbytes = avail_out - xar->bzstream.avail_out; 1529 break; 1530#endif 1531#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1532 case LZMA: 1533 case XZ: 1534 xar->lzstream.next_in = b; 1535 xar->lzstream.avail_in = avail_in; 1536 xar->lzstream.next_out = (unsigned char *)outbuff; 1537 xar->lzstream.avail_out = avail_out; 1538 r = lzma_code(&(xar->lzstream), LZMA_RUN); 1539 switch (r) { 1540 case LZMA_STREAM_END: /* Found end of stream. */ 1541 lzma_end(&(xar->lzstream)); 1542 xar->lzstream_valid = 0; 1543 /* FALLTHROUGH */ 1544 case LZMA_OK: /* Decompressor made some progress. */ 1545 break; 1546 default: 1547 archive_set_error(&(a->archive), 1548 ARCHIVE_ERRNO_MISC, 1549 "%s decompression failed(%d)", 1550 (xar->entry_encoding == XZ)?"xz":"lzma", 1551 r); 1552 return (ARCHIVE_FATAL); 1553 } 1554 *used = avail_in - xar->lzstream.avail_in; 1555 *outbytes = avail_out - xar->lzstream.avail_out; 1556 break; 1557#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) 1558 case LZMA: 1559 xar->lzstream.next_in = (unsigned char *)(uintptr_t)b; 1560 xar->lzstream.avail_in = avail_in; 1561 xar->lzstream.next_out = (unsigned char *)outbuff; 1562 xar->lzstream.avail_out = avail_out; 1563 r = lzmadec_decode(&(xar->lzstream), 0); 1564 switch (r) { 1565 case LZMADEC_STREAM_END: /* Found end of stream. */ 1566 switch (lzmadec_end(&(xar->lzstream))) { 1567 case LZMADEC_OK: 1568 break; 1569 default: 1570 archive_set_error(&(a->archive), 1571 ARCHIVE_ERRNO_MISC, 1572 "Failed to clean up lzmadec decompressor"); 1573 return (ARCHIVE_FATAL); 1574 } 1575 xar->lzstream_valid = 0; 1576 /* FALLTHROUGH */ 1577 case LZMADEC_OK: /* Decompressor made some progress. */ 1578 break; 1579 default: 1580 archive_set_error(&(a->archive), 1581 ARCHIVE_ERRNO_MISC, 1582 "lzmadec decompression failed(%d)", 1583 r); 1584 return (ARCHIVE_FATAL); 1585 } 1586 *used = avail_in - xar->lzstream.avail_in; 1587 *outbytes = avail_out - xar->lzstream.avail_out; 1588 break; 1589#endif 1590#ifndef HAVE_BZLIB_H 1591 case BZIP2: 1592#endif 1593#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) 1594#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) 1595 case LZMA: 1596#endif 1597 case XZ: 1598#endif 1599 case NONE: 1600 default: 1601 if (outbuff == xar->buff) { 1602 *buff = b; 1603 *used = avail_in; 1604 *outbytes = avail_in; 1605 } else { 1606 if (avail_out > avail_in) 1607 avail_out = avail_in; 1608 memcpy(outbuff, b, avail_out); 1609 *used = avail_out; 1610 *outbytes = avail_out; 1611 } 1612 break; 1613 } 1614 return (ARCHIVE_OK); 1615} 1616 1617static int 1618decompression_cleanup(struct archive_read *a) 1619{ 1620 struct xar *xar; 1621 int r; 1622 1623 xar = (struct xar *)(a->format->data); 1624 r = ARCHIVE_OK; 1625 if (xar->stream_valid) { 1626 if (inflateEnd(&(xar->stream)) != Z_OK) { 1627 archive_set_error(&a->archive, 1628 ARCHIVE_ERRNO_MISC, 1629 "Failed to clean up zlib decompressor"); 1630 r = ARCHIVE_FATAL; 1631 } 1632 } 1633#ifdef HAVE_BZLIB_H 1634 if (xar->bzstream_valid) { 1635 if (BZ2_bzDecompressEnd(&(xar->bzstream)) != BZ_OK) { 1636 archive_set_error(&a->archive, 1637 ARCHIVE_ERRNO_MISC, 1638 "Failed to clean up bzip2 decompressor"); 1639 r = ARCHIVE_FATAL; 1640 } 1641 } 1642#endif 1643#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1644 if (xar->lzstream_valid) 1645 lzma_end(&(xar->lzstream)); 1646#elif defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1647 if (xar->lzstream_valid) { 1648 if (lzmadec_end(&(xar->lzstream)) != LZMADEC_OK) { 1649 archive_set_error(&a->archive, 1650 ARCHIVE_ERRNO_MISC, 1651 "Failed to clean up lzmadec decompressor"); 1652 r = ARCHIVE_FATAL; 1653 } 1654 } 1655#endif 1656 return (r); 1657} 1658 1659static void 1660xmlattr_cleanup(struct xmlattr_list *list) 1661{ 1662 struct xmlattr *attr, *next; 1663 1664 attr = list->first; 1665 while (attr != NULL) { 1666 next = attr->next; 1667 free(attr->name); 1668 free(attr->value); 1669 free(attr); 1670 attr = next; 1671 } 1672 list->first = NULL; 1673 list->last = &(list->first); 1674} 1675 1676static void 1677file_new(struct xar *xar, struct xmlattr_list *list) 1678{ 1679 struct xar_file *file; 1680 struct xmlattr *attr; 1681 1682 file = calloc(1, sizeof(*file)); 1683 if (file == NULL) 1684 __archive_errx(1, "Out of memory"); 1685 file->parent = xar->file; 1686 file->mode = 0777 | AE_IFREG; 1687 file->atime = time(NULL); 1688 file->mtime = time(NULL); 1689 xar->file = file; 1690 xar->xattr = NULL; 1691 for (attr = list->first; attr != NULL; attr = attr->next) { 1692 if (strcmp(attr->name, "id") == 0) 1693 file->id = atol10(attr->value, strlen(attr->value)); 1694 } 1695 file->nlink = 1; 1696 heap_add_entry(&(xar->file_queue), file); 1697} 1698 1699static void 1700file_free(struct xar_file *file) 1701{ 1702 struct xattr *xattr; 1703 1704 archive_string_free(&(file->pathname)); 1705 archive_string_free(&(file->symlink)); 1706 archive_string_free(&(file->uname)); 1707 archive_string_free(&(file->gname)); 1708 archive_string_free(&(file->hardlink)); 1709 xattr = file->xattr_list; 1710 while (xattr != NULL) { 1711 struct xattr *next; 1712 1713 next = xattr->next; 1714 xattr_free(xattr); 1715 xattr = next; 1716 } 1717 1718 free(file); 1719} 1720 1721static void 1722xattr_new(struct xar *xar, struct xmlattr_list *list) 1723{ 1724 struct xattr *xattr, **nx; 1725 struct xmlattr *attr; 1726 1727 xattr = calloc(1, sizeof(*xattr)); 1728 if (xattr == NULL) 1729 __archive_errx(1, "Out of memory"); 1730 xar->xattr = xattr; 1731 for (attr = list->first; attr != NULL; attr = attr->next) { 1732 if (strcmp(attr->name, "id") == 0) 1733 xattr->id = atol10(attr->value, strlen(attr->value)); 1734 } 1735 /* Chain to xattr list. */ 1736 for (nx = &(xar->file->xattr_list); 1737 *nx != NULL; nx = &((*nx)->next)) { 1738 if (xattr->id < (*nx)->id) 1739 break; 1740 } 1741 xattr->next = *nx; 1742 *nx = xattr; 1743} 1744 1745static void 1746xattr_free(struct xattr *xattr) 1747{ 1748 archive_string_free(&(xattr->name)); 1749 free(xattr); 1750} 1751 1752static int 1753getencoding(struct xmlattr_list *list) 1754{ 1755 struct xmlattr *attr; 1756 enum enctype encoding = NONE; 1757 1758 for (attr = list->first; attr != NULL; attr = attr->next) { 1759 if (strcmp(attr->name, "style") == 0) { 1760 if (strcmp(attr->value, "application/octet-stream") == 0) 1761 encoding = NONE; 1762 else if (strcmp(attr->value, "application/x-gzip") == 0) 1763 encoding = GZIP; 1764 else if (strcmp(attr->value, "application/x-bzip2") == 0) 1765 encoding = BZIP2; 1766 else if (strcmp(attr->value, "application/x-lzma") == 0) 1767 encoding = LZMA; 1768 else if (strcmp(attr->value, "application/x-xz") == 0) 1769 encoding = XZ; 1770 } 1771 } 1772 return (encoding); 1773} 1774 1775static int 1776getsumalgorithm(struct xmlattr_list *list) 1777{ 1778 struct xmlattr *attr; 1779 int alg = CKSUM_NONE; 1780 1781 for (attr = list->first; attr != NULL; attr = attr->next) { 1782 if (strcmp(attr->name, "style") == 0) { 1783 const char *v = attr->value; 1784 if ((v[0] == 'S' || v[0] == 's') && 1785 (v[1] == 'H' || v[1] == 'h') && 1786 (v[2] == 'A' || v[2] == 'a') && 1787 v[3] == '1' && v[4] == '\0') 1788 alg = CKSUM_SHA1; 1789 if ((v[0] == 'M' || v[0] == 'm') && 1790 (v[1] == 'D' || v[1] == 'd') && 1791 v[2] == '5' && v[3] == '\0') 1792 alg = CKSUM_MD5; 1793 } 1794 } 1795 return (alg); 1796} 1797 1798static void 1799unknowntag_start(struct xar *xar, const char *name) 1800{ 1801 struct unknown_tag *tag; 1802 1803#if DEBUG 1804 fprintf(stderr, "unknowntag_start:%s\n", name); 1805#endif 1806 tag = malloc(sizeof(*tag)); 1807 if (tag == NULL) 1808 __archive_errx(1, "Out of memory"); 1809 tag->next = xar->unknowntags; 1810 archive_string_init(&(tag->name)); 1811 archive_strcpy(&(tag->name), name); 1812 if (xar->unknowntags == NULL) { 1813 xar->xmlsts_unknown = xar->xmlsts; 1814 xar->xmlsts = UNKNOWN; 1815 } 1816 xar->unknowntags = tag; 1817} 1818 1819static void 1820unknowntag_end(struct xar *xar, const char *name) 1821{ 1822 struct unknown_tag *tag; 1823 1824#if DEBUG 1825 fprintf(stderr, "unknowntag_end:%s\n", name); 1826#endif 1827 tag = xar->unknowntags; 1828 if (tag == NULL || name == NULL) 1829 return; 1830 if (strcmp(tag->name.s, name) == 0) { 1831 xar->unknowntags = tag->next; 1832 archive_string_free(&(tag->name)); 1833 free(tag); 1834 if (xar->unknowntags == NULL) 1835 xar->xmlsts = xar->xmlsts_unknown; 1836 } 1837} 1838 1839static void 1840xml_start(void *userData, const char *name, struct xmlattr_list *list) 1841{ 1842 struct archive_read *a; 1843 struct xar *xar; 1844 struct xmlattr *attr; 1845 1846 a = (struct archive_read *)userData; 1847 xar = (struct xar *)(a->format->data); 1848 1849#if DEBUG 1850 fprintf(stderr, "xml_sta:[%s]\n", name); 1851 for (attr = list->first; attr != NULL; attr = attr->next) 1852 fprintf(stderr, " attr:\"%s\"=\"%s\"\n", 1853 attr->name, attr->value); 1854#endif 1855 xar->base64text = 0; 1856 switch (xar->xmlsts) { 1857 case INIT: 1858 if (strcmp(name, "xar") == 0) 1859 xar->xmlsts = XAR; 1860 else 1861 unknowntag_start(xar, name); 1862 break; 1863 case XAR: 1864 if (strcmp(name, "toc") == 0) 1865 xar->xmlsts = TOC; 1866 else 1867 unknowntag_start(xar, name); 1868 break; 1869 case TOC: 1870 if (strcmp(name, "creation-time") == 0) 1871 xar->xmlsts = TOC_CREATION_TIME; 1872 else if (strcmp(name, "checksum") == 0) 1873 xar->xmlsts = TOC_CHECKSUM; 1874 else if (strcmp(name, "file") == 0) { 1875 file_new(xar, list); 1876 xar->xmlsts = TOC_FILE; 1877 } 1878 else 1879 unknowntag_start(xar, name); 1880 break; 1881 case TOC_CHECKSUM: 1882 if (strcmp(name, "offset") == 0) 1883 xar->xmlsts = TOC_CHECKSUM_OFFSET; 1884 else if (strcmp(name, "size") == 0) 1885 xar->xmlsts = TOC_CHECKSUM_SIZE; 1886 else 1887 unknowntag_start(xar, name); 1888 break; 1889 case TOC_FILE: 1890 if (strcmp(name, "file") == 0) { 1891 file_new(xar, list); 1892 } 1893 else if (strcmp(name, "data") == 0) 1894 xar->xmlsts = FILE_DATA; 1895 else if (strcmp(name, "ea") == 0) { 1896 xattr_new(xar, list); 1897 xar->xmlsts = FILE_EA; 1898 } 1899 else if (strcmp(name, "ctime") == 0) 1900 xar->xmlsts = FILE_CTIME; 1901 else if (strcmp(name, "mtime") == 0) 1902 xar->xmlsts = FILE_MTIME; 1903 else if (strcmp(name, "atime") == 0) 1904 xar->xmlsts = FILE_ATIME; 1905 else if (strcmp(name, "group") == 0) 1906 xar->xmlsts = FILE_GROUP; 1907 else if (strcmp(name, "gid") == 0) 1908 xar->xmlsts = FILE_GID; 1909 else if (strcmp(name, "user") == 0) 1910 xar->xmlsts = FILE_USER; 1911 else if (strcmp(name, "uid") == 0) 1912 xar->xmlsts = FILE_UID; 1913 else if (strcmp(name, "mode") == 0) 1914 xar->xmlsts = FILE_MODE; 1915 else if (strcmp(name, "device") == 0) 1916 xar->xmlsts = FILE_DEVICE; 1917 else if (strcmp(name, "deviceno") == 0) 1918 xar->xmlsts = FILE_DEVICENO; 1919 else if (strcmp(name, "inode") == 0) 1920 xar->xmlsts = FILE_INODE; 1921 else if (strcmp(name, "link") == 0) 1922 xar->xmlsts = FILE_LINK; 1923 else if (strcmp(name, "type") == 0) { 1924 xar->xmlsts = FILE_TYPE; 1925 for (attr = list->first; attr != NULL; 1926 attr = attr->next) { 1927 if (strcmp(attr->name, "link") != 0) 1928 continue; 1929 if (strcmp(attr->value, "original") == 0) { 1930 xar->file->hdnext = xar->hdlink_orgs; 1931 xar->hdlink_orgs = xar->file; 1932 } else { 1933 xar->file->link = atol10(attr->value, 1934 strlen(attr->value)); 1935 if (xar->file->link > 0) 1936 add_link(xar, xar->file); 1937 } 1938 } 1939 } 1940 else if (strcmp(name, "name") == 0) { 1941 xar->xmlsts = FILE_NAME; 1942 for (attr = list->first; attr != NULL; 1943 attr = attr->next) { 1944 if (strcmp(attr->name, "enctype") == 0 && 1945 strcmp(attr->value, "base64") == 0) 1946 xar->base64text = 1; 1947 } 1948 } 1949 else if (strcmp(name, "acl") == 0) 1950 xar->xmlsts = FILE_ACL; 1951 else if (strcmp(name, "flags") == 0) 1952 xar->xmlsts = FILE_FLAGS; 1953 else if (strcmp(name, "ext2") == 0) 1954 xar->xmlsts = FILE_EXT2; 1955 else 1956 unknowntag_start(xar, name); 1957 break; 1958 case FILE_DATA: 1959 if (strcmp(name, "length") == 0) 1960 xar->xmlsts = FILE_DATA_LENGTH; 1961 else if (strcmp(name, "offset") == 0) 1962 xar->xmlsts = FILE_DATA_OFFSET; 1963 else if (strcmp(name, "size") == 0) 1964 xar->xmlsts = FILE_DATA_SIZE; 1965 else if (strcmp(name, "encoding") == 0) { 1966 xar->xmlsts = FILE_DATA_ENCODING; 1967 xar->file->encoding = getencoding(list); 1968 } 1969 else if (strcmp(name, "archived-checksum") == 0) { 1970 xar->xmlsts = FILE_DATA_A_CHECKSUM; 1971 xar->file->a_sum.alg = getsumalgorithm(list); 1972 } 1973 else if (strcmp(name, "extracted-checksum") == 0) { 1974 xar->xmlsts = FILE_DATA_E_CHECKSUM; 1975 xar->file->e_sum.alg = getsumalgorithm(list); 1976 } 1977 else if (strcmp(name, "content") == 0) 1978 xar->xmlsts = FILE_DATA_CONTENT; 1979 else 1980 unknowntag_start(xar, name); 1981 break; 1982 case FILE_DEVICE: 1983 if (strcmp(name, "major") == 0) 1984 xar->xmlsts = FILE_DEVICE_MAJOR; 1985 else if (strcmp(name, "minor") == 0) 1986 xar->xmlsts = FILE_DEVICE_MINOR; 1987 else 1988 unknowntag_start(xar, name); 1989 break; 1990 case FILE_DATA_CONTENT: 1991 unknowntag_start(xar, name); 1992 break; 1993 case FILE_EA: 1994 if (strcmp(name, "length") == 0) 1995 xar->xmlsts = FILE_EA_LENGTH; 1996 else if (strcmp(name, "offset") == 0) 1997 xar->xmlsts = FILE_EA_OFFSET; 1998 else if (strcmp(name, "size") == 0) 1999 xar->xmlsts = FILE_EA_SIZE; 2000 else if (strcmp(name, "encoding") == 0) { 2001 xar->xmlsts = FILE_EA_ENCODING; 2002 xar->xattr->encoding = getencoding(list); 2003 } else if (strcmp(name, "archived-checksum") == 0) 2004 xar->xmlsts = FILE_EA_A_CHECKSUM; 2005 else if (strcmp(name, "extracted-checksum") == 0) 2006 xar->xmlsts = FILE_EA_E_CHECKSUM; 2007 else if (strcmp(name, "name") == 0) 2008 xar->xmlsts = FILE_EA_NAME; 2009 else if (strcmp(name, "fstype") == 0) 2010 xar->xmlsts = FILE_EA_FSTYPE; 2011 else 2012 unknowntag_start(xar, name); 2013 break; 2014 case FILE_ACL: 2015 if (strcmp(name, "appleextended") == 0) 2016 xar->xmlsts = FILE_ACL_APPLEEXTENDED; 2017 if (strcmp(name, "default") == 0) 2018 xar->xmlsts = FILE_ACL_DEFAULT; 2019 else if (strcmp(name, "access") == 0) 2020 xar->xmlsts = FILE_ACL_ACCESS; 2021 else 2022 unknowntag_start(xar, name); 2023 break; 2024 case FILE_FLAGS: 2025 if (!xml_parse_file_flags(xar, name)) 2026 unknowntag_start(xar, name); 2027 break; 2028 case FILE_EXT2: 2029 if (!xml_parse_file_ext2(xar, name)) 2030 unknowntag_start(xar, name); 2031 break; 2032 case TOC_CREATION_TIME: 2033 case TOC_CHECKSUM_OFFSET: 2034 case TOC_CHECKSUM_SIZE: 2035 case FILE_DATA_LENGTH: 2036 case FILE_DATA_OFFSET: 2037 case FILE_DATA_SIZE: 2038 case FILE_DATA_ENCODING: 2039 case FILE_DATA_A_CHECKSUM: 2040 case FILE_DATA_E_CHECKSUM: 2041 case FILE_EA_LENGTH: 2042 case FILE_EA_OFFSET: 2043 case FILE_EA_SIZE: 2044 case FILE_EA_ENCODING: 2045 case FILE_EA_A_CHECKSUM: 2046 case FILE_EA_E_CHECKSUM: 2047 case FILE_EA_NAME: 2048 case FILE_EA_FSTYPE: 2049 case FILE_CTIME: 2050 case FILE_MTIME: 2051 case FILE_ATIME: 2052 case FILE_GROUP: 2053 case FILE_GID: 2054 case FILE_USER: 2055 case FILE_UID: 2056 case FILE_INODE: 2057 case FILE_DEVICE_MAJOR: 2058 case FILE_DEVICE_MINOR: 2059 case FILE_DEVICENO: 2060 case FILE_MODE: 2061 case FILE_TYPE: 2062 case FILE_LINK: 2063 case FILE_NAME: 2064 case FILE_ACL_DEFAULT: 2065 case FILE_ACL_ACCESS: 2066 case FILE_ACL_APPLEEXTENDED: 2067 case FILE_FLAGS_USER_NODUMP: 2068 case FILE_FLAGS_USER_IMMUTABLE: 2069 case FILE_FLAGS_USER_APPEND: 2070 case FILE_FLAGS_USER_OPAQUE: 2071 case FILE_FLAGS_USER_NOUNLINK: 2072 case FILE_FLAGS_SYS_ARCHIVED: 2073 case FILE_FLAGS_SYS_IMMUTABLE: 2074 case FILE_FLAGS_SYS_APPEND: 2075 case FILE_FLAGS_SYS_NOUNLINK: 2076 case FILE_FLAGS_SYS_SNAPSHOT: 2077 case FILE_EXT2_SecureDeletion: 2078 case FILE_EXT2_Undelete: 2079 case FILE_EXT2_Compress: 2080 case FILE_EXT2_Synchronous: 2081 case FILE_EXT2_Immutable: 2082 case FILE_EXT2_AppendOnly: 2083 case FILE_EXT2_NoDump: 2084 case FILE_EXT2_NoAtime: 2085 case FILE_EXT2_CompDirty: 2086 case FILE_EXT2_CompBlock: 2087 case FILE_EXT2_NoCompBlock: 2088 case FILE_EXT2_CompError: 2089 case FILE_EXT2_BTree: 2090 case FILE_EXT2_HashIndexed: 2091 case FILE_EXT2_iMagic: 2092 case FILE_EXT2_Journaled: 2093 case FILE_EXT2_NoTail: 2094 case FILE_EXT2_DirSync: 2095 case FILE_EXT2_TopDir: 2096 case FILE_EXT2_Reserved: 2097 case UNKNOWN: 2098 unknowntag_start(xar, name); 2099 break; 2100 } 2101} 2102 2103static void 2104xml_end(void *userData, const char *name) 2105{ 2106 struct archive_read *a; 2107 struct xar *xar; 2108 2109 a = (struct archive_read *)userData; 2110 xar = (struct xar *)(a->format->data); 2111 2112#if DEBUG 2113 fprintf(stderr, "xml_end:[%s]\n", name); 2114#endif 2115 switch (xar->xmlsts) { 2116 case INIT: 2117 break; 2118 case XAR: 2119 if (strcmp(name, "xar") == 0) 2120 xar->xmlsts = INIT; 2121 break; 2122 case TOC: 2123 if (strcmp(name, "toc") == 0) 2124 xar->xmlsts = XAR; 2125 break; 2126 case TOC_CREATION_TIME: 2127 if (strcmp(name, "creation-time") == 0) 2128 xar->xmlsts = TOC; 2129 break; 2130 case TOC_CHECKSUM: 2131 if (strcmp(name, "checksum") == 0) 2132 xar->xmlsts = TOC; 2133 break; 2134 case TOC_CHECKSUM_OFFSET: 2135 if (strcmp(name, "offset") == 0) 2136 xar->xmlsts = TOC_CHECKSUM; 2137 break; 2138 case TOC_CHECKSUM_SIZE: 2139 if (strcmp(name, "size") == 0) 2140 xar->xmlsts = TOC_CHECKSUM; 2141 break; 2142 case TOC_FILE: 2143 if (strcmp(name, "file") == 0) { 2144 if (xar->file->parent != NULL && 2145 ((xar->file->mode & AE_IFMT) == AE_IFDIR)) 2146 xar->file->parent->subdirs++; 2147 xar->file = xar->file->parent; 2148 if (xar->file == NULL) 2149 xar->xmlsts = TOC; 2150 } 2151 break; 2152 case FILE_DATA: 2153 if (strcmp(name, "data") == 0) 2154 xar->xmlsts = TOC_FILE; 2155 break; 2156 case FILE_DATA_LENGTH: 2157 if (strcmp(name, "length") == 0) 2158 xar->xmlsts = FILE_DATA; 2159 break; 2160 case FILE_DATA_OFFSET: 2161 if (strcmp(name, "offset") == 0) 2162 xar->xmlsts = FILE_DATA; 2163 break; 2164 case FILE_DATA_SIZE: 2165 if (strcmp(name, "size") == 0) 2166 xar->xmlsts = FILE_DATA; 2167 break; 2168 case FILE_DATA_ENCODING: 2169 if (strcmp(name, "encoding") == 0) 2170 xar->xmlsts = FILE_DATA; 2171 break; 2172 case FILE_DATA_A_CHECKSUM: 2173 if (strcmp(name, "archived-checksum") == 0) 2174 xar->xmlsts = FILE_DATA; 2175 break; 2176 case FILE_DATA_E_CHECKSUM: 2177 if (strcmp(name, "extracted-checksum") == 0) 2178 xar->xmlsts = FILE_DATA; 2179 break; 2180 case FILE_DATA_CONTENT: 2181 if (strcmp(name, "content") == 0) 2182 xar->xmlsts = FILE_DATA; 2183 break; 2184 case FILE_EA: 2185 if (strcmp(name, "ea") == 0) { 2186 xar->xmlsts = TOC_FILE; 2187 xar->xattr = NULL; 2188 } 2189 break; 2190 case FILE_EA_LENGTH: 2191 if (strcmp(name, "length") == 0) 2192 xar->xmlsts = FILE_EA; 2193 break; 2194 case FILE_EA_OFFSET: 2195 if (strcmp(name, "offset") == 0) 2196 xar->xmlsts = FILE_EA; 2197 break; 2198 case FILE_EA_SIZE: 2199 if (strcmp(name, "size") == 0) 2200 xar->xmlsts = FILE_EA; 2201 break; 2202 case FILE_EA_ENCODING: 2203 if (strcmp(name, "encoding") == 0) 2204 xar->xmlsts = FILE_EA; 2205 break; 2206 case FILE_EA_A_CHECKSUM: 2207 if (strcmp(name, "archived-checksum") == 0) 2208 xar->xmlsts = FILE_EA; 2209 break; 2210 case FILE_EA_E_CHECKSUM: 2211 if (strcmp(name, "extracted-checksum") == 0) 2212 xar->xmlsts = FILE_EA; 2213 break; 2214 case FILE_EA_NAME: 2215 if (strcmp(name, "name") == 0) 2216 xar->xmlsts = FILE_EA; 2217 break; 2218 case FILE_EA_FSTYPE: 2219 if (strcmp(name, "fstype") == 0) 2220 xar->xmlsts = FILE_EA; 2221 break; 2222 case FILE_CTIME: 2223 if (strcmp(name, "ctime") == 0) 2224 xar->xmlsts = TOC_FILE; 2225 break; 2226 case FILE_MTIME: 2227 if (strcmp(name, "mtime") == 0) 2228 xar->xmlsts = TOC_FILE; 2229 break; 2230 case FILE_ATIME: 2231 if (strcmp(name, "atime") == 0) 2232 xar->xmlsts = TOC_FILE; 2233 break; 2234 case FILE_GROUP: 2235 if (strcmp(name, "group") == 0) 2236 xar->xmlsts = TOC_FILE; 2237 break; 2238 case FILE_GID: 2239 if (strcmp(name, "gid") == 0) 2240 xar->xmlsts = TOC_FILE; 2241 break; 2242 case FILE_USER: 2243 if (strcmp(name, "user") == 0) 2244 xar->xmlsts = TOC_FILE; 2245 break; 2246 case FILE_UID: 2247 if (strcmp(name, "uid") == 0) 2248 xar->xmlsts = TOC_FILE; 2249 break; 2250 case FILE_MODE: 2251 if (strcmp(name, "mode") == 0) 2252 xar->xmlsts = TOC_FILE; 2253 break; 2254 case FILE_DEVICE: 2255 if (strcmp(name, "device") == 0) 2256 xar->xmlsts = TOC_FILE; 2257 break; 2258 case FILE_DEVICE_MAJOR: 2259 if (strcmp(name, "major") == 0) 2260 xar->xmlsts = FILE_DEVICE; 2261 break; 2262 case FILE_DEVICE_MINOR: 2263 if (strcmp(name, "minor") == 0) 2264 xar->xmlsts = FILE_DEVICE; 2265 break; 2266 case FILE_DEVICENO: 2267 if (strcmp(name, "deviceno") == 0) 2268 xar->xmlsts = TOC_FILE; 2269 break; 2270 case FILE_INODE: 2271 if (strcmp(name, "inode") == 0) 2272 xar->xmlsts = TOC_FILE; 2273 break; 2274 case FILE_LINK: 2275 if (strcmp(name, "link") == 0) 2276 xar->xmlsts = TOC_FILE; 2277 break; 2278 case FILE_TYPE: 2279 if (strcmp(name, "type") == 0) 2280 xar->xmlsts = TOC_FILE; 2281 break; 2282 case FILE_NAME: 2283 if (strcmp(name, "name") == 0) 2284 xar->xmlsts = TOC_FILE; 2285 break; 2286 case FILE_ACL: 2287 if (strcmp(name, "acl") == 0) 2288 xar->xmlsts = TOC_FILE; 2289 break; 2290 case FILE_ACL_DEFAULT: 2291 if (strcmp(name, "default") == 0) 2292 xar->xmlsts = FILE_ACL; 2293 break; 2294 case FILE_ACL_ACCESS: 2295 if (strcmp(name, "access") == 0) 2296 xar->xmlsts = FILE_ACL; 2297 break; 2298 case FILE_ACL_APPLEEXTENDED: 2299 if (strcmp(name, "appleextended") == 0) 2300 xar->xmlsts = FILE_ACL; 2301 break; 2302 case FILE_FLAGS: 2303 if (strcmp(name, "flags") == 0) 2304 xar->xmlsts = TOC_FILE; 2305 break; 2306 case FILE_FLAGS_USER_NODUMP: 2307 if (strcmp(name, "UserNoDump") == 0) 2308 xar->xmlsts = FILE_FLAGS; 2309 break; 2310 case FILE_FLAGS_USER_IMMUTABLE: 2311 if (strcmp(name, "UserImmutable") == 0) 2312 xar->xmlsts = FILE_FLAGS; 2313 break; 2314 case FILE_FLAGS_USER_APPEND: 2315 if (strcmp(name, "UserAppend") == 0) 2316 xar->xmlsts = FILE_FLAGS; 2317 break; 2318 case FILE_FLAGS_USER_OPAQUE: 2319 if (strcmp(name, "UserOpaque") == 0) 2320 xar->xmlsts = FILE_FLAGS; 2321 break; 2322 case FILE_FLAGS_USER_NOUNLINK: 2323 if (strcmp(name, "UserNoUnlink") == 0) 2324 xar->xmlsts = FILE_FLAGS; 2325 break; 2326 case FILE_FLAGS_SYS_ARCHIVED: 2327 if (strcmp(name, "SystemArchived") == 0) 2328 xar->xmlsts = FILE_FLAGS; 2329 break; 2330 case FILE_FLAGS_SYS_IMMUTABLE: 2331 if (strcmp(name, "SystemImmutable") == 0) 2332 xar->xmlsts = FILE_FLAGS; 2333 break; 2334 case FILE_FLAGS_SYS_APPEND: 2335 if (strcmp(name, "SystemAppend") == 0) 2336 xar->xmlsts = FILE_FLAGS; 2337 break; 2338 case FILE_FLAGS_SYS_NOUNLINK: 2339 if (strcmp(name, "SystemNoUnlink") == 0) 2340 xar->xmlsts = FILE_FLAGS; 2341 break; 2342 case FILE_FLAGS_SYS_SNAPSHOT: 2343 if (strcmp(name, "SystemSnapshot") == 0) 2344 xar->xmlsts = FILE_FLAGS; 2345 break; 2346 case FILE_EXT2: 2347 if (strcmp(name, "ext2") == 0) 2348 xar->xmlsts = TOC_FILE; 2349 break; 2350 case FILE_EXT2_SecureDeletion: 2351 if (strcmp(name, "SecureDeletion") == 0) 2352 xar->xmlsts = FILE_EXT2; 2353 break; 2354 case FILE_EXT2_Undelete: 2355 if (strcmp(name, "Undelete") == 0) 2356 xar->xmlsts = FILE_EXT2; 2357 break; 2358 case FILE_EXT2_Compress: 2359 if (strcmp(name, "Compress") == 0) 2360 xar->xmlsts = FILE_EXT2; 2361 break; 2362 case FILE_EXT2_Synchronous: 2363 if (strcmp(name, "Synchronous") == 0) 2364 xar->xmlsts = FILE_EXT2; 2365 break; 2366 case FILE_EXT2_Immutable: 2367 if (strcmp(name, "Immutable") == 0) 2368 xar->xmlsts = FILE_EXT2; 2369 break; 2370 case FILE_EXT2_AppendOnly: 2371 if (strcmp(name, "AppendOnly") == 0) 2372 xar->xmlsts = FILE_EXT2; 2373 break; 2374 case FILE_EXT2_NoDump: 2375 if (strcmp(name, "NoDump") == 0) 2376 xar->xmlsts = FILE_EXT2; 2377 break; 2378 case FILE_EXT2_NoAtime: 2379 if (strcmp(name, "NoAtime") == 0) 2380 xar->xmlsts = FILE_EXT2; 2381 break; 2382 case FILE_EXT2_CompDirty: 2383 if (strcmp(name, "CompDirty") == 0) 2384 xar->xmlsts = FILE_EXT2; 2385 break; 2386 case FILE_EXT2_CompBlock: 2387 if (strcmp(name, "CompBlock") == 0) 2388 xar->xmlsts = FILE_EXT2; 2389 break; 2390 case FILE_EXT2_NoCompBlock: 2391 if (strcmp(name, "NoCompBlock") == 0) 2392 xar->xmlsts = FILE_EXT2; 2393 break; 2394 case FILE_EXT2_CompError: 2395 if (strcmp(name, "CompError") == 0) 2396 xar->xmlsts = FILE_EXT2; 2397 break; 2398 case FILE_EXT2_BTree: 2399 if (strcmp(name, "BTree") == 0) 2400 xar->xmlsts = FILE_EXT2; 2401 break; 2402 case FILE_EXT2_HashIndexed: 2403 if (strcmp(name, "HashIndexed") == 0) 2404 xar->xmlsts = FILE_EXT2; 2405 break; 2406 case FILE_EXT2_iMagic: 2407 if (strcmp(name, "iMagic") == 0) 2408 xar->xmlsts = FILE_EXT2; 2409 break; 2410 case FILE_EXT2_Journaled: 2411 if (strcmp(name, "Journaled") == 0) 2412 xar->xmlsts = FILE_EXT2; 2413 break; 2414 case FILE_EXT2_NoTail: 2415 if (strcmp(name, "NoTail") == 0) 2416 xar->xmlsts = FILE_EXT2; 2417 break; 2418 case FILE_EXT2_DirSync: 2419 if (strcmp(name, "DirSync") == 0) 2420 xar->xmlsts = FILE_EXT2; 2421 break; 2422 case FILE_EXT2_TopDir: 2423 if (strcmp(name, "TopDir") == 0) 2424 xar->xmlsts = FILE_EXT2; 2425 break; 2426 case FILE_EXT2_Reserved: 2427 if (strcmp(name, "Reserved") == 0) 2428 xar->xmlsts = FILE_EXT2; 2429 break; 2430 case UNKNOWN: 2431 unknowntag_end(xar, name); 2432 break; 2433 } 2434} 2435 2436static const int base64[256] = { 2437 -1, -1, -1, -1, -1, -1, -1, -1, 2438 -1, -1, -1, -1, -1, -1, -1, -1, /* 00 - 0F */ 2439 -1, -1, -1, -1, -1, -1, -1, -1, 2440 -1, -1, -1, -1, -1, -1, -1, -1, /* 10 - 1F */ 2441 -1, -1, -1, -1, -1, -1, -1, -1, 2442 -1, -1, -1, 62, -1, -1, -1, 63, /* 20 - 2F */ 2443 52, 53, 54, 55, 56, 57, 58, 59, 2444 60, 61, -1, -1, -1, -1, -1, -1, /* 30 - 3F */ 2445 -1, 0, 1, 2, 3, 4, 5, 6, 2446 7, 8, 9, 10, 11, 12, 13, 14, /* 40 - 4F */ 2447 15, 16, 17, 18, 19, 20, 21, 22, 2448 23, 24, 25, -1, -1, -1, -1, -1, /* 50 - 5F */ 2449 -1, 26, 27, 28, 29, 30, 31, 32, 2450 33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */ 2451 41, 42, 43, 44, 45, 46, 47, 48, 2452 49, 50, 51, -1, -1, -1, -1, -1, /* 70 - 7F */ 2453 -1, -1, -1, -1, -1, -1, -1, -1, 2454 -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 8F */ 2455 -1, -1, -1, -1, -1, -1, -1, -1, 2456 -1, -1, -1, -1, -1, -1, -1, -1, /* 90 - 9F */ 2457 -1, -1, -1, -1, -1, -1, -1, -1, 2458 -1, -1, -1, -1, -1, -1, -1, -1, /* A0 - AF */ 2459 -1, -1, -1, -1, -1, -1, -1, -1, 2460 -1, -1, -1, -1, -1, -1, -1, -1, /* B0 - BF */ 2461 -1, -1, -1, -1, -1, -1, -1, -1, 2462 -1, -1, -1, -1, -1, -1, -1, -1, /* C0 - CF */ 2463 -1, -1, -1, -1, -1, -1, -1, -1, 2464 -1, -1, -1, -1, -1, -1, -1, -1, /* D0 - DF */ 2465 -1, -1, -1, -1, -1, -1, -1, -1, 2466 -1, -1, -1, -1, -1, -1, -1, -1, /* E0 - EF */ 2467 -1, -1, -1, -1, -1, -1, -1, -1, 2468 -1, -1, -1, -1, -1, -1, -1, -1, /* F0 - FF */ 2469}; 2470 2471static void 2472strappend_base64(struct archive_string *as, const char *s, size_t l) 2473{ 2474 unsigned char buff[256]; 2475 unsigned char *out; 2476 const unsigned char *b; 2477 size_t len; 2478 2479 len = 0; 2480 out = buff; 2481 b = (const unsigned char *)s; 2482 while (l > 0) { 2483 int n = 0; 2484 2485 if (l > 0) { 2486 if (base64[b[0]] < 0 || base64[b[1]] < 0) 2487 break; 2488 n = base64[*b++] << 18; 2489 n |= base64[*b++] << 12; 2490 *out++ = n >> 16; 2491 len++; 2492 l -= 2; 2493 } 2494 if (l > 0) { 2495 if (base64[*b] < 0) 2496 break; 2497 n |= base64[*b++] << 6; 2498 *out++ = (n >> 8) & 0xFF; 2499 len++; 2500 --l; 2501 } 2502 if (l > 0) { 2503 if (base64[*b] < 0) 2504 break; 2505 n |= base64[*b++]; 2506 *out++ = n & 0xFF; 2507 len++; 2508 --l; 2509 } 2510 if (len+3 >= sizeof(buff)) { 2511 archive_strncat(as, (const char *)buff, len); 2512 len = 0; 2513 out = buff; 2514 } 2515 } 2516 if (len > 0) 2517 archive_strncat(as, (const char *)buff, len); 2518} 2519 2520static void 2521xml_data(void *userData, const char *s, int len) 2522{ 2523 struct archive_read *a; 2524 struct xar *xar; 2525 2526 a = (struct archive_read *)userData; 2527 xar = (struct xar *)(a->format->data); 2528 2529#if DEBUG 2530 { 2531 char buff[1024]; 2532 if (len > sizeof(buff)-1) 2533 len = sizeof(buff)-1; 2534 memcpy(buff, s, len); 2535 buff[len] = 0; 2536 fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff); 2537 } 2538#endif 2539 switch (xar->xmlsts) { 2540 case TOC_CHECKSUM_OFFSET: 2541 xar->toc_chksum_offset = atol10(s, len); 2542 break; 2543 case TOC_CHECKSUM_SIZE: 2544 xar->toc_chksum_size = atol10(s, len); 2545 break; 2546 default: 2547 break; 2548 } 2549 if (xar->file == NULL) 2550 return; 2551 2552 switch (xar->xmlsts) { 2553 case FILE_NAME: 2554 if (xar->file->parent != NULL) { 2555 archive_string_concat(&(xar->file->pathname), 2556 &(xar->file->parent->pathname)); 2557 archive_strappend_char(&(xar->file->pathname), '/'); 2558 } 2559 xar->file->has |= HAS_PATHNAME; 2560 if (xar->base64text) 2561 strappend_base64(&(xar->file->pathname), s, len); 2562 else 2563 archive_strncat(&(xar->file->pathname), s, len); 2564 break; 2565 case FILE_LINK: 2566 xar->file->has |= HAS_SYMLINK; 2567 archive_strncpy(&(xar->file->symlink), s, len); 2568 break; 2569 case FILE_TYPE: 2570 if (strncmp("file", s, len) == 0 || 2571 strncmp("hardlink", s, len) == 0) 2572 xar->file->mode = 2573 (xar->file->mode & ~AE_IFMT) | AE_IFREG; 2574 if (strncmp("directory", s, len) == 0) 2575 xar->file->mode = 2576 (xar->file->mode & ~AE_IFMT) | AE_IFDIR; 2577 if (strncmp("symlink", s, len) == 0) 2578 xar->file->mode = 2579 (xar->file->mode & ~AE_IFMT) | AE_IFLNK; 2580 if (strncmp("character special", s, len) == 0) 2581 xar->file->mode = 2582 (xar->file->mode & ~AE_IFMT) | AE_IFCHR; 2583 if (strncmp("block special", s, len) == 0) 2584 xar->file->mode = 2585 (xar->file->mode & ~AE_IFMT) | AE_IFBLK; 2586 if (strncmp("socket", s, len) == 0) 2587 xar->file->mode = 2588 (xar->file->mode & ~AE_IFMT) | AE_IFSOCK; 2589 if (strncmp("fifo", s, len) == 0) 2590 xar->file->mode = 2591 (xar->file->mode & ~AE_IFMT) | AE_IFIFO; 2592 xar->file->has |= HAS_TYPE; 2593 break; 2594 case FILE_INODE: 2595 xar->file->has |= HAS_INO; 2596 xar->file->ino64 = atol10(s, len); 2597 break; 2598 case FILE_DEVICE_MAJOR: 2599 xar->file->has |= HAS_DEVMAJOR; 2600 xar->file->devmajor = (dev_t)atol10(s, len); 2601 break; 2602 case FILE_DEVICE_MINOR: 2603 xar->file->has |= HAS_DEVMINOR; 2604 xar->file->devminor = (dev_t)atol10(s, len); 2605 break; 2606 case FILE_DEVICENO: 2607 xar->file->has |= HAS_DEV; 2608 xar->file->dev = (dev_t)atol10(s, len); 2609 break; 2610 case FILE_MODE: 2611 xar->file->has |= HAS_MODE; 2612 xar->file->mode = 2613 (xar->file->mode & AE_IFMT) | 2614 (atol8(s, len) & ~AE_IFMT); 2615 break; 2616 case FILE_GROUP: 2617 xar->file->has |= HAS_GID; 2618 archive_strncpy(&(xar->file->gname), s, len); 2619 break; 2620 case FILE_GID: 2621 xar->file->has |= HAS_GID; 2622 xar->file->gid = atol10(s, len); 2623 break; 2624 case FILE_USER: 2625 xar->file->has |= HAS_UID; 2626 archive_strncpy(&(xar->file->uname), s, len); 2627 break; 2628 case FILE_UID: 2629 xar->file->has |= HAS_UID; 2630 xar->file->uid = atol10(s, len); 2631 break; 2632 case FILE_CTIME: 2633 xar->file->has |= HAS_TIME; 2634 xar->file->ctime = parse_time(s, len); 2635 break; 2636 case FILE_MTIME: 2637 xar->file->has |= HAS_TIME; 2638 xar->file->mtime = parse_time(s, len); 2639 break; 2640 case FILE_ATIME: 2641 xar->file->has |= HAS_TIME; 2642 xar->file->atime = parse_time(s, len); 2643 break; 2644 case FILE_DATA_LENGTH: 2645 xar->file->has |= HAS_DATA; 2646 xar->file->length = atol10(s, len); 2647 break; 2648 case FILE_DATA_OFFSET: 2649 xar->file->has |= HAS_DATA; 2650 xar->file->offset = atol10(s, len); 2651 break; 2652 case FILE_DATA_SIZE: 2653 xar->file->has |= HAS_DATA; 2654 xar->file->size = atol10(s, len); 2655 break; 2656 case FILE_DATA_A_CHECKSUM: 2657 xar->file->a_sum.len = atohex(xar->file->a_sum.val, 2658 sizeof(xar->file->a_sum.val), s, len); 2659 break; 2660 case FILE_DATA_E_CHECKSUM: 2661 xar->file->e_sum.len = atohex(xar->file->e_sum.val, 2662 sizeof(xar->file->e_sum.val), s, len); 2663 break; 2664 case FILE_EA_LENGTH: 2665 xar->file->has |= HAS_XATTR; 2666 xar->xattr->length = atol10(s, len); 2667 break; 2668 case FILE_EA_OFFSET: 2669 xar->file->has |= HAS_XATTR; 2670 xar->xattr->offset = atol10(s, len); 2671 break; 2672 case FILE_EA_SIZE: 2673 xar->file->has |= HAS_XATTR; 2674 xar->xattr->size = atol10(s, len); 2675 break; 2676 case FILE_EA_A_CHECKSUM: 2677 xar->file->has |= HAS_XATTR; 2678 xar->xattr->a_sum.len = atohex(xar->xattr->a_sum.val, 2679 sizeof(xar->xattr->a_sum.val), s, len); 2680 break; 2681 case FILE_EA_E_CHECKSUM: 2682 xar->file->has |= HAS_XATTR; 2683 xar->xattr->e_sum.len = atohex(xar->xattr->e_sum.val, 2684 sizeof(xar->xattr->e_sum.val), s, len); 2685 break; 2686 case FILE_EA_NAME: 2687 xar->file->has |= HAS_XATTR; 2688 archive_strncpy(&(xar->xattr->name), s, len); 2689 break; 2690 case FILE_EA_FSTYPE: 2691 xar->file->has |= HAS_XATTR; 2692 archive_strncpy(&(xar->xattr->fstype), s, len); 2693 break; 2694 break; 2695 case FILE_ACL_DEFAULT: 2696 case FILE_ACL_ACCESS: 2697 case FILE_ACL_APPLEEXTENDED: 2698 xar->file->has |= HAS_ACL; 2699 /* TODO */ 2700 break; 2701 case INIT: 2702 case XAR: 2703 case TOC: 2704 case TOC_CREATION_TIME: 2705 case TOC_CHECKSUM: 2706 case TOC_CHECKSUM_OFFSET: 2707 case TOC_CHECKSUM_SIZE: 2708 case TOC_FILE: 2709 case FILE_DATA: 2710 case FILE_DATA_ENCODING: 2711 case FILE_DATA_CONTENT: 2712 case FILE_DEVICE: 2713 case FILE_EA: 2714 case FILE_EA_ENCODING: 2715 case FILE_ACL: 2716 case FILE_FLAGS: 2717 case FILE_FLAGS_USER_NODUMP: 2718 case FILE_FLAGS_USER_IMMUTABLE: 2719 case FILE_FLAGS_USER_APPEND: 2720 case FILE_FLAGS_USER_OPAQUE: 2721 case FILE_FLAGS_USER_NOUNLINK: 2722 case FILE_FLAGS_SYS_ARCHIVED: 2723 case FILE_FLAGS_SYS_IMMUTABLE: 2724 case FILE_FLAGS_SYS_APPEND: 2725 case FILE_FLAGS_SYS_NOUNLINK: 2726 case FILE_FLAGS_SYS_SNAPSHOT: 2727 case FILE_EXT2: 2728 case FILE_EXT2_SecureDeletion: 2729 case FILE_EXT2_Undelete: 2730 case FILE_EXT2_Compress: 2731 case FILE_EXT2_Synchronous: 2732 case FILE_EXT2_Immutable: 2733 case FILE_EXT2_AppendOnly: 2734 case FILE_EXT2_NoDump: 2735 case FILE_EXT2_NoAtime: 2736 case FILE_EXT2_CompDirty: 2737 case FILE_EXT2_CompBlock: 2738 case FILE_EXT2_NoCompBlock: 2739 case FILE_EXT2_CompError: 2740 case FILE_EXT2_BTree: 2741 case FILE_EXT2_HashIndexed: 2742 case FILE_EXT2_iMagic: 2743 case FILE_EXT2_Journaled: 2744 case FILE_EXT2_NoTail: 2745 case FILE_EXT2_DirSync: 2746 case FILE_EXT2_TopDir: 2747 case FILE_EXT2_Reserved: 2748 case UNKNOWN: 2749 break; 2750 } 2751} 2752 2753/* 2754 * BSD file flags. 2755 */ 2756static int 2757xml_parse_file_flags(struct xar *xar, const char *name) 2758{ 2759 const char *flag = NULL; 2760 2761 if (strcmp(name, "UserNoDump") == 0) { 2762 xar->xmlsts = FILE_FLAGS_USER_NODUMP; 2763 flag = "nodump"; 2764 } 2765 else if (strcmp(name, "UserImmutable") == 0) { 2766 xar->xmlsts = FILE_FLAGS_USER_IMMUTABLE; 2767 flag = "uimmutable"; 2768 } 2769 else if (strcmp(name, "UserAppend") == 0) { 2770 xar->xmlsts = FILE_FLAGS_USER_APPEND; 2771 flag = "uappend"; 2772 } 2773 else if (strcmp(name, "UserOpaque") == 0) { 2774 xar->xmlsts = FILE_FLAGS_USER_OPAQUE; 2775 flag = "opaque"; 2776 } 2777 else if (strcmp(name, "UserNoUnlink") == 0) { 2778 xar->xmlsts = FILE_FLAGS_USER_NOUNLINK; 2779 flag = "nouunlink"; 2780 } 2781 else if (strcmp(name, "SystemArchived") == 0) { 2782 xar->xmlsts = FILE_FLAGS_SYS_ARCHIVED; 2783 flag = "archived"; 2784 } 2785 else if (strcmp(name, "SystemImmutable") == 0) { 2786 xar->xmlsts = FILE_FLAGS_SYS_IMMUTABLE; 2787 flag = "simmutable"; 2788 } 2789 else if (strcmp(name, "SystemAppend") == 0) { 2790 xar->xmlsts = FILE_FLAGS_SYS_APPEND; 2791 flag = "sappend"; 2792 } 2793 else if (strcmp(name, "SystemNoUnlink") == 0) { 2794 xar->xmlsts = FILE_FLAGS_SYS_NOUNLINK; 2795 flag = "nosunlink"; 2796 } 2797 else if (strcmp(name, "SystemSnapshot") == 0) { 2798 xar->xmlsts = FILE_FLAGS_SYS_SNAPSHOT; 2799 flag = "snapshot"; 2800 } 2801 2802 if (flag == NULL) 2803 return (0); 2804 xar->file->has |= HAS_FFLAGS; 2805 if (archive_strlen(&(xar->file->fflags_text)) > 0) 2806 archive_strappend_char(&(xar->file->fflags_text), ','); 2807 archive_strcat(&(xar->file->fflags_text), flag); 2808 return (1); 2809} 2810 2811/* 2812 * Linux file flags. 2813 */ 2814static int 2815xml_parse_file_ext2(struct xar *xar, const char *name) 2816{ 2817 const char *flag = NULL; 2818 2819 if (strcmp(name, "SecureDeletion") == 0) { 2820 xar->xmlsts = FILE_EXT2_SecureDeletion; 2821 flag = "securedeletion"; 2822 } 2823 else if (strcmp(name, "Undelete") == 0) { 2824 xar->xmlsts = FILE_EXT2_Undelete; 2825 flag = "nouunlink"; 2826 } 2827 else if (strcmp(name, "Compress") == 0) { 2828 xar->xmlsts = FILE_EXT2_Compress; 2829 flag = "compress"; 2830 } 2831 else if (strcmp(name, "Synchronous") == 0) { 2832 xar->xmlsts = FILE_EXT2_Synchronous; 2833 flag = "sync"; 2834 } 2835 else if (strcmp(name, "Immutable") == 0) { 2836 xar->xmlsts = FILE_EXT2_Immutable; 2837 flag = "simmutable"; 2838 } 2839 else if (strcmp(name, "AppendOnly") == 0) { 2840 xar->xmlsts = FILE_EXT2_AppendOnly; 2841 flag = "sappend"; 2842 } 2843 else if (strcmp(name, "NoDump") == 0) { 2844 xar->xmlsts = FILE_EXT2_NoDump; 2845 flag = "nodump"; 2846 } 2847 else if (strcmp(name, "NoAtime") == 0) { 2848 xar->xmlsts = FILE_EXT2_NoAtime; 2849 flag = "noatime"; 2850 } 2851 else if (strcmp(name, "CompDirty") == 0) { 2852 xar->xmlsts = FILE_EXT2_CompDirty; 2853 flag = "compdirty"; 2854 } 2855 else if (strcmp(name, "CompBlock") == 0) { 2856 xar->xmlsts = FILE_EXT2_CompBlock; 2857 flag = "comprblk"; 2858 } 2859 else if (strcmp(name, "NoCompBlock") == 0) { 2860 xar->xmlsts = FILE_EXT2_NoCompBlock; 2861 flag = "nocomprblk"; 2862 } 2863 else if (strcmp(name, "CompError") == 0) { 2864 xar->xmlsts = FILE_EXT2_CompError; 2865 flag = "comperr"; 2866 } 2867 else if (strcmp(name, "BTree") == 0) { 2868 xar->xmlsts = FILE_EXT2_BTree; 2869 flag = "btree"; 2870 } 2871 else if (strcmp(name, "HashIndexed") == 0) { 2872 xar->xmlsts = FILE_EXT2_HashIndexed; 2873 flag = "hashidx"; 2874 } 2875 else if (strcmp(name, "iMagic") == 0) { 2876 xar->xmlsts = FILE_EXT2_iMagic; 2877 flag = "imagic"; 2878 } 2879 else if (strcmp(name, "Journaled") == 0) { 2880 xar->xmlsts = FILE_EXT2_Journaled; 2881 flag = "journal"; 2882 } 2883 else if (strcmp(name, "NoTail") == 0) { 2884 xar->xmlsts = FILE_EXT2_NoTail; 2885 flag = "notail"; 2886 } 2887 else if (strcmp(name, "DirSync") == 0) { 2888 xar->xmlsts = FILE_EXT2_DirSync; 2889 flag = "dirsync"; 2890 } 2891 else if (strcmp(name, "TopDir") == 0) { 2892 xar->xmlsts = FILE_EXT2_TopDir; 2893 flag = "topdir"; 2894 } 2895 else if (strcmp(name, "Reserved") == 0) { 2896 xar->xmlsts = FILE_EXT2_Reserved; 2897 flag = "reserved"; 2898 } 2899 2900 if (flag == NULL) 2901 return (0); 2902 if (archive_strlen(&(xar->file->fflags_text)) > 0) 2903 archive_strappend_char(&(xar->file->fflags_text), ','); 2904 archive_strcat(&(xar->file->fflags_text), flag); 2905 return (1); 2906} 2907 2908#ifdef HAVE_LIBXML_XMLREADER_H 2909 2910static int 2911xml2_xmlattr_setup(struct xmlattr_list *list, xmlTextReaderPtr reader) 2912{ 2913 struct xmlattr *attr; 2914 int r; 2915 2916 list->first = NULL; 2917 list->last = &(list->first); 2918 r = xmlTextReaderMoveToFirstAttribute(reader); 2919 while (r == 1) { 2920 attr = malloc(sizeof*(attr)); 2921 if (attr == NULL) 2922 __archive_errx(1, "Out of memory"); 2923 attr->name = strdup( 2924 (const char *)xmlTextReaderConstLocalName(reader)); 2925 if (attr->name == NULL) 2926 __archive_errx(1, "Out of memory"); 2927 attr->value = strdup( 2928 (const char *)xmlTextReaderConstValue(reader)); 2929 if (attr->value == NULL) 2930 __archive_errx(1, "Out of memory"); 2931 attr->next = NULL; 2932 *list->last = attr; 2933 list->last = &(attr->next); 2934 r = xmlTextReaderMoveToNextAttribute(reader); 2935 } 2936 return (r); 2937} 2938 2939static int 2940xml2_read_cb(void *context, char *buffer, int len) 2941{ 2942 struct archive_read *a; 2943 struct xar *xar; 2944 const void *d; 2945 size_t outbytes; 2946 size_t used; 2947 int r; 2948 2949 a = (struct archive_read *)context; 2950 xar = (struct xar *)(a->format->data); 2951 2952 if (xar->toc_remaining <= 0) 2953 return (0); 2954 d = buffer; 2955 outbytes = len; 2956 r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); 2957 if (r != ARCHIVE_OK) 2958 return (r); 2959 __archive_read_consume(a, used); 2960 xar->toc_remaining -= used; 2961 xar->offset += used; 2962 xar->toc_total += outbytes; 2963 PRINT_TOC(buffer, len); 2964 2965 return ((int)outbytes); 2966} 2967 2968static int 2969xml2_close_cb(void *context) 2970{ 2971 2972 (void)context; /* UNUSED */ 2973 return (0); 2974} 2975 2976static void 2977xml2_error_hdr(void *arg, const char *msg, xmlParserSeverities severity, 2978 xmlTextReaderLocatorPtr locator) 2979{ 2980 struct archive_read *a; 2981 2982 (void)locator; /* UNUSED */ 2983 a = (struct archive_read *)arg; 2984 switch (severity) { 2985 case XML_PARSER_SEVERITY_VALIDITY_WARNING: 2986 case XML_PARSER_SEVERITY_WARNING: 2987 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 2988 "XML Parsing error: %s", msg); 2989 break; 2990 case XML_PARSER_SEVERITY_VALIDITY_ERROR: 2991 case XML_PARSER_SEVERITY_ERROR: 2992 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 2993 "XML Parsing error: %s", msg); 2994 break; 2995 } 2996} 2997 2998static int 2999xml2_read_toc(struct archive_read *a) 3000{ 3001 xmlTextReaderPtr reader; 3002 struct xmlattr_list list; 3003 int r; 3004 3005 reader = xmlReaderForIO(xml2_read_cb, xml2_close_cb, a, NULL, NULL, 0); 3006 if (reader == NULL) { 3007 archive_set_error(&a->archive, ENOMEM, 3008 "Couldn't allocate memory for xml parser"); 3009 return (ARCHIVE_FATAL); 3010 } 3011 xmlTextReaderSetErrorHandler(reader, xml2_error_hdr, a); 3012 3013 while ((r = xmlTextReaderRead(reader)) == 1) { 3014 const char *name, *value; 3015 int type, empty; 3016 3017 type = xmlTextReaderNodeType(reader); 3018 name = (const char *)xmlTextReaderConstLocalName(reader); 3019 switch (type) { 3020 case XML_READER_TYPE_ELEMENT: 3021 empty = xmlTextReaderIsEmptyElement(reader); 3022 r = xml2_xmlattr_setup(&list, reader); 3023 if (r == 0) { 3024 xml_start(a, name, &list); 3025 xmlattr_cleanup(&list); 3026 if (empty) 3027 xml_end(a, name); 3028 } 3029 break; 3030 case XML_READER_TYPE_END_ELEMENT: 3031 xml_end(a, name); 3032 break; 3033 case XML_READER_TYPE_TEXT: 3034 value = (const char *)xmlTextReaderConstValue(reader); 3035 xml_data(a, value, strlen(value)); 3036 break; 3037 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: 3038 default: 3039 break; 3040 } 3041 if (r < 0) 3042 break; 3043 } 3044 xmlFreeTextReader(reader); 3045 xmlCleanupParser(); 3046 3047 return ((r == 0)?ARCHIVE_OK:ARCHIVE_FATAL); 3048} 3049 3050#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) 3051 3052static void 3053expat_xmlattr_setup(struct xmlattr_list *list, const XML_Char **atts) 3054{ 3055 struct xmlattr *attr; 3056 3057 list->first = NULL; 3058 list->last = &(list->first); 3059 if (atts == NULL) 3060 return; 3061 while (atts[0] != NULL && atts[1] != NULL) { 3062 attr = malloc(sizeof*(attr)); 3063 if (attr == NULL) 3064 __archive_errx(1, "Out of memory"); 3065 attr->name = strdup(atts[0]); 3066 if (attr->name == NULL) 3067 __archive_errx(1, "Out of memory"); 3068 attr->value = strdup(atts[1]); 3069 if (attr->value == NULL) 3070 __archive_errx(1, "Out of memory"); 3071 attr->next = NULL; 3072 *list->last = attr; 3073 list->last = &(attr->next); 3074 atts += 2; 3075 } 3076} 3077 3078static void 3079expat_start_cb(void *userData, const XML_Char *name, const XML_Char **atts) 3080{ 3081 struct xmlattr_list list; 3082 3083 expat_xmlattr_setup(&list, atts); 3084 xml_start(userData, (const char *)name, &list); 3085 xmlattr_cleanup(&list); 3086} 3087 3088static void 3089expat_end_cb(void *userData, const XML_Char *name) 3090{ 3091 xml_end(userData, (const char *)name); 3092} 3093 3094static void 3095expat_data_cb(void *userData, const XML_Char *s, int len) 3096{ 3097 xml_data(userData, s, len); 3098} 3099 3100static int 3101expat_read_toc(struct archive_read *a) 3102{ 3103 struct xar *xar; 3104 XML_Parser parser; 3105 3106 xar = (struct xar *)(a->format->data); 3107 3108 /* Initialize XML Parser library. */ 3109 parser = XML_ParserCreate(NULL); 3110 if (parser == NULL) { 3111 archive_set_error(&a->archive, ENOMEM, 3112 "Couldn't allocate memory for xml parser"); 3113 return (ARCHIVE_FATAL); 3114 } 3115 XML_SetUserData(parser, a); 3116 XML_SetElementHandler(parser, expat_start_cb, expat_end_cb); 3117 XML_SetCharacterDataHandler(parser, expat_data_cb); 3118 xar->xmlsts = INIT; 3119 3120 while (xar->toc_remaining) { 3121 enum XML_Status xr; 3122 const void *d; 3123 size_t outbytes; 3124 size_t used; 3125 int r; 3126 3127 d = NULL; 3128 r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); 3129 if (r != ARCHIVE_OK) 3130 return (r); 3131 __archive_read_consume(a, used); 3132 xar->toc_remaining -= used; 3133 xar->offset += used; 3134 xar->toc_total += outbytes; 3135 PRINT_TOC(d, outbytes); 3136 3137 xr = XML_Parse(parser, d, outbytes, xar->toc_remaining == 0); 3138 if (xr == XML_STATUS_ERROR) { 3139 XML_ParserFree(parser); 3140 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 3141 "XML Parsing failed"); 3142 return (ARCHIVE_FATAL); 3143 } 3144 } 3145 XML_ParserFree(parser); 3146 return (ARCHIVE_OK); 3147} 3148#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */ 3149 3150#endif /* Support xar format */ 3151