1228753Smm/*- 2228753Smm * Copyright (c) 2009 Michihiro NAKAJIMA 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm#include "archive_platform.h" 26228753Smm__FBSDID("$FreeBSD: releng/10.3/contrib/libarchive/libarchive/archive_read_support_format_xar.c 248616 2013-03-22 13:36:03Z mm $"); 27228753Smm 28228753Smm#ifdef HAVE_ERRNO_H 29228753Smm#include <errno.h> 30228753Smm#endif 31228753Smm#ifdef HAVE_STDLIB_H 32228753Smm#include <stdlib.h> 33228753Smm#endif 34228753Smm#if HAVE_LIBXML_XMLREADER_H 35228753Smm#include <libxml/xmlreader.h> 36228753Smm#elif HAVE_BSDXML_H 37228753Smm#include <bsdxml.h> 38228753Smm#elif HAVE_EXPAT_H 39228753Smm#include <expat.h> 40228753Smm#endif 41228753Smm#ifdef HAVE_BZLIB_H 42228753Smm#include <bzlib.h> 43228753Smm#endif 44228753Smm#if HAVE_LZMA_H 45228753Smm#include <lzma.h> 46228753Smm#elif HAVE_LZMADEC_H 47228753Smm#include <lzmadec.h> 48228753Smm#endif 49228753Smm#ifdef HAVE_ZLIB_H 50228753Smm#include <zlib.h> 51228753Smm#endif 52228753Smm 53228753Smm#include "archive.h" 54232153Smm#include "archive_crypto_private.h" 55228753Smm#include "archive_endian.h" 56228753Smm#include "archive_entry.h" 57232153Smm#include "archive_entry_locale.h" 58228753Smm#include "archive_private.h" 59228753Smm#include "archive_read_private.h" 60228753Smm 61228753Smm#if (!defined(HAVE_LIBXML_XMLREADER_H) && \ 62228753Smm !defined(HAVE_BSDXML_H) && !defined(HAVE_EXPAT_H)) ||\ 63228753Smm !defined(HAVE_ZLIB_H) || \ 64228753Smm !defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1) 65228753Smm/* 66228753Smm * xar needs several external libraries. 67228753Smm * o libxml2 or expat --- XML parser 68228753Smm * o openssl or MD5/SHA1 hash function 69228753Smm * o zlib 70228753Smm * o bzlib2 (option) 71228753Smm * o liblzma (option) 72228753Smm */ 73228753Smmint 74228753Smmarchive_read_support_format_xar(struct archive *_a) 75228753Smm{ 76228753Smm struct archive_read *a = (struct archive_read *)_a; 77232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 78232153Smm ARCHIVE_STATE_NEW, "archive_read_support_format_xar"); 79228753Smm 80228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 81228753Smm "Xar not supported on this platform"); 82228753Smm return (ARCHIVE_WARN); 83228753Smm} 84228753Smm 85228753Smm#else /* Support xar format */ 86228753Smm 87232153Smm/* #define DEBUG 1 */ 88232153Smm/* #define DEBUG_PRINT_TOC 1 */ 89228753Smm#if DEBUG_PRINT_TOC 90228753Smm#define PRINT_TOC(d, outbytes) do { \ 91228753Smm unsigned char *x = (unsigned char *)(uintptr_t)d; \ 92228753Smm unsigned char c = x[outbytes-1]; \ 93228753Smm x[outbytes - 1] = 0; \ 94228753Smm fprintf(stderr, "%s", x); \ 95228753Smm fprintf(stderr, "%c", c); \ 96228753Smm x[outbytes - 1] = c; \ 97228753Smm} while (0) 98228753Smm#else 99228753Smm#define PRINT_TOC(d, outbytes) 100228753Smm#endif 101228753Smm 102228753Smm#define HEADER_MAGIC 0x78617221 103228753Smm#define HEADER_SIZE 28 104228753Smm#define HEADER_VERSION 1 105228753Smm#define CKSUM_NONE 0 106228753Smm#define CKSUM_SHA1 1 107228753Smm#define CKSUM_MD5 2 108228753Smm 109228753Smm#define MD5_SIZE 16 110228753Smm#define SHA1_SIZE 20 111228753Smm#define MAX_SUM_SIZE 20 112228753Smm 113228753Smmenum enctype { 114228753Smm NONE, 115228753Smm GZIP, 116228753Smm BZIP2, 117228753Smm LZMA, 118228753Smm XZ, 119228753Smm}; 120228753Smm 121228753Smmstruct chksumval { 122228753Smm int alg; 123228753Smm size_t len; 124228753Smm unsigned char val[MAX_SUM_SIZE]; 125228753Smm}; 126228753Smm 127228753Smmstruct chksumwork { 128228753Smm int alg; 129228753Smm#ifdef ARCHIVE_HAS_MD5 130228753Smm archive_md5_ctx md5ctx; 131228753Smm#endif 132228753Smm#ifdef ARCHIVE_HAS_SHA1 133228753Smm archive_sha1_ctx sha1ctx; 134228753Smm#endif 135228753Smm}; 136228753Smm 137228753Smmstruct xattr { 138228753Smm struct xattr *next; 139228753Smm struct archive_string name; 140228753Smm uint64_t id; 141228753Smm uint64_t length; 142228753Smm uint64_t offset; 143228753Smm uint64_t size; 144228753Smm enum enctype encoding; 145228753Smm struct chksumval a_sum; 146228753Smm struct chksumval e_sum; 147228753Smm struct archive_string fstype; 148228753Smm}; 149228753Smm 150228753Smmstruct xar_file { 151228753Smm struct xar_file *next; 152228753Smm struct xar_file *hdnext; 153228753Smm struct xar_file *parent; 154228753Smm int subdirs; 155228753Smm 156228753Smm unsigned int has; 157228753Smm#define HAS_DATA 0x00001 158228753Smm#define HAS_PATHNAME 0x00002 159228753Smm#define HAS_SYMLINK 0x00004 160228753Smm#define HAS_TIME 0x00008 161228753Smm#define HAS_UID 0x00010 162228753Smm#define HAS_GID 0x00020 163228753Smm#define HAS_MODE 0x00040 164228753Smm#define HAS_TYPE 0x00080 165228753Smm#define HAS_DEV 0x00100 166228753Smm#define HAS_DEVMAJOR 0x00200 167228753Smm#define HAS_DEVMINOR 0x00400 168228753Smm#define HAS_INO 0x00800 169228753Smm#define HAS_FFLAGS 0x01000 170228753Smm#define HAS_XATTR 0x02000 171228753Smm#define HAS_ACL 0x04000 172228753Smm 173228753Smm uint64_t id; 174228753Smm uint64_t length; 175228753Smm uint64_t offset; 176228753Smm uint64_t size; 177228753Smm enum enctype encoding; 178228753Smm struct chksumval a_sum; 179228753Smm struct chksumval e_sum; 180228753Smm struct archive_string pathname; 181228753Smm struct archive_string symlink; 182228753Smm time_t ctime; 183228753Smm time_t mtime; 184228753Smm time_t atime; 185228753Smm struct archive_string uname; 186238856Smm int64_t uid; 187228753Smm struct archive_string gname; 188238856Smm int64_t gid; 189228753Smm mode_t mode; 190228753Smm dev_t dev; 191228753Smm dev_t devmajor; 192228753Smm dev_t devminor; 193228753Smm int64_t ino64; 194228753Smm struct archive_string fflags_text; 195228753Smm unsigned int link; 196228753Smm unsigned int nlink; 197228753Smm struct archive_string hardlink; 198228753Smm struct xattr *xattr_list; 199228753Smm}; 200228753Smm 201228753Smmstruct hdlink { 202228753Smm struct hdlink *next; 203228753Smm 204228753Smm unsigned int id; 205228753Smm int cnt; 206228753Smm struct xar_file *files; 207228753Smm}; 208228753Smm 209228753Smmstruct heap_queue { 210228753Smm struct xar_file **files; 211228753Smm int allocated; 212228753Smm int used; 213228753Smm}; 214228753Smm 215228753Smmenum xmlstatus { 216228753Smm INIT, 217228753Smm XAR, 218228753Smm TOC, 219228753Smm TOC_CREATION_TIME, 220228753Smm TOC_CHECKSUM, 221228753Smm TOC_CHECKSUM_OFFSET, 222228753Smm TOC_CHECKSUM_SIZE, 223228753Smm TOC_FILE, 224228753Smm FILE_DATA, 225228753Smm FILE_DATA_LENGTH, 226228753Smm FILE_DATA_OFFSET, 227228753Smm FILE_DATA_SIZE, 228228753Smm FILE_DATA_ENCODING, 229228753Smm FILE_DATA_A_CHECKSUM, 230228753Smm FILE_DATA_E_CHECKSUM, 231228753Smm FILE_DATA_CONTENT, 232228753Smm FILE_EA, 233228753Smm FILE_EA_LENGTH, 234228753Smm FILE_EA_OFFSET, 235228753Smm FILE_EA_SIZE, 236228753Smm FILE_EA_ENCODING, 237228753Smm FILE_EA_A_CHECKSUM, 238228753Smm FILE_EA_E_CHECKSUM, 239228753Smm FILE_EA_NAME, 240228753Smm FILE_EA_FSTYPE, 241228753Smm FILE_CTIME, 242228753Smm FILE_MTIME, 243228753Smm FILE_ATIME, 244228753Smm FILE_GROUP, 245228753Smm FILE_GID, 246228753Smm FILE_USER, 247228753Smm FILE_UID, 248228753Smm FILE_MODE, 249228753Smm FILE_DEVICE, 250228753Smm FILE_DEVICE_MAJOR, 251228753Smm FILE_DEVICE_MINOR, 252228753Smm FILE_DEVICENO, 253228753Smm FILE_INODE, 254228753Smm FILE_LINK, 255228753Smm FILE_TYPE, 256228753Smm FILE_NAME, 257228753Smm FILE_ACL, 258228753Smm FILE_ACL_DEFAULT, 259228753Smm FILE_ACL_ACCESS, 260228753Smm FILE_ACL_APPLEEXTENDED, 261228753Smm /* BSD file flags. */ 262228753Smm FILE_FLAGS, 263228753Smm FILE_FLAGS_USER_NODUMP, 264228753Smm FILE_FLAGS_USER_IMMUTABLE, 265228753Smm FILE_FLAGS_USER_APPEND, 266228753Smm FILE_FLAGS_USER_OPAQUE, 267228753Smm FILE_FLAGS_USER_NOUNLINK, 268228753Smm FILE_FLAGS_SYS_ARCHIVED, 269228753Smm FILE_FLAGS_SYS_IMMUTABLE, 270228753Smm FILE_FLAGS_SYS_APPEND, 271228753Smm FILE_FLAGS_SYS_NOUNLINK, 272228753Smm FILE_FLAGS_SYS_SNAPSHOT, 273228753Smm /* Linux file flags. */ 274228753Smm FILE_EXT2, 275228753Smm FILE_EXT2_SecureDeletion, 276228753Smm FILE_EXT2_Undelete, 277228753Smm FILE_EXT2_Compress, 278228753Smm FILE_EXT2_Synchronous, 279228753Smm FILE_EXT2_Immutable, 280228753Smm FILE_EXT2_AppendOnly, 281228753Smm FILE_EXT2_NoDump, 282228753Smm FILE_EXT2_NoAtime, 283228753Smm FILE_EXT2_CompDirty, 284228753Smm FILE_EXT2_CompBlock, 285228753Smm FILE_EXT2_NoCompBlock, 286228753Smm FILE_EXT2_CompError, 287228753Smm FILE_EXT2_BTree, 288228753Smm FILE_EXT2_HashIndexed, 289228753Smm FILE_EXT2_iMagic, 290228753Smm FILE_EXT2_Journaled, 291228753Smm FILE_EXT2_NoTail, 292228753Smm FILE_EXT2_DirSync, 293228753Smm FILE_EXT2_TopDir, 294228753Smm FILE_EXT2_Reserved, 295228753Smm UNKNOWN, 296228753Smm}; 297228753Smm 298228753Smmstruct unknown_tag { 299228753Smm struct unknown_tag *next; 300228753Smm struct archive_string name; 301228753Smm}; 302228753Smm 303228753Smmstruct xar { 304228753Smm uint64_t offset; /* Current position in the file. */ 305228753Smm int64_t total; 306228753Smm uint64_t h_base; 307228753Smm int end_of_file; 308232153Smm#define OUTBUFF_SIZE (1024 * 64) 309232153Smm unsigned char *outbuff; 310228753Smm 311228753Smm enum xmlstatus xmlsts; 312228753Smm enum xmlstatus xmlsts_unknown; 313228753Smm struct unknown_tag *unknowntags; 314228753Smm int base64text; 315228753Smm 316228753Smm /* 317228753Smm * TOC 318228753Smm */ 319228753Smm uint64_t toc_remaining; 320228753Smm uint64_t toc_total; 321228753Smm uint64_t toc_chksum_offset; 322228753Smm uint64_t toc_chksum_size; 323228753Smm 324228753Smm /* 325228753Smm * For Decoding data. 326228753Smm */ 327228753Smm enum enctype rd_encoding; 328228753Smm z_stream stream; 329228753Smm int stream_valid; 330228753Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 331228753Smm bz_stream bzstream; 332228753Smm int bzstream_valid; 333228753Smm#endif 334228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 335228753Smm lzma_stream lzstream; 336228753Smm int lzstream_valid; 337228753Smm#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC 338228753Smm lzmadec_stream lzstream; 339228753Smm int lzstream_valid; 340228753Smm#endif 341228753Smm /* 342228753Smm * For Checksum data. 343228753Smm */ 344228753Smm struct chksumwork a_sumwrk; 345228753Smm struct chksumwork e_sumwrk; 346228753Smm 347228753Smm struct xar_file *file; /* current reading file. */ 348228753Smm struct xattr *xattr; /* current reading extended attribute. */ 349228753Smm struct heap_queue file_queue; 350228753Smm struct xar_file *hdlink_orgs; 351228753Smm struct hdlink *hdlink_list; 352228753Smm 353228753Smm int entry_init; 354228753Smm uint64_t entry_total; 355228753Smm uint64_t entry_remaining; 356232153Smm size_t entry_unconsumed; 357228753Smm uint64_t entry_size; 358228753Smm enum enctype entry_encoding; 359228753Smm struct chksumval entry_a_sum; 360228753Smm struct chksumval entry_e_sum; 361232153Smm 362232153Smm struct archive_string_conv *sconv; 363228753Smm}; 364228753Smm 365228753Smmstruct xmlattr { 366228753Smm struct xmlattr *next; 367228753Smm char *name; 368228753Smm char *value; 369228753Smm}; 370228753Smm 371228753Smmstruct xmlattr_list { 372228753Smm struct xmlattr *first; 373228753Smm struct xmlattr **last; 374228753Smm}; 375228753Smm 376232153Smmstatic int xar_bid(struct archive_read *, int); 377228753Smmstatic int xar_read_header(struct archive_read *, 378228753Smm struct archive_entry *); 379228753Smmstatic int xar_read_data(struct archive_read *, 380232153Smm const void **, size_t *, int64_t *); 381228753Smmstatic int xar_read_data_skip(struct archive_read *); 382228753Smmstatic int xar_cleanup(struct archive_read *); 383228753Smmstatic int move_reading_point(struct archive_read *, uint64_t); 384228753Smmstatic int rd_contents_init(struct archive_read *, 385228753Smm enum enctype, int, int); 386228753Smmstatic int rd_contents(struct archive_read *, const void **, 387228753Smm size_t *, size_t *, uint64_t); 388228753Smmstatic uint64_t atol10(const char *, size_t); 389228753Smmstatic int64_t atol8(const char *, size_t); 390228753Smmstatic size_t atohex(unsigned char *, size_t, const char *, size_t); 391228753Smmstatic time_t parse_time(const char *p, size_t n); 392232153Smmstatic int heap_add_entry(struct archive_read *a, 393232153Smm struct heap_queue *, struct xar_file *); 394228753Smmstatic struct xar_file *heap_get_entry(struct heap_queue *); 395232153Smmstatic int add_link(struct archive_read *, 396232153Smm struct xar *, struct xar_file *); 397228753Smmstatic void checksum_init(struct archive_read *, int, int); 398228753Smmstatic void checksum_update(struct archive_read *, const void *, 399228753Smm size_t, const void *, size_t); 400228753Smmstatic int checksum_final(struct archive_read *, const void *, 401228753Smm size_t, const void *, size_t); 402228753Smmstatic int decompression_init(struct archive_read *, enum enctype); 403228753Smmstatic int decompress(struct archive_read *, const void **, 404228753Smm size_t *, const void *, size_t *); 405228753Smmstatic int decompression_cleanup(struct archive_read *); 406228753Smmstatic void xmlattr_cleanup(struct xmlattr_list *); 407232153Smmstatic int file_new(struct archive_read *, 408232153Smm struct xar *, struct xmlattr_list *); 409228753Smmstatic void file_free(struct xar_file *); 410232153Smmstatic int xattr_new(struct archive_read *, 411232153Smm struct xar *, struct xmlattr_list *); 412228753Smmstatic void xattr_free(struct xattr *); 413228753Smmstatic int getencoding(struct xmlattr_list *); 414228753Smmstatic int getsumalgorithm(struct xmlattr_list *); 415232153Smmstatic int unknowntag_start(struct archive_read *, 416232153Smm struct xar *, const char *); 417228753Smmstatic void unknowntag_end(struct xar *, const char *); 418232153Smmstatic int xml_start(struct archive_read *, 419232153Smm const char *, struct xmlattr_list *); 420228753Smmstatic void xml_end(void *, const char *); 421228753Smmstatic void xml_data(void *, const char *, int); 422228753Smmstatic int xml_parse_file_flags(struct xar *, const char *); 423228753Smmstatic int xml_parse_file_ext2(struct xar *, const char *); 424228753Smm#if defined(HAVE_LIBXML_XMLREADER_H) 425232153Smmstatic int xml2_xmlattr_setup(struct archive_read *, 426232153Smm struct xmlattr_list *, xmlTextReaderPtr); 427228753Smmstatic int xml2_read_cb(void *, char *, int); 428228753Smmstatic int xml2_close_cb(void *); 429228753Smmstatic void xml2_error_hdr(void *, const char *, xmlParserSeverities, 430228753Smm xmlTextReaderLocatorPtr); 431228753Smmstatic int xml2_read_toc(struct archive_read *); 432228753Smm#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) 433232153Smmstruct expat_userData { 434232153Smm int state; 435232153Smm struct archive_read *archive; 436232153Smm}; 437232153Smmstatic int expat_xmlattr_setup(struct archive_read *, 438232153Smm struct xmlattr_list *, const XML_Char **); 439228753Smmstatic void expat_start_cb(void *, const XML_Char *, const XML_Char **); 440228753Smmstatic void expat_end_cb(void *, const XML_Char *); 441228753Smmstatic void expat_data_cb(void *, const XML_Char *, int); 442228753Smmstatic int expat_read_toc(struct archive_read *); 443228753Smm#endif 444228753Smm 445228753Smmint 446228753Smmarchive_read_support_format_xar(struct archive *_a) 447228753Smm{ 448228753Smm struct xar *xar; 449228753Smm struct archive_read *a = (struct archive_read *)_a; 450228753Smm int r; 451228753Smm 452232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 453232153Smm ARCHIVE_STATE_NEW, "archive_read_support_format_xar"); 454232153Smm 455228753Smm xar = (struct xar *)calloc(1, sizeof(*xar)); 456228753Smm if (xar == NULL) { 457228753Smm archive_set_error(&a->archive, ENOMEM, 458228753Smm "Can't allocate xar data"); 459228753Smm return (ARCHIVE_FATAL); 460228753Smm } 461228753Smm 462228753Smm r = __archive_read_register_format(a, 463228753Smm xar, 464228753Smm "xar", 465228753Smm xar_bid, 466228753Smm NULL, 467228753Smm xar_read_header, 468228753Smm xar_read_data, 469228753Smm xar_read_data_skip, 470248616Smm NULL, 471228753Smm xar_cleanup); 472228753Smm if (r != ARCHIVE_OK) 473228753Smm free(xar); 474228753Smm return (r); 475228753Smm} 476228753Smm 477228753Smmstatic int 478232153Smmxar_bid(struct archive_read *a, int best_bid) 479228753Smm{ 480228753Smm const unsigned char *b; 481228753Smm int bid; 482228753Smm 483232153Smm (void)best_bid; /* UNUSED */ 484232153Smm 485228753Smm b = __archive_read_ahead(a, HEADER_SIZE, NULL); 486228753Smm if (b == NULL) 487228753Smm return (-1); 488228753Smm 489228753Smm bid = 0; 490228753Smm /* 491228753Smm * Verify magic code 492228753Smm */ 493228753Smm if (archive_be32dec(b) != HEADER_MAGIC) 494228753Smm return (0); 495228753Smm bid += 32; 496228753Smm /* 497228753Smm * Verify header size 498228753Smm */ 499228753Smm if (archive_be16dec(b+4) != HEADER_SIZE) 500228753Smm return (0); 501228753Smm bid += 16; 502228753Smm /* 503228753Smm * Verify header version 504228753Smm */ 505228753Smm if (archive_be16dec(b+6) != HEADER_VERSION) 506228753Smm return (0); 507228753Smm bid += 16; 508228753Smm /* 509228753Smm * Verify type of checksum 510228753Smm */ 511228753Smm switch (archive_be32dec(b+24)) { 512228753Smm case CKSUM_NONE: 513228753Smm case CKSUM_SHA1: 514228753Smm case CKSUM_MD5: 515228753Smm bid += 32; 516228753Smm break; 517228753Smm default: 518228753Smm return (0); 519228753Smm } 520228753Smm 521228753Smm return (bid); 522228753Smm} 523228753Smm 524228753Smmstatic int 525228753Smmread_toc(struct archive_read *a) 526228753Smm{ 527228753Smm struct xar *xar; 528228753Smm struct xar_file *file; 529228753Smm const unsigned char *b; 530228753Smm uint64_t toc_compressed_size; 531228753Smm uint64_t toc_uncompressed_size; 532228753Smm uint32_t toc_chksum_alg; 533228753Smm ssize_t bytes; 534228753Smm int r; 535228753Smm 536228753Smm xar = (struct xar *)(a->format->data); 537228753Smm 538228753Smm /* 539228753Smm * Read xar header. 540228753Smm */ 541228753Smm b = __archive_read_ahead(a, HEADER_SIZE, &bytes); 542228753Smm if (bytes < 0) 543228753Smm return ((int)bytes); 544228753Smm if (bytes < HEADER_SIZE) { 545228753Smm archive_set_error(&a->archive, 546228753Smm ARCHIVE_ERRNO_FILE_FORMAT, 547228753Smm "Truncated archive header"); 548228753Smm return (ARCHIVE_FATAL); 549228753Smm } 550228753Smm 551228753Smm if (archive_be32dec(b) != HEADER_MAGIC) { 552228753Smm archive_set_error(&a->archive, 553228753Smm ARCHIVE_ERRNO_FILE_FORMAT, 554228753Smm "Invalid header magic"); 555228753Smm return (ARCHIVE_FATAL); 556228753Smm } 557228753Smm if (archive_be16dec(b+6) != HEADER_VERSION) { 558228753Smm archive_set_error(&a->archive, 559228753Smm ARCHIVE_ERRNO_FILE_FORMAT, 560228753Smm "Unsupported header version(%d)", 561228753Smm archive_be16dec(b+6)); 562228753Smm return (ARCHIVE_FATAL); 563228753Smm } 564228753Smm toc_compressed_size = archive_be64dec(b+8); 565228753Smm xar->toc_remaining = toc_compressed_size; 566228753Smm toc_uncompressed_size = archive_be64dec(b+16); 567228753Smm toc_chksum_alg = archive_be32dec(b+24); 568228753Smm __archive_read_consume(a, HEADER_SIZE); 569228753Smm xar->offset += HEADER_SIZE; 570228753Smm xar->toc_total = 0; 571228753Smm 572228753Smm /* 573228753Smm * Read TOC(Table of Contents). 574228753Smm */ 575228753Smm /* Initialize reading contents. */ 576228753Smm r = move_reading_point(a, HEADER_SIZE); 577228753Smm if (r != ARCHIVE_OK) 578228753Smm return (r); 579228753Smm r = rd_contents_init(a, GZIP, toc_chksum_alg, CKSUM_NONE); 580228753Smm if (r != ARCHIVE_OK) 581228753Smm return (r); 582228753Smm 583228753Smm#ifdef HAVE_LIBXML_XMLREADER_H 584228753Smm r = xml2_read_toc(a); 585228753Smm#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) 586228753Smm r = expat_read_toc(a); 587228753Smm#endif 588228753Smm if (r != ARCHIVE_OK) 589228753Smm return (r); 590228753Smm 591228753Smm /* Set 'The HEAP' base. */ 592228753Smm xar->h_base = xar->offset; 593228753Smm if (xar->toc_total != toc_uncompressed_size) { 594228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 595228753Smm "TOC uncompressed size error"); 596228753Smm return (ARCHIVE_FATAL); 597228753Smm } 598228753Smm 599228753Smm /* 600228753Smm * Checksum TOC 601228753Smm */ 602228753Smm if (toc_chksum_alg != CKSUM_NONE) { 603228753Smm r = move_reading_point(a, xar->toc_chksum_offset); 604228753Smm if (r != ARCHIVE_OK) 605228753Smm return (r); 606238856Smm b = __archive_read_ahead(a, 607238856Smm (size_t)xar->toc_chksum_size, &bytes); 608228753Smm if (bytes < 0) 609228753Smm return ((int)bytes); 610228753Smm if ((uint64_t)bytes < xar->toc_chksum_size) { 611228753Smm archive_set_error(&a->archive, 612228753Smm ARCHIVE_ERRNO_FILE_FORMAT, 613228753Smm "Truncated archive file"); 614228753Smm return (ARCHIVE_FATAL); 615228753Smm } 616238856Smm r = checksum_final(a, b, 617238856Smm (size_t)xar->toc_chksum_size, NULL, 0); 618228753Smm __archive_read_consume(a, xar->toc_chksum_size); 619228753Smm xar->offset += xar->toc_chksum_size; 620228753Smm if (r != ARCHIVE_OK) 621228753Smm return (ARCHIVE_FATAL); 622228753Smm } 623228753Smm 624228753Smm /* 625228753Smm * Connect hardlinked files. 626228753Smm */ 627228753Smm for (file = xar->hdlink_orgs; file != NULL; file = file->hdnext) { 628228753Smm struct hdlink **hdlink; 629228753Smm 630228753Smm for (hdlink = &(xar->hdlink_list); *hdlink != NULL; 631228753Smm hdlink = &((*hdlink)->next)) { 632228753Smm if ((*hdlink)->id == file->id) { 633228753Smm struct hdlink *hltmp; 634228753Smm struct xar_file *f2; 635228753Smm int nlink = (*hdlink)->cnt + 1; 636228753Smm 637228753Smm file->nlink = nlink; 638228753Smm for (f2 = (*hdlink)->files; f2 != NULL; 639228753Smm f2 = f2->hdnext) { 640228753Smm f2->nlink = nlink; 641228753Smm archive_string_copy( 642228753Smm &(f2->hardlink), &(file->pathname)); 643228753Smm } 644228753Smm /* Remove resolved files from hdlist_list. */ 645228753Smm hltmp = *hdlink; 646228753Smm *hdlink = hltmp->next; 647228753Smm free(hltmp); 648228753Smm break; 649228753Smm } 650228753Smm } 651228753Smm } 652228753Smm a->archive.archive_format = ARCHIVE_FORMAT_XAR; 653228753Smm a->archive.archive_format_name = "xar"; 654228753Smm 655228753Smm return (ARCHIVE_OK); 656228753Smm} 657228753Smm 658228753Smmstatic int 659228753Smmxar_read_header(struct archive_read *a, struct archive_entry *entry) 660228753Smm{ 661228753Smm struct xar *xar; 662228753Smm struct xar_file *file; 663228753Smm struct xattr *xattr; 664228753Smm int r; 665228753Smm 666228753Smm xar = (struct xar *)(a->format->data); 667232153Smm r = ARCHIVE_OK; 668228753Smm 669228753Smm if (xar->offset == 0) { 670232153Smm /* Create a character conversion object. */ 671232153Smm if (xar->sconv == NULL) { 672232153Smm xar->sconv = archive_string_conversion_from_charset( 673232153Smm &(a->archive), "UTF-8", 1); 674232153Smm if (xar->sconv == NULL) 675232153Smm return (ARCHIVE_FATAL); 676232153Smm } 677232153Smm 678228753Smm /* Read TOC. */ 679228753Smm r = read_toc(a); 680228753Smm if (r != ARCHIVE_OK) 681228753Smm return (r); 682228753Smm } 683228753Smm 684228753Smm for (;;) { 685228753Smm file = xar->file = heap_get_entry(&(xar->file_queue)); 686228753Smm if (file == NULL) { 687228753Smm xar->end_of_file = 1; 688228753Smm return (ARCHIVE_EOF); 689228753Smm } 690228753Smm if ((file->mode & AE_IFMT) != AE_IFDIR) 691228753Smm break; 692228753Smm if (file->has != (HAS_PATHNAME | HAS_TYPE)) 693228753Smm break; 694228753Smm /* 695228753Smm * If a file type is a directory and it does not have 696228753Smm * any metadata, do not export. 697228753Smm */ 698228753Smm file_free(file); 699228753Smm } 700228753Smm archive_entry_set_atime(entry, file->atime, 0); 701228753Smm archive_entry_set_ctime(entry, file->ctime, 0); 702228753Smm archive_entry_set_mtime(entry, file->mtime, 0); 703228753Smm archive_entry_set_gid(entry, file->gid); 704232153Smm if (file->gname.length > 0 && 705232153Smm archive_entry_copy_gname_l(entry, file->gname.s, 706232153Smm archive_strlen(&(file->gname)), xar->sconv) != 0) { 707232153Smm if (errno == ENOMEM) { 708232153Smm archive_set_error(&a->archive, ENOMEM, 709232153Smm "Can't allocate memory for Gname"); 710232153Smm return (ARCHIVE_FATAL); 711232153Smm } 712232153Smm archive_set_error(&a->archive, 713232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 714232153Smm "Gname cannot be converted from %s to current locale.", 715232153Smm archive_string_conversion_charset_name(xar->sconv)); 716232153Smm r = ARCHIVE_WARN; 717232153Smm } 718228753Smm archive_entry_set_uid(entry, file->uid); 719232153Smm if (file->uname.length > 0 && 720232153Smm archive_entry_copy_uname_l(entry, file->uname.s, 721232153Smm archive_strlen(&(file->uname)), xar->sconv) != 0) { 722232153Smm if (errno == ENOMEM) { 723232153Smm archive_set_error(&a->archive, ENOMEM, 724232153Smm "Can't allocate memory for Uname"); 725232153Smm return (ARCHIVE_FATAL); 726232153Smm } 727232153Smm archive_set_error(&a->archive, 728232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 729232153Smm "Uname cannot be converted from %s to current locale.", 730232153Smm archive_string_conversion_charset_name(xar->sconv)); 731232153Smm r = ARCHIVE_WARN; 732232153Smm } 733228753Smm archive_entry_set_mode(entry, file->mode); 734232153Smm if (archive_entry_copy_pathname_l(entry, file->pathname.s, 735232153Smm archive_strlen(&(file->pathname)), xar->sconv) != 0) { 736232153Smm if (errno == ENOMEM) { 737232153Smm archive_set_error(&a->archive, ENOMEM, 738232153Smm "Can't allocate memory for Pathname"); 739232153Smm return (ARCHIVE_FATAL); 740232153Smm } 741232153Smm archive_set_error(&a->archive, 742232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 743232153Smm "Pathname cannot be converted from %s to current locale.", 744232153Smm archive_string_conversion_charset_name(xar->sconv)); 745232153Smm r = ARCHIVE_WARN; 746232153Smm } 747232153Smm 748232153Smm 749232153Smm if (file->symlink.length > 0 && 750232153Smm archive_entry_copy_symlink_l(entry, file->symlink.s, 751232153Smm archive_strlen(&(file->symlink)), xar->sconv) != 0) { 752232153Smm if (errno == ENOMEM) { 753232153Smm archive_set_error(&a->archive, ENOMEM, 754232153Smm "Can't allocate memory for Linkname"); 755232153Smm return (ARCHIVE_FATAL); 756232153Smm } 757232153Smm archive_set_error(&a->archive, 758232153Smm ARCHIVE_ERRNO_FILE_FORMAT, 759232153Smm "Linkname cannot be converted from %s to current locale.", 760232153Smm archive_string_conversion_charset_name(xar->sconv)); 761232153Smm r = ARCHIVE_WARN; 762232153Smm } 763228753Smm /* Set proper nlink. */ 764228753Smm if ((file->mode & AE_IFMT) == AE_IFDIR) 765228753Smm archive_entry_set_nlink(entry, file->subdirs + 2); 766228753Smm else 767228753Smm archive_entry_set_nlink(entry, file->nlink); 768228753Smm archive_entry_set_size(entry, file->size); 769228753Smm if (archive_strlen(&(file->hardlink)) > 0) 770232153Smm archive_entry_set_hardlink(entry, file->hardlink.s); 771228753Smm archive_entry_set_ino64(entry, file->ino64); 772228753Smm if (file->has & HAS_DEV) 773228753Smm archive_entry_set_dev(entry, file->dev); 774228753Smm if (file->has & HAS_DEVMAJOR) 775228753Smm archive_entry_set_devmajor(entry, file->devmajor); 776228753Smm if (file->has & HAS_DEVMINOR) 777228753Smm archive_entry_set_devminor(entry, file->devminor); 778228753Smm if (archive_strlen(&(file->fflags_text)) > 0) 779228753Smm archive_entry_copy_fflags_text(entry, file->fflags_text.s); 780228753Smm 781228753Smm xar->entry_init = 1; 782228753Smm xar->entry_total = 0; 783228753Smm xar->entry_remaining = file->length; 784228753Smm xar->entry_size = file->size; 785228753Smm xar->entry_encoding = file->encoding; 786228753Smm xar->entry_a_sum = file->a_sum; 787228753Smm xar->entry_e_sum = file->e_sum; 788228753Smm /* 789228753Smm * Read extended attributes. 790228753Smm */ 791228753Smm xattr = file->xattr_list; 792228753Smm while (xattr != NULL) { 793228753Smm const void *d; 794228753Smm size_t outbytes, used; 795228753Smm 796228753Smm r = move_reading_point(a, xattr->offset); 797228753Smm if (r != ARCHIVE_OK) 798228753Smm break; 799228753Smm r = rd_contents_init(a, xattr->encoding, 800228753Smm xattr->a_sum.alg, xattr->e_sum.alg); 801228753Smm if (r != ARCHIVE_OK) 802228753Smm break; 803228753Smm d = NULL; 804228753Smm r = rd_contents(a, &d, &outbytes, &used, xattr->length); 805228753Smm if (r != ARCHIVE_OK) 806228753Smm break; 807228753Smm if (outbytes != xattr->size) { 808228753Smm archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, 809228753Smm "Decompressed size error"); 810228753Smm r = ARCHIVE_FATAL; 811228753Smm break; 812228753Smm } 813228753Smm r = checksum_final(a, 814228753Smm xattr->a_sum.val, xattr->a_sum.len, 815228753Smm xattr->e_sum.val, xattr->e_sum.len); 816228753Smm if (r != ARCHIVE_OK) 817228753Smm break; 818228753Smm archive_entry_xattr_add_entry(entry, 819228753Smm xattr->name.s, d, outbytes); 820228753Smm xattr = xattr->next; 821228753Smm } 822228753Smm if (r != ARCHIVE_OK) { 823228753Smm file_free(file); 824228753Smm return (r); 825228753Smm } 826228753Smm 827228753Smm if (xar->entry_remaining > 0) 828228753Smm /* Move reading point to the beginning of current 829228753Smm * file contents. */ 830228753Smm r = move_reading_point(a, file->offset); 831228753Smm else 832228753Smm r = ARCHIVE_OK; 833228753Smm 834228753Smm file_free(file); 835228753Smm return (r); 836228753Smm} 837228753Smm 838228753Smmstatic int 839228753Smmxar_read_data(struct archive_read *a, 840232153Smm const void **buff, size_t *size, int64_t *offset) 841228753Smm{ 842228753Smm struct xar *xar; 843228753Smm size_t used; 844228753Smm int r; 845228753Smm 846228753Smm xar = (struct xar *)(a->format->data); 847232153Smm 848232153Smm if (xar->entry_unconsumed) { 849232153Smm __archive_read_consume(a, xar->entry_unconsumed); 850232153Smm xar->entry_unconsumed = 0; 851232153Smm } 852232153Smm 853228753Smm if (xar->end_of_file || xar->entry_remaining <= 0) { 854228753Smm r = ARCHIVE_EOF; 855228753Smm goto abort_read_data; 856228753Smm } 857228753Smm 858228753Smm if (xar->entry_init) { 859228753Smm r = rd_contents_init(a, xar->entry_encoding, 860228753Smm xar->entry_a_sum.alg, xar->entry_e_sum.alg); 861228753Smm if (r != ARCHIVE_OK) { 862228753Smm xar->entry_remaining = 0; 863228753Smm return (r); 864228753Smm } 865228753Smm xar->entry_init = 0; 866228753Smm } 867228753Smm 868228753Smm *buff = NULL; 869228753Smm r = rd_contents(a, buff, size, &used, xar->entry_remaining); 870228753Smm if (r != ARCHIVE_OK) 871228753Smm goto abort_read_data; 872228753Smm 873228753Smm *offset = xar->entry_total; 874228753Smm xar->entry_total += *size; 875228753Smm xar->total += *size; 876228753Smm xar->offset += used; 877228753Smm xar->entry_remaining -= used; 878232153Smm xar->entry_unconsumed = used; 879228753Smm 880228753Smm if (xar->entry_remaining == 0) { 881228753Smm if (xar->entry_total != xar->entry_size) { 882228753Smm archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, 883228753Smm "Decompressed size error"); 884228753Smm r = ARCHIVE_FATAL; 885228753Smm goto abort_read_data; 886228753Smm } 887228753Smm r = checksum_final(a, 888228753Smm xar->entry_a_sum.val, xar->entry_a_sum.len, 889228753Smm xar->entry_e_sum.val, xar->entry_e_sum.len); 890228753Smm if (r != ARCHIVE_OK) 891228753Smm goto abort_read_data; 892228753Smm } 893228753Smm 894228753Smm return (ARCHIVE_OK); 895228753Smmabort_read_data: 896228753Smm *buff = NULL; 897228753Smm *size = 0; 898228753Smm *offset = xar->total; 899228753Smm return (r); 900228753Smm} 901228753Smm 902228753Smmstatic int 903228753Smmxar_read_data_skip(struct archive_read *a) 904228753Smm{ 905228753Smm struct xar *xar; 906228753Smm int64_t bytes_skipped; 907228753Smm 908228753Smm xar = (struct xar *)(a->format->data); 909228753Smm if (xar->end_of_file) 910228753Smm return (ARCHIVE_EOF); 911232153Smm bytes_skipped = __archive_read_consume(a, xar->entry_remaining + 912232153Smm xar->entry_unconsumed); 913228753Smm if (bytes_skipped < 0) 914228753Smm return (ARCHIVE_FATAL); 915228753Smm xar->offset += bytes_skipped; 916232153Smm xar->entry_unconsumed = 0; 917228753Smm return (ARCHIVE_OK); 918228753Smm} 919228753Smm 920228753Smmstatic int 921228753Smmxar_cleanup(struct archive_read *a) 922228753Smm{ 923228753Smm struct xar *xar; 924228753Smm struct hdlink *hdlink; 925228753Smm int i; 926228753Smm int r; 927228753Smm 928228753Smm xar = (struct xar *)(a->format->data); 929228753Smm r = decompression_cleanup(a); 930228753Smm hdlink = xar->hdlink_list; 931228753Smm while (hdlink != NULL) { 932228753Smm struct hdlink *next = hdlink->next; 933228753Smm 934228753Smm free(hdlink); 935228753Smm hdlink = next; 936228753Smm } 937228753Smm for (i = 0; i < xar->file_queue.used; i++) 938228753Smm file_free(xar->file_queue.files[i]); 939228753Smm while (xar->unknowntags != NULL) { 940228753Smm struct unknown_tag *tag; 941228753Smm 942228753Smm tag = xar->unknowntags; 943228753Smm xar->unknowntags = tag->next; 944228753Smm archive_string_free(&(tag->name)); 945228753Smm free(tag); 946228753Smm } 947232153Smm free(xar->outbuff); 948228753Smm free(xar); 949228753Smm a->format->data = NULL; 950228753Smm return (r); 951228753Smm} 952228753Smm 953228753Smmstatic int 954228753Smmmove_reading_point(struct archive_read *a, uint64_t offset) 955228753Smm{ 956228753Smm struct xar *xar; 957228753Smm 958228753Smm xar = (struct xar *)(a->format->data); 959228753Smm if (xar->offset - xar->h_base != offset) { 960228753Smm /* Seek forward to the start of file contents. */ 961228753Smm int64_t step; 962228753Smm 963228753Smm step = offset - (xar->offset - xar->h_base); 964228753Smm if (step > 0) { 965232153Smm step = __archive_read_consume(a, step); 966228753Smm if (step < 0) 967228753Smm return ((int)step); 968228753Smm xar->offset += step; 969228753Smm } else { 970228753Smm archive_set_error(&(a->archive), 971228753Smm ARCHIVE_ERRNO_MISC, 972228753Smm "Cannot seek."); 973228753Smm return (ARCHIVE_FAILED); 974228753Smm } 975228753Smm } 976228753Smm return (ARCHIVE_OK); 977228753Smm} 978228753Smm 979228753Smmstatic int 980228753Smmrd_contents_init(struct archive_read *a, enum enctype encoding, 981228753Smm int a_sum_alg, int e_sum_alg) 982228753Smm{ 983228753Smm int r; 984228753Smm 985228753Smm /* Init decompress library. */ 986228753Smm if ((r = decompression_init(a, encoding)) != ARCHIVE_OK) 987228753Smm return (r); 988228753Smm /* Init checksum library. */ 989228753Smm checksum_init(a, a_sum_alg, e_sum_alg); 990228753Smm return (ARCHIVE_OK); 991228753Smm} 992228753Smm 993228753Smmstatic int 994228753Smmrd_contents(struct archive_read *a, const void **buff, size_t *size, 995228753Smm size_t *used, uint64_t remaining) 996228753Smm{ 997228753Smm const unsigned char *b; 998228753Smm ssize_t bytes; 999228753Smm 1000228753Smm /* Get whatever bytes are immediately available. */ 1001228753Smm b = __archive_read_ahead(a, 1, &bytes); 1002228753Smm if (bytes < 0) 1003228753Smm return ((int)bytes); 1004228753Smm if (bytes == 0) { 1005228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1006228753Smm "Truncated archive file"); 1007228753Smm return (ARCHIVE_FATAL); 1008228753Smm } 1009228753Smm if ((uint64_t)bytes > remaining) 1010228753Smm bytes = (ssize_t)remaining; 1011228753Smm 1012228753Smm /* 1013228753Smm * Decompress contents of file. 1014228753Smm */ 1015228753Smm *used = bytes; 1016228753Smm if (decompress(a, buff, size, b, used) != ARCHIVE_OK) 1017228753Smm return (ARCHIVE_FATAL); 1018228753Smm 1019228753Smm /* 1020228753Smm * Update checksum of a compressed data and a extracted data. 1021228753Smm */ 1022228753Smm checksum_update(a, b, *used, *buff, *size); 1023228753Smm 1024228753Smm return (ARCHIVE_OK); 1025228753Smm} 1026228753Smm 1027228753Smm/* 1028228753Smm * Note that this implementation does not (and should not!) obey 1029228753Smm * locale settings; you cannot simply substitute strtol here, since 1030228753Smm * it does obey locale. 1031228753Smm */ 1032228753Smm 1033228753Smmstatic uint64_t 1034228753Smmatol10(const char *p, size_t char_cnt) 1035228753Smm{ 1036228753Smm uint64_t l; 1037228753Smm int digit; 1038228753Smm 1039228753Smm l = 0; 1040228753Smm digit = *p - '0'; 1041228753Smm while (digit >= 0 && digit < 10 && char_cnt-- > 0) { 1042228753Smm l = (l * 10) + digit; 1043228753Smm digit = *++p - '0'; 1044228753Smm } 1045228753Smm return (l); 1046228753Smm} 1047228753Smm 1048228753Smmstatic int64_t 1049228753Smmatol8(const char *p, size_t char_cnt) 1050228753Smm{ 1051228753Smm int64_t l; 1052228753Smm int digit; 1053228753Smm 1054228753Smm l = 0; 1055228753Smm while (char_cnt-- > 0) { 1056228753Smm if (*p >= '0' && *p <= '7') 1057228753Smm digit = *p - '0'; 1058228753Smm else 1059228753Smm break; 1060228753Smm p++; 1061228753Smm l <<= 3; 1062228753Smm l |= digit; 1063228753Smm } 1064228753Smm return (l); 1065228753Smm} 1066228753Smm 1067228753Smmstatic size_t 1068228753Smmatohex(unsigned char *b, size_t bsize, const char *p, size_t psize) 1069228753Smm{ 1070228753Smm size_t fbsize = bsize; 1071228753Smm 1072228753Smm while (bsize && psize > 1) { 1073228753Smm unsigned char x; 1074228753Smm 1075228753Smm if (p[0] >= 'a' && p[0] <= 'z') 1076228753Smm x = (p[0] - 'a' + 0x0a) << 4; 1077228753Smm else if (p[0] >= 'A' && p[0] <= 'Z') 1078228753Smm x = (p[0] - 'A' + 0x0a) << 4; 1079228753Smm else if (p[0] >= '0' && p[0] <= '9') 1080228753Smm x = (p[0] - '0') << 4; 1081228753Smm else 1082228753Smm return (-1); 1083228753Smm if (p[1] >= 'a' && p[1] <= 'z') 1084228753Smm x |= p[1] - 'a' + 0x0a; 1085228753Smm else if (p[1] >= 'A' && p[1] <= 'Z') 1086228753Smm x |= p[1] - 'A' + 0x0a; 1087228753Smm else if (p[1] >= '0' && p[1] <= '9') 1088228753Smm x |= p[1] - '0'; 1089228753Smm else 1090228753Smm return (-1); 1091228753Smm 1092228753Smm *b++ = x; 1093228753Smm bsize--; 1094228753Smm p += 2; 1095228753Smm psize -= 2; 1096228753Smm } 1097228753Smm return (fbsize - bsize); 1098228753Smm} 1099228753Smm 1100228753Smmstatic time_t 1101228753Smmtime_from_tm(struct tm *t) 1102228753Smm{ 1103228753Smm#if HAVE_TIMEGM 1104228753Smm /* Use platform timegm() if available. */ 1105228753Smm return (timegm(t)); 1106232153Smm#elif HAVE__MKGMTIME64 1107232153Smm return (_mkgmtime64(t)); 1108228753Smm#else 1109228753Smm /* Else use direct calculation using POSIX assumptions. */ 1110228753Smm /* First, fix up tm_yday based on the year/month/day. */ 1111228753Smm mktime(t); 1112228753Smm /* Then we can compute timegm() from first principles. */ 1113228753Smm return (t->tm_sec + t->tm_min * 60 + t->tm_hour * 3600 1114228753Smm + t->tm_yday * 86400 + (t->tm_year - 70) * 31536000 1115228753Smm + ((t->tm_year - 69) / 4) * 86400 - 1116228753Smm ((t->tm_year - 1) / 100) * 86400 1117228753Smm + ((t->tm_year + 299) / 400) * 86400); 1118228753Smm#endif 1119228753Smm} 1120228753Smm 1121228753Smmstatic time_t 1122228753Smmparse_time(const char *p, size_t n) 1123228753Smm{ 1124228753Smm struct tm tm; 1125228753Smm time_t t = 0; 1126228753Smm int64_t data; 1127228753Smm 1128228753Smm memset(&tm, 0, sizeof(tm)); 1129228753Smm if (n != 20) 1130228753Smm return (t); 1131228753Smm data = atol10(p, 4); 1132228753Smm if (data < 1900) 1133228753Smm return (t); 1134228753Smm tm.tm_year = (int)data - 1900; 1135228753Smm p += 4; 1136228753Smm if (*p++ != '-') 1137228753Smm return (t); 1138228753Smm data = atol10(p, 2); 1139228753Smm if (data < 1 || data > 12) 1140228753Smm return (t); 1141228753Smm tm.tm_mon = (int)data -1; 1142228753Smm p += 2; 1143228753Smm if (*p++ != '-') 1144228753Smm return (t); 1145228753Smm data = atol10(p, 2); 1146228753Smm if (data < 1 || data > 31) 1147228753Smm return (t); 1148228753Smm tm.tm_mday = (int)data; 1149228753Smm p += 2; 1150228753Smm if (*p++ != 'T') 1151228753Smm return (t); 1152228753Smm data = atol10(p, 2); 1153228753Smm if (data < 0 || data > 23) 1154228753Smm return (t); 1155228753Smm tm.tm_hour = (int)data; 1156228753Smm p += 2; 1157228753Smm if (*p++ != ':') 1158228753Smm return (t); 1159228753Smm data = atol10(p, 2); 1160228753Smm if (data < 0 || data > 59) 1161228753Smm return (t); 1162228753Smm tm.tm_min = (int)data; 1163228753Smm p += 2; 1164228753Smm if (*p++ != ':') 1165228753Smm return (t); 1166228753Smm data = atol10(p, 2); 1167228753Smm if (data < 0 || data > 60) 1168228753Smm return (t); 1169228753Smm tm.tm_sec = (int)data; 1170228753Smm#if 0 1171228753Smm p += 2; 1172228753Smm if (*p != 'Z') 1173228753Smm return (t); 1174228753Smm#endif 1175228753Smm 1176228753Smm t = time_from_tm(&tm); 1177228753Smm 1178228753Smm return (t); 1179228753Smm} 1180228753Smm 1181232153Smmstatic int 1182232153Smmheap_add_entry(struct archive_read *a, 1183232153Smm struct heap_queue *heap, struct xar_file *file) 1184228753Smm{ 1185228753Smm uint64_t file_id, parent_id; 1186228753Smm int hole, parent; 1187228753Smm 1188228753Smm /* Expand our pending files list as necessary. */ 1189228753Smm if (heap->used >= heap->allocated) { 1190228753Smm struct xar_file **new_pending_files; 1191228753Smm int new_size = heap->allocated * 2; 1192228753Smm 1193228753Smm if (heap->allocated < 1024) 1194228753Smm new_size = 1024; 1195228753Smm /* Overflow might keep us from growing the list. */ 1196232153Smm if (new_size <= heap->allocated) { 1197232153Smm archive_set_error(&a->archive, 1198232153Smm ENOMEM, "Out of memory"); 1199232153Smm return (ARCHIVE_FATAL); 1200232153Smm } 1201228753Smm new_pending_files = (struct xar_file **) 1202228753Smm malloc(new_size * sizeof(new_pending_files[0])); 1203232153Smm if (new_pending_files == NULL) { 1204232153Smm archive_set_error(&a->archive, 1205232153Smm ENOMEM, "Out of memory"); 1206232153Smm return (ARCHIVE_FATAL); 1207232153Smm } 1208228753Smm memcpy(new_pending_files, heap->files, 1209228753Smm heap->allocated * sizeof(new_pending_files[0])); 1210228753Smm if (heap->files != NULL) 1211228753Smm free(heap->files); 1212228753Smm heap->files = new_pending_files; 1213228753Smm heap->allocated = new_size; 1214228753Smm } 1215228753Smm 1216228753Smm file_id = file->id; 1217228753Smm 1218228753Smm /* 1219228753Smm * Start with hole at end, walk it up tree to find insertion point. 1220228753Smm */ 1221228753Smm hole = heap->used++; 1222228753Smm while (hole > 0) { 1223228753Smm parent = (hole - 1)/2; 1224228753Smm parent_id = heap->files[parent]->id; 1225228753Smm if (file_id >= parent_id) { 1226228753Smm heap->files[hole] = file; 1227232153Smm return (ARCHIVE_OK); 1228228753Smm } 1229232153Smm /* Move parent into hole <==> move hole up tree. */ 1230228753Smm heap->files[hole] = heap->files[parent]; 1231228753Smm hole = parent; 1232228753Smm } 1233228753Smm heap->files[0] = file; 1234232153Smm 1235232153Smm return (ARCHIVE_OK); 1236228753Smm} 1237228753Smm 1238228753Smmstatic struct xar_file * 1239228753Smmheap_get_entry(struct heap_queue *heap) 1240228753Smm{ 1241228753Smm uint64_t a_id, b_id, c_id; 1242228753Smm int a, b, c; 1243228753Smm struct xar_file *r, *tmp; 1244228753Smm 1245228753Smm if (heap->used < 1) 1246228753Smm return (NULL); 1247228753Smm 1248228753Smm /* 1249228753Smm * The first file in the list is the earliest; we'll return this. 1250228753Smm */ 1251228753Smm r = heap->files[0]; 1252228753Smm 1253228753Smm /* 1254228753Smm * Move the last item in the heap to the root of the tree 1255228753Smm */ 1256228753Smm heap->files[0] = heap->files[--(heap->used)]; 1257228753Smm 1258228753Smm /* 1259228753Smm * Rebalance the heap. 1260228753Smm */ 1261232153Smm a = 0; /* Starting element and its heap key */ 1262228753Smm a_id = heap->files[a]->id; 1263228753Smm for (;;) { 1264232153Smm b = a + a + 1; /* First child */ 1265228753Smm if (b >= heap->used) 1266228753Smm return (r); 1267228753Smm b_id = heap->files[b]->id; 1268232153Smm c = b + 1; /* Use second child if it is smaller. */ 1269228753Smm if (c < heap->used) { 1270228753Smm c_id = heap->files[c]->id; 1271228753Smm if (c_id < b_id) { 1272228753Smm b = c; 1273228753Smm b_id = c_id; 1274228753Smm } 1275228753Smm } 1276228753Smm if (a_id <= b_id) 1277228753Smm return (r); 1278228753Smm tmp = heap->files[a]; 1279228753Smm heap->files[a] = heap->files[b]; 1280228753Smm heap->files[b] = tmp; 1281228753Smm a = b; 1282228753Smm } 1283228753Smm} 1284228753Smm 1285232153Smmstatic int 1286232153Smmadd_link(struct archive_read *a, struct xar *xar, struct xar_file *file) 1287228753Smm{ 1288228753Smm struct hdlink *hdlink; 1289228753Smm 1290228753Smm for (hdlink = xar->hdlink_list; hdlink != NULL; hdlink = hdlink->next) { 1291228753Smm if (hdlink->id == file->link) { 1292228753Smm file->hdnext = hdlink->files; 1293228753Smm hdlink->cnt++; 1294228753Smm hdlink->files = file; 1295232153Smm return (ARCHIVE_OK); 1296228753Smm } 1297228753Smm } 1298228753Smm hdlink = malloc(sizeof(*hdlink)); 1299232153Smm if (hdlink == NULL) { 1300232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 1301232153Smm return (ARCHIVE_FATAL); 1302232153Smm } 1303228753Smm file->hdnext = NULL; 1304228753Smm hdlink->id = file->link; 1305228753Smm hdlink->cnt = 1; 1306228753Smm hdlink->files = file; 1307228753Smm hdlink->next = xar->hdlink_list; 1308228753Smm xar->hdlink_list = hdlink; 1309232153Smm return (ARCHIVE_OK); 1310228753Smm} 1311228753Smm 1312228753Smmstatic void 1313228753Smm_checksum_init(struct chksumwork *sumwrk, int sum_alg) 1314228753Smm{ 1315228753Smm sumwrk->alg = sum_alg; 1316228753Smm switch (sum_alg) { 1317228753Smm case CKSUM_NONE: 1318228753Smm break; 1319228753Smm case CKSUM_SHA1: 1320228753Smm archive_sha1_init(&(sumwrk->sha1ctx)); 1321228753Smm break; 1322228753Smm case CKSUM_MD5: 1323228753Smm archive_md5_init(&(sumwrk->md5ctx)); 1324228753Smm break; 1325228753Smm } 1326228753Smm} 1327228753Smm 1328228753Smmstatic void 1329228753Smm_checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size) 1330228753Smm{ 1331228753Smm 1332228753Smm switch (sumwrk->alg) { 1333228753Smm case CKSUM_NONE: 1334228753Smm break; 1335228753Smm case CKSUM_SHA1: 1336228753Smm archive_sha1_update(&(sumwrk->sha1ctx), buff, size); 1337228753Smm break; 1338228753Smm case CKSUM_MD5: 1339228753Smm archive_md5_update(&(sumwrk->md5ctx), buff, size); 1340228753Smm break; 1341228753Smm } 1342228753Smm} 1343228753Smm 1344228753Smmstatic int 1345228753Smm_checksum_final(struct chksumwork *sumwrk, const void *val, size_t len) 1346228753Smm{ 1347228753Smm unsigned char sum[MAX_SUM_SIZE]; 1348228753Smm int r = ARCHIVE_OK; 1349228753Smm 1350228753Smm switch (sumwrk->alg) { 1351228753Smm case CKSUM_NONE: 1352228753Smm break; 1353228753Smm case CKSUM_SHA1: 1354228753Smm archive_sha1_final(&(sumwrk->sha1ctx), sum); 1355228753Smm if (len != SHA1_SIZE || 1356228753Smm memcmp(val, sum, SHA1_SIZE) != 0) 1357228753Smm r = ARCHIVE_FAILED; 1358228753Smm break; 1359228753Smm case CKSUM_MD5: 1360228753Smm archive_md5_final(&(sumwrk->md5ctx), sum); 1361228753Smm if (len != MD5_SIZE || 1362228753Smm memcmp(val, sum, MD5_SIZE) != 0) 1363228753Smm r = ARCHIVE_FAILED; 1364228753Smm break; 1365228753Smm } 1366228753Smm return (r); 1367228753Smm} 1368228753Smm 1369228753Smmstatic void 1370228753Smmchecksum_init(struct archive_read *a, int a_sum_alg, int e_sum_alg) 1371228753Smm{ 1372228753Smm struct xar *xar; 1373228753Smm 1374228753Smm xar = (struct xar *)(a->format->data); 1375228753Smm _checksum_init(&(xar->a_sumwrk), a_sum_alg); 1376228753Smm _checksum_init(&(xar->e_sumwrk), e_sum_alg); 1377228753Smm} 1378228753Smm 1379228753Smmstatic void 1380228753Smmchecksum_update(struct archive_read *a, const void *abuff, size_t asize, 1381228753Smm const void *ebuff, size_t esize) 1382228753Smm{ 1383228753Smm struct xar *xar; 1384228753Smm 1385228753Smm xar = (struct xar *)(a->format->data); 1386228753Smm _checksum_update(&(xar->a_sumwrk), abuff, asize); 1387228753Smm _checksum_update(&(xar->e_sumwrk), ebuff, esize); 1388228753Smm} 1389228753Smm 1390228753Smmstatic int 1391228753Smmchecksum_final(struct archive_read *a, const void *a_sum_val, 1392228753Smm size_t a_sum_len, const void *e_sum_val, size_t e_sum_len) 1393228753Smm{ 1394228753Smm struct xar *xar; 1395228753Smm int r; 1396228753Smm 1397228753Smm xar = (struct xar *)(a->format->data); 1398228753Smm r = _checksum_final(&(xar->a_sumwrk), a_sum_val, a_sum_len); 1399228753Smm if (r == ARCHIVE_OK) 1400228753Smm r = _checksum_final(&(xar->e_sumwrk), e_sum_val, e_sum_len); 1401228753Smm if (r != ARCHIVE_OK) 1402228753Smm archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC, 1403228753Smm "Sumcheck error"); 1404228753Smm return (r); 1405228753Smm} 1406228753Smm 1407228753Smmstatic int 1408228753Smmdecompression_init(struct archive_read *a, enum enctype encoding) 1409228753Smm{ 1410228753Smm struct xar *xar; 1411228753Smm const char *detail; 1412228753Smm int r; 1413228753Smm 1414228753Smm xar = (struct xar *)(a->format->data); 1415228753Smm xar->rd_encoding = encoding; 1416228753Smm switch (encoding) { 1417228753Smm case NONE: 1418228753Smm break; 1419228753Smm case GZIP: 1420228753Smm if (xar->stream_valid) 1421228753Smm r = inflateReset(&(xar->stream)); 1422228753Smm else 1423228753Smm r = inflateInit(&(xar->stream)); 1424228753Smm if (r != Z_OK) { 1425228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1426228753Smm "Couldn't initialize zlib stream."); 1427228753Smm return (ARCHIVE_FATAL); 1428228753Smm } 1429228753Smm xar->stream_valid = 1; 1430228753Smm xar->stream.total_in = 0; 1431228753Smm xar->stream.total_out = 0; 1432228753Smm break; 1433228753Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 1434228753Smm case BZIP2: 1435228753Smm if (xar->bzstream_valid) { 1436228753Smm BZ2_bzDecompressEnd(&(xar->bzstream)); 1437228753Smm xar->bzstream_valid = 0; 1438228753Smm } 1439228753Smm r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 0); 1440228753Smm if (r == BZ_MEM_ERROR) 1441228753Smm r = BZ2_bzDecompressInit(&(xar->bzstream), 0, 1); 1442228753Smm if (r != BZ_OK) { 1443228753Smm int err = ARCHIVE_ERRNO_MISC; 1444228753Smm detail = NULL; 1445228753Smm switch (r) { 1446228753Smm case BZ_PARAM_ERROR: 1447228753Smm detail = "invalid setup parameter"; 1448228753Smm break; 1449228753Smm case BZ_MEM_ERROR: 1450228753Smm err = ENOMEM; 1451228753Smm detail = "out of memory"; 1452228753Smm break; 1453228753Smm case BZ_CONFIG_ERROR: 1454228753Smm detail = "mis-compiled library"; 1455228753Smm break; 1456228753Smm } 1457228753Smm archive_set_error(&a->archive, err, 1458228753Smm "Internal error initializing decompressor: %s", 1459228753Smm detail == NULL ? "??" : detail); 1460228753Smm xar->bzstream_valid = 0; 1461228753Smm return (ARCHIVE_FATAL); 1462228753Smm } 1463228753Smm xar->bzstream_valid = 1; 1464228753Smm xar->bzstream.total_in_lo32 = 0; 1465228753Smm xar->bzstream.total_in_hi32 = 0; 1466228753Smm xar->bzstream.total_out_lo32 = 0; 1467228753Smm xar->bzstream.total_out_hi32 = 0; 1468228753Smm break; 1469228753Smm#endif 1470228753Smm#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1471232153Smm#if LZMA_VERSION_MAJOR >= 5 1472232153Smm/* Effectively disable the limiter. */ 1473232153Smm#define LZMA_MEMLIMIT UINT64_MAX 1474232153Smm#else 1475232153Smm/* NOTE: This needs to check memory size which running system has. */ 1476232153Smm#define LZMA_MEMLIMIT (1U << 30) 1477232153Smm#endif 1478228753Smm case XZ: 1479228753Smm case LZMA: 1480228753Smm if (xar->lzstream_valid) { 1481228753Smm lzma_end(&(xar->lzstream)); 1482228753Smm xar->lzstream_valid = 0; 1483228753Smm } 1484228753Smm if (xar->entry_encoding == XZ) 1485228753Smm r = lzma_stream_decoder(&(xar->lzstream), 1486232153Smm LZMA_MEMLIMIT,/* memlimit */ 1487228753Smm LZMA_CONCATENATED); 1488228753Smm else 1489228753Smm r = lzma_alone_decoder(&(xar->lzstream), 1490232153Smm LZMA_MEMLIMIT);/* memlimit */ 1491228753Smm if (r != LZMA_OK) { 1492228753Smm switch (r) { 1493228753Smm case LZMA_MEM_ERROR: 1494228753Smm archive_set_error(&a->archive, 1495228753Smm ENOMEM, 1496228753Smm "Internal error initializing " 1497228753Smm "compression library: " 1498228753Smm "Cannot allocate memory"); 1499228753Smm break; 1500228753Smm case LZMA_OPTIONS_ERROR: 1501228753Smm archive_set_error(&a->archive, 1502228753Smm ARCHIVE_ERRNO_MISC, 1503228753Smm "Internal error initializing " 1504228753Smm "compression library: " 1505228753Smm "Invalid or unsupported options"); 1506228753Smm break; 1507228753Smm default: 1508228753Smm archive_set_error(&a->archive, 1509228753Smm ARCHIVE_ERRNO_MISC, 1510228753Smm "Internal error initializing " 1511228753Smm "lzma library"); 1512228753Smm break; 1513228753Smm } 1514228753Smm return (ARCHIVE_FATAL); 1515228753Smm } 1516228753Smm xar->lzstream_valid = 1; 1517228753Smm xar->lzstream.total_in = 0; 1518228753Smm xar->lzstream.total_out = 0; 1519228753Smm break; 1520228753Smm#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) 1521228753Smm case LZMA: 1522228753Smm if (xar->lzstream_valid) 1523228753Smm lzmadec_end(&(xar->lzstream)); 1524228753Smm r = lzmadec_init(&(xar->lzstream)); 1525228753Smm if (r != LZMADEC_OK) { 1526228753Smm switch (r) { 1527228753Smm case LZMADEC_HEADER_ERROR: 1528228753Smm archive_set_error(&a->archive, 1529228753Smm ARCHIVE_ERRNO_MISC, 1530228753Smm "Internal error initializing " 1531228753Smm "compression library: " 1532228753Smm "invalid header"); 1533228753Smm break; 1534228753Smm case LZMADEC_MEM_ERROR: 1535228753Smm archive_set_error(&a->archive, 1536228753Smm ENOMEM, 1537228753Smm "Internal error initializing " 1538228753Smm "compression library: " 1539228753Smm "out of memory"); 1540228753Smm break; 1541228753Smm } 1542228753Smm return (ARCHIVE_FATAL); 1543228753Smm } 1544228753Smm xar->lzstream_valid = 1; 1545228753Smm xar->lzstream.total_in = 0; 1546228753Smm xar->lzstream.total_out = 0; 1547228753Smm break; 1548228753Smm#endif 1549228753Smm /* 1550228753Smm * Unsupported compression. 1551228753Smm */ 1552228753Smm default: 1553228753Smm#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) 1554228753Smm case BZIP2: 1555228753Smm#endif 1556228753Smm#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) 1557228753Smm#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) 1558228753Smm case LZMA: 1559228753Smm#endif 1560228753Smm case XZ: 1561228753Smm#endif 1562228753Smm switch (xar->entry_encoding) { 1563228753Smm case BZIP2: detail = "bzip2"; break; 1564228753Smm case LZMA: detail = "lzma"; break; 1565228753Smm case XZ: detail = "xz"; break; 1566228753Smm default: detail = "??"; break; 1567228753Smm } 1568228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1569228753Smm "%s compression not supported on this platform", 1570228753Smm detail); 1571228753Smm return (ARCHIVE_FAILED); 1572228753Smm } 1573228753Smm return (ARCHIVE_OK); 1574228753Smm} 1575228753Smm 1576228753Smmstatic int 1577228753Smmdecompress(struct archive_read *a, const void **buff, size_t *outbytes, 1578228753Smm const void *b, size_t *used) 1579228753Smm{ 1580228753Smm struct xar *xar; 1581228753Smm void *outbuff; 1582228753Smm size_t avail_in, avail_out; 1583228753Smm int r; 1584228753Smm 1585228753Smm xar = (struct xar *)(a->format->data); 1586228753Smm avail_in = *used; 1587228753Smm outbuff = (void *)(uintptr_t)*buff; 1588228753Smm if (outbuff == NULL) { 1589232153Smm if (xar->outbuff == NULL) { 1590232153Smm xar->outbuff = malloc(OUTBUFF_SIZE); 1591232153Smm if (xar->outbuff == NULL) { 1592232153Smm archive_set_error(&a->archive, ENOMEM, 1593232153Smm "Couldn't allocate memory for out buffer"); 1594232153Smm return (ARCHIVE_FATAL); 1595232153Smm } 1596232153Smm } 1597232153Smm outbuff = xar->outbuff; 1598228753Smm *buff = outbuff; 1599232153Smm avail_out = OUTBUFF_SIZE; 1600228753Smm } else 1601228753Smm avail_out = *outbytes; 1602228753Smm switch (xar->rd_encoding) { 1603228753Smm case GZIP: 1604228753Smm xar->stream.next_in = (Bytef *)(uintptr_t)b; 1605228753Smm xar->stream.avail_in = avail_in; 1606228753Smm xar->stream.next_out = (unsigned char *)outbuff; 1607228753Smm xar->stream.avail_out = avail_out; 1608228753Smm r = inflate(&(xar->stream), 0); 1609228753Smm switch (r) { 1610228753Smm case Z_OK: /* Decompressor made some progress.*/ 1611228753Smm case Z_STREAM_END: /* Found end of stream. */ 1612228753Smm break; 1613228753Smm default: 1614228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1615228753Smm "File decompression failed (%d)", r); 1616228753Smm return (ARCHIVE_FATAL); 1617228753Smm } 1618228753Smm *used = avail_in - xar->stream.avail_in; 1619228753Smm *outbytes = avail_out - xar->stream.avail_out; 1620228753Smm break; 1621228753Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 1622228753Smm case BZIP2: 1623228753Smm xar->bzstream.next_in = (char *)(uintptr_t)b; 1624228753Smm xar->bzstream.avail_in = avail_in; 1625228753Smm xar->bzstream.next_out = (char *)outbuff; 1626228753Smm xar->bzstream.avail_out = avail_out; 1627228753Smm r = BZ2_bzDecompress(&(xar->bzstream)); 1628228753Smm switch (r) { 1629228753Smm case BZ_STREAM_END: /* Found end of stream. */ 1630228753Smm switch (BZ2_bzDecompressEnd(&(xar->bzstream))) { 1631228753Smm case BZ_OK: 1632228753Smm break; 1633228753Smm default: 1634228753Smm archive_set_error(&(a->archive), 1635228753Smm ARCHIVE_ERRNO_MISC, 1636228753Smm "Failed to clean up decompressor"); 1637228753Smm return (ARCHIVE_FATAL); 1638228753Smm } 1639228753Smm xar->bzstream_valid = 0; 1640228753Smm /* FALLTHROUGH */ 1641228753Smm case BZ_OK: /* Decompressor made some progress. */ 1642228753Smm break; 1643228753Smm default: 1644228753Smm archive_set_error(&(a->archive), 1645228753Smm ARCHIVE_ERRNO_MISC, 1646228753Smm "bzip decompression failed"); 1647228753Smm return (ARCHIVE_FATAL); 1648228753Smm } 1649228753Smm *used = avail_in - xar->bzstream.avail_in; 1650228753Smm *outbytes = avail_out - xar->bzstream.avail_out; 1651228753Smm break; 1652228753Smm#endif 1653228753Smm#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1654228753Smm case LZMA: 1655228753Smm case XZ: 1656228753Smm xar->lzstream.next_in = b; 1657228753Smm xar->lzstream.avail_in = avail_in; 1658228753Smm xar->lzstream.next_out = (unsigned char *)outbuff; 1659228753Smm xar->lzstream.avail_out = avail_out; 1660228753Smm r = lzma_code(&(xar->lzstream), LZMA_RUN); 1661228753Smm switch (r) { 1662228753Smm case LZMA_STREAM_END: /* Found end of stream. */ 1663228753Smm lzma_end(&(xar->lzstream)); 1664228753Smm xar->lzstream_valid = 0; 1665228753Smm /* FALLTHROUGH */ 1666228753Smm case LZMA_OK: /* Decompressor made some progress. */ 1667228753Smm break; 1668228753Smm default: 1669228753Smm archive_set_error(&(a->archive), 1670228753Smm ARCHIVE_ERRNO_MISC, 1671228753Smm "%s decompression failed(%d)", 1672228753Smm (xar->entry_encoding == XZ)?"xz":"lzma", 1673228753Smm r); 1674228753Smm return (ARCHIVE_FATAL); 1675228753Smm } 1676228753Smm *used = avail_in - xar->lzstream.avail_in; 1677228753Smm *outbytes = avail_out - xar->lzstream.avail_out; 1678228753Smm break; 1679228753Smm#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) 1680228753Smm case LZMA: 1681228753Smm xar->lzstream.next_in = (unsigned char *)(uintptr_t)b; 1682228753Smm xar->lzstream.avail_in = avail_in; 1683228753Smm xar->lzstream.next_out = (unsigned char *)outbuff; 1684228753Smm xar->lzstream.avail_out = avail_out; 1685228753Smm r = lzmadec_decode(&(xar->lzstream), 0); 1686228753Smm switch (r) { 1687228753Smm case LZMADEC_STREAM_END: /* Found end of stream. */ 1688228753Smm switch (lzmadec_end(&(xar->lzstream))) { 1689228753Smm case LZMADEC_OK: 1690228753Smm break; 1691228753Smm default: 1692228753Smm archive_set_error(&(a->archive), 1693228753Smm ARCHIVE_ERRNO_MISC, 1694228753Smm "Failed to clean up lzmadec decompressor"); 1695228753Smm return (ARCHIVE_FATAL); 1696228753Smm } 1697228753Smm xar->lzstream_valid = 0; 1698228753Smm /* FALLTHROUGH */ 1699228753Smm case LZMADEC_OK: /* Decompressor made some progress. */ 1700228753Smm break; 1701228753Smm default: 1702228753Smm archive_set_error(&(a->archive), 1703228753Smm ARCHIVE_ERRNO_MISC, 1704228753Smm "lzmadec decompression failed(%d)", 1705228753Smm r); 1706228753Smm return (ARCHIVE_FATAL); 1707228753Smm } 1708228753Smm *used = avail_in - xar->lzstream.avail_in; 1709228753Smm *outbytes = avail_out - xar->lzstream.avail_out; 1710228753Smm break; 1711228753Smm#endif 1712228753Smm#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) 1713228753Smm case BZIP2: 1714228753Smm#endif 1715228753Smm#if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) 1716228753Smm#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) 1717228753Smm case LZMA: 1718228753Smm#endif 1719228753Smm case XZ: 1720228753Smm#endif 1721228753Smm case NONE: 1722228753Smm default: 1723232153Smm if (outbuff == xar->outbuff) { 1724228753Smm *buff = b; 1725228753Smm *used = avail_in; 1726228753Smm *outbytes = avail_in; 1727228753Smm } else { 1728228753Smm if (avail_out > avail_in) 1729228753Smm avail_out = avail_in; 1730228753Smm memcpy(outbuff, b, avail_out); 1731228753Smm *used = avail_out; 1732228753Smm *outbytes = avail_out; 1733228753Smm } 1734228753Smm break; 1735228753Smm } 1736228753Smm return (ARCHIVE_OK); 1737228753Smm} 1738228753Smm 1739228753Smmstatic int 1740228753Smmdecompression_cleanup(struct archive_read *a) 1741228753Smm{ 1742228753Smm struct xar *xar; 1743228753Smm int r; 1744228753Smm 1745228753Smm xar = (struct xar *)(a->format->data); 1746228753Smm r = ARCHIVE_OK; 1747228753Smm if (xar->stream_valid) { 1748228753Smm if (inflateEnd(&(xar->stream)) != Z_OK) { 1749228753Smm archive_set_error(&a->archive, 1750228753Smm ARCHIVE_ERRNO_MISC, 1751228753Smm "Failed to clean up zlib decompressor"); 1752228753Smm r = ARCHIVE_FATAL; 1753228753Smm } 1754228753Smm } 1755228753Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 1756228753Smm if (xar->bzstream_valid) { 1757228753Smm if (BZ2_bzDecompressEnd(&(xar->bzstream)) != BZ_OK) { 1758228753Smm archive_set_error(&a->archive, 1759228753Smm ARCHIVE_ERRNO_MISC, 1760228753Smm "Failed to clean up bzip2 decompressor"); 1761228753Smm r = ARCHIVE_FATAL; 1762228753Smm } 1763228753Smm } 1764228753Smm#endif 1765228753Smm#if defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1766228753Smm if (xar->lzstream_valid) 1767228753Smm lzma_end(&(xar->lzstream)); 1768228753Smm#elif defined(HAVE_LZMA_H) && defined(HAVE_LIBLZMA) 1769228753Smm if (xar->lzstream_valid) { 1770228753Smm if (lzmadec_end(&(xar->lzstream)) != LZMADEC_OK) { 1771228753Smm archive_set_error(&a->archive, 1772228753Smm ARCHIVE_ERRNO_MISC, 1773228753Smm "Failed to clean up lzmadec decompressor"); 1774228753Smm r = ARCHIVE_FATAL; 1775228753Smm } 1776228753Smm } 1777228753Smm#endif 1778228753Smm return (r); 1779228753Smm} 1780228753Smm 1781228753Smmstatic void 1782228753Smmxmlattr_cleanup(struct xmlattr_list *list) 1783228753Smm{ 1784228753Smm struct xmlattr *attr, *next; 1785228753Smm 1786228753Smm attr = list->first; 1787228753Smm while (attr != NULL) { 1788228753Smm next = attr->next; 1789228753Smm free(attr->name); 1790228753Smm free(attr->value); 1791228753Smm free(attr); 1792228753Smm attr = next; 1793228753Smm } 1794228753Smm list->first = NULL; 1795228753Smm list->last = &(list->first); 1796228753Smm} 1797228753Smm 1798232153Smmstatic int 1799232153Smmfile_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) 1800228753Smm{ 1801228753Smm struct xar_file *file; 1802228753Smm struct xmlattr *attr; 1803228753Smm 1804228753Smm file = calloc(1, sizeof(*file)); 1805232153Smm if (file == NULL) { 1806232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 1807232153Smm return (ARCHIVE_FATAL); 1808232153Smm } 1809228753Smm file->parent = xar->file; 1810228753Smm file->mode = 0777 | AE_IFREG; 1811228753Smm file->atime = time(NULL); 1812228753Smm file->mtime = time(NULL); 1813228753Smm xar->file = file; 1814228753Smm xar->xattr = NULL; 1815228753Smm for (attr = list->first; attr != NULL; attr = attr->next) { 1816228753Smm if (strcmp(attr->name, "id") == 0) 1817228753Smm file->id = atol10(attr->value, strlen(attr->value)); 1818228753Smm } 1819228753Smm file->nlink = 1; 1820232153Smm if (heap_add_entry(a, &(xar->file_queue), file) != ARCHIVE_OK) 1821232153Smm return (ARCHIVE_FATAL); 1822232153Smm return (ARCHIVE_OK); 1823228753Smm} 1824228753Smm 1825228753Smmstatic void 1826228753Smmfile_free(struct xar_file *file) 1827228753Smm{ 1828228753Smm struct xattr *xattr; 1829228753Smm 1830228753Smm archive_string_free(&(file->pathname)); 1831228753Smm archive_string_free(&(file->symlink)); 1832228753Smm archive_string_free(&(file->uname)); 1833228753Smm archive_string_free(&(file->gname)); 1834228753Smm archive_string_free(&(file->hardlink)); 1835228753Smm xattr = file->xattr_list; 1836228753Smm while (xattr != NULL) { 1837228753Smm struct xattr *next; 1838228753Smm 1839228753Smm next = xattr->next; 1840228753Smm xattr_free(xattr); 1841228753Smm xattr = next; 1842228753Smm } 1843228753Smm 1844228753Smm free(file); 1845228753Smm} 1846228753Smm 1847232153Smmstatic int 1848232153Smmxattr_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list) 1849228753Smm{ 1850228753Smm struct xattr *xattr, **nx; 1851228753Smm struct xmlattr *attr; 1852228753Smm 1853228753Smm xattr = calloc(1, sizeof(*xattr)); 1854232153Smm if (xattr == NULL) { 1855232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 1856232153Smm return (ARCHIVE_FATAL); 1857232153Smm } 1858228753Smm xar->xattr = xattr; 1859228753Smm for (attr = list->first; attr != NULL; attr = attr->next) { 1860228753Smm if (strcmp(attr->name, "id") == 0) 1861228753Smm xattr->id = atol10(attr->value, strlen(attr->value)); 1862228753Smm } 1863228753Smm /* Chain to xattr list. */ 1864228753Smm for (nx = &(xar->file->xattr_list); 1865228753Smm *nx != NULL; nx = &((*nx)->next)) { 1866228753Smm if (xattr->id < (*nx)->id) 1867228753Smm break; 1868228753Smm } 1869228753Smm xattr->next = *nx; 1870228753Smm *nx = xattr; 1871232153Smm 1872232153Smm return (ARCHIVE_OK); 1873228753Smm} 1874228753Smm 1875228753Smmstatic void 1876228753Smmxattr_free(struct xattr *xattr) 1877228753Smm{ 1878228753Smm archive_string_free(&(xattr->name)); 1879228753Smm free(xattr); 1880228753Smm} 1881228753Smm 1882228753Smmstatic int 1883228753Smmgetencoding(struct xmlattr_list *list) 1884228753Smm{ 1885228753Smm struct xmlattr *attr; 1886228753Smm enum enctype encoding = NONE; 1887228753Smm 1888228753Smm for (attr = list->first; attr != NULL; attr = attr->next) { 1889228753Smm if (strcmp(attr->name, "style") == 0) { 1890228753Smm if (strcmp(attr->value, "application/octet-stream") == 0) 1891228753Smm encoding = NONE; 1892228753Smm else if (strcmp(attr->value, "application/x-gzip") == 0) 1893228753Smm encoding = GZIP; 1894228753Smm else if (strcmp(attr->value, "application/x-bzip2") == 0) 1895228753Smm encoding = BZIP2; 1896228753Smm else if (strcmp(attr->value, "application/x-lzma") == 0) 1897228753Smm encoding = LZMA; 1898228753Smm else if (strcmp(attr->value, "application/x-xz") == 0) 1899228753Smm encoding = XZ; 1900228753Smm } 1901228753Smm } 1902228753Smm return (encoding); 1903228753Smm} 1904228753Smm 1905228753Smmstatic int 1906228753Smmgetsumalgorithm(struct xmlattr_list *list) 1907228753Smm{ 1908228753Smm struct xmlattr *attr; 1909228753Smm int alg = CKSUM_NONE; 1910228753Smm 1911228753Smm for (attr = list->first; attr != NULL; attr = attr->next) { 1912228753Smm if (strcmp(attr->name, "style") == 0) { 1913228753Smm const char *v = attr->value; 1914228753Smm if ((v[0] == 'S' || v[0] == 's') && 1915228753Smm (v[1] == 'H' || v[1] == 'h') && 1916228753Smm (v[2] == 'A' || v[2] == 'a') && 1917228753Smm v[3] == '1' && v[4] == '\0') 1918228753Smm alg = CKSUM_SHA1; 1919228753Smm if ((v[0] == 'M' || v[0] == 'm') && 1920228753Smm (v[1] == 'D' || v[1] == 'd') && 1921228753Smm v[2] == '5' && v[3] == '\0') 1922228753Smm alg = CKSUM_MD5; 1923228753Smm } 1924228753Smm } 1925228753Smm return (alg); 1926228753Smm} 1927228753Smm 1928232153Smmstatic int 1929232153Smmunknowntag_start(struct archive_read *a, struct xar *xar, const char *name) 1930228753Smm{ 1931228753Smm struct unknown_tag *tag; 1932228753Smm 1933228753Smm#if DEBUG 1934228753Smm fprintf(stderr, "unknowntag_start:%s\n", name); 1935228753Smm#endif 1936228753Smm tag = malloc(sizeof(*tag)); 1937232153Smm if (tag == NULL) { 1938232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 1939232153Smm return (ARCHIVE_FATAL); 1940232153Smm } 1941228753Smm tag->next = xar->unknowntags; 1942228753Smm archive_string_init(&(tag->name)); 1943228753Smm archive_strcpy(&(tag->name), name); 1944228753Smm if (xar->unknowntags == NULL) { 1945228753Smm xar->xmlsts_unknown = xar->xmlsts; 1946228753Smm xar->xmlsts = UNKNOWN; 1947228753Smm } 1948228753Smm xar->unknowntags = tag; 1949232153Smm return (ARCHIVE_OK); 1950228753Smm} 1951228753Smm 1952228753Smmstatic void 1953228753Smmunknowntag_end(struct xar *xar, const char *name) 1954228753Smm{ 1955228753Smm struct unknown_tag *tag; 1956228753Smm 1957228753Smm#if DEBUG 1958228753Smm fprintf(stderr, "unknowntag_end:%s\n", name); 1959228753Smm#endif 1960228753Smm tag = xar->unknowntags; 1961228753Smm if (tag == NULL || name == NULL) 1962228753Smm return; 1963228753Smm if (strcmp(tag->name.s, name) == 0) { 1964228753Smm xar->unknowntags = tag->next; 1965228753Smm archive_string_free(&(tag->name)); 1966228753Smm free(tag); 1967228753Smm if (xar->unknowntags == NULL) 1968228753Smm xar->xmlsts = xar->xmlsts_unknown; 1969228753Smm } 1970228753Smm} 1971228753Smm 1972232153Smmstatic int 1973232153Smmxml_start(struct archive_read *a, const char *name, struct xmlattr_list *list) 1974228753Smm{ 1975228753Smm struct xar *xar; 1976228753Smm struct xmlattr *attr; 1977228753Smm 1978228753Smm xar = (struct xar *)(a->format->data); 1979228753Smm 1980228753Smm#if DEBUG 1981228753Smm fprintf(stderr, "xml_sta:[%s]\n", name); 1982228753Smm for (attr = list->first; attr != NULL; attr = attr->next) 1983228753Smm fprintf(stderr, " attr:\"%s\"=\"%s\"\n", 1984228753Smm attr->name, attr->value); 1985228753Smm#endif 1986228753Smm xar->base64text = 0; 1987228753Smm switch (xar->xmlsts) { 1988228753Smm case INIT: 1989228753Smm if (strcmp(name, "xar") == 0) 1990228753Smm xar->xmlsts = XAR; 1991228753Smm else 1992232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 1993232153Smm return (ARCHIVE_FATAL); 1994228753Smm break; 1995228753Smm case XAR: 1996228753Smm if (strcmp(name, "toc") == 0) 1997228753Smm xar->xmlsts = TOC; 1998228753Smm else 1999232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2000232153Smm return (ARCHIVE_FATAL); 2001228753Smm break; 2002228753Smm case TOC: 2003228753Smm if (strcmp(name, "creation-time") == 0) 2004228753Smm xar->xmlsts = TOC_CREATION_TIME; 2005228753Smm else if (strcmp(name, "checksum") == 0) 2006228753Smm xar->xmlsts = TOC_CHECKSUM; 2007228753Smm else if (strcmp(name, "file") == 0) { 2008232153Smm if (file_new(a, xar, list) != ARCHIVE_OK) 2009232153Smm return (ARCHIVE_FATAL); 2010228753Smm xar->xmlsts = TOC_FILE; 2011228753Smm } 2012228753Smm else 2013232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2014232153Smm return (ARCHIVE_FATAL); 2015228753Smm break; 2016228753Smm case TOC_CHECKSUM: 2017228753Smm if (strcmp(name, "offset") == 0) 2018228753Smm xar->xmlsts = TOC_CHECKSUM_OFFSET; 2019228753Smm else if (strcmp(name, "size") == 0) 2020228753Smm xar->xmlsts = TOC_CHECKSUM_SIZE; 2021228753Smm else 2022232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2023232153Smm return (ARCHIVE_FATAL); 2024228753Smm break; 2025228753Smm case TOC_FILE: 2026228753Smm if (strcmp(name, "file") == 0) { 2027232153Smm if (file_new(a, xar, list) != ARCHIVE_OK) 2028232153Smm return (ARCHIVE_FATAL); 2029228753Smm } 2030228753Smm else if (strcmp(name, "data") == 0) 2031228753Smm xar->xmlsts = FILE_DATA; 2032228753Smm else if (strcmp(name, "ea") == 0) { 2033232153Smm if (xattr_new(a, xar, list) != ARCHIVE_OK) 2034232153Smm return (ARCHIVE_FATAL); 2035228753Smm xar->xmlsts = FILE_EA; 2036228753Smm } 2037228753Smm else if (strcmp(name, "ctime") == 0) 2038228753Smm xar->xmlsts = FILE_CTIME; 2039228753Smm else if (strcmp(name, "mtime") == 0) 2040228753Smm xar->xmlsts = FILE_MTIME; 2041228753Smm else if (strcmp(name, "atime") == 0) 2042228753Smm xar->xmlsts = FILE_ATIME; 2043228753Smm else if (strcmp(name, "group") == 0) 2044228753Smm xar->xmlsts = FILE_GROUP; 2045228753Smm else if (strcmp(name, "gid") == 0) 2046228753Smm xar->xmlsts = FILE_GID; 2047228753Smm else if (strcmp(name, "user") == 0) 2048228753Smm xar->xmlsts = FILE_USER; 2049228753Smm else if (strcmp(name, "uid") == 0) 2050228753Smm xar->xmlsts = FILE_UID; 2051228753Smm else if (strcmp(name, "mode") == 0) 2052228753Smm xar->xmlsts = FILE_MODE; 2053228753Smm else if (strcmp(name, "device") == 0) 2054228753Smm xar->xmlsts = FILE_DEVICE; 2055228753Smm else if (strcmp(name, "deviceno") == 0) 2056228753Smm xar->xmlsts = FILE_DEVICENO; 2057228753Smm else if (strcmp(name, "inode") == 0) 2058228753Smm xar->xmlsts = FILE_INODE; 2059228753Smm else if (strcmp(name, "link") == 0) 2060228753Smm xar->xmlsts = FILE_LINK; 2061228753Smm else if (strcmp(name, "type") == 0) { 2062228753Smm xar->xmlsts = FILE_TYPE; 2063228753Smm for (attr = list->first; attr != NULL; 2064228753Smm attr = attr->next) { 2065228753Smm if (strcmp(attr->name, "link") != 0) 2066228753Smm continue; 2067228753Smm if (strcmp(attr->value, "original") == 0) { 2068228753Smm xar->file->hdnext = xar->hdlink_orgs; 2069228753Smm xar->hdlink_orgs = xar->file; 2070228753Smm } else { 2071238856Smm xar->file->link = (unsigned)atol10(attr->value, 2072228753Smm strlen(attr->value)); 2073228753Smm if (xar->file->link > 0) 2074232153Smm if (add_link(a, xar, xar->file) != ARCHIVE_OK) { 2075232153Smm return (ARCHIVE_FATAL); 2076232153Smm }; 2077228753Smm } 2078228753Smm } 2079228753Smm } 2080228753Smm else if (strcmp(name, "name") == 0) { 2081228753Smm xar->xmlsts = FILE_NAME; 2082228753Smm for (attr = list->first; attr != NULL; 2083228753Smm attr = attr->next) { 2084228753Smm if (strcmp(attr->name, "enctype") == 0 && 2085228753Smm strcmp(attr->value, "base64") == 0) 2086228753Smm xar->base64text = 1; 2087228753Smm } 2088228753Smm } 2089228753Smm else if (strcmp(name, "acl") == 0) 2090228753Smm xar->xmlsts = FILE_ACL; 2091228753Smm else if (strcmp(name, "flags") == 0) 2092228753Smm xar->xmlsts = FILE_FLAGS; 2093228753Smm else if (strcmp(name, "ext2") == 0) 2094228753Smm xar->xmlsts = FILE_EXT2; 2095228753Smm else 2096232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2097232153Smm return (ARCHIVE_FATAL); 2098228753Smm break; 2099228753Smm case FILE_DATA: 2100228753Smm if (strcmp(name, "length") == 0) 2101228753Smm xar->xmlsts = FILE_DATA_LENGTH; 2102228753Smm else if (strcmp(name, "offset") == 0) 2103228753Smm xar->xmlsts = FILE_DATA_OFFSET; 2104228753Smm else if (strcmp(name, "size") == 0) 2105228753Smm xar->xmlsts = FILE_DATA_SIZE; 2106228753Smm else if (strcmp(name, "encoding") == 0) { 2107228753Smm xar->xmlsts = FILE_DATA_ENCODING; 2108228753Smm xar->file->encoding = getencoding(list); 2109228753Smm } 2110228753Smm else if (strcmp(name, "archived-checksum") == 0) { 2111228753Smm xar->xmlsts = FILE_DATA_A_CHECKSUM; 2112228753Smm xar->file->a_sum.alg = getsumalgorithm(list); 2113228753Smm } 2114228753Smm else if (strcmp(name, "extracted-checksum") == 0) { 2115228753Smm xar->xmlsts = FILE_DATA_E_CHECKSUM; 2116228753Smm xar->file->e_sum.alg = getsumalgorithm(list); 2117228753Smm } 2118228753Smm else if (strcmp(name, "content") == 0) 2119228753Smm xar->xmlsts = FILE_DATA_CONTENT; 2120228753Smm else 2121232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2122232153Smm return (ARCHIVE_FATAL); 2123228753Smm break; 2124228753Smm case FILE_DEVICE: 2125228753Smm if (strcmp(name, "major") == 0) 2126228753Smm xar->xmlsts = FILE_DEVICE_MAJOR; 2127228753Smm else if (strcmp(name, "minor") == 0) 2128228753Smm xar->xmlsts = FILE_DEVICE_MINOR; 2129228753Smm else 2130232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2131232153Smm return (ARCHIVE_FATAL); 2132228753Smm break; 2133228753Smm case FILE_DATA_CONTENT: 2134232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2135232153Smm return (ARCHIVE_FATAL); 2136228753Smm break; 2137228753Smm case FILE_EA: 2138228753Smm if (strcmp(name, "length") == 0) 2139228753Smm xar->xmlsts = FILE_EA_LENGTH; 2140228753Smm else if (strcmp(name, "offset") == 0) 2141228753Smm xar->xmlsts = FILE_EA_OFFSET; 2142228753Smm else if (strcmp(name, "size") == 0) 2143228753Smm xar->xmlsts = FILE_EA_SIZE; 2144228753Smm else if (strcmp(name, "encoding") == 0) { 2145228753Smm xar->xmlsts = FILE_EA_ENCODING; 2146228753Smm xar->xattr->encoding = getencoding(list); 2147228753Smm } else if (strcmp(name, "archived-checksum") == 0) 2148228753Smm xar->xmlsts = FILE_EA_A_CHECKSUM; 2149228753Smm else if (strcmp(name, "extracted-checksum") == 0) 2150228753Smm xar->xmlsts = FILE_EA_E_CHECKSUM; 2151228753Smm else if (strcmp(name, "name") == 0) 2152228753Smm xar->xmlsts = FILE_EA_NAME; 2153228753Smm else if (strcmp(name, "fstype") == 0) 2154228753Smm xar->xmlsts = FILE_EA_FSTYPE; 2155228753Smm else 2156232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2157232153Smm return (ARCHIVE_FATAL); 2158228753Smm break; 2159228753Smm case FILE_ACL: 2160228753Smm if (strcmp(name, "appleextended") == 0) 2161228753Smm xar->xmlsts = FILE_ACL_APPLEEXTENDED; 2162228753Smm if (strcmp(name, "default") == 0) 2163228753Smm xar->xmlsts = FILE_ACL_DEFAULT; 2164228753Smm else if (strcmp(name, "access") == 0) 2165228753Smm xar->xmlsts = FILE_ACL_ACCESS; 2166228753Smm else 2167232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2168232153Smm return (ARCHIVE_FATAL); 2169228753Smm break; 2170228753Smm case FILE_FLAGS: 2171228753Smm if (!xml_parse_file_flags(xar, name)) 2172232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2173232153Smm return (ARCHIVE_FATAL); 2174228753Smm break; 2175228753Smm case FILE_EXT2: 2176228753Smm if (!xml_parse_file_ext2(xar, name)) 2177232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2178232153Smm return (ARCHIVE_FATAL); 2179228753Smm break; 2180228753Smm case TOC_CREATION_TIME: 2181228753Smm case TOC_CHECKSUM_OFFSET: 2182228753Smm case TOC_CHECKSUM_SIZE: 2183228753Smm case FILE_DATA_LENGTH: 2184228753Smm case FILE_DATA_OFFSET: 2185228753Smm case FILE_DATA_SIZE: 2186228753Smm case FILE_DATA_ENCODING: 2187228753Smm case FILE_DATA_A_CHECKSUM: 2188228753Smm case FILE_DATA_E_CHECKSUM: 2189228753Smm case FILE_EA_LENGTH: 2190228753Smm case FILE_EA_OFFSET: 2191228753Smm case FILE_EA_SIZE: 2192228753Smm case FILE_EA_ENCODING: 2193228753Smm case FILE_EA_A_CHECKSUM: 2194228753Smm case FILE_EA_E_CHECKSUM: 2195228753Smm case FILE_EA_NAME: 2196228753Smm case FILE_EA_FSTYPE: 2197228753Smm case FILE_CTIME: 2198228753Smm case FILE_MTIME: 2199228753Smm case FILE_ATIME: 2200228753Smm case FILE_GROUP: 2201228753Smm case FILE_GID: 2202228753Smm case FILE_USER: 2203228753Smm case FILE_UID: 2204228753Smm case FILE_INODE: 2205228753Smm case FILE_DEVICE_MAJOR: 2206228753Smm case FILE_DEVICE_MINOR: 2207228753Smm case FILE_DEVICENO: 2208228753Smm case FILE_MODE: 2209228753Smm case FILE_TYPE: 2210228753Smm case FILE_LINK: 2211228753Smm case FILE_NAME: 2212228753Smm case FILE_ACL_DEFAULT: 2213228753Smm case FILE_ACL_ACCESS: 2214228753Smm case FILE_ACL_APPLEEXTENDED: 2215228753Smm case FILE_FLAGS_USER_NODUMP: 2216228753Smm case FILE_FLAGS_USER_IMMUTABLE: 2217228753Smm case FILE_FLAGS_USER_APPEND: 2218228753Smm case FILE_FLAGS_USER_OPAQUE: 2219228753Smm case FILE_FLAGS_USER_NOUNLINK: 2220228753Smm case FILE_FLAGS_SYS_ARCHIVED: 2221228753Smm case FILE_FLAGS_SYS_IMMUTABLE: 2222228753Smm case FILE_FLAGS_SYS_APPEND: 2223228753Smm case FILE_FLAGS_SYS_NOUNLINK: 2224228753Smm case FILE_FLAGS_SYS_SNAPSHOT: 2225228753Smm case FILE_EXT2_SecureDeletion: 2226228753Smm case FILE_EXT2_Undelete: 2227228753Smm case FILE_EXT2_Compress: 2228228753Smm case FILE_EXT2_Synchronous: 2229228753Smm case FILE_EXT2_Immutable: 2230228753Smm case FILE_EXT2_AppendOnly: 2231228753Smm case FILE_EXT2_NoDump: 2232228753Smm case FILE_EXT2_NoAtime: 2233228753Smm case FILE_EXT2_CompDirty: 2234228753Smm case FILE_EXT2_CompBlock: 2235228753Smm case FILE_EXT2_NoCompBlock: 2236228753Smm case FILE_EXT2_CompError: 2237228753Smm case FILE_EXT2_BTree: 2238228753Smm case FILE_EXT2_HashIndexed: 2239228753Smm case FILE_EXT2_iMagic: 2240228753Smm case FILE_EXT2_Journaled: 2241228753Smm case FILE_EXT2_NoTail: 2242228753Smm case FILE_EXT2_DirSync: 2243228753Smm case FILE_EXT2_TopDir: 2244228753Smm case FILE_EXT2_Reserved: 2245228753Smm case UNKNOWN: 2246232153Smm if (unknowntag_start(a, xar, name) != ARCHIVE_OK) 2247232153Smm return (ARCHIVE_FATAL); 2248228753Smm break; 2249228753Smm } 2250232153Smm return (ARCHIVE_OK); 2251228753Smm} 2252228753Smm 2253228753Smmstatic void 2254228753Smmxml_end(void *userData, const char *name) 2255228753Smm{ 2256228753Smm struct archive_read *a; 2257228753Smm struct xar *xar; 2258228753Smm 2259228753Smm a = (struct archive_read *)userData; 2260228753Smm xar = (struct xar *)(a->format->data); 2261228753Smm 2262228753Smm#if DEBUG 2263228753Smm fprintf(stderr, "xml_end:[%s]\n", name); 2264228753Smm#endif 2265228753Smm switch (xar->xmlsts) { 2266228753Smm case INIT: 2267228753Smm break; 2268228753Smm case XAR: 2269228753Smm if (strcmp(name, "xar") == 0) 2270228753Smm xar->xmlsts = INIT; 2271228753Smm break; 2272228753Smm case TOC: 2273228753Smm if (strcmp(name, "toc") == 0) 2274228753Smm xar->xmlsts = XAR; 2275228753Smm break; 2276228753Smm case TOC_CREATION_TIME: 2277228753Smm if (strcmp(name, "creation-time") == 0) 2278228753Smm xar->xmlsts = TOC; 2279228753Smm break; 2280228753Smm case TOC_CHECKSUM: 2281228753Smm if (strcmp(name, "checksum") == 0) 2282228753Smm xar->xmlsts = TOC; 2283228753Smm break; 2284228753Smm case TOC_CHECKSUM_OFFSET: 2285228753Smm if (strcmp(name, "offset") == 0) 2286228753Smm xar->xmlsts = TOC_CHECKSUM; 2287228753Smm break; 2288228753Smm case TOC_CHECKSUM_SIZE: 2289228753Smm if (strcmp(name, "size") == 0) 2290228753Smm xar->xmlsts = TOC_CHECKSUM; 2291228753Smm break; 2292228753Smm case TOC_FILE: 2293228753Smm if (strcmp(name, "file") == 0) { 2294228753Smm if (xar->file->parent != NULL && 2295228753Smm ((xar->file->mode & AE_IFMT) == AE_IFDIR)) 2296228753Smm xar->file->parent->subdirs++; 2297228753Smm xar->file = xar->file->parent; 2298228753Smm if (xar->file == NULL) 2299228753Smm xar->xmlsts = TOC; 2300228753Smm } 2301228753Smm break; 2302228753Smm case FILE_DATA: 2303228753Smm if (strcmp(name, "data") == 0) 2304228753Smm xar->xmlsts = TOC_FILE; 2305228753Smm break; 2306228753Smm case FILE_DATA_LENGTH: 2307228753Smm if (strcmp(name, "length") == 0) 2308228753Smm xar->xmlsts = FILE_DATA; 2309228753Smm break; 2310228753Smm case FILE_DATA_OFFSET: 2311228753Smm if (strcmp(name, "offset") == 0) 2312228753Smm xar->xmlsts = FILE_DATA; 2313228753Smm break; 2314228753Smm case FILE_DATA_SIZE: 2315228753Smm if (strcmp(name, "size") == 0) 2316228753Smm xar->xmlsts = FILE_DATA; 2317228753Smm break; 2318228753Smm case FILE_DATA_ENCODING: 2319228753Smm if (strcmp(name, "encoding") == 0) 2320228753Smm xar->xmlsts = FILE_DATA; 2321228753Smm break; 2322228753Smm case FILE_DATA_A_CHECKSUM: 2323228753Smm if (strcmp(name, "archived-checksum") == 0) 2324228753Smm xar->xmlsts = FILE_DATA; 2325228753Smm break; 2326228753Smm case FILE_DATA_E_CHECKSUM: 2327228753Smm if (strcmp(name, "extracted-checksum") == 0) 2328228753Smm xar->xmlsts = FILE_DATA; 2329228753Smm break; 2330228753Smm case FILE_DATA_CONTENT: 2331228753Smm if (strcmp(name, "content") == 0) 2332228753Smm xar->xmlsts = FILE_DATA; 2333228753Smm break; 2334228753Smm case FILE_EA: 2335228753Smm if (strcmp(name, "ea") == 0) { 2336228753Smm xar->xmlsts = TOC_FILE; 2337228753Smm xar->xattr = NULL; 2338228753Smm } 2339228753Smm break; 2340228753Smm case FILE_EA_LENGTH: 2341228753Smm if (strcmp(name, "length") == 0) 2342228753Smm xar->xmlsts = FILE_EA; 2343228753Smm break; 2344228753Smm case FILE_EA_OFFSET: 2345228753Smm if (strcmp(name, "offset") == 0) 2346228753Smm xar->xmlsts = FILE_EA; 2347228753Smm break; 2348228753Smm case FILE_EA_SIZE: 2349228753Smm if (strcmp(name, "size") == 0) 2350228753Smm xar->xmlsts = FILE_EA; 2351228753Smm break; 2352228753Smm case FILE_EA_ENCODING: 2353228753Smm if (strcmp(name, "encoding") == 0) 2354228753Smm xar->xmlsts = FILE_EA; 2355228753Smm break; 2356228753Smm case FILE_EA_A_CHECKSUM: 2357228753Smm if (strcmp(name, "archived-checksum") == 0) 2358228753Smm xar->xmlsts = FILE_EA; 2359228753Smm break; 2360228753Smm case FILE_EA_E_CHECKSUM: 2361228753Smm if (strcmp(name, "extracted-checksum") == 0) 2362228753Smm xar->xmlsts = FILE_EA; 2363228753Smm break; 2364228753Smm case FILE_EA_NAME: 2365228753Smm if (strcmp(name, "name") == 0) 2366228753Smm xar->xmlsts = FILE_EA; 2367228753Smm break; 2368228753Smm case FILE_EA_FSTYPE: 2369228753Smm if (strcmp(name, "fstype") == 0) 2370228753Smm xar->xmlsts = FILE_EA; 2371228753Smm break; 2372228753Smm case FILE_CTIME: 2373228753Smm if (strcmp(name, "ctime") == 0) 2374228753Smm xar->xmlsts = TOC_FILE; 2375228753Smm break; 2376228753Smm case FILE_MTIME: 2377228753Smm if (strcmp(name, "mtime") == 0) 2378228753Smm xar->xmlsts = TOC_FILE; 2379228753Smm break; 2380228753Smm case FILE_ATIME: 2381228753Smm if (strcmp(name, "atime") == 0) 2382228753Smm xar->xmlsts = TOC_FILE; 2383228753Smm break; 2384228753Smm case FILE_GROUP: 2385228753Smm if (strcmp(name, "group") == 0) 2386228753Smm xar->xmlsts = TOC_FILE; 2387228753Smm break; 2388228753Smm case FILE_GID: 2389228753Smm if (strcmp(name, "gid") == 0) 2390228753Smm xar->xmlsts = TOC_FILE; 2391228753Smm break; 2392228753Smm case FILE_USER: 2393228753Smm if (strcmp(name, "user") == 0) 2394228753Smm xar->xmlsts = TOC_FILE; 2395228753Smm break; 2396228753Smm case FILE_UID: 2397228753Smm if (strcmp(name, "uid") == 0) 2398228753Smm xar->xmlsts = TOC_FILE; 2399228753Smm break; 2400228753Smm case FILE_MODE: 2401228753Smm if (strcmp(name, "mode") == 0) 2402228753Smm xar->xmlsts = TOC_FILE; 2403228753Smm break; 2404228753Smm case FILE_DEVICE: 2405228753Smm if (strcmp(name, "device") == 0) 2406228753Smm xar->xmlsts = TOC_FILE; 2407228753Smm break; 2408228753Smm case FILE_DEVICE_MAJOR: 2409228753Smm if (strcmp(name, "major") == 0) 2410228753Smm xar->xmlsts = FILE_DEVICE; 2411228753Smm break; 2412228753Smm case FILE_DEVICE_MINOR: 2413228753Smm if (strcmp(name, "minor") == 0) 2414228753Smm xar->xmlsts = FILE_DEVICE; 2415228753Smm break; 2416228753Smm case FILE_DEVICENO: 2417228753Smm if (strcmp(name, "deviceno") == 0) 2418228753Smm xar->xmlsts = TOC_FILE; 2419228753Smm break; 2420228753Smm case FILE_INODE: 2421228753Smm if (strcmp(name, "inode") == 0) 2422228753Smm xar->xmlsts = TOC_FILE; 2423228753Smm break; 2424228753Smm case FILE_LINK: 2425228753Smm if (strcmp(name, "link") == 0) 2426228753Smm xar->xmlsts = TOC_FILE; 2427228753Smm break; 2428228753Smm case FILE_TYPE: 2429228753Smm if (strcmp(name, "type") == 0) 2430228753Smm xar->xmlsts = TOC_FILE; 2431228753Smm break; 2432228753Smm case FILE_NAME: 2433228753Smm if (strcmp(name, "name") == 0) 2434228753Smm xar->xmlsts = TOC_FILE; 2435228753Smm break; 2436228753Smm case FILE_ACL: 2437228753Smm if (strcmp(name, "acl") == 0) 2438228753Smm xar->xmlsts = TOC_FILE; 2439228753Smm break; 2440228753Smm case FILE_ACL_DEFAULT: 2441228753Smm if (strcmp(name, "default") == 0) 2442228753Smm xar->xmlsts = FILE_ACL; 2443228753Smm break; 2444228753Smm case FILE_ACL_ACCESS: 2445228753Smm if (strcmp(name, "access") == 0) 2446228753Smm xar->xmlsts = FILE_ACL; 2447228753Smm break; 2448228753Smm case FILE_ACL_APPLEEXTENDED: 2449228753Smm if (strcmp(name, "appleextended") == 0) 2450228753Smm xar->xmlsts = FILE_ACL; 2451228753Smm break; 2452228753Smm case FILE_FLAGS: 2453228753Smm if (strcmp(name, "flags") == 0) 2454228753Smm xar->xmlsts = TOC_FILE; 2455228753Smm break; 2456228753Smm case FILE_FLAGS_USER_NODUMP: 2457228753Smm if (strcmp(name, "UserNoDump") == 0) 2458228753Smm xar->xmlsts = FILE_FLAGS; 2459228753Smm break; 2460228753Smm case FILE_FLAGS_USER_IMMUTABLE: 2461228753Smm if (strcmp(name, "UserImmutable") == 0) 2462228753Smm xar->xmlsts = FILE_FLAGS; 2463228753Smm break; 2464228753Smm case FILE_FLAGS_USER_APPEND: 2465228753Smm if (strcmp(name, "UserAppend") == 0) 2466228753Smm xar->xmlsts = FILE_FLAGS; 2467228753Smm break; 2468228753Smm case FILE_FLAGS_USER_OPAQUE: 2469228753Smm if (strcmp(name, "UserOpaque") == 0) 2470228753Smm xar->xmlsts = FILE_FLAGS; 2471228753Smm break; 2472228753Smm case FILE_FLAGS_USER_NOUNLINK: 2473228753Smm if (strcmp(name, "UserNoUnlink") == 0) 2474228753Smm xar->xmlsts = FILE_FLAGS; 2475228753Smm break; 2476228753Smm case FILE_FLAGS_SYS_ARCHIVED: 2477228753Smm if (strcmp(name, "SystemArchived") == 0) 2478228753Smm xar->xmlsts = FILE_FLAGS; 2479228753Smm break; 2480228753Smm case FILE_FLAGS_SYS_IMMUTABLE: 2481228753Smm if (strcmp(name, "SystemImmutable") == 0) 2482228753Smm xar->xmlsts = FILE_FLAGS; 2483228753Smm break; 2484228753Smm case FILE_FLAGS_SYS_APPEND: 2485228753Smm if (strcmp(name, "SystemAppend") == 0) 2486228753Smm xar->xmlsts = FILE_FLAGS; 2487228753Smm break; 2488228753Smm case FILE_FLAGS_SYS_NOUNLINK: 2489228753Smm if (strcmp(name, "SystemNoUnlink") == 0) 2490228753Smm xar->xmlsts = FILE_FLAGS; 2491228753Smm break; 2492228753Smm case FILE_FLAGS_SYS_SNAPSHOT: 2493228753Smm if (strcmp(name, "SystemSnapshot") == 0) 2494228753Smm xar->xmlsts = FILE_FLAGS; 2495228753Smm break; 2496228753Smm case FILE_EXT2: 2497228753Smm if (strcmp(name, "ext2") == 0) 2498228753Smm xar->xmlsts = TOC_FILE; 2499228753Smm break; 2500228753Smm case FILE_EXT2_SecureDeletion: 2501228753Smm if (strcmp(name, "SecureDeletion") == 0) 2502228753Smm xar->xmlsts = FILE_EXT2; 2503228753Smm break; 2504228753Smm case FILE_EXT2_Undelete: 2505228753Smm if (strcmp(name, "Undelete") == 0) 2506228753Smm xar->xmlsts = FILE_EXT2; 2507228753Smm break; 2508228753Smm case FILE_EXT2_Compress: 2509228753Smm if (strcmp(name, "Compress") == 0) 2510228753Smm xar->xmlsts = FILE_EXT2; 2511228753Smm break; 2512228753Smm case FILE_EXT2_Synchronous: 2513228753Smm if (strcmp(name, "Synchronous") == 0) 2514228753Smm xar->xmlsts = FILE_EXT2; 2515228753Smm break; 2516228753Smm case FILE_EXT2_Immutable: 2517228753Smm if (strcmp(name, "Immutable") == 0) 2518228753Smm xar->xmlsts = FILE_EXT2; 2519228753Smm break; 2520228753Smm case FILE_EXT2_AppendOnly: 2521228753Smm if (strcmp(name, "AppendOnly") == 0) 2522228753Smm xar->xmlsts = FILE_EXT2; 2523228753Smm break; 2524228753Smm case FILE_EXT2_NoDump: 2525228753Smm if (strcmp(name, "NoDump") == 0) 2526228753Smm xar->xmlsts = FILE_EXT2; 2527228753Smm break; 2528228753Smm case FILE_EXT2_NoAtime: 2529228753Smm if (strcmp(name, "NoAtime") == 0) 2530228753Smm xar->xmlsts = FILE_EXT2; 2531228753Smm break; 2532228753Smm case FILE_EXT2_CompDirty: 2533228753Smm if (strcmp(name, "CompDirty") == 0) 2534228753Smm xar->xmlsts = FILE_EXT2; 2535228753Smm break; 2536228753Smm case FILE_EXT2_CompBlock: 2537228753Smm if (strcmp(name, "CompBlock") == 0) 2538228753Smm xar->xmlsts = FILE_EXT2; 2539228753Smm break; 2540228753Smm case FILE_EXT2_NoCompBlock: 2541228753Smm if (strcmp(name, "NoCompBlock") == 0) 2542228753Smm xar->xmlsts = FILE_EXT2; 2543228753Smm break; 2544228753Smm case FILE_EXT2_CompError: 2545228753Smm if (strcmp(name, "CompError") == 0) 2546228753Smm xar->xmlsts = FILE_EXT2; 2547228753Smm break; 2548228753Smm case FILE_EXT2_BTree: 2549228753Smm if (strcmp(name, "BTree") == 0) 2550228753Smm xar->xmlsts = FILE_EXT2; 2551228753Smm break; 2552228753Smm case FILE_EXT2_HashIndexed: 2553228753Smm if (strcmp(name, "HashIndexed") == 0) 2554228753Smm xar->xmlsts = FILE_EXT2; 2555228753Smm break; 2556228753Smm case FILE_EXT2_iMagic: 2557228753Smm if (strcmp(name, "iMagic") == 0) 2558228753Smm xar->xmlsts = FILE_EXT2; 2559228753Smm break; 2560228753Smm case FILE_EXT2_Journaled: 2561228753Smm if (strcmp(name, "Journaled") == 0) 2562228753Smm xar->xmlsts = FILE_EXT2; 2563228753Smm break; 2564228753Smm case FILE_EXT2_NoTail: 2565228753Smm if (strcmp(name, "NoTail") == 0) 2566228753Smm xar->xmlsts = FILE_EXT2; 2567228753Smm break; 2568228753Smm case FILE_EXT2_DirSync: 2569228753Smm if (strcmp(name, "DirSync") == 0) 2570228753Smm xar->xmlsts = FILE_EXT2; 2571228753Smm break; 2572228753Smm case FILE_EXT2_TopDir: 2573228753Smm if (strcmp(name, "TopDir") == 0) 2574228753Smm xar->xmlsts = FILE_EXT2; 2575228753Smm break; 2576228753Smm case FILE_EXT2_Reserved: 2577228753Smm if (strcmp(name, "Reserved") == 0) 2578228753Smm xar->xmlsts = FILE_EXT2; 2579228753Smm break; 2580228753Smm case UNKNOWN: 2581228753Smm unknowntag_end(xar, name); 2582228753Smm break; 2583228753Smm } 2584228753Smm} 2585228753Smm 2586228753Smmstatic const int base64[256] = { 2587228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2588228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* 00 - 0F */ 2589228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2590228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* 10 - 1F */ 2591228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2592228753Smm -1, -1, -1, 62, -1, -1, -1, 63, /* 20 - 2F */ 2593228753Smm 52, 53, 54, 55, 56, 57, 58, 59, 2594228753Smm 60, 61, -1, -1, -1, -1, -1, -1, /* 30 - 3F */ 2595228753Smm -1, 0, 1, 2, 3, 4, 5, 6, 2596228753Smm 7, 8, 9, 10, 11, 12, 13, 14, /* 40 - 4F */ 2597228753Smm 15, 16, 17, 18, 19, 20, 21, 22, 2598228753Smm 23, 24, 25, -1, -1, -1, -1, -1, /* 50 - 5F */ 2599228753Smm -1, 26, 27, 28, 29, 30, 31, 32, 2600228753Smm 33, 34, 35, 36, 37, 38, 39, 40, /* 60 - 6F */ 2601228753Smm 41, 42, 43, 44, 45, 46, 47, 48, 2602228753Smm 49, 50, 51, -1, -1, -1, -1, -1, /* 70 - 7F */ 2603228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2604228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 8F */ 2605228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2606228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* 90 - 9F */ 2607228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2608228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* A0 - AF */ 2609228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2610228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* B0 - BF */ 2611228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2612228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* C0 - CF */ 2613228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2614228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* D0 - DF */ 2615228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2616228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* E0 - EF */ 2617228753Smm -1, -1, -1, -1, -1, -1, -1, -1, 2618228753Smm -1, -1, -1, -1, -1, -1, -1, -1, /* F0 - FF */ 2619228753Smm}; 2620228753Smm 2621228753Smmstatic void 2622232153Smmstrappend_base64(struct xar *xar, 2623232153Smm struct archive_string *as, const char *s, size_t l) 2624228753Smm{ 2625228753Smm unsigned char buff[256]; 2626228753Smm unsigned char *out; 2627228753Smm const unsigned char *b; 2628228753Smm size_t len; 2629228753Smm 2630232153Smm (void)xar; /* UNUSED */ 2631228753Smm len = 0; 2632228753Smm out = buff; 2633228753Smm b = (const unsigned char *)s; 2634228753Smm while (l > 0) { 2635228753Smm int n = 0; 2636228753Smm 2637228753Smm if (l > 0) { 2638228753Smm if (base64[b[0]] < 0 || base64[b[1]] < 0) 2639228753Smm break; 2640228753Smm n = base64[*b++] << 18; 2641228753Smm n |= base64[*b++] << 12; 2642228753Smm *out++ = n >> 16; 2643228753Smm len++; 2644228753Smm l -= 2; 2645228753Smm } 2646228753Smm if (l > 0) { 2647228753Smm if (base64[*b] < 0) 2648228753Smm break; 2649228753Smm n |= base64[*b++] << 6; 2650228753Smm *out++ = (n >> 8) & 0xFF; 2651228753Smm len++; 2652228753Smm --l; 2653228753Smm } 2654228753Smm if (l > 0) { 2655228753Smm if (base64[*b] < 0) 2656228753Smm break; 2657228753Smm n |= base64[*b++]; 2658228753Smm *out++ = n & 0xFF; 2659228753Smm len++; 2660228753Smm --l; 2661228753Smm } 2662228753Smm if (len+3 >= sizeof(buff)) { 2663228753Smm archive_strncat(as, (const char *)buff, len); 2664228753Smm len = 0; 2665228753Smm out = buff; 2666228753Smm } 2667228753Smm } 2668228753Smm if (len > 0) 2669228753Smm archive_strncat(as, (const char *)buff, len); 2670228753Smm} 2671228753Smm 2672228753Smmstatic void 2673228753Smmxml_data(void *userData, const char *s, int len) 2674228753Smm{ 2675228753Smm struct archive_read *a; 2676228753Smm struct xar *xar; 2677228753Smm 2678228753Smm a = (struct archive_read *)userData; 2679228753Smm xar = (struct xar *)(a->format->data); 2680228753Smm 2681228753Smm#if DEBUG 2682228753Smm { 2683228753Smm char buff[1024]; 2684232153Smm if (len > sizeof(buff)-1) 2685232153Smm len = sizeof(buff)-1; 2686228753Smm memcpy(buff, s, len); 2687228753Smm buff[len] = 0; 2688228753Smm fprintf(stderr, "\tlen=%d:\"%s\"\n", len, buff); 2689228753Smm } 2690228753Smm#endif 2691228753Smm switch (xar->xmlsts) { 2692228753Smm case TOC_CHECKSUM_OFFSET: 2693228753Smm xar->toc_chksum_offset = atol10(s, len); 2694228753Smm break; 2695228753Smm case TOC_CHECKSUM_SIZE: 2696228753Smm xar->toc_chksum_size = atol10(s, len); 2697228753Smm break; 2698228753Smm default: 2699228753Smm break; 2700228753Smm } 2701228753Smm if (xar->file == NULL) 2702228753Smm return; 2703228753Smm 2704228753Smm switch (xar->xmlsts) { 2705228753Smm case FILE_NAME: 2706228753Smm if (xar->file->parent != NULL) { 2707228753Smm archive_string_concat(&(xar->file->pathname), 2708228753Smm &(xar->file->parent->pathname)); 2709228753Smm archive_strappend_char(&(xar->file->pathname), '/'); 2710228753Smm } 2711228753Smm xar->file->has |= HAS_PATHNAME; 2712232153Smm if (xar->base64text) { 2713232153Smm strappend_base64(xar, 2714232153Smm &(xar->file->pathname), s, len); 2715232153Smm } else 2716228753Smm archive_strncat(&(xar->file->pathname), s, len); 2717228753Smm break; 2718228753Smm case FILE_LINK: 2719228753Smm xar->file->has |= HAS_SYMLINK; 2720228753Smm archive_strncpy(&(xar->file->symlink), s, len); 2721228753Smm break; 2722228753Smm case FILE_TYPE: 2723228753Smm if (strncmp("file", s, len) == 0 || 2724228753Smm strncmp("hardlink", s, len) == 0) 2725228753Smm xar->file->mode = 2726228753Smm (xar->file->mode & ~AE_IFMT) | AE_IFREG; 2727228753Smm if (strncmp("directory", s, len) == 0) 2728228753Smm xar->file->mode = 2729228753Smm (xar->file->mode & ~AE_IFMT) | AE_IFDIR; 2730228753Smm if (strncmp("symlink", s, len) == 0) 2731228753Smm xar->file->mode = 2732228753Smm (xar->file->mode & ~AE_IFMT) | AE_IFLNK; 2733228753Smm if (strncmp("character special", s, len) == 0) 2734228753Smm xar->file->mode = 2735228753Smm (xar->file->mode & ~AE_IFMT) | AE_IFCHR; 2736228753Smm if (strncmp("block special", s, len) == 0) 2737228753Smm xar->file->mode = 2738228753Smm (xar->file->mode & ~AE_IFMT) | AE_IFBLK; 2739228753Smm if (strncmp("socket", s, len) == 0) 2740228753Smm xar->file->mode = 2741228753Smm (xar->file->mode & ~AE_IFMT) | AE_IFSOCK; 2742228753Smm if (strncmp("fifo", s, len) == 0) 2743228753Smm xar->file->mode = 2744228753Smm (xar->file->mode & ~AE_IFMT) | AE_IFIFO; 2745228753Smm xar->file->has |= HAS_TYPE; 2746228753Smm break; 2747228753Smm case FILE_INODE: 2748228753Smm xar->file->has |= HAS_INO; 2749228753Smm xar->file->ino64 = atol10(s, len); 2750228753Smm break; 2751228753Smm case FILE_DEVICE_MAJOR: 2752228753Smm xar->file->has |= HAS_DEVMAJOR; 2753228753Smm xar->file->devmajor = (dev_t)atol10(s, len); 2754228753Smm break; 2755228753Smm case FILE_DEVICE_MINOR: 2756228753Smm xar->file->has |= HAS_DEVMINOR; 2757228753Smm xar->file->devminor = (dev_t)atol10(s, len); 2758228753Smm break; 2759228753Smm case FILE_DEVICENO: 2760228753Smm xar->file->has |= HAS_DEV; 2761228753Smm xar->file->dev = (dev_t)atol10(s, len); 2762228753Smm break; 2763228753Smm case FILE_MODE: 2764228753Smm xar->file->has |= HAS_MODE; 2765228753Smm xar->file->mode = 2766228753Smm (xar->file->mode & AE_IFMT) | 2767238856Smm ((mode_t)(atol8(s, len)) & ~AE_IFMT); 2768228753Smm break; 2769228753Smm case FILE_GROUP: 2770228753Smm xar->file->has |= HAS_GID; 2771228753Smm archive_strncpy(&(xar->file->gname), s, len); 2772228753Smm break; 2773228753Smm case FILE_GID: 2774228753Smm xar->file->has |= HAS_GID; 2775228753Smm xar->file->gid = atol10(s, len); 2776228753Smm break; 2777228753Smm case FILE_USER: 2778228753Smm xar->file->has |= HAS_UID; 2779228753Smm archive_strncpy(&(xar->file->uname), s, len); 2780228753Smm break; 2781228753Smm case FILE_UID: 2782228753Smm xar->file->has |= HAS_UID; 2783228753Smm xar->file->uid = atol10(s, len); 2784228753Smm break; 2785228753Smm case FILE_CTIME: 2786228753Smm xar->file->has |= HAS_TIME; 2787228753Smm xar->file->ctime = parse_time(s, len); 2788228753Smm break; 2789228753Smm case FILE_MTIME: 2790228753Smm xar->file->has |= HAS_TIME; 2791228753Smm xar->file->mtime = parse_time(s, len); 2792228753Smm break; 2793228753Smm case FILE_ATIME: 2794228753Smm xar->file->has |= HAS_TIME; 2795228753Smm xar->file->atime = parse_time(s, len); 2796228753Smm break; 2797228753Smm case FILE_DATA_LENGTH: 2798228753Smm xar->file->has |= HAS_DATA; 2799228753Smm xar->file->length = atol10(s, len); 2800228753Smm break; 2801228753Smm case FILE_DATA_OFFSET: 2802228753Smm xar->file->has |= HAS_DATA; 2803228753Smm xar->file->offset = atol10(s, len); 2804228753Smm break; 2805228753Smm case FILE_DATA_SIZE: 2806228753Smm xar->file->has |= HAS_DATA; 2807228753Smm xar->file->size = atol10(s, len); 2808228753Smm break; 2809228753Smm case FILE_DATA_A_CHECKSUM: 2810228753Smm xar->file->a_sum.len = atohex(xar->file->a_sum.val, 2811228753Smm sizeof(xar->file->a_sum.val), s, len); 2812228753Smm break; 2813228753Smm case FILE_DATA_E_CHECKSUM: 2814228753Smm xar->file->e_sum.len = atohex(xar->file->e_sum.val, 2815228753Smm sizeof(xar->file->e_sum.val), s, len); 2816228753Smm break; 2817228753Smm case FILE_EA_LENGTH: 2818228753Smm xar->file->has |= HAS_XATTR; 2819228753Smm xar->xattr->length = atol10(s, len); 2820228753Smm break; 2821228753Smm case FILE_EA_OFFSET: 2822228753Smm xar->file->has |= HAS_XATTR; 2823228753Smm xar->xattr->offset = atol10(s, len); 2824228753Smm break; 2825228753Smm case FILE_EA_SIZE: 2826228753Smm xar->file->has |= HAS_XATTR; 2827228753Smm xar->xattr->size = atol10(s, len); 2828228753Smm break; 2829228753Smm case FILE_EA_A_CHECKSUM: 2830228753Smm xar->file->has |= HAS_XATTR; 2831228753Smm xar->xattr->a_sum.len = atohex(xar->xattr->a_sum.val, 2832228753Smm sizeof(xar->xattr->a_sum.val), s, len); 2833228753Smm break; 2834228753Smm case FILE_EA_E_CHECKSUM: 2835228753Smm xar->file->has |= HAS_XATTR; 2836228753Smm xar->xattr->e_sum.len = atohex(xar->xattr->e_sum.val, 2837228753Smm sizeof(xar->xattr->e_sum.val), s, len); 2838228753Smm break; 2839228753Smm case FILE_EA_NAME: 2840228753Smm xar->file->has |= HAS_XATTR; 2841228753Smm archive_strncpy(&(xar->xattr->name), s, len); 2842228753Smm break; 2843228753Smm case FILE_EA_FSTYPE: 2844228753Smm xar->file->has |= HAS_XATTR; 2845228753Smm archive_strncpy(&(xar->xattr->fstype), s, len); 2846228753Smm break; 2847228753Smm break; 2848228753Smm case FILE_ACL_DEFAULT: 2849228753Smm case FILE_ACL_ACCESS: 2850228753Smm case FILE_ACL_APPLEEXTENDED: 2851228753Smm xar->file->has |= HAS_ACL; 2852228753Smm /* TODO */ 2853228753Smm break; 2854228753Smm case INIT: 2855228753Smm case XAR: 2856228753Smm case TOC: 2857228753Smm case TOC_CREATION_TIME: 2858228753Smm case TOC_CHECKSUM: 2859228753Smm case TOC_CHECKSUM_OFFSET: 2860228753Smm case TOC_CHECKSUM_SIZE: 2861228753Smm case TOC_FILE: 2862228753Smm case FILE_DATA: 2863228753Smm case FILE_DATA_ENCODING: 2864228753Smm case FILE_DATA_CONTENT: 2865228753Smm case FILE_DEVICE: 2866228753Smm case FILE_EA: 2867228753Smm case FILE_EA_ENCODING: 2868228753Smm case FILE_ACL: 2869228753Smm case FILE_FLAGS: 2870228753Smm case FILE_FLAGS_USER_NODUMP: 2871228753Smm case FILE_FLAGS_USER_IMMUTABLE: 2872228753Smm case FILE_FLAGS_USER_APPEND: 2873228753Smm case FILE_FLAGS_USER_OPAQUE: 2874228753Smm case FILE_FLAGS_USER_NOUNLINK: 2875228753Smm case FILE_FLAGS_SYS_ARCHIVED: 2876228753Smm case FILE_FLAGS_SYS_IMMUTABLE: 2877228753Smm case FILE_FLAGS_SYS_APPEND: 2878228753Smm case FILE_FLAGS_SYS_NOUNLINK: 2879228753Smm case FILE_FLAGS_SYS_SNAPSHOT: 2880228753Smm case FILE_EXT2: 2881228753Smm case FILE_EXT2_SecureDeletion: 2882228753Smm case FILE_EXT2_Undelete: 2883228753Smm case FILE_EXT2_Compress: 2884228753Smm case FILE_EXT2_Synchronous: 2885228753Smm case FILE_EXT2_Immutable: 2886228753Smm case FILE_EXT2_AppendOnly: 2887228753Smm case FILE_EXT2_NoDump: 2888228753Smm case FILE_EXT2_NoAtime: 2889228753Smm case FILE_EXT2_CompDirty: 2890228753Smm case FILE_EXT2_CompBlock: 2891228753Smm case FILE_EXT2_NoCompBlock: 2892228753Smm case FILE_EXT2_CompError: 2893228753Smm case FILE_EXT2_BTree: 2894228753Smm case FILE_EXT2_HashIndexed: 2895228753Smm case FILE_EXT2_iMagic: 2896228753Smm case FILE_EXT2_Journaled: 2897228753Smm case FILE_EXT2_NoTail: 2898228753Smm case FILE_EXT2_DirSync: 2899228753Smm case FILE_EXT2_TopDir: 2900228753Smm case FILE_EXT2_Reserved: 2901228753Smm case UNKNOWN: 2902228753Smm break; 2903228753Smm } 2904228753Smm} 2905228753Smm 2906228753Smm/* 2907228753Smm * BSD file flags. 2908228753Smm */ 2909228753Smmstatic int 2910228753Smmxml_parse_file_flags(struct xar *xar, const char *name) 2911228753Smm{ 2912228753Smm const char *flag = NULL; 2913228753Smm 2914228753Smm if (strcmp(name, "UserNoDump") == 0) { 2915228753Smm xar->xmlsts = FILE_FLAGS_USER_NODUMP; 2916228753Smm flag = "nodump"; 2917228753Smm } 2918228753Smm else if (strcmp(name, "UserImmutable") == 0) { 2919228753Smm xar->xmlsts = FILE_FLAGS_USER_IMMUTABLE; 2920228753Smm flag = "uimmutable"; 2921228753Smm } 2922228753Smm else if (strcmp(name, "UserAppend") == 0) { 2923228753Smm xar->xmlsts = FILE_FLAGS_USER_APPEND; 2924228753Smm flag = "uappend"; 2925228753Smm } 2926228753Smm else if (strcmp(name, "UserOpaque") == 0) { 2927228753Smm xar->xmlsts = FILE_FLAGS_USER_OPAQUE; 2928228753Smm flag = "opaque"; 2929228753Smm } 2930228753Smm else if (strcmp(name, "UserNoUnlink") == 0) { 2931228753Smm xar->xmlsts = FILE_FLAGS_USER_NOUNLINK; 2932228753Smm flag = "nouunlink"; 2933228753Smm } 2934228753Smm else if (strcmp(name, "SystemArchived") == 0) { 2935228753Smm xar->xmlsts = FILE_FLAGS_SYS_ARCHIVED; 2936228753Smm flag = "archived"; 2937228753Smm } 2938228753Smm else if (strcmp(name, "SystemImmutable") == 0) { 2939228753Smm xar->xmlsts = FILE_FLAGS_SYS_IMMUTABLE; 2940228753Smm flag = "simmutable"; 2941228753Smm } 2942228753Smm else if (strcmp(name, "SystemAppend") == 0) { 2943228753Smm xar->xmlsts = FILE_FLAGS_SYS_APPEND; 2944228753Smm flag = "sappend"; 2945228753Smm } 2946228753Smm else if (strcmp(name, "SystemNoUnlink") == 0) { 2947228753Smm xar->xmlsts = FILE_FLAGS_SYS_NOUNLINK; 2948228753Smm flag = "nosunlink"; 2949228753Smm } 2950228753Smm else if (strcmp(name, "SystemSnapshot") == 0) { 2951228753Smm xar->xmlsts = FILE_FLAGS_SYS_SNAPSHOT; 2952228753Smm flag = "snapshot"; 2953228753Smm } 2954228753Smm 2955228753Smm if (flag == NULL) 2956228753Smm return (0); 2957228753Smm xar->file->has |= HAS_FFLAGS; 2958228753Smm if (archive_strlen(&(xar->file->fflags_text)) > 0) 2959228753Smm archive_strappend_char(&(xar->file->fflags_text), ','); 2960228753Smm archive_strcat(&(xar->file->fflags_text), flag); 2961228753Smm return (1); 2962228753Smm} 2963228753Smm 2964228753Smm/* 2965228753Smm * Linux file flags. 2966228753Smm */ 2967228753Smmstatic int 2968228753Smmxml_parse_file_ext2(struct xar *xar, const char *name) 2969228753Smm{ 2970228753Smm const char *flag = NULL; 2971228753Smm 2972228753Smm if (strcmp(name, "SecureDeletion") == 0) { 2973228753Smm xar->xmlsts = FILE_EXT2_SecureDeletion; 2974228753Smm flag = "securedeletion"; 2975228753Smm } 2976228753Smm else if (strcmp(name, "Undelete") == 0) { 2977228753Smm xar->xmlsts = FILE_EXT2_Undelete; 2978228753Smm flag = "nouunlink"; 2979228753Smm } 2980228753Smm else if (strcmp(name, "Compress") == 0) { 2981228753Smm xar->xmlsts = FILE_EXT2_Compress; 2982228753Smm flag = "compress"; 2983228753Smm } 2984228753Smm else if (strcmp(name, "Synchronous") == 0) { 2985228753Smm xar->xmlsts = FILE_EXT2_Synchronous; 2986228753Smm flag = "sync"; 2987228753Smm } 2988228753Smm else if (strcmp(name, "Immutable") == 0) { 2989228753Smm xar->xmlsts = FILE_EXT2_Immutable; 2990228753Smm flag = "simmutable"; 2991228753Smm } 2992228753Smm else if (strcmp(name, "AppendOnly") == 0) { 2993228753Smm xar->xmlsts = FILE_EXT2_AppendOnly; 2994228753Smm flag = "sappend"; 2995228753Smm } 2996228753Smm else if (strcmp(name, "NoDump") == 0) { 2997228753Smm xar->xmlsts = FILE_EXT2_NoDump; 2998228753Smm flag = "nodump"; 2999228753Smm } 3000228753Smm else if (strcmp(name, "NoAtime") == 0) { 3001228753Smm xar->xmlsts = FILE_EXT2_NoAtime; 3002228753Smm flag = "noatime"; 3003228753Smm } 3004228753Smm else if (strcmp(name, "CompDirty") == 0) { 3005228753Smm xar->xmlsts = FILE_EXT2_CompDirty; 3006228753Smm flag = "compdirty"; 3007228753Smm } 3008228753Smm else if (strcmp(name, "CompBlock") == 0) { 3009228753Smm xar->xmlsts = FILE_EXT2_CompBlock; 3010228753Smm flag = "comprblk"; 3011228753Smm } 3012228753Smm else if (strcmp(name, "NoCompBlock") == 0) { 3013228753Smm xar->xmlsts = FILE_EXT2_NoCompBlock; 3014228753Smm flag = "nocomprblk"; 3015228753Smm } 3016228753Smm else if (strcmp(name, "CompError") == 0) { 3017228753Smm xar->xmlsts = FILE_EXT2_CompError; 3018228753Smm flag = "comperr"; 3019228753Smm } 3020228753Smm else if (strcmp(name, "BTree") == 0) { 3021228753Smm xar->xmlsts = FILE_EXT2_BTree; 3022228753Smm flag = "btree"; 3023228753Smm } 3024228753Smm else if (strcmp(name, "HashIndexed") == 0) { 3025228753Smm xar->xmlsts = FILE_EXT2_HashIndexed; 3026228753Smm flag = "hashidx"; 3027228753Smm } 3028228753Smm else if (strcmp(name, "iMagic") == 0) { 3029228753Smm xar->xmlsts = FILE_EXT2_iMagic; 3030228753Smm flag = "imagic"; 3031228753Smm } 3032228753Smm else if (strcmp(name, "Journaled") == 0) { 3033228753Smm xar->xmlsts = FILE_EXT2_Journaled; 3034228753Smm flag = "journal"; 3035228753Smm } 3036228753Smm else if (strcmp(name, "NoTail") == 0) { 3037228753Smm xar->xmlsts = FILE_EXT2_NoTail; 3038228753Smm flag = "notail"; 3039228753Smm } 3040228753Smm else if (strcmp(name, "DirSync") == 0) { 3041228753Smm xar->xmlsts = FILE_EXT2_DirSync; 3042228753Smm flag = "dirsync"; 3043228753Smm } 3044228753Smm else if (strcmp(name, "TopDir") == 0) { 3045228753Smm xar->xmlsts = FILE_EXT2_TopDir; 3046228753Smm flag = "topdir"; 3047228753Smm } 3048228753Smm else if (strcmp(name, "Reserved") == 0) { 3049228753Smm xar->xmlsts = FILE_EXT2_Reserved; 3050228753Smm flag = "reserved"; 3051228753Smm } 3052228753Smm 3053228753Smm if (flag == NULL) 3054228753Smm return (0); 3055228753Smm if (archive_strlen(&(xar->file->fflags_text)) > 0) 3056228753Smm archive_strappend_char(&(xar->file->fflags_text), ','); 3057228753Smm archive_strcat(&(xar->file->fflags_text), flag); 3058228753Smm return (1); 3059228753Smm} 3060228753Smm 3061228753Smm#ifdef HAVE_LIBXML_XMLREADER_H 3062228753Smm 3063228753Smmstatic int 3064232153Smmxml2_xmlattr_setup(struct archive_read *a, 3065232153Smm struct xmlattr_list *list, xmlTextReaderPtr reader) 3066228753Smm{ 3067228753Smm struct xmlattr *attr; 3068228753Smm int r; 3069228753Smm 3070228753Smm list->first = NULL; 3071228753Smm list->last = &(list->first); 3072228753Smm r = xmlTextReaderMoveToFirstAttribute(reader); 3073228753Smm while (r == 1) { 3074228753Smm attr = malloc(sizeof*(attr)); 3075232153Smm if (attr == NULL) { 3076232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 3077232153Smm return (ARCHIVE_FATAL); 3078232153Smm } 3079228753Smm attr->name = strdup( 3080228753Smm (const char *)xmlTextReaderConstLocalName(reader)); 3081232153Smm if (attr->name == NULL) { 3082238856Smm free(attr); 3083232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 3084232153Smm return (ARCHIVE_FATAL); 3085232153Smm } 3086228753Smm attr->value = strdup( 3087228753Smm (const char *)xmlTextReaderConstValue(reader)); 3088232153Smm if (attr->value == NULL) { 3089238856Smm free(attr->name); 3090238856Smm free(attr); 3091232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 3092232153Smm return (ARCHIVE_FATAL); 3093232153Smm } 3094228753Smm attr->next = NULL; 3095228753Smm *list->last = attr; 3096228753Smm list->last = &(attr->next); 3097228753Smm r = xmlTextReaderMoveToNextAttribute(reader); 3098228753Smm } 3099228753Smm return (r); 3100228753Smm} 3101228753Smm 3102228753Smmstatic int 3103228753Smmxml2_read_cb(void *context, char *buffer, int len) 3104228753Smm{ 3105228753Smm struct archive_read *a; 3106228753Smm struct xar *xar; 3107228753Smm const void *d; 3108228753Smm size_t outbytes; 3109228753Smm size_t used; 3110228753Smm int r; 3111228753Smm 3112228753Smm a = (struct archive_read *)context; 3113228753Smm xar = (struct xar *)(a->format->data); 3114228753Smm 3115228753Smm if (xar->toc_remaining <= 0) 3116228753Smm return (0); 3117228753Smm d = buffer; 3118228753Smm outbytes = len; 3119228753Smm r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); 3120228753Smm if (r != ARCHIVE_OK) 3121228753Smm return (r); 3122228753Smm __archive_read_consume(a, used); 3123228753Smm xar->toc_remaining -= used; 3124228753Smm xar->offset += used; 3125228753Smm xar->toc_total += outbytes; 3126228753Smm PRINT_TOC(buffer, len); 3127228753Smm 3128228753Smm return ((int)outbytes); 3129228753Smm} 3130228753Smm 3131228753Smmstatic int 3132228753Smmxml2_close_cb(void *context) 3133228753Smm{ 3134228753Smm 3135228753Smm (void)context; /* UNUSED */ 3136228753Smm return (0); 3137228753Smm} 3138228753Smm 3139228753Smmstatic void 3140228753Smmxml2_error_hdr(void *arg, const char *msg, xmlParserSeverities severity, 3141228753Smm xmlTextReaderLocatorPtr locator) 3142228753Smm{ 3143228753Smm struct archive_read *a; 3144228753Smm 3145228753Smm (void)locator; /* UNUSED */ 3146228753Smm a = (struct archive_read *)arg; 3147228753Smm switch (severity) { 3148228753Smm case XML_PARSER_SEVERITY_VALIDITY_WARNING: 3149228753Smm case XML_PARSER_SEVERITY_WARNING: 3150228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 3151228753Smm "XML Parsing error: %s", msg); 3152228753Smm break; 3153228753Smm case XML_PARSER_SEVERITY_VALIDITY_ERROR: 3154228753Smm case XML_PARSER_SEVERITY_ERROR: 3155228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 3156228753Smm "XML Parsing error: %s", msg); 3157228753Smm break; 3158228753Smm } 3159228753Smm} 3160228753Smm 3161228753Smmstatic int 3162228753Smmxml2_read_toc(struct archive_read *a) 3163228753Smm{ 3164228753Smm xmlTextReaderPtr reader; 3165228753Smm struct xmlattr_list list; 3166228753Smm int r; 3167228753Smm 3168228753Smm reader = xmlReaderForIO(xml2_read_cb, xml2_close_cb, a, NULL, NULL, 0); 3169228753Smm if (reader == NULL) { 3170228753Smm archive_set_error(&a->archive, ENOMEM, 3171228753Smm "Couldn't allocate memory for xml parser"); 3172228753Smm return (ARCHIVE_FATAL); 3173228753Smm } 3174228753Smm xmlTextReaderSetErrorHandler(reader, xml2_error_hdr, a); 3175228753Smm 3176228753Smm while ((r = xmlTextReaderRead(reader)) == 1) { 3177228753Smm const char *name, *value; 3178228753Smm int type, empty; 3179228753Smm 3180228753Smm type = xmlTextReaderNodeType(reader); 3181228753Smm name = (const char *)xmlTextReaderConstLocalName(reader); 3182228753Smm switch (type) { 3183228753Smm case XML_READER_TYPE_ELEMENT: 3184228753Smm empty = xmlTextReaderIsEmptyElement(reader); 3185232153Smm r = xml2_xmlattr_setup(a, &list, reader); 3186232153Smm if (r != ARCHIVE_OK) 3187232153Smm return (r); 3188232153Smm r = xml_start(a, name, &list); 3189232153Smm xmlattr_cleanup(&list); 3190232153Smm if (r != ARCHIVE_OK) 3191232153Smm return (r); 3192232153Smm if (empty) 3193232153Smm xml_end(a, name); 3194228753Smm break; 3195228753Smm case XML_READER_TYPE_END_ELEMENT: 3196228753Smm xml_end(a, name); 3197228753Smm break; 3198228753Smm case XML_READER_TYPE_TEXT: 3199228753Smm value = (const char *)xmlTextReaderConstValue(reader); 3200228753Smm xml_data(a, value, strlen(value)); 3201228753Smm break; 3202228753Smm case XML_READER_TYPE_SIGNIFICANT_WHITESPACE: 3203228753Smm default: 3204228753Smm break; 3205228753Smm } 3206228753Smm if (r < 0) 3207228753Smm break; 3208228753Smm } 3209228753Smm xmlFreeTextReader(reader); 3210228753Smm xmlCleanupParser(); 3211228753Smm 3212228753Smm return ((r == 0)?ARCHIVE_OK:ARCHIVE_FATAL); 3213228753Smm} 3214228753Smm 3215228753Smm#elif defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) 3216228753Smm 3217232153Smmstatic int 3218232153Smmexpat_xmlattr_setup(struct archive_read *a, 3219232153Smm struct xmlattr_list *list, const XML_Char **atts) 3220228753Smm{ 3221228753Smm struct xmlattr *attr; 3222232153Smm char *name, *value; 3223228753Smm 3224228753Smm list->first = NULL; 3225228753Smm list->last = &(list->first); 3226228753Smm if (atts == NULL) 3227232153Smm return (ARCHIVE_OK); 3228228753Smm while (atts[0] != NULL && atts[1] != NULL) { 3229228753Smm attr = malloc(sizeof*(attr)); 3230232153Smm name = strdup(atts[0]); 3231232153Smm value = strdup(atts[1]); 3232232153Smm if (attr == NULL || name == NULL || value == NULL) { 3233232153Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 3234232153Smm return (ARCHIVE_FATAL); 3235232153Smm } 3236232153Smm attr->name = name; 3237232153Smm attr->value = value; 3238228753Smm attr->next = NULL; 3239228753Smm *list->last = attr; 3240228753Smm list->last = &(attr->next); 3241228753Smm atts += 2; 3242228753Smm } 3243232153Smm return (ARCHIVE_OK); 3244228753Smm} 3245228753Smm 3246228753Smmstatic void 3247228753Smmexpat_start_cb(void *userData, const XML_Char *name, const XML_Char **atts) 3248228753Smm{ 3249232153Smm struct expat_userData *ud = (struct expat_userData *)userData; 3250232153Smm struct archive_read *a = ud->archive; 3251228753Smm struct xmlattr_list list; 3252232153Smm int r; 3253228753Smm 3254232153Smm r = expat_xmlattr_setup(a, &list, atts); 3255232153Smm if (r == ARCHIVE_OK) 3256232153Smm r = xml_start(a, (const char *)name, &list); 3257228753Smm xmlattr_cleanup(&list); 3258232153Smm ud->state = r; 3259228753Smm} 3260228753Smm 3261228753Smmstatic void 3262228753Smmexpat_end_cb(void *userData, const XML_Char *name) 3263228753Smm{ 3264232153Smm struct expat_userData *ud = (struct expat_userData *)userData; 3265232153Smm 3266232153Smm xml_end(ud->archive, (const char *)name); 3267228753Smm} 3268228753Smm 3269228753Smmstatic void 3270228753Smmexpat_data_cb(void *userData, const XML_Char *s, int len) 3271228753Smm{ 3272232153Smm struct expat_userData *ud = (struct expat_userData *)userData; 3273232153Smm 3274232153Smm xml_data(ud->archive, s, len); 3275228753Smm} 3276228753Smm 3277228753Smmstatic int 3278228753Smmexpat_read_toc(struct archive_read *a) 3279228753Smm{ 3280228753Smm struct xar *xar; 3281228753Smm XML_Parser parser; 3282232153Smm struct expat_userData ud; 3283228753Smm 3284232153Smm ud.state = ARCHIVE_OK; 3285232153Smm ud.archive = a; 3286232153Smm 3287228753Smm xar = (struct xar *)(a->format->data); 3288228753Smm 3289228753Smm /* Initialize XML Parser library. */ 3290228753Smm parser = XML_ParserCreate(NULL); 3291228753Smm if (parser == NULL) { 3292228753Smm archive_set_error(&a->archive, ENOMEM, 3293228753Smm "Couldn't allocate memory for xml parser"); 3294228753Smm return (ARCHIVE_FATAL); 3295228753Smm } 3296232153Smm XML_SetUserData(parser, &ud); 3297228753Smm XML_SetElementHandler(parser, expat_start_cb, expat_end_cb); 3298228753Smm XML_SetCharacterDataHandler(parser, expat_data_cb); 3299228753Smm xar->xmlsts = INIT; 3300228753Smm 3301232153Smm while (xar->toc_remaining && ud.state == ARCHIVE_OK) { 3302228753Smm enum XML_Status xr; 3303228753Smm const void *d; 3304228753Smm size_t outbytes; 3305228753Smm size_t used; 3306228753Smm int r; 3307228753Smm 3308228753Smm d = NULL; 3309228753Smm r = rd_contents(a, &d, &outbytes, &used, xar->toc_remaining); 3310228753Smm if (r != ARCHIVE_OK) 3311228753Smm return (r); 3312228753Smm xar->toc_remaining -= used; 3313228753Smm xar->offset += used; 3314228753Smm xar->toc_total += outbytes; 3315228753Smm PRINT_TOC(d, outbytes); 3316228753Smm 3317228753Smm xr = XML_Parse(parser, d, outbytes, xar->toc_remaining == 0); 3318232153Smm __archive_read_consume(a, used); 3319228753Smm if (xr == XML_STATUS_ERROR) { 3320228753Smm XML_ParserFree(parser); 3321228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 3322228753Smm "XML Parsing failed"); 3323228753Smm return (ARCHIVE_FATAL); 3324228753Smm } 3325228753Smm } 3326228753Smm XML_ParserFree(parser); 3327232153Smm return (ud.state); 3328228753Smm} 3329228753Smm#endif /* defined(HAVE_BSDXML_H) || defined(HAVE_EXPAT_H) */ 3330228753Smm 3331228753Smm#endif /* Support xar format */ 3332