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