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