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