xref: /freebsd/contrib/libarchive/libarchive/archive_write_set_format_xar.c (revision eb5165bb491138f60d9004bc4c781490016d9288)
1 /*-
2  * Copyright (c) 2010-2012 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 
26 #include "archive_platform.h"
27 
28 #ifdef HAVE_ERRNO_H
29 #include <errno.h>
30 #endif
31 #ifdef HAVE_LIMITS_H
32 #include <limits.h>
33 #endif
34 #include <stdlib.h>
35 #if HAVE_LIBXML_XMLWRITER_H
36 #include <libxml/xmlwriter.h>
37 #if defined(LIBXML_VERSION) && LIBXML_VERSION >= 20703
38 #define XAR_WRITER_HAS_XML
39 #endif /* LIBXML_VERSION */
40 #elif HAVE_XMLLITE_H
41 #include <objidl.h>
42 #include <initguid.h>
43 #include <xmllite.h>
44 #define XAR_WRITER_HAS_XML
45 #endif
46 #ifdef HAVE_BZLIB_H
47 #include <bzlib.h>
48 #endif
49 #if HAVE_LZMA_H
50 #include <lzma.h>
51 #endif
52 #ifdef HAVE_ZLIB_H
53 #include <zlib.h>
54 #endif
55 
56 #include "archive.h"
57 #include "archive_digest_private.h"
58 #include "archive_endian.h"
59 #include "archive_entry.h"
60 #include "archive_entry_locale.h"
61 #include "archive_private.h"
62 #include "archive_rb.h"
63 #include "archive_string.h"
64 #include "archive_write_private.h"
65 
66 /*
67  * Differences to xar utility.
68  * - Subdocument is not supported yet.
69  * - ACL is not supported yet.
70  * - When writing an XML element <link type="<file-type>">, <file-type>
71  *   which is a file type a symbolic link is referencing is always marked
72  *   as "broken". Xar utility uses stat(2) to get the file type, but, in
73  *   libarchive format writer, we should not use it; if it is needed, we
74  *   should get about it at archive_read_disk.c.
75  * - It is possible to appear both <flags> and <ext2> elements.
76  *   Xar utility generates <flags> on BSD platform and <ext2> on Linux
77  *   platform.
78  *
79  */
80 
81 #if !defined(XAR_WRITER_HAS_XML) ||\
82 	!defined(HAVE_ZLIB_H) || \
83 	!defined(ARCHIVE_HAS_MD5) || !defined(ARCHIVE_HAS_SHA1)
84 /*
85  * xar needs several external libraries.
86  *   o libxml2 or xmllite (on Windows)
87  *   o openssl or MD5/SHA1 hash function
88  *   o zlib
89  *   o bzlib2 (option)
90  *   o liblzma (option)
91  */
92 int
archive_write_set_format_xar(struct archive * _a)93 archive_write_set_format_xar(struct archive *_a)
94 {
95 	struct archive_write *a = (struct archive_write *)_a;
96 
97 	archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
98 	    "Xar not supported on this platform");
99 	return (ARCHIVE_WARN);
100 }
101 
102 #else	/* Support xar format */
103 
104 struct xml_writer;
105 static int xml_writer_create(struct xml_writer **pctx);
106 static int xml_writer_start_document(struct xml_writer *ctx);
107 static int xml_writer_end_document(struct xml_writer *ctx);
108 static int xml_writer_set_indent(struct xml_writer *ctx, unsigned int indent);
109 static int xml_writer_start_element(struct xml_writer *ctx,
110     const char *localName);
111 static int xml_writer_write_attribute(struct xml_writer *ctx, const char *key,
112     const char *value);
113 static int xml_writer_write_attributef(struct xml_writer *ctx, const char *key,
114     const char *format, ...);
115 static int xml_writer_write_string(struct xml_writer *ctx, const char *string);
116 static int xml_writer_write_base64(struct xml_writer* ctx,
117     const char *data, size_t start, size_t len);
118 static int xml_writer_end_element(struct xml_writer *ctx);
119 static int xml_writer_get_final_content_and_length(struct xml_writer *ctx,
120     const char **out, size_t *size);
121 static int xml_writer_destroy(struct xml_writer *ctx);
122 
123 /*#define DEBUG_PRINT_TOC		1 */
124 
125 #define HEADER_MAGIC	0x78617221
126 #define HEADER_SIZE	28
127 #define HEADER_VERSION	1
128 
129 enum sumalg {
130 	CKSUM_NONE = 0,
131 	CKSUM_SHA1 = 1,
132 	CKSUM_MD5 = 2
133 };
134 
135 #define MD5_SIZE	16
136 #define SHA1_SIZE	20
137 #define MAX_SUM_SIZE	20
138 #define MD5_NAME	"md5"
139 #define SHA1_NAME	"sha1"
140 
141 enum enctype {
142 	NONE,
143 	GZIP,
144 	BZIP2,
145 	LZMA,
146 	XZ,
147 };
148 
149 struct chksumwork {
150 	enum sumalg		 alg;
151 #ifdef ARCHIVE_HAS_MD5
152 	archive_md5_ctx		 md5ctx;
153 #endif
154 #ifdef ARCHIVE_HAS_SHA1
155 	archive_sha1_ctx	 sha1ctx;
156 #endif
157 };
158 
159 enum la_zaction {
160 	ARCHIVE_Z_FINISH,
161 	ARCHIVE_Z_RUN
162 };
163 
164 /*
165  * Universal zstream.
166  */
167 struct la_zstream {
168 	const unsigned char	*next_in;
169 	size_t			 avail_in;
170 	uint64_t		 total_in;
171 
172 	unsigned char		*next_out;
173 	size_t			 avail_out;
174 	uint64_t		 total_out;
175 
176 	int			 valid;
177 	void			*real_stream;
178 	int			 (*code) (struct archive *a,
179 				    struct la_zstream *lastrm,
180 				    enum la_zaction action);
181 	int			 (*end)(struct archive *a,
182 				    struct la_zstream *lastrm);
183 };
184 
185 struct chksumval {
186 	enum sumalg		 alg;
187 	size_t			 len;
188 	unsigned char		 val[MAX_SUM_SIZE];
189 };
190 
191 struct heap_data {
192 	int			 id;
193 	struct heap_data	*next;
194 	uint64_t		 temp_offset;
195 	uint64_t		 length;	/* archived size.	*/
196 	uint64_t		 size;		/* extracted size.	*/
197 	enum enctype		 compression;
198 	struct chksumval	 a_sum;		/* archived checksum.	*/
199 	struct chksumval	 e_sum;		/* extracted checksum.	*/
200 };
201 
202 struct file {
203 	struct archive_rb_node	 rbnode;
204 
205 	int			 id;
206 	struct archive_entry	*entry;
207 
208 	struct archive_rb_tree	 rbtree;
209 	struct file		*next;
210 	struct file		*chnext;
211 	struct file		*hlnext;
212 	/* For hardlinked files.
213 	 * Use only when archive_entry_nlink() > 1 */
214 	struct file		*hardlink_target;
215 	struct file		*parent;	/* parent directory entry */
216 	/*
217 	 * To manage sub directory files.
218 	 * We use 'chnext' (a member of struct file) to chain.
219 	 */
220 	struct {
221 		struct file	*first;
222 		struct file	**last;
223 	}			 children;
224 
225 	/* For making a directory tree. */
226         struct archive_string    parentdir;
227         struct archive_string    basename;
228         struct archive_string    symlink;
229 
230 	int			 ea_idx;
231 	struct {
232 		struct heap_data *first;
233 		struct heap_data **last;
234 	}			 xattr;
235 	struct heap_data	 data;
236         struct archive_string    script;
237 
238 	unsigned int		 virtual:1;
239 	unsigned int		 dir:1;
240 };
241 
242 struct hardlink {
243 	struct archive_rb_node	 rbnode;
244 	int			 nlink;
245 	struct {
246 		struct file	*first;
247 		struct file	**last;
248 	}			 file_list;
249 };
250 
251 struct xar {
252 	int			 temp_fd;
253 	uint64_t		 temp_offset;
254 
255 	int			 file_idx;
256 	struct file		*root;
257 	struct file		*cur_dirent;
258 	struct archive_string	 cur_dirstr;
259 	struct file		*cur_file;
260 	uint64_t		 bytes_remaining;
261 	struct archive_string	 tstr;
262 	struct archive_string	 vstr;
263 
264 	enum sumalg		 opt_toc_sumalg;
265 	enum sumalg		 opt_sumalg;
266 	enum enctype		 opt_compression;
267 	int			 opt_compression_level;
268 	uint32_t		 opt_threads;
269 
270 	struct chksumwork	 a_sumwrk;	/* archived checksum.	*/
271 	struct chksumwork	 e_sumwrk;	/* extracted checksum.	*/
272 	struct la_zstream	 stream;
273 	struct archive_string_conv *sconv;
274 	/*
275 	 * Compressed data buffer.
276 	 */
277 	unsigned char		 wbuff[1024 * 64];
278 	size_t			 wbuff_remaining;
279 
280 	struct heap_data	 toc;
281 	/*
282 	 * The list of all file entries is used to manage struct file
283 	 * objects.
284 	 * We use 'next' (a member of struct file) to chain.
285 	 */
286 	struct {
287 		struct file	*first;
288 		struct file	**last;
289 	}			 file_list;
290 	/*
291 	 * The list of hard-linked file entries.
292 	 * We use 'hlnext' (a member of struct file) to chain.
293 	 */
294 	struct archive_rb_tree	 hardlink_rbtree;
295 };
296 
297 static int	xar_options(struct archive_write *,
298 		    const char *, const char *);
299 static int	xar_write_header(struct archive_write *,
300 		    struct archive_entry *);
301 static ssize_t	xar_write_data(struct archive_write *,
302 		    const void *, size_t);
303 static int	xar_finish_entry(struct archive_write *);
304 static int	xar_close(struct archive_write *);
305 static int	xar_free(struct archive_write *);
306 
307 static struct file *file_new(struct archive_write *a, struct archive_entry *);
308 static void	file_free(struct file *);
309 static struct file *file_create_virtual_dir(struct archive_write *a, struct xar *,
310 		    const char *);
311 static int	file_add_child_tail(struct file *, struct file *);
312 static struct file *file_find_child(struct file *, const char *);
313 static int	file_gen_utility_names(struct archive_write *,
314 		    struct file *);
315 static int	get_path_component(char *, int, const char *);
316 static int	file_tree(struct archive_write *, struct file **);
317 static void	file_register(struct xar *, struct file *);
318 static void	file_init_register(struct xar *);
319 static void	file_free_register(struct xar *);
320 static int	file_register_hardlink(struct archive_write *,
321 		    struct file *);
322 static void	file_connect_hardlink_files(struct xar *);
323 static void	file_init_hardlinks(struct xar *);
324 static void	file_free_hardlinks(struct xar *);
325 
326 static void	checksum_init(struct chksumwork *, enum sumalg);
327 static void	checksum_update(struct chksumwork *, const void *, size_t);
328 static void	checksum_final(struct chksumwork *, struct chksumval *);
329 static int	compression_init_encoder_gzip(struct archive *,
330 		    struct la_zstream *, int, int);
331 static int	compression_code_gzip(struct archive *,
332 		    struct la_zstream *, enum la_zaction);
333 static int	compression_end_gzip(struct archive *, struct la_zstream *);
334 static int	compression_init_encoder_bzip2(struct archive *,
335 		    struct la_zstream *, int);
336 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
337 static int	compression_code_bzip2(struct archive *,
338 		    struct la_zstream *, enum la_zaction);
339 static int	compression_end_bzip2(struct archive *, struct la_zstream *);
340 #endif
341 static int	compression_init_encoder_lzma(struct archive *,
342 		    struct la_zstream *, int);
343 static int	compression_init_encoder_xz(struct archive *,
344 		    struct la_zstream *, int, int);
345 #if defined(HAVE_LZMA_H)
346 static int	compression_code_lzma(struct archive *,
347 		    struct la_zstream *, enum la_zaction);
348 static int	compression_end_lzma(struct archive *, struct la_zstream *);
349 #endif
350 static int	xar_compression_init_encoder(struct archive_write *);
351 static int	compression_code(struct archive *,
352 		    struct la_zstream *, enum la_zaction);
353 static int	compression_end(struct archive *,
354 		    struct la_zstream *);
355 static int	save_xattrs(struct archive_write *, struct file *);
356 static int	getalgsize(enum sumalg);
357 static const char *getalgname(enum sumalg);
358 
359 int
archive_write_set_format_xar(struct archive * _a)360 archive_write_set_format_xar(struct archive *_a)
361 {
362 	struct archive_write *a = (struct archive_write *)_a;
363 	struct xar *xar;
364 
365 	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
366 	    ARCHIVE_STATE_NEW, "archive_write_set_format_xar");
367 
368 	/* If another format was already registered, unregister it. */
369 	if (a->format_free != NULL)
370 		(a->format_free)(a);
371 
372 	xar = calloc(1, sizeof(*xar));
373 	if (xar == NULL) {
374 		archive_set_error(&a->archive, ENOMEM,
375 		    "Can't allocate xar data");
376 		return (ARCHIVE_FATAL);
377 	}
378 	xar->temp_fd = -1;
379 	file_init_register(xar);
380 	file_init_hardlinks(xar);
381 	archive_string_init(&(xar->tstr));
382 	archive_string_init(&(xar->vstr));
383 
384 	/*
385 	 * Create the root directory.
386 	 */
387 	xar->root = file_create_virtual_dir(a, xar, "");
388 	if (xar->root == NULL) {
389 		free(xar);
390 		archive_set_error(&a->archive, ENOMEM,
391 		    "Can't allocate xar data");
392 		return (ARCHIVE_FATAL);
393 	}
394 	xar->root->parent = xar->root;
395 	file_register(xar, xar->root);
396 	xar->cur_dirent = xar->root;
397 	archive_string_init(&(xar->cur_dirstr));
398 	archive_string_ensure(&(xar->cur_dirstr), 1);
399 	xar->cur_dirstr.s[0] = 0;
400 
401 	/*
402 	 * Initialize option.
403 	 */
404 	/* Set default checksum type. */
405 	xar->opt_toc_sumalg = CKSUM_SHA1;
406 	xar->opt_sumalg = CKSUM_SHA1;
407 	/* Set default compression type, level, and number of threads. */
408 	xar->opt_compression = GZIP;
409 	xar->opt_compression_level = 6;
410 	xar->opt_threads = 1;
411 
412 	a->format_data = xar;
413 
414 	a->format_name = "xar";
415 	a->format_options = xar_options;
416 	a->format_write_header = xar_write_header;
417 	a->format_write_data = xar_write_data;
418 	a->format_finish_entry = xar_finish_entry;
419 	a->format_close = xar_close;
420 	a->format_free = xar_free;
421 	a->archive.archive_format = ARCHIVE_FORMAT_XAR;
422 	a->archive.archive_format_name = "xar";
423 
424 	return (ARCHIVE_OK);
425 }
426 
427 static int
xar_options(struct archive_write * a,const char * key,const char * value)428 xar_options(struct archive_write *a, const char *key, const char *value)
429 {
430 	struct xar *xar;
431 
432 	xar = (struct xar *)a->format_data;
433 
434 	if (strcmp(key, "checksum") == 0) {
435 		if (value == NULL)
436 			xar->opt_sumalg = CKSUM_NONE;
437 		else if (strcmp(value, "none") == 0)
438 			xar->opt_sumalg = CKSUM_NONE;
439 		else if (strcmp(value, "sha1") == 0)
440 			xar->opt_sumalg = CKSUM_SHA1;
441 		else if (strcmp(value, "md5") == 0)
442 			xar->opt_sumalg = CKSUM_MD5;
443 		else {
444 			archive_set_error(&(a->archive),
445 			    ARCHIVE_ERRNO_MISC,
446 			    "Unknown checksum name: `%s'",
447 			    value);
448 			return (ARCHIVE_FAILED);
449 		}
450 		return (ARCHIVE_OK);
451 	}
452 	if (strcmp(key, "compression") == 0) {
453 		const char *name = NULL;
454 
455 		if (value == NULL)
456 			xar->opt_compression = NONE;
457 		else if (strcmp(value, "none") == 0)
458 			xar->opt_compression = NONE;
459 		else if (strcmp(value, "gzip") == 0)
460 			xar->opt_compression = GZIP;
461 		else if (strcmp(value, "bzip2") == 0)
462 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
463 			xar->opt_compression = BZIP2;
464 #else
465 			name = "bzip2";
466 #endif
467 		else if (strcmp(value, "lzma") == 0)
468 #if HAVE_LZMA_H
469 			xar->opt_compression = LZMA;
470 #else
471 			name = "lzma";
472 #endif
473 		else if (strcmp(value, "xz") == 0)
474 #if HAVE_LZMA_H
475 			xar->opt_compression = XZ;
476 #else
477 			name = "xz";
478 #endif
479 		else {
480 			archive_set_error(&(a->archive),
481 			    ARCHIVE_ERRNO_MISC,
482 			    "Unknown compression name: `%s'",
483 			    value);
484 			return (ARCHIVE_FAILED);
485 		}
486 		if (name != NULL) {
487 			archive_set_error(&(a->archive),
488 			    ARCHIVE_ERRNO_MISC,
489 			    "`%s' compression not supported "
490 			    "on this platform",
491 			    name);
492 			return (ARCHIVE_FAILED);
493 		}
494 		return (ARCHIVE_OK);
495 	}
496 	if (strcmp(key, "compression-level") == 0) {
497 		if (value == NULL ||
498 		    !(value[0] >= '0' && value[0] <= '9') ||
499 		    value[1] != '\0') {
500 			archive_set_error(&(a->archive),
501 			    ARCHIVE_ERRNO_MISC,
502 			    "Illegal value `%s'",
503 			    value);
504 			return (ARCHIVE_FAILED);
505 		}
506 		xar->opt_compression_level = value[0] - '0';
507 		return (ARCHIVE_OK);
508 	}
509 	if (strcmp(key, "toc-checksum") == 0) {
510 		if (value == NULL)
511 			xar->opt_toc_sumalg = CKSUM_NONE;
512 		else if (strcmp(value, "none") == 0)
513 			xar->opt_toc_sumalg = CKSUM_NONE;
514 		else if (strcmp(value, "sha1") == 0)
515 			xar->opt_toc_sumalg = CKSUM_SHA1;
516 		else if (strcmp(value, "md5") == 0)
517 			xar->opt_toc_sumalg = CKSUM_MD5;
518 		else {
519 			archive_set_error(&(a->archive),
520 			    ARCHIVE_ERRNO_MISC,
521 			    "Unknown checksum name: `%s'",
522 			    value);
523 			return (ARCHIVE_FAILED);
524 		}
525 		return (ARCHIVE_OK);
526 	}
527 	if (strcmp(key, "threads") == 0) {
528 		char *endptr;
529 		unsigned long val;
530 
531 		if (value == NULL)
532 			return (ARCHIVE_FAILED);
533 		errno = 0;
534 		val = strtoul(value, &endptr, 10);
535 		if (errno != 0 || *endptr != '\0' || val > (unsigned)INT_MAX) {
536 			xar->opt_threads = 1;
537 			archive_set_error(&(a->archive),
538 			    ARCHIVE_ERRNO_MISC,
539 			    "Illegal value `%s'",
540 			    value);
541 			return (ARCHIVE_FAILED);
542 		}
543 		xar->opt_threads = (int)val;
544 		if (xar->opt_threads == 0) {
545 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
546 			xar->opt_threads = lzma_cputhreads();
547 #else
548 			xar->opt_threads = 1;
549 #endif
550 		}
551 	}
552 
553 	/* Note: The "warn" return is just to inform the options
554 	 * supervisor that we didn't handle it.  It will generate
555 	 * a suitable error if no one used this option. */
556 	return (ARCHIVE_WARN);
557 }
558 
559 static int
xar_write_header(struct archive_write * a,struct archive_entry * entry)560 xar_write_header(struct archive_write *a, struct archive_entry *entry)
561 {
562 	struct xar *xar;
563 	struct file *file;
564 	struct archive_entry *file_entry;
565 	int r, r2;
566 
567 	xar = (struct xar *)a->format_data;
568 	xar->cur_file = NULL;
569 	xar->bytes_remaining = 0;
570 
571 	if (xar->sconv == NULL) {
572 		xar->sconv = archive_string_conversion_to_charset(
573 		    &a->archive, "UTF-8", 1);
574 		if (xar->sconv == NULL)
575 			return (ARCHIVE_FATAL);
576 	}
577 
578 	file = file_new(a, entry);
579 	if (file == NULL) {
580 		archive_set_error(&a->archive, ENOMEM,
581 		    "Can't allocate data");
582 		return (ARCHIVE_FATAL);
583 	}
584 	r2 = file_gen_utility_names(a, file);
585 	if (r2 < ARCHIVE_WARN)
586 		return (r2);
587 
588 	/*
589 	 * Ignore a path which looks like the top of directory name
590 	 * since we have already made the root directory of an Xar archive.
591 	 */
592 	if (archive_strlen(&(file->parentdir)) == 0 &&
593 	    archive_strlen(&(file->basename)) == 0) {
594 		file_free(file);
595 		return (r2);
596 	}
597 
598 	/* Add entry into tree */
599 	file_entry = file->entry;
600 	r = file_tree(a, &file);
601 	if (r != ARCHIVE_OK)
602 		return (r);
603 	/* There is the same file in tree and
604 	 * the current file is older than the file in tree.
605 	 * So we don't need the current file data anymore. */
606 	if (file->entry != file_entry)
607 		return (r2);
608 	if (file->id == 0)
609 		file_register(xar, file);
610 
611 	/* A virtual file, which is a directory, does not have
612 	 * any contents and we won't store it into a archive
613 	 * file other than its name. */
614 	if (file->virtual)
615 		return (r2);
616 
617 	/*
618 	 * Prepare to save the contents of the file.
619 	 */
620 	if (xar->temp_fd == -1) {
621 		int algsize;
622 		xar->temp_offset = 0;
623 		xar->temp_fd = __archive_mktemp(NULL);
624 		if (xar->temp_fd < 0) {
625 			archive_set_error(&a->archive, errno,
626 			    "Couldn't create temporary file");
627 			return (ARCHIVE_FATAL);
628 		}
629 		algsize = getalgsize(xar->opt_toc_sumalg);
630 		if (algsize > 0) {
631 			if (lseek(xar->temp_fd, algsize, SEEK_SET) < 0) {
632 				archive_set_error(&(a->archive), errno,
633 				    "lseek failed");
634 				return (ARCHIVE_FATAL);
635 			}
636 			xar->temp_offset = algsize;
637 		}
638 	}
639 
640 	if (archive_entry_hardlink(file->entry) == NULL) {
641 		r = save_xattrs(a, file);
642 		if (r != ARCHIVE_OK)
643 			return (ARCHIVE_FATAL);
644 	}
645 
646 	/* Non regular files contents are unneeded to be saved to
647 	 * a temporary file. */
648 	if (archive_entry_filetype(file->entry) != AE_IFREG)
649 		return (r2);
650 
651 	/*
652 	 * Set the current file to cur_file to read its contents.
653 	 */
654 	xar->cur_file = file;
655 
656 	if (archive_entry_nlink(file->entry) > 1) {
657 		r = file_register_hardlink(a, file);
658 		if (r != ARCHIVE_OK)
659 			return (r);
660 		if (archive_entry_hardlink(file->entry) != NULL) {
661 			archive_entry_unset_size(file->entry);
662 			return (r2);
663 		}
664 	}
665 
666 	/* Save a offset of current file in temporary file. */
667 	file->data.temp_offset = xar->temp_offset;
668 	file->data.size = archive_entry_size(file->entry);
669 	file->data.compression = xar->opt_compression;
670 	xar->bytes_remaining = archive_entry_size(file->entry);
671 	checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
672 	checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
673 	r = xar_compression_init_encoder(a);
674 
675 	if (r != ARCHIVE_OK)
676 		return (r);
677 	else
678 		return (r2);
679 }
680 
681 static int
write_to_temp(struct archive_write * a,const void * buff,size_t s)682 write_to_temp(struct archive_write *a, const void *buff, size_t s)
683 {
684 	struct xar *xar;
685 	const unsigned char *p;
686 	ssize_t ws;
687 
688 	xar = (struct xar *)a->format_data;
689 	p = (const unsigned char *)buff;
690 	while (s) {
691 		ws = write(xar->temp_fd, p, s);
692 		if (ws < 0) {
693 			archive_set_error(&(a->archive), errno,
694 			    "write function failed");
695 			return (ARCHIVE_FATAL);
696 		}
697 		s -= ws;
698 		p += ws;
699 		xar->temp_offset += ws;
700 	}
701 	return (ARCHIVE_OK);
702 }
703 
704 static ssize_t
xar_write_data(struct archive_write * a,const void * buff,size_t s)705 xar_write_data(struct archive_write *a, const void *buff, size_t s)
706 {
707 	struct xar *xar;
708 	enum la_zaction run;
709 	size_t size = 0;
710 	size_t rsize;
711 	int r;
712 
713 	xar = (struct xar *)a->format_data;
714 
715 	if (s > xar->bytes_remaining)
716 		s = (size_t)xar->bytes_remaining;
717 	if (s == 0 || xar->cur_file == NULL)
718 		return (0);
719 	if (xar->cur_file->data.compression == NONE) {
720 		checksum_update(&(xar->e_sumwrk), buff, s);
721 		checksum_update(&(xar->a_sumwrk), buff, s);
722 		size = rsize = s;
723 	} else {
724 		xar->stream.next_in = (const unsigned char *)buff;
725 		xar->stream.avail_in = s;
726 		if (xar->bytes_remaining > s)
727 			run = ARCHIVE_Z_RUN;
728 		else
729 			run = ARCHIVE_Z_FINISH;
730 		/* Compress file data. */
731 		for (;;) {
732 			r = compression_code(&(a->archive), &(xar->stream),
733 			    run);
734 			if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
735 				return (ARCHIVE_FATAL);
736 			if (xar->stream.avail_out == 0 ||
737 			    run == ARCHIVE_Z_FINISH) {
738 				size = sizeof(xar->wbuff) -
739 				    xar->stream.avail_out;
740 				checksum_update(&(xar->a_sumwrk), xar->wbuff,
741 				    size);
742 				xar->cur_file->data.length += size;
743 				if (write_to_temp(a, xar->wbuff,
744 				    size) != ARCHIVE_OK)
745 					return (ARCHIVE_FATAL);
746 				if (r == ARCHIVE_OK) {
747 					/* Output buffer was full */
748 					xar->stream.next_out = xar->wbuff;
749 					xar->stream.avail_out =
750 					    sizeof(xar->wbuff);
751 				} else {
752 					/* ARCHIVE_EOF - We are done */
753 					break;
754 				}
755 			} else {
756 				/* Compressor wants more input */
757 				break;
758 			}
759 		}
760 		rsize = s - xar->stream.avail_in;
761 		checksum_update(&(xar->e_sumwrk), buff, rsize);
762 	}
763 #if !defined(_WIN32) || defined(__CYGWIN__)
764 	if (xar->bytes_remaining ==
765 	    (uint64_t)archive_entry_size(xar->cur_file->entry)) {
766 		/*
767 		 * Get the path of a shell script if so.
768 		 */
769 		const unsigned char *b = (const unsigned char *)buff;
770 
771 		archive_string_empty(&(xar->cur_file->script));
772 		if (rsize > 2 && b[0] == '#' && b[1] == '!') {
773 			size_t i, end, off;
774 
775 			off = 2;
776 			if (b[off] == ' ')
777 				off++;
778 #ifdef PATH_MAX
779 			if ((rsize - off) > PATH_MAX)
780 				end = off + PATH_MAX;
781 			else
782 #endif
783 				end = rsize;
784 			/* Find the end of a script path. */
785 			for (i = off; i < end && b[i] != '\0' &&
786 			    b[i] != '\n' && b[i] != '\r' &&
787 			    b[i] != ' ' && b[i] != '\t'; i++)
788 				;
789 			archive_strncpy(&(xar->cur_file->script), b + off,
790 			    i - off);
791 		}
792 	}
793 #endif
794 
795 	if (xar->cur_file->data.compression == NONE) {
796 		if (write_to_temp(a, buff, size) != ARCHIVE_OK)
797 			return (ARCHIVE_FATAL);
798 		xar->cur_file->data.length += size;
799 	}
800 	xar->bytes_remaining -= rsize;
801 
802 	return (rsize);
803 }
804 
805 static int
xar_finish_entry(struct archive_write * a)806 xar_finish_entry(struct archive_write *a)
807 {
808 	struct xar *xar;
809 	struct file *file;
810 	size_t s;
811 	ssize_t w;
812 
813 	xar = (struct xar *)a->format_data;
814 	if (xar->cur_file == NULL)
815 		return (ARCHIVE_OK);
816 
817 	while (xar->bytes_remaining > 0) {
818 		s = (size_t)xar->bytes_remaining;
819 		if (s > a->null_length)
820 			s = a->null_length;
821 		w = xar_write_data(a, a->nulls, s);
822 		if (w > 0)
823 			xar->bytes_remaining -= w;
824 		else
825 			return ((int)w);
826 	}
827 	file = xar->cur_file;
828 	checksum_final(&(xar->e_sumwrk), &(file->data.e_sum));
829 	checksum_final(&(xar->a_sumwrk), &(file->data.a_sum));
830 	xar->cur_file = NULL;
831 
832 	return (ARCHIVE_OK);
833 }
834 
835 static int
xmlwrite_string_attr(struct archive_write * a,struct xml_writer * writer,const char * key,const char * value,const char * attrkey,const char * attrvalue)836 xmlwrite_string_attr(struct archive_write *a, struct xml_writer *writer,
837 	const char *key, const char *value,
838 	const char *attrkey, const char *attrvalue)
839 {
840 	int r;
841 
842 	r = xml_writer_start_element(writer, key);
843 	if (r < 0) {
844 		archive_set_error(&a->archive,
845 		    ARCHIVE_ERRNO_MISC,
846 		    "xml_writer_start_element() failed: %d", r);
847 		return (ARCHIVE_FATAL);
848 	}
849 	if (attrkey != NULL && attrvalue != NULL) {
850 		r = xml_writer_write_attribute(writer, attrkey, attrvalue);
851 		if (r < 0) {
852 			archive_set_error(&a->archive,
853 			    ARCHIVE_ERRNO_MISC,
854 			    "xml_writer_write_attribute() failed: %d", r);
855 			return (ARCHIVE_FATAL);
856 		}
857 	}
858 	if (value != NULL) {
859 		r = xml_writer_write_string(writer, value);
860 		if (r < 0) {
861 			archive_set_error(&a->archive,
862 			    ARCHIVE_ERRNO_MISC,
863 			    "xml_writer_write_string() failed: %d", r);
864 			return (ARCHIVE_FATAL);
865 		}
866 	}
867 	r = xml_writer_end_element(writer);
868 	if (r < 0) {
869 		archive_set_error(&a->archive,
870 		    ARCHIVE_ERRNO_MISC,
871 		    "xml_writer_end_element() failed: %d", r);
872 		return (ARCHIVE_FATAL);
873 	}
874 	return (ARCHIVE_OK);
875 }
876 
877 static int
xmlwrite_string(struct archive_write * a,struct xml_writer * writer,const char * key,const char * value)878 xmlwrite_string(struct archive_write *a, struct xml_writer *writer,
879 	const char *key, const char *value)
880 {
881 	int r;
882 
883 	if (value == NULL)
884 		return (ARCHIVE_OK);
885 
886 	r = xml_writer_start_element(writer, key);
887 	if (r < 0) {
888 		archive_set_error(&a->archive,
889 		    ARCHIVE_ERRNO_MISC,
890 		    "xml_writer_start_element() failed: %d", r);
891 		return (ARCHIVE_FATAL);
892 	}
893 	if (value != NULL) {
894 		r = xml_writer_write_string(writer, value);
895 		if (r < 0) {
896 			archive_set_error(&a->archive,
897 			    ARCHIVE_ERRNO_MISC,
898 			    "xml_writer_write_string() failed: %d", r);
899 			return (ARCHIVE_FATAL);
900 		}
901 	}
902 	r = xml_writer_end_element(writer);
903 	if (r < 0) {
904 		archive_set_error(&a->archive,
905 		    ARCHIVE_ERRNO_MISC,
906 		    "xml_writer_end_element() failed: %d", r);
907 		return (ARCHIVE_FATAL);
908 	}
909 	return (ARCHIVE_OK);
910 }
911 
912 static int
xmlwrite_fstring(struct archive_write * a,struct xml_writer * writer,const char * key,const char * fmt,...)913 xmlwrite_fstring(struct archive_write *a, struct xml_writer *writer,
914 	const char *key, const char *fmt, ...)
915 {
916 	struct xar *xar;
917 	va_list ap;
918 
919 	xar = (struct xar *)a->format_data;
920 	va_start(ap, fmt);
921 	archive_string_empty(&xar->vstr);
922 	archive_string_vsprintf(&xar->vstr, fmt, ap);
923 	va_end(ap);
924 	return (xmlwrite_string(a, writer, key, xar->vstr.s));
925 }
926 
927 static int
xmlwrite_time(struct archive_write * a,struct xml_writer * writer,const char * key,time_t t,int z)928 xmlwrite_time(struct archive_write *a, struct xml_writer *writer,
929 	const char *key, time_t t, int z)
930 {
931 	char timestr[100];
932 	struct tm tm;
933 
934 #if defined(HAVE_GMTIME_S)
935 	gmtime_s(&tm, &t);
936 #elif defined(HAVE_GMTIME_R)
937 	gmtime_r(&t, &tm);
938 #else
939 	memcpy(&tm, gmtime(&t), sizeof(tm));
940 #endif
941 	memset(&timestr, 0, sizeof(timestr));
942 	/* Do not use %F and %T for portability. */
943 	strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &tm);
944 	if (z)
945 		strcat(timestr, "Z");
946 	return (xmlwrite_string(a, writer, key, timestr));
947 }
948 
949 static int
xmlwrite_mode(struct archive_write * a,struct xml_writer * writer,const char * key,mode_t mode)950 xmlwrite_mode(struct archive_write *a, struct xml_writer *writer,
951 	const char *key, mode_t mode)
952 {
953 	char ms[5];
954 
955 	ms[0] = '0';
956 	ms[1] = '0' + ((mode >> 6) & 07);
957 	ms[2] = '0' + ((mode >> 3) & 07);
958 	ms[3] = '0' + (mode & 07);
959 	ms[4] = '\0';
960 
961 	return (xmlwrite_string(a, writer, key, ms));
962 }
963 
964 static int
xmlwrite_sum(struct archive_write * a,struct xml_writer * writer,const char * key,struct chksumval * sum)965 xmlwrite_sum(struct archive_write *a, struct xml_writer *writer,
966 	const char *key, struct chksumval *sum)
967 {
968 	const char *algname;
969 	int algsize;
970 	char buff[MAX_SUM_SIZE*2 + 1];
971 	char *p;
972 	unsigned char *s;
973 	int i, r;
974 
975 	if (sum->len > 0) {
976 		algname = getalgname(sum->alg);
977 		algsize = getalgsize(sum->alg);
978 		if (algname != NULL) {
979 			const char *hex = "0123456789abcdef";
980 			p = buff;
981 			s = sum->val;
982 			for (i = 0; i < algsize; i++) {
983 				*p++ = hex[(*s >> 4)];
984 				*p++ = hex[(*s & 0x0f)];
985 				s++;
986 			}
987 			*p = '\0';
988 			r = xmlwrite_string_attr(a, writer,
989 			    key, buff,
990 			    "style", algname);
991 			if (r < 0)
992 				return (ARCHIVE_FATAL);
993 		}
994 	}
995 	return (ARCHIVE_OK);
996 }
997 
998 static int
xmlwrite_heap(struct archive_write * a,struct xml_writer * writer,struct heap_data * heap)999 xmlwrite_heap(struct archive_write *a, struct xml_writer *writer,
1000 	struct heap_data *heap)
1001 {
1002 	const char *encname;
1003 	int r;
1004 
1005 	r = xmlwrite_fstring(a, writer, "length", "%ju", (uintmax_t)heap->length);
1006 	if (r < 0)
1007 		return (ARCHIVE_FATAL);
1008 	r = xmlwrite_fstring(a, writer, "offset", "%ju", (uintmax_t)heap->temp_offset);
1009 	if (r < 0)
1010 		return (ARCHIVE_FATAL);
1011 	r = xmlwrite_fstring(a, writer, "size", "%ju", (uintmax_t)heap->size);
1012 	if (r < 0)
1013 		return (ARCHIVE_FATAL);
1014 	switch (heap->compression) {
1015 	case GZIP:
1016 		encname = "application/x-gzip"; break;
1017 	case BZIP2:
1018 		encname = "application/x-bzip2"; break;
1019 	case LZMA:
1020 		encname = "application/x-lzma"; break;
1021 	case XZ:
1022 		encname = "application/x-xz"; break;
1023 	default:
1024 		encname = "application/octet-stream"; break;
1025 	}
1026 	r = xmlwrite_string_attr(a, writer, "encoding", NULL,
1027 	    "style", encname);
1028 	if (r < 0)
1029 		return (ARCHIVE_FATAL);
1030 	r = xmlwrite_sum(a, writer, "archived-checksum", &(heap->a_sum));
1031 	if (r < 0)
1032 		return (ARCHIVE_FATAL);
1033 	r = xmlwrite_sum(a, writer, "extracted-checksum", &(heap->e_sum));
1034 	if (r < 0)
1035 		return (ARCHIVE_FATAL);
1036 	return (ARCHIVE_OK);
1037 }
1038 
1039 /*
1040  * xar utility records fflags as following xml elements:
1041  *   <flags>
1042  *     <UserNoDump/>
1043  *     .....
1044  *   </flags>
1045  * or
1046  *   <ext2>
1047  *     <NoDump/>
1048  *     .....
1049  *   </ext2>
1050  * If xar is running on BSD platform, records <flags>..</flags>;
1051  * if xar is running on linux platform, records <ext2>..</ext2>;
1052  * otherwise does not record.
1053  *
1054  * Our implements records both <flags> and <ext2> if it's necessary.
1055  */
1056 static int
make_fflags_entry(struct archive_write * a,struct xml_writer * writer,const char * element,const char * fflags_text)1057 make_fflags_entry(struct archive_write *a, struct xml_writer *writer,
1058     const char *element, const char *fflags_text)
1059 {
1060 	static const struct flagentry {
1061 		const char	*name;
1062 		const char	*xarname;
1063 	}
1064 	flagbsd[] = {
1065 		{ "sappnd",	"SystemAppend"},
1066 		{ "sappend",	"SystemAppend"},
1067 		{ "arch",	"SystemArchived"},
1068 		{ "archived",	"SystemArchived"},
1069 		{ "schg",	"SystemImmutable"},
1070 		{ "schange",	"SystemImmutable"},
1071 		{ "simmutable",	"SystemImmutable"},
1072 		{ "nosunlnk",	"SystemNoUnlink"},
1073 		{ "nosunlink",	"SystemNoUnlink"},
1074 		{ "snapshot",	"SystemSnapshot"},
1075 		{ "uappnd",	"UserAppend"},
1076 		{ "uappend",	"UserAppend"},
1077 		{ "uchg",	"UserImmutable"},
1078 		{ "uchange",	"UserImmutable"},
1079 		{ "uimmutable",	"UserImmutable"},
1080 		{ "nodump",	"UserNoDump"},
1081 		{ "noopaque",	"UserOpaque"},
1082 		{ "nouunlnk",	"UserNoUnlink"},
1083 		{ "nouunlink",	"UserNoUnlink"},
1084 		{ NULL, NULL}
1085 	},
1086 	flagext2[] = {
1087 		{ "sappnd",	"AppendOnly"},
1088 		{ "sappend",	"AppendOnly"},
1089 		{ "schg",	"Immutable"},
1090 		{ "schange",	"Immutable"},
1091 		{ "simmutable",	"Immutable"},
1092 		{ "nodump",	"NoDump"},
1093 		{ "nouunlnk",	"Undelete"},
1094 		{ "nouunlink",	"Undelete"},
1095 		{ "btree",	"BTree"},
1096 		{ "comperr",	"CompError"},
1097 		{ "compress",	"Compress"},
1098 		{ "noatime",	"NoAtime"},
1099 		{ "compdirty",	"CompDirty"},
1100 		{ "comprblk",	"CompBlock"},
1101 		{ "dirsync",	"DirSync"},
1102 		{ "hashidx",	"HashIndexed"},
1103 		{ "imagic",	"iMagic"},
1104 		{ "journal",	"Journaled"},
1105 		{ "securedeletion",	"SecureDeletion"},
1106 		{ "sync",	"Synchronous"},
1107 		{ "notail",	"NoTail"},
1108 		{ "topdir",	"TopDir"},
1109 		{ "reserved",	"Reserved"},
1110 		{ NULL, NULL}
1111 	};
1112 	const struct flagentry *fe, *flagentry;
1113 #define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd))
1114 	const struct flagentry *avail[FLAGENTRY_MAXSIZE];
1115 	const char *p;
1116 	int i, n, r;
1117 
1118 	if (strcmp(element, "ext2") == 0)
1119 		flagentry = flagext2;
1120 	else
1121 		flagentry = flagbsd;
1122 	n = 0;
1123 	p = fflags_text;
1124 	do {
1125 		const char *cp;
1126 
1127 		cp = strchr(p, ',');
1128 		if (cp == NULL)
1129 			cp = p + strlen(p);
1130 
1131 		for (fe = flagentry; fe->name != NULL; fe++) {
1132 			if (fe->name[cp - p] != '\0'
1133 			    || p[0] != fe->name[0])
1134 				continue;
1135 			if (strncmp(p, fe->name, cp - p) == 0) {
1136 				avail[n++] = fe;
1137 				break;
1138 			}
1139 		}
1140 		if (*cp == ',')
1141 			p = cp + 1;
1142 		else
1143 			p = NULL;
1144 	} while (p != NULL);
1145 
1146 	if (n > 0) {
1147 		r = xml_writer_start_element(writer, element);
1148 		if (r < 0) {
1149 			archive_set_error(&a->archive,
1150 			    ARCHIVE_ERRNO_MISC,
1151 			    "xml_writer_start_element() failed: %d", r);
1152 			return (ARCHIVE_FATAL);
1153 		}
1154 		for (i = 0; i < n; i++) {
1155 			r = xmlwrite_string(a, writer,
1156 			    avail[i]->xarname, NULL);
1157 			if (r != ARCHIVE_OK)
1158 				return (r);
1159 		}
1160 
1161 		r = xml_writer_end_element(writer);
1162 		if (r < 0) {
1163 			archive_set_error(&a->archive,
1164 			    ARCHIVE_ERRNO_MISC,
1165 			    "xml_writer_end_element() failed: %d", r);
1166 			return (ARCHIVE_FATAL);
1167 		}
1168 	}
1169 	return (ARCHIVE_OK);
1170 }
1171 
1172 /*
1173  * This function determines whether a UTF-8 string contains
1174  * only codepoints that are convertible to Latin-1. Strings
1175  * beyond Latin-1 are stored base64-encoded in the XAR TOC.
1176  */
1177 static int
is_u8_zstring_latin1(const char * in)1178 is_u8_zstring_latin1(const char *in)
1179 {
1180 	unsigned int c;
1181 	while (*in) {
1182 		c = *in++;
1183 		if (c < 0x80) continue;
1184 		/*
1185 		 * Filter out non-continuation, any continuation of 2-3
1186 		 * bytes, and any continuation of 1 byte whose high 3 bits
1187 		 * are non-zero. Recall, 1-byte continuations can store 11
1188 		 * bits whereas Latin-1 codepoints are only 8 bits wide.
1189 		 */
1190 		if ((c & 0xFC) != 0xC0)
1191 			return (0);
1192 		c = *in++;
1193 		/*
1194 		 * If we get any non-continuation byte (including 0x00!),
1195 		 * the string is not valid UTF-8.
1196 		 */
1197 		if ((c & 0xC0) != 0x80)
1198 			return (0); /* invalid unicode */
1199 	}
1200 	return (1);
1201 }
1202 
1203 static int
make_file_entry(struct archive_write * a,struct xml_writer * writer,struct file * file)1204 make_file_entry(struct archive_write *a, struct xml_writer *writer,
1205     struct file *file)
1206 {
1207 	struct xar *xar;
1208 	const char *filetype, *filelink, *fflags;
1209 	struct archive_string linkto;
1210 	struct heap_data *heap;
1211 	const char *p;
1212 	size_t len;
1213 	int r, r2;
1214 
1215 	xar = (struct xar *)a->format_data;
1216 	r2 = ARCHIVE_OK;
1217 
1218 	/*
1219 	 * Make a file name entry, "<name>".
1220 	 */
1221 	if (!is_u8_zstring_latin1(file->basename.s)) {
1222 		r = xml_writer_start_element(writer, "name");
1223 		if (r < 0) {
1224 			archive_set_error(&a->archive,
1225 			    ARCHIVE_ERRNO_MISC,
1226 			    "xml_writer_start_element() failed: %d", r);
1227 			return (ARCHIVE_FATAL);
1228 		}
1229 		r = xml_writer_write_attribute(writer,
1230 		    "enctype", "base64");
1231 		if (r < 0) {
1232 			archive_set_error(&a->archive,
1233 			    ARCHIVE_ERRNO_MISC,
1234 			    "xml_writer_write_attribute() failed: %d", r);
1235 			return (ARCHIVE_FATAL);
1236 		}
1237 		r = xml_writer_write_base64(writer, file->basename.s,
1238 		    0, (int)archive_strlen(&(file->basename)));
1239 		if (r < 0) {
1240 			archive_set_error(&a->archive,
1241 			    ARCHIVE_ERRNO_MISC,
1242 			    "xml_writer_write_base64() failed: %d", r);
1243 			return (ARCHIVE_FATAL);
1244 		}
1245 		r = xml_writer_end_element(writer);
1246 		if (r < 0) {
1247 			archive_set_error(&a->archive,
1248 			    ARCHIVE_ERRNO_MISC,
1249 			    "xml_writer_end_element() failed: %d", r);
1250 			return (ARCHIVE_FATAL);
1251 		}
1252 	} else {
1253 		r = xmlwrite_string(a, writer, "name", file->basename.s);
1254 		if (r < 0)
1255 			return (ARCHIVE_FATAL);
1256 	}
1257 
1258 	/*
1259 	 * Make a file type entry, "<type>".
1260 	 */
1261 	filelink = NULL;
1262 	archive_string_init(&linkto);
1263 	switch (archive_entry_filetype(file->entry)) {
1264 	case AE_IFDIR:
1265 		filetype = "directory"; break;
1266 	case AE_IFLNK:
1267 		filetype = "symlink"; break;
1268 	case AE_IFCHR:
1269 		filetype = "character special"; break;
1270 	case AE_IFBLK:
1271 		filetype = "block special"; break;
1272 	case AE_IFSOCK:
1273 		filetype = "socket"; break;
1274 	case AE_IFIFO:
1275 		filetype = "fifo"; break;
1276 	case AE_IFREG:
1277 	default:
1278 		if (file->hardlink_target != NULL) {
1279 			filetype = "hardlink";
1280 			filelink = "link";
1281 			if (file->hardlink_target == file)
1282 				archive_strcpy(&linkto, "original");
1283 			else
1284 				archive_string_sprintf(&linkto, "%d",
1285 				    file->hardlink_target->id);
1286 		} else
1287 			filetype = "file";
1288 		break;
1289 	}
1290 	r = xmlwrite_string_attr(a, writer, "type", filetype,
1291 	    filelink, linkto.s);
1292 	archive_string_free(&linkto);
1293 	if (r < 0)
1294 		return (ARCHIVE_FATAL);
1295 
1296 	/*
1297 	 * On a virtual directory, we record "name" and "type" only.
1298 	 */
1299 	if (file->virtual)
1300 		return (ARCHIVE_OK);
1301 
1302 	switch (archive_entry_filetype(file->entry)) {
1303 	case AE_IFLNK:
1304 		/*
1305 		 * xar utility has checked a file type, which
1306 		 * a symbolic-link file has referenced.
1307 		 * For example:
1308 		 *   <link type="directory">../ref/</link>
1309 		 *   The symlink target file is "../ref/" and its
1310 		 *   file type is a directory.
1311 		 *
1312 		 *   <link type="file">../f</link>
1313 		 *   The symlink target file is "../f" and its
1314 		 *   file type is a regular file.
1315 		 *
1316 		 * But our implementation cannot do it, and then we
1317 		 * always record that a attribute "type" is "broken",
1318 		 * for example:
1319 		 *   <link type="broken">foo/bar</link>
1320 		 *   It means "foo/bar" is not reachable.
1321 		 */
1322 		r = xmlwrite_string_attr(a, writer, "link",
1323 		    file->symlink.s,
1324 		    "type", "broken");
1325 		if (r < 0)
1326 			return (ARCHIVE_FATAL);
1327 		break;
1328 	case AE_IFCHR:
1329 	case AE_IFBLK:
1330 		r = xml_writer_start_element(writer, "device");
1331 		if (r < 0) {
1332 			archive_set_error(&a->archive,
1333 			    ARCHIVE_ERRNO_MISC,
1334 			    "xml_writer_start_element() failed: %d", r);
1335 			return (ARCHIVE_FATAL);
1336 		}
1337 		r = xmlwrite_fstring(a, writer, "major",
1338 		    "%d", archive_entry_rdevmajor(file->entry));
1339 		if (r < 0)
1340 			return (ARCHIVE_FATAL);
1341 		r = xmlwrite_fstring(a, writer, "minor",
1342 		    "%d", archive_entry_rdevminor(file->entry));
1343 		if (r < 0)
1344 			return (ARCHIVE_FATAL);
1345 		r = xml_writer_end_element(writer);
1346 		if (r < 0) {
1347 			archive_set_error(&a->archive,
1348 			    ARCHIVE_ERRNO_MISC,
1349 			    "xml_writer_end_element() failed: %d", r);
1350 			return (ARCHIVE_FATAL);
1351 		}
1352 		break;
1353 	default:
1354 		break;
1355 	}
1356 
1357 	/*
1358 	 * Make a inode entry, "<inode>".
1359 	 */
1360 	r = xmlwrite_fstring(a, writer, "inode",
1361 	    "%jd", (intmax_t)archive_entry_ino64(file->entry));
1362 	if (r < 0)
1363 		return (ARCHIVE_FATAL);
1364 	if (archive_entry_dev(file->entry) != 0) {
1365 		r = xmlwrite_fstring(a, writer, "deviceno",
1366 		    "%d", archive_entry_dev(file->entry));
1367 		if (r < 0)
1368 			return (ARCHIVE_FATAL);
1369 	}
1370 
1371 	/*
1372 	 * Make a file mode entry, "<mode>".
1373 	 */
1374 	r = xmlwrite_mode(a, writer, "mode",
1375 	    archive_entry_mode(file->entry));
1376 	if (r < 0)
1377 		return (ARCHIVE_FATAL);
1378 
1379 	/*
1380 	 * Make a user entry, "<uid>" and "<user>.
1381 	 */
1382 	r = xmlwrite_fstring(a, writer, "uid",
1383 	    "%jd", (intmax_t)archive_entry_uid(file->entry));
1384 	if (r < 0)
1385 		return (ARCHIVE_FATAL);
1386 	r = archive_entry_uname_l(file->entry, &p, &len, xar->sconv);
1387 	if (r != 0) {
1388 		if (errno == ENOMEM) {
1389 			archive_set_error(&a->archive, ENOMEM,
1390 			    "Can't allocate memory for Uname");
1391 			return (ARCHIVE_FATAL);
1392 		}
1393 		archive_set_error(&a->archive,
1394 		    ARCHIVE_ERRNO_FILE_FORMAT,
1395 		    "Can't translate uname '%s' to UTF-8",
1396 		    archive_entry_uname(file->entry));
1397 		r2 = ARCHIVE_WARN;
1398 	}
1399 	if (len > 0) {
1400 		r = xmlwrite_string(a, writer, "user", p);
1401 		if (r < 0)
1402 			return (ARCHIVE_FATAL);
1403 	}
1404 
1405 	/*
1406 	 * Make a group entry, "<gid>" and "<group>.
1407 	 */
1408 	r = xmlwrite_fstring(a, writer, "gid",
1409 	    "%jd", (intmax_t)archive_entry_gid(file->entry));
1410 	if (r < 0)
1411 		return (ARCHIVE_FATAL);
1412 	r = archive_entry_gname_l(file->entry, &p, &len, xar->sconv);
1413 	if (r != 0) {
1414 		if (errno == ENOMEM) {
1415 			archive_set_error(&a->archive, ENOMEM,
1416 			    "Can't allocate memory for Gname");
1417 			return (ARCHIVE_FATAL);
1418 		}
1419 		archive_set_error(&a->archive,
1420 		    ARCHIVE_ERRNO_FILE_FORMAT,
1421 		    "Can't translate gname '%s' to UTF-8",
1422 		    archive_entry_gname(file->entry));
1423 		r2 = ARCHIVE_WARN;
1424 	}
1425 	if (len > 0) {
1426 		r = xmlwrite_string(a, writer, "group", p);
1427 		if (r < 0)
1428 			return (ARCHIVE_FATAL);
1429 	}
1430 
1431 	/*
1432 	 * Make a ctime entry, "<ctime>".
1433 	 */
1434 	if (archive_entry_ctime_is_set(file->entry)) {
1435 		r = xmlwrite_time(a, writer, "ctime",
1436 		    archive_entry_ctime(file->entry), 1);
1437 		if (r < 0)
1438 			return (ARCHIVE_FATAL);
1439 	}
1440 
1441 	/*
1442 	 * Make a mtime entry, "<mtime>".
1443 	 */
1444 	if (archive_entry_mtime_is_set(file->entry)) {
1445 		r = xmlwrite_time(a, writer, "mtime",
1446 		    archive_entry_mtime(file->entry), 1);
1447 		if (r < 0)
1448 			return (ARCHIVE_FATAL);
1449 	}
1450 
1451 	/*
1452 	 * Make a atime entry, "<atime>".
1453 	 */
1454 	if (archive_entry_atime_is_set(file->entry)) {
1455 		r = xmlwrite_time(a, writer, "atime",
1456 		    archive_entry_atime(file->entry), 1);
1457 		if (r < 0)
1458 			return (ARCHIVE_FATAL);
1459 	}
1460 
1461 	/*
1462 	 * Make fflags entries, "<flags>" and "<ext2>".
1463 	 */
1464 	fflags = archive_entry_fflags_text(file->entry);
1465 	if (fflags != NULL) {
1466 		r = make_fflags_entry(a, writer, "flags", fflags);
1467 		if (r < 0)
1468 			return (r);
1469 		r = make_fflags_entry(a, writer, "ext2", fflags);
1470 		if (r < 0)
1471 			return (r);
1472 	}
1473 
1474 	/*
1475 	 * Make extended attribute entries, "<ea>".
1476 	 */
1477 	archive_entry_xattr_reset(file->entry);
1478 	for (heap = file->xattr.first; heap != NULL; heap = heap->next) {
1479 		const char *name;
1480 		const void *value;
1481 		size_t size;
1482 
1483 		archive_entry_xattr_next(file->entry,
1484 		    &name, &value, &size);
1485 		r = xml_writer_start_element(writer, "ea");
1486 		if (r < 0) {
1487 			archive_set_error(&a->archive,
1488 			    ARCHIVE_ERRNO_MISC,
1489 			    "xml_writer_start_element() failed: %d", r);
1490 			return (ARCHIVE_FATAL);
1491 		}
1492 		r = xml_writer_write_attributef(writer,
1493 		    "id", "%d", heap->id);
1494 		if (r < 0) {
1495 			archive_set_error(&a->archive,
1496 			    ARCHIVE_ERRNO_MISC,
1497 			    "xml_writer_write_attributef() failed: %d", r);
1498 			return (ARCHIVE_FATAL);
1499 		}
1500 		r = xmlwrite_heap(a, writer, heap);
1501 		if (r < 0)
1502 			return (ARCHIVE_FATAL);
1503 		r = xmlwrite_string(a, writer, "name", name);
1504 		if (r < 0)
1505 			return (ARCHIVE_FATAL);
1506 
1507 		r = xml_writer_end_element(writer);
1508 		if (r < 0) {
1509 			archive_set_error(&a->archive,
1510 			    ARCHIVE_ERRNO_MISC,
1511 			    "xml_writer_end_element() failed: %d", r);
1512 			return (ARCHIVE_FATAL);
1513 		}
1514 	}
1515 
1516 	/*
1517 	 * Make a file data entry, "<data>".
1518 	 */
1519 	if (file->data.length > 0) {
1520 		r = xml_writer_start_element(writer, "data");
1521 		if (r < 0) {
1522 			archive_set_error(&a->archive,
1523 			    ARCHIVE_ERRNO_MISC,
1524 			    "xml_writer_start_element() failed: %d", r);
1525 			return (ARCHIVE_FATAL);
1526 		}
1527 
1528 		r = xmlwrite_heap(a, writer, &(file->data));
1529 		if (r < 0)
1530 			return (ARCHIVE_FATAL);
1531 
1532 		r = xml_writer_end_element(writer);
1533 		if (r < 0) {
1534 			archive_set_error(&a->archive,
1535 			    ARCHIVE_ERRNO_MISC,
1536 			    "xml_writer_end_element() failed: %d", r);
1537 			return (ARCHIVE_FATAL);
1538 		}
1539 	}
1540 
1541 	if (archive_strlen(&file->script) > 0) {
1542 		r = xml_writer_start_element(writer, "content");
1543 		if (r < 0) {
1544 			archive_set_error(&a->archive,
1545 			    ARCHIVE_ERRNO_MISC,
1546 			    "xml_writer_start_element() failed: %d", r);
1547 			return (ARCHIVE_FATAL);
1548 		}
1549 
1550 		r = xmlwrite_string(a, writer,
1551 		    "interpreter", file->script.s);
1552 		if (r < 0)
1553 			return (ARCHIVE_FATAL);
1554 
1555 		r = xmlwrite_string(a, writer, "type", "script");
1556 		if (r < 0)
1557 			return (ARCHIVE_FATAL);
1558 
1559 		r = xml_writer_end_element(writer);
1560 		if (r < 0) {
1561 			archive_set_error(&a->archive,
1562 			    ARCHIVE_ERRNO_MISC,
1563 			    "xml_writer_end_element() failed: %d", r);
1564 			return (ARCHIVE_FATAL);
1565 		}
1566 	}
1567 
1568 	return (r2);
1569 }
1570 
1571 /*
1572  * Make the TOC
1573  */
1574 static int
make_toc(struct archive_write * a)1575 make_toc(struct archive_write *a)
1576 {
1577 	struct xar *xar;
1578 	struct file *np;
1579 	struct xml_writer *writer;
1580 	const char* content;
1581 	size_t use;
1582 	int algsize;
1583 	int r, ret;
1584 
1585 	xar = (struct xar *)a->format_data;
1586 
1587 	ret = ARCHIVE_FATAL;
1588 
1589 	/*
1590 	 * Initialize xml writer.
1591 	 */
1592 	writer = NULL;
1593 	r = xml_writer_create(&writer);
1594 	if (r < 0) {
1595 		archive_set_error(&a->archive,
1596 		    ARCHIVE_ERRNO_MISC,
1597 		    "xml_writer_create() failed: %d", r);
1598 		goto exit_toc;
1599 	}
1600 	r = xml_writer_set_indent(writer, 4);
1601 	if (r < 0) {
1602 		archive_set_error(&a->archive,
1603 		    ARCHIVE_ERRNO_MISC,
1604 		    "xml_writer_set_indent() failed: %d", r);
1605 		goto exit_toc;
1606 	}
1607 	r = xml_writer_start_document(writer);
1608 	if (r < 0) {
1609 		archive_set_error(&a->archive,
1610 		    ARCHIVE_ERRNO_MISC,
1611 		    "xml_writer_start_document() failed: %d", r);
1612 		goto exit_toc;
1613 	}
1614 
1615 	/*
1616 	 * Start recording TOC
1617 	 */
1618 	r = xml_writer_start_element(writer, "xar");
1619 	if (r < 0) {
1620 		archive_set_error(&a->archive,
1621 		    ARCHIVE_ERRNO_MISC,
1622 		    "xml_writer_start_element() failed: %d", r);
1623 		goto exit_toc;
1624 	}
1625 	r = xml_writer_start_element(writer, "toc");
1626 	if (r < 0) {
1627 		archive_set_error(&a->archive,
1628 		    ARCHIVE_ERRNO_MISC,
1629 		    "xml_writer_start_element() failed: %d", r);
1630 		goto exit_toc;
1631 	}
1632 
1633 	/*
1634 	 * Record the creation time of the archive file.
1635 	 */
1636 	r = xmlwrite_time(a, writer, "creation-time", time(NULL), 0);
1637 	if (r < 0)
1638 		goto exit_toc;
1639 
1640 	/*
1641 	 * Record the checksum value of TOC
1642 	 */
1643 	algsize = getalgsize(xar->opt_toc_sumalg);
1644 	if (algsize) {
1645 		/*
1646 		 * Record TOC checksum
1647 		 */
1648 		r = xml_writer_start_element(writer, "checksum");
1649 		if (r < 0) {
1650 			archive_set_error(&a->archive,
1651 			    ARCHIVE_ERRNO_MISC,
1652 			    "xml_writer_start_element() failed: %d", r);
1653 			goto exit_toc;
1654 		}
1655 		r = xml_writer_write_attribute(writer, "style",
1656 		    getalgname(xar->opt_toc_sumalg));
1657 		if (r < 0) {
1658 			archive_set_error(&a->archive,
1659 			    ARCHIVE_ERRNO_MISC,
1660 			    "xml_writer_write_attribute() failed: %d", r);
1661 			goto exit_toc;
1662 		}
1663 
1664 		/*
1665 		 * Record the offset of the value of checksum of TOC
1666 		 */
1667 		r = xmlwrite_string(a, writer, "offset", "0");
1668 		if (r < 0)
1669 			goto exit_toc;
1670 
1671 		/*
1672 		 * Record the size of the value of checksum of TOC
1673 		 */
1674 		r = xmlwrite_fstring(a, writer, "size", "%d", algsize);
1675 		if (r < 0)
1676 			goto exit_toc;
1677 
1678 		r = xml_writer_end_element(writer);
1679 		if (r < 0) {
1680 			archive_set_error(&a->archive,
1681 			    ARCHIVE_ERRNO_MISC,
1682 			    "xml_writer_end_element() failed: %d", r);
1683 			goto exit_toc;
1684 		}
1685 	}
1686 
1687 	np = xar->root;
1688 	do {
1689 		if (np != np->parent) {
1690 			r = make_file_entry(a, writer, np);
1691 			if (r != ARCHIVE_OK)
1692 				goto exit_toc;
1693 		}
1694 
1695 		if (np->dir && np->children.first != NULL) {
1696 			/* Enter to sub directories. */
1697 			np = np->children.first;
1698 			r = xml_writer_start_element(writer,
1699 			    "file");
1700 			if (r < 0) {
1701 				archive_set_error(&a->archive,
1702 				    ARCHIVE_ERRNO_MISC,
1703 				    "xml_writer_start_element() "
1704 				    "failed: %d", r);
1705 				goto exit_toc;
1706 			}
1707 			r = xml_writer_write_attributef(
1708 			    writer, "id", "%d", np->id);
1709 			if (r < 0) {
1710 				archive_set_error(&a->archive,
1711 				    ARCHIVE_ERRNO_MISC,
1712 				    "xml_writer_write_attributef() "
1713 				    "failed: %d", r);
1714 				goto exit_toc;
1715 			}
1716 			continue;
1717 		}
1718 		while (np != np->parent) {
1719 			r = xml_writer_end_element(writer);
1720 			if (r < 0) {
1721 				archive_set_error(&a->archive,
1722 				    ARCHIVE_ERRNO_MISC,
1723 				    "xml_writer_end_element() "
1724 				    "failed: %d", r);
1725 				goto exit_toc;
1726 			}
1727 			if (np->chnext == NULL) {
1728 				/* Return to the parent directory. */
1729 				np = np->parent;
1730 			} else {
1731 				np = np->chnext;
1732 				r = xml_writer_start_element(writer,
1733 				    "file");
1734 				if (r < 0) {
1735 					archive_set_error(&a->archive,
1736 					    ARCHIVE_ERRNO_MISC,
1737 					    "xml_writer_start_element() "
1738 					    "failed: %d", r);
1739 					goto exit_toc;
1740 				}
1741 				r = xml_writer_write_attributef(
1742 				    writer, "id", "%d", np->id);
1743 				if (r < 0) {
1744 					archive_set_error(&a->archive,
1745 					    ARCHIVE_ERRNO_MISC,
1746 					    "xml_writer_write_attributef() "
1747 					    "failed: %d", r);
1748 					goto exit_toc;
1749 				}
1750 				break;
1751 			}
1752 		}
1753 	} while (np != np->parent);
1754 
1755 	r = xml_writer_end_document(writer);
1756 	if (r < 0) {
1757 		archive_set_error(&a->archive,
1758 		    ARCHIVE_ERRNO_MISC,
1759 		    "xml_writer_end_document() failed: %d", r);
1760 		goto exit_toc;
1761 	}
1762 
1763 	r = xml_writer_get_final_content_and_length(writer, &content, &use);
1764 	if (r < 0) {
1765 		archive_set_error(&a->archive,
1766 		    ARCHIVE_ERRNO_MISC,
1767 		    "xml_writer_get_final_content_and_length() failed: %d", r);
1768 		goto exit_toc;
1769 	}
1770 
1771 #if DEBUG_PRINT_TOC
1772 	fprintf(stderr, "\n---TOC-- %d bytes --\n%s\n",
1773 	    (int)strlen(content), content);
1774 #endif
1775 
1776 	/*
1777 	 * Compress the TOC and calculate the sum of the TOC.
1778 	 */
1779 	xar->toc.temp_offset = xar->temp_offset;
1780 	xar->toc.size = (uint64_t)use;
1781 	checksum_init(&(xar->a_sumwrk), xar->opt_toc_sumalg);
1782 
1783 	r = compression_init_encoder_gzip(&(a->archive),
1784 	    &(xar->stream), 6, 1);
1785 	if (r != ARCHIVE_OK)
1786 		goto exit_toc;
1787 	xar->stream.next_in = (const unsigned char *)content;
1788 	xar->stream.avail_in = use;
1789 	xar->stream.total_in = 0;
1790 	xar->stream.next_out = xar->wbuff;
1791 	xar->stream.avail_out = sizeof(xar->wbuff);
1792 	xar->stream.total_out = 0;
1793 	for (;;) {
1794 		size_t size;
1795 
1796 		r = compression_code(&(a->archive),
1797 		    &(xar->stream), ARCHIVE_Z_FINISH);
1798 		if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
1799 			goto exit_toc;
1800 		size = sizeof(xar->wbuff) - xar->stream.avail_out;
1801 		checksum_update(&(xar->a_sumwrk), xar->wbuff, size);
1802 		if (write_to_temp(a, xar->wbuff, size) != ARCHIVE_OK)
1803 			goto exit_toc;
1804 		if (r == ARCHIVE_EOF)
1805 			break;
1806 		xar->stream.next_out = xar->wbuff;
1807 		xar->stream.avail_out = sizeof(xar->wbuff);
1808 	}
1809 	r = compression_end(&(a->archive), &(xar->stream));
1810 	if (r != ARCHIVE_OK)
1811 		goto exit_toc;
1812 	xar->toc.length = xar->stream.total_out;
1813 	xar->toc.compression = GZIP;
1814 	checksum_final(&(xar->a_sumwrk), &(xar->toc.a_sum));
1815 
1816 	ret = ARCHIVE_OK;
1817 exit_toc:
1818 	if (writer)
1819 		xml_writer_destroy(writer);
1820 
1821 	return (ret);
1822 }
1823 
1824 static int
flush_wbuff(struct archive_write * a)1825 flush_wbuff(struct archive_write *a)
1826 {
1827 	struct xar *xar;
1828 	int r;
1829 	size_t s;
1830 
1831 	xar = (struct xar *)a->format_data;
1832 	s = sizeof(xar->wbuff) - xar->wbuff_remaining;
1833 	r = __archive_write_output(a, xar->wbuff, s);
1834 	if (r != ARCHIVE_OK)
1835 		return (r);
1836 	xar->wbuff_remaining = sizeof(xar->wbuff);
1837 	return (r);
1838 }
1839 
1840 static int
copy_out(struct archive_write * a,uint64_t offset,uint64_t length)1841 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
1842 {
1843 	struct xar *xar;
1844 	int r;
1845 
1846 	xar = (struct xar *)a->format_data;
1847 	if (lseek(xar->temp_fd, offset, SEEK_SET) < 0) {
1848 		archive_set_error(&(a->archive), errno, "lseek failed");
1849 		return (ARCHIVE_FATAL);
1850 	}
1851 	while (length) {
1852 		size_t rsize;
1853 		ssize_t rs;
1854 		unsigned char *wb;
1855 
1856 		if (length > xar->wbuff_remaining)
1857 			rsize = xar->wbuff_remaining;
1858 		else
1859 			rsize = (size_t)length;
1860 		wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1861 		rs = read(xar->temp_fd, wb, rsize);
1862 		if (rs < 0) {
1863 			archive_set_error(&(a->archive), errno,
1864 			    "Can't read temporary file(%jd)",
1865 			    (intmax_t)rs);
1866 			return (ARCHIVE_FATAL);
1867 		}
1868 		if (rs == 0) {
1869 			archive_set_error(&(a->archive), 0,
1870 			    "Truncated xar archive");
1871 			return (ARCHIVE_FATAL);
1872 		}
1873 		xar->wbuff_remaining -= rs;
1874 		length -= rs;
1875 		if (xar->wbuff_remaining == 0) {
1876 			r = flush_wbuff(a);
1877 			if (r != ARCHIVE_OK)
1878 				return (r);
1879 		}
1880 	}
1881 	return (ARCHIVE_OK);
1882 }
1883 
1884 static int
xar_close(struct archive_write * a)1885 xar_close(struct archive_write *a)
1886 {
1887 	struct xar *xar;
1888 	unsigned char *wb;
1889 	uint64_t length;
1890 	int r;
1891 
1892 	xar = (struct xar *)a->format_data;
1893 
1894 	/* Empty! */
1895 	if (xar->root->children.first == NULL)
1896 		return (ARCHIVE_OK);
1897 
1898 	/* Save the length of all file extended attributes and contents. */
1899 	length = xar->temp_offset;
1900 
1901 	/* Connect hardlinked files */
1902 	file_connect_hardlink_files(xar);
1903 
1904 	/* Make the TOC */
1905 	r = make_toc(a);
1906 	if (r != ARCHIVE_OK)
1907 		return (r);
1908 	/*
1909 	 * Make the xar header on wbuff(write buffer).
1910 	 */
1911 	wb = xar->wbuff;
1912 	xar->wbuff_remaining = sizeof(xar->wbuff);
1913 	archive_be32enc(&wb[0], HEADER_MAGIC);
1914 	archive_be16enc(&wb[4], HEADER_SIZE);
1915 	archive_be16enc(&wb[6], HEADER_VERSION);
1916 	archive_be64enc(&wb[8], xar->toc.length);
1917 	archive_be64enc(&wb[16], xar->toc.size);
1918 	archive_be32enc(&wb[24], xar->toc.a_sum.alg);
1919 	xar->wbuff_remaining -= HEADER_SIZE;
1920 
1921 	/*
1922 	 * Write the TOC
1923 	 */
1924 	r = copy_out(a, xar->toc.temp_offset, xar->toc.length);
1925 	if (r != ARCHIVE_OK)
1926 		return (r);
1927 
1928 	/* Write the checksum value of the TOC. */
1929 	if (xar->toc.a_sum.len) {
1930 		if (xar->wbuff_remaining < xar->toc.a_sum.len) {
1931 			r = flush_wbuff(a);
1932 			if (r != ARCHIVE_OK)
1933 				return (r);
1934 		}
1935 		wb = xar->wbuff + (sizeof(xar->wbuff) - xar->wbuff_remaining);
1936 		memcpy(wb, xar->toc.a_sum.val, xar->toc.a_sum.len);
1937 		xar->wbuff_remaining -= xar->toc.a_sum.len;
1938 	}
1939 
1940 	/*
1941 	 * Write all file extended attributes and contents.
1942 	 */
1943 	r = copy_out(a, xar->toc.a_sum.len, length);
1944 	if (r != ARCHIVE_OK)
1945 		return (r);
1946 	r = flush_wbuff(a);
1947 	return (r);
1948 }
1949 
1950 static int
xar_free(struct archive_write * a)1951 xar_free(struct archive_write *a)
1952 {
1953 	struct xar *xar;
1954 
1955 	xar = (struct xar *)a->format_data;
1956 
1957 	/* Close the temporary file. */
1958 	if (xar->temp_fd >= 0)
1959 		close(xar->temp_fd);
1960 
1961 	archive_string_free(&(xar->cur_dirstr));
1962 	archive_string_free(&(xar->tstr));
1963 	archive_string_free(&(xar->vstr));
1964 	file_free_hardlinks(xar);
1965 	file_free_register(xar);
1966 	compression_end(&(a->archive), &(xar->stream));
1967 	free(xar);
1968 
1969 	return (ARCHIVE_OK);
1970 }
1971 
1972 static int
file_cmp_node(const struct archive_rb_node * n1,const struct archive_rb_node * n2)1973 file_cmp_node(const struct archive_rb_node *n1,
1974     const struct archive_rb_node *n2)
1975 {
1976 	const struct file *f1 = (const struct file *)n1;
1977 	const struct file *f2 = (const struct file *)n2;
1978 
1979 	return (strcmp(f1->basename.s, f2->basename.s));
1980 }
1981 
1982 static int
file_cmp_key(const struct archive_rb_node * n,const void * key)1983 file_cmp_key(const struct archive_rb_node *n, const void *key)
1984 {
1985 	const struct file *f = (const struct file *)n;
1986 
1987 	return (strcmp(f->basename.s, (const char *)key));
1988 }
1989 
1990 static struct file *
file_new(struct archive_write * a,struct archive_entry * entry)1991 file_new(struct archive_write *a, struct archive_entry *entry)
1992 {
1993 	struct file *file;
1994 	static const struct archive_rb_tree_ops rb_ops = {
1995 		file_cmp_node, file_cmp_key
1996 	};
1997 
1998 	file = calloc(1, sizeof(*file));
1999 	if (file == NULL)
2000 		return (NULL);
2001 
2002 	if (entry != NULL)
2003 		file->entry = archive_entry_clone(entry);
2004 	else
2005 		file->entry = archive_entry_new2(&a->archive);
2006 	if (file->entry == NULL) {
2007 		free(file);
2008 		return (NULL);
2009 	}
2010 	__archive_rb_tree_init(&(file->rbtree), &rb_ops);
2011 	file->children.first = NULL;
2012 	file->children.last = &(file->children.first);
2013 	file->xattr.first = NULL;
2014 	file->xattr.last = &(file->xattr.first);
2015 	archive_string_init(&(file->parentdir));
2016 	archive_string_init(&(file->basename));
2017 	archive_string_init(&(file->symlink));
2018 	archive_string_init(&(file->script));
2019 	if (entry != NULL && archive_entry_filetype(entry) == AE_IFDIR)
2020 		file->dir = 1;
2021 
2022 	return (file);
2023 }
2024 
2025 static void
file_free(struct file * file)2026 file_free(struct file *file)
2027 {
2028 	struct heap_data *heap, *next_heap;
2029 
2030 	heap = file->xattr.first;
2031 	while (heap != NULL) {
2032 		next_heap = heap->next;
2033 		free(heap);
2034 		heap = next_heap;
2035 	}
2036 	archive_string_free(&(file->parentdir));
2037 	archive_string_free(&(file->basename));
2038 	archive_string_free(&(file->symlink));
2039 	archive_string_free(&(file->script));
2040 	archive_entry_free(file->entry);
2041 	free(file);
2042 }
2043 
2044 static struct file *
file_create_virtual_dir(struct archive_write * a,struct xar * xar,const char * pathname)2045 file_create_virtual_dir(struct archive_write *a, struct xar *xar,
2046     const char *pathname)
2047 {
2048 	struct file *file;
2049 
2050 	(void)xar; /* UNUSED */
2051 
2052 	file = file_new(a, NULL);
2053 	if (file == NULL)
2054 		return (NULL);
2055 	archive_entry_set_pathname(file->entry, pathname);
2056 	archive_entry_set_mode(file->entry, 0555 | AE_IFDIR);
2057 
2058 	file->dir = 1;
2059 	file->virtual = 1;
2060 
2061 	return (file);
2062 }
2063 
2064 static int
file_add_child_tail(struct file * parent,struct file * child)2065 file_add_child_tail(struct file *parent, struct file *child)
2066 {
2067 	if (!__archive_rb_tree_insert_node(
2068 	    &(parent->rbtree), (struct archive_rb_node *)child))
2069 		return (0);
2070 	child->chnext = NULL;
2071 	*parent->children.last = child;
2072 	parent->children.last = &(child->chnext);
2073 	child->parent = parent;
2074 	return (1);
2075 }
2076 
2077 /*
2078  * Find a entry from `parent'
2079  */
2080 static struct file *
file_find_child(struct file * parent,const char * child_name)2081 file_find_child(struct file *parent, const char *child_name)
2082 {
2083 	struct file *np;
2084 
2085 	np = (struct file *)__archive_rb_tree_find_node(
2086 	    &(parent->rbtree), child_name);
2087 	return (np);
2088 }
2089 
2090 #if defined(_WIN32) || defined(__CYGWIN__)
2091 static void
cleanup_backslash(char * utf8,size_t len)2092 cleanup_backslash(char *utf8, size_t len)
2093 {
2094 
2095 	/* Convert a path-separator from '\' to  '/' */
2096 	while (*utf8 != '\0' && len) {
2097 		if (*utf8 == '\\')
2098 			*utf8 = '/';
2099 		++utf8;
2100 		--len;
2101 	}
2102 }
2103 #else
2104 #define cleanup_backslash(p, len)	/* nop */
2105 #endif
2106 
2107 /*
2108  * Generate a parent directory name and a base name from a pathname.
2109  */
2110 static int
file_gen_utility_names(struct archive_write * a,struct file * file)2111 file_gen_utility_names(struct archive_write *a, struct file *file)
2112 {
2113 	struct xar *xar;
2114 	const char *pp;
2115 	char *p, *dirname, *slash;
2116 	size_t len;
2117 	int r = ARCHIVE_OK;
2118 
2119 	xar = (struct xar *)a->format_data;
2120 	archive_string_empty(&(file->parentdir));
2121 	archive_string_empty(&(file->basename));
2122 	archive_string_empty(&(file->symlink));
2123 
2124 	if (file->parent == file)/* virtual root */
2125 		return (ARCHIVE_OK);
2126 
2127 	if (archive_entry_pathname_l(file->entry, &pp, &len, xar->sconv)
2128 	    != 0) {
2129 		if (errno == ENOMEM) {
2130 			archive_set_error(&a->archive, ENOMEM,
2131 			    "Can't allocate memory for Pathname");
2132 			return (ARCHIVE_FATAL);
2133 		}
2134 		archive_set_error(&a->archive,
2135 		    ARCHIVE_ERRNO_FILE_FORMAT,
2136 		    "Can't translate pathname '%s' to UTF-8",
2137 		    archive_entry_pathname(file->entry));
2138 		r = ARCHIVE_WARN;
2139 	}
2140 	archive_strncpy(&(file->parentdir), pp, len);
2141 	len = file->parentdir.length;
2142 	p = dirname = file->parentdir.s;
2143 	/*
2144 	 * Convert a path-separator from '\' to  '/'
2145 	 */
2146 	cleanup_backslash(p, len);
2147 
2148 	/*
2149 	 * Remove leading '/', '../' and './' elements
2150 	 */
2151 	while (*p) {
2152 		if (p[0] == '/') {
2153 			p++;
2154 			len--;
2155 		} else if (p[0] != '.')
2156 			break;
2157 		else if (p[1] == '.' && p[2] == '/') {
2158 			p += 3;
2159 			len -= 3;
2160 		} else if (p[1] == '/' || (p[1] == '.' && p[2] == '\0')) {
2161 			p += 2;
2162 			len -= 2;
2163 		} else if (p[1] == '\0') {
2164 			p++;
2165 			len--;
2166 		} else
2167 			break;
2168 	}
2169 	if (p != dirname) {
2170 		memmove(dirname, p, len+1);
2171 		p = dirname;
2172 	}
2173 	/*
2174 	 * Remove "/","/." and "/.." elements from tail.
2175 	 */
2176 	while (len > 0) {
2177 		size_t ll = len;
2178 
2179 		if (p[len-1] == '/') {
2180 			p[len-1] = '\0';
2181 			len--;
2182 		}
2183 		if (len > 1 && p[len-2] == '/' && p[len-1] == '.') {
2184 			p[len-2] = '\0';
2185 			len -= 2;
2186 		}
2187 		if (len > 2 && p[len-3] == '/' && p[len-2] == '.' &&
2188 		    p[len-1] == '.') {
2189 			p[len-3] = '\0';
2190 			len -= 3;
2191 		}
2192 		if (ll == len)
2193 			break;
2194 	}
2195 	while (*p) {
2196 		if (p[0] == '/') {
2197 			if (p[1] == '/')
2198 				/* Convert '//' --> '/' */
2199 				memmove(p, p+1, strlen(p+1) + 1);
2200 			else if (p[1] == '.' && p[2] == '/')
2201 				/* Convert '/./' --> '/' */
2202 				memmove(p, p+2, strlen(p+2) + 1);
2203 			else if (p[1] == '.' && p[2] == '.' && p[3] == '/') {
2204 				/* Convert 'dir/dir1/../dir2/'
2205 				 *     --> 'dir/dir2/'
2206 				 */
2207 				char *rp = p -1;
2208 				while (rp >= dirname) {
2209 					if (*rp == '/')
2210 						break;
2211 					--rp;
2212 				}
2213 				if (rp > dirname) {
2214 					strcpy(rp, p+3);
2215 					p = rp;
2216 				} else {
2217 					strcpy(dirname, p+4);
2218 					p = dirname;
2219 				}
2220 			} else
2221 				p++;
2222 		} else
2223 			p++;
2224 	}
2225 	p = dirname;
2226 	len = strlen(p);
2227 
2228 	if (archive_entry_filetype(file->entry) == AE_IFLNK) {
2229 		size_t len2;
2230 		/* Convert symlink name too. */
2231 		if (archive_entry_symlink_l(file->entry, &pp, &len2,
2232 		    xar->sconv) != 0) {
2233 			if (errno == ENOMEM) {
2234 				archive_set_error(&a->archive, ENOMEM,
2235 				    "Can't allocate memory for Linkname");
2236 				return (ARCHIVE_FATAL);
2237 			}
2238 			archive_set_error(&a->archive,
2239 			    ARCHIVE_ERRNO_FILE_FORMAT,
2240 			    "Can't translate symlink '%s' to UTF-8",
2241 			    archive_entry_symlink(file->entry));
2242 			r = ARCHIVE_WARN;
2243 		}
2244 		archive_strncpy(&(file->symlink), pp, len2);
2245 		cleanup_backslash(file->symlink.s, file->symlink.length);
2246 	}
2247 	/*
2248 	 * - Count up directory elements.
2249 	 * - Find out the position which points the last position of
2250 	 *   path separator('/').
2251 	 */
2252 	slash = NULL;
2253 	for (; *p != '\0'; p++)
2254 		if (*p == '/')
2255 			slash = p;
2256 	if (slash == NULL) {
2257 		/* The pathname doesn't have a parent directory. */
2258 		file->parentdir.length = len;
2259 		archive_string_copy(&(file->basename), &(file->parentdir));
2260 		archive_string_empty(&(file->parentdir));
2261 		*file->parentdir.s = '\0';
2262 		return (r);
2263 	}
2264 
2265 	/* Make a basename from dirname and slash */
2266 	*slash  = '\0';
2267 	file->parentdir.length = slash - dirname;
2268 	archive_strcpy(&(file->basename),  slash + 1);
2269 	return (r);
2270 }
2271 
2272 static int
get_path_component(char * name,int n,const char * fn)2273 get_path_component(char *name, int n, const char *fn)
2274 {
2275 	char *p;
2276 	int l;
2277 
2278 	p = strchr(fn, '/');
2279 	if (p == NULL) {
2280 		if ((l = (int)strlen(fn)) == 0)
2281 			return (0);
2282 	} else
2283 		l = (int)(p - fn);
2284 	if (l > n -1)
2285 		return (-1);
2286 	memcpy(name, fn, l);
2287 	name[l] = '\0';
2288 
2289 	return (l);
2290 }
2291 
2292 /*
2293  * Add a new entry into the tree.
2294  */
2295 static int
file_tree(struct archive_write * a,struct file ** filepp)2296 file_tree(struct archive_write *a, struct file **filepp)
2297 {
2298 #if defined(_WIN32) && !defined(__CYGWIN__)
2299 	char name[_MAX_FNAME];/* Included null terminator size. */
2300 #elif defined(NAME_MAX) && NAME_MAX >= 255
2301 	char name[NAME_MAX+1];
2302 #else
2303 	char name[256];
2304 #endif
2305 	struct xar *xar = (struct xar *)a->format_data;
2306 	struct file *dent, *file, *np;
2307 	struct archive_entry *ent;
2308 	const char *fn, *p;
2309 	int l;
2310 
2311 	file = *filepp;
2312 	dent = xar->root;
2313 	if (file->parentdir.length > 0)
2314 		fn = p = file->parentdir.s;
2315 	else
2316 		fn = p = "";
2317 
2318 	/*
2319 	 * If the path of the parent directory of `file' entry is
2320 	 * the same as the path of `cur_dirent', add isoent to
2321 	 * `cur_dirent'.
2322 	 */
2323 	if (archive_strlen(&(xar->cur_dirstr))
2324 	      == archive_strlen(&(file->parentdir)) &&
2325 	    strcmp(xar->cur_dirstr.s, fn) == 0) {
2326 		if (!file_add_child_tail(xar->cur_dirent, file)) {
2327 			np = (struct file *)__archive_rb_tree_find_node(
2328 			    &(xar->cur_dirent->rbtree),
2329 			    file->basename.s);
2330 			goto same_entry;
2331 		}
2332 		return (ARCHIVE_OK);
2333 	}
2334 
2335 	for (;;) {
2336 		l = get_path_component(name, sizeof(name), fn);
2337 		if (l == 0) {
2338 			np = NULL;
2339 			break;
2340 		}
2341 		if (l < 0) {
2342 			archive_set_error(&a->archive,
2343 			    ARCHIVE_ERRNO_MISC,
2344 			    "A name buffer is too small");
2345 			file_free(file);
2346 			*filepp = NULL;
2347 			return (ARCHIVE_FATAL);
2348 		}
2349 
2350 		np = file_find_child(dent, name);
2351 		if (np == NULL || fn[0] == '\0')
2352 			break;
2353 
2354 		/* Find next subdirectory. */
2355 		if (!np->dir) {
2356 			/* NOT Directory! */
2357 			archive_set_error(&a->archive,
2358 			    ARCHIVE_ERRNO_MISC,
2359 			    "`%s' is not directory, we cannot insert `%s' ",
2360 			    archive_entry_pathname(np->entry),
2361 			    archive_entry_pathname(file->entry));
2362 			file_free(file);
2363 			*filepp = NULL;
2364 			return (ARCHIVE_FAILED);
2365 		}
2366 		fn += l;
2367 		if (fn[0] == '/')
2368 			fn++;
2369 		dent = np;
2370 	}
2371 	if (np == NULL) {
2372 		/*
2373 		 * Create virtual parent directories.
2374 		 */
2375 		while (fn[0] != '\0') {
2376 			struct file *vp;
2377 			struct archive_string as;
2378 
2379 			archive_string_init(&as);
2380 			archive_strncat(&as, p, fn - p + l);
2381 			if (as.s[as.length-1] == '/') {
2382 				as.s[as.length-1] = '\0';
2383 				as.length--;
2384 			}
2385 			vp = file_create_virtual_dir(a, xar, as.s);
2386 			if (vp == NULL) {
2387 				archive_string_free(&as);
2388 				archive_set_error(&a->archive, ENOMEM,
2389 				    "Can't allocate memory");
2390 				file_free(file);
2391 				*filepp = NULL;
2392 				return (ARCHIVE_FATAL);
2393 			}
2394 			archive_string_free(&as);
2395 			if (file_gen_utility_names(a, vp) <= ARCHIVE_FAILED)
2396 				return (ARCHIVE_FATAL);
2397 			file_add_child_tail(dent, vp);
2398 			file_register(xar, vp);
2399 			np = vp;
2400 
2401 			fn += l;
2402 			if (fn[0] == '/')
2403 				fn++;
2404 			l = get_path_component(name, sizeof(name), fn);
2405 			if (l < 0) {
2406 				archive_string_free(&as);
2407 				archive_set_error(&a->archive,
2408 				    ARCHIVE_ERRNO_MISC,
2409 				    "A name buffer is too small");
2410 				file_free(file);
2411 				*filepp = NULL;
2412 				return (ARCHIVE_FATAL);
2413 			}
2414 			dent = np;
2415 		}
2416 
2417 		/* Found out the parent directory where isoent can be
2418 		 * inserted. */
2419 		xar->cur_dirent = dent;
2420 		archive_string_empty(&(xar->cur_dirstr));
2421 		archive_string_ensure(&(xar->cur_dirstr),
2422 		    archive_strlen(&(dent->parentdir)) +
2423 		    archive_strlen(&(dent->basename)) + 2);
2424 		if (archive_strlen(&(dent->parentdir)) +
2425 		    archive_strlen(&(dent->basename)) == 0)
2426 			xar->cur_dirstr.s[0] = 0;
2427 		else {
2428 			if (archive_strlen(&(dent->parentdir)) > 0) {
2429 				archive_string_copy(&(xar->cur_dirstr),
2430 				    &(dent->parentdir));
2431 				archive_strappend_char(&(xar->cur_dirstr), '/');
2432 			}
2433 			archive_string_concat(&(xar->cur_dirstr),
2434 			    &(dent->basename));
2435 		}
2436 
2437 		if (!file_add_child_tail(dent, file)) {
2438 			np = (struct file *)__archive_rb_tree_find_node(
2439 			    &(dent->rbtree), file->basename.s);
2440 			goto same_entry;
2441 		}
2442 		return (ARCHIVE_OK);
2443 	}
2444 
2445 same_entry:
2446 	/*
2447 	 * We have already has the entry the filename of which is
2448 	 * the same.
2449 	 */
2450 	if (archive_entry_filetype(np->entry) !=
2451 	    archive_entry_filetype(file->entry)) {
2452 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2453 		    "Found duplicate entries `%s' and its file type is "
2454 		    "different",
2455 		    archive_entry_pathname(np->entry));
2456 		file_free(file);
2457 		*filepp = NULL;
2458 		return (ARCHIVE_FAILED);
2459 	}
2460 
2461 	/* Swap files. */
2462 	ent = np->entry;
2463 	np->entry = file->entry;
2464 	file->entry = ent;
2465 	np->virtual = 0;
2466 
2467 	file_free(file);
2468 	*filepp = np;
2469 	return (ARCHIVE_OK);
2470 }
2471 
2472 static void
file_register(struct xar * xar,struct file * file)2473 file_register(struct xar *xar, struct file *file)
2474 {
2475 	file->id = xar->file_idx++;
2476         file->next = NULL;
2477         *xar->file_list.last = file;
2478         xar->file_list.last = &(file->next);
2479 }
2480 
2481 static void
file_init_register(struct xar * xar)2482 file_init_register(struct xar *xar)
2483 {
2484 	xar->file_list.first = NULL;
2485 	xar->file_list.last = &(xar->file_list.first);
2486 }
2487 
2488 static void
file_free_register(struct xar * xar)2489 file_free_register(struct xar *xar)
2490 {
2491 	struct file *file, *file_next;
2492 
2493 	file = xar->file_list.first;
2494 	while (file != NULL) {
2495 		file_next = file->next;
2496 		file_free(file);
2497 		file = file_next;
2498 	}
2499 }
2500 
2501 /*
2502  * Register entry to get a hardlink target.
2503  */
2504 static int
file_register_hardlink(struct archive_write * a,struct file * file)2505 file_register_hardlink(struct archive_write *a, struct file *file)
2506 {
2507 	struct xar *xar = (struct xar *)a->format_data;
2508 	struct hardlink *hl;
2509 	const char *pathname;
2510 
2511 	archive_entry_set_nlink(file->entry, 1);
2512 	pathname = archive_entry_hardlink(file->entry);
2513 	if (pathname == NULL) {
2514 		/* This `file` is a hardlink target. */
2515 		hl = malloc(sizeof(*hl));
2516 		if (hl == NULL) {
2517 			archive_set_error(&a->archive, ENOMEM,
2518 			    "Can't allocate memory");
2519 			return (ARCHIVE_FATAL);
2520 		}
2521 		hl->nlink = 1;
2522 		/* A hardlink target must be the first position. */
2523 		file->hlnext = NULL;
2524 		hl->file_list.first = file;
2525 		hl->file_list.last = &(file->hlnext);
2526 		__archive_rb_tree_insert_node(&(xar->hardlink_rbtree),
2527 		    (struct archive_rb_node *)hl);
2528 	} else {
2529 		hl = (struct hardlink *)__archive_rb_tree_find_node(
2530 		    &(xar->hardlink_rbtree), pathname);
2531 		if (hl != NULL) {
2532 			/* Insert `file` entry into the tail. */
2533 			file->hlnext = NULL;
2534 			*hl->file_list.last = file;
2535 			hl->file_list.last = &(file->hlnext);
2536 			hl->nlink++;
2537 		}
2538 		archive_entry_unset_size(file->entry);
2539 	}
2540 
2541 	return (ARCHIVE_OK);
2542 }
2543 
2544 /*
2545  * Hardlinked files have to have the same location of extent.
2546  * We have to find out hardlink target entries for entries which
2547  * have a hardlink target name.
2548  */
2549 static void
file_connect_hardlink_files(struct xar * xar)2550 file_connect_hardlink_files(struct xar *xar)
2551 {
2552 	struct archive_rb_node *n;
2553 	struct hardlink *hl;
2554 	struct file *target, *nf;
2555 
2556 	ARCHIVE_RB_TREE_FOREACH(n, &(xar->hardlink_rbtree)) {
2557 		hl = (struct hardlink *)n;
2558 
2559 		/* The first entry must be a hardlink target. */
2560 		target = hl->file_list.first;
2561 		archive_entry_set_nlink(target->entry, hl->nlink);
2562 		if (hl->nlink > 1)
2563 			/* It means this file is a hardlink
2564 			 * target itself. */
2565 			target->hardlink_target = target;
2566 		for (nf = target->hlnext;
2567 		    nf != NULL; nf = nf->hlnext) {
2568 			nf->hardlink_target = target;
2569 			archive_entry_set_nlink(nf->entry, hl->nlink);
2570 		}
2571 	}
2572 }
2573 
2574 static int
file_hd_cmp_node(const struct archive_rb_node * n1,const struct archive_rb_node * n2)2575 file_hd_cmp_node(const struct archive_rb_node *n1,
2576     const struct archive_rb_node *n2)
2577 {
2578 	const struct hardlink *h1 = (const struct hardlink *)n1;
2579 	const struct hardlink *h2 = (const struct hardlink *)n2;
2580 
2581 	return (strcmp(archive_entry_pathname(h1->file_list.first->entry),
2582 		       archive_entry_pathname(h2->file_list.first->entry)));
2583 }
2584 
2585 static int
file_hd_cmp_key(const struct archive_rb_node * n,const void * key)2586 file_hd_cmp_key(const struct archive_rb_node *n, const void *key)
2587 {
2588 	const struct hardlink *h = (const struct hardlink *)n;
2589 
2590 	return (strcmp(archive_entry_pathname(h->file_list.first->entry),
2591 		       (const char *)key));
2592 }
2593 
2594 
2595 static void
file_init_hardlinks(struct xar * xar)2596 file_init_hardlinks(struct xar *xar)
2597 {
2598 	static const struct archive_rb_tree_ops rb_ops = {
2599 		file_hd_cmp_node, file_hd_cmp_key,
2600 	};
2601 
2602 	__archive_rb_tree_init(&(xar->hardlink_rbtree), &rb_ops);
2603 }
2604 
2605 static void
file_free_hardlinks(struct xar * xar)2606 file_free_hardlinks(struct xar *xar)
2607 {
2608 	struct archive_rb_node *n, *tmp;
2609 
2610 	ARCHIVE_RB_TREE_FOREACH_SAFE(n, &(xar->hardlink_rbtree), tmp) {
2611 		__archive_rb_tree_remove_node(&(xar->hardlink_rbtree), n);
2612 		free(n);
2613 	}
2614 }
2615 
2616 static void
checksum_init(struct chksumwork * sumwrk,enum sumalg sum_alg)2617 checksum_init(struct chksumwork *sumwrk, enum sumalg sum_alg)
2618 {
2619 	sumwrk->alg = sum_alg;
2620 	switch (sum_alg) {
2621 	case CKSUM_NONE:
2622 		break;
2623 	case CKSUM_SHA1:
2624 		archive_sha1_init(&(sumwrk->sha1ctx));
2625 		break;
2626 	case CKSUM_MD5:
2627 		archive_md5_init(&(sumwrk->md5ctx));
2628 		break;
2629 	}
2630 }
2631 
2632 static void
checksum_update(struct chksumwork * sumwrk,const void * buff,size_t size)2633 checksum_update(struct chksumwork *sumwrk, const void *buff, size_t size)
2634 {
2635 
2636 	switch (sumwrk->alg) {
2637 	case CKSUM_NONE:
2638 		break;
2639 	case CKSUM_SHA1:
2640 		archive_sha1_update(&(sumwrk->sha1ctx), buff, size);
2641 		break;
2642 	case CKSUM_MD5:
2643 		archive_md5_update(&(sumwrk->md5ctx), buff, size);
2644 		break;
2645 	}
2646 }
2647 
2648 static void
checksum_final(struct chksumwork * sumwrk,struct chksumval * sumval)2649 checksum_final(struct chksumwork *sumwrk, struct chksumval *sumval)
2650 {
2651 
2652 	switch (sumwrk->alg) {
2653 	case CKSUM_NONE:
2654 		sumval->len = 0;
2655 		break;
2656 	case CKSUM_SHA1:
2657 		archive_sha1_final(&(sumwrk->sha1ctx), sumval->val);
2658 		sumval->len = SHA1_SIZE;
2659 		break;
2660 	case CKSUM_MD5:
2661 		archive_md5_final(&(sumwrk->md5ctx), sumval->val);
2662 		sumval->len = MD5_SIZE;
2663 		break;
2664 	}
2665 	sumval->alg = sumwrk->alg;
2666 }
2667 
2668 #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
2669 static int
compression_unsupported_encoder(struct archive * a,struct la_zstream * lastrm,const char * name)2670 compression_unsupported_encoder(struct archive *a,
2671     struct la_zstream *lastrm, const char *name)
2672 {
2673 
2674 	archive_set_error(a, ARCHIVE_ERRNO_MISC,
2675 	    "%s compression not supported on this platform", name);
2676 	lastrm->valid = 0;
2677 	lastrm->real_stream = NULL;
2678 	return (ARCHIVE_FAILED);
2679 }
2680 #endif
2681 
2682 static int
compression_init_encoder_gzip(struct archive * a,struct la_zstream * lastrm,int level,int withheader)2683 compression_init_encoder_gzip(struct archive *a,
2684     struct la_zstream *lastrm, int level, int withheader)
2685 {
2686 	z_stream *strm;
2687 
2688 	if (lastrm->valid)
2689 		compression_end(a, lastrm);
2690 	strm = calloc(1, sizeof(*strm));
2691 	if (strm == NULL) {
2692 		archive_set_error(a, ENOMEM,
2693 		    "Can't allocate memory for gzip stream");
2694 		return (ARCHIVE_FATAL);
2695 	}
2696 	/* zlib.h is not const-correct, so we need this one bit
2697 	 * of ugly hackery to convert a const * pointer to
2698 	 * a non-const pointer. */
2699 	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2700 	strm->avail_in = (uInt)lastrm->avail_in;
2701 	strm->total_in = (uLong)lastrm->total_in;
2702 	strm->next_out = lastrm->next_out;
2703 	strm->avail_out = (uInt)lastrm->avail_out;
2704 	strm->total_out = (uLong)lastrm->total_out;
2705 	if (deflateInit2(strm, level, Z_DEFLATED,
2706 	    (withheader)?15:-15,
2707 	    8, Z_DEFAULT_STRATEGY) != Z_OK) {
2708 		free(strm);
2709 		lastrm->real_stream = NULL;
2710 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
2711 		    "Internal error initializing compression library");
2712 		return (ARCHIVE_FATAL);
2713 	}
2714 	lastrm->real_stream = strm;
2715 	lastrm->valid = 1;
2716 	lastrm->code = compression_code_gzip;
2717 	lastrm->end = compression_end_gzip;
2718 	return (ARCHIVE_OK);
2719 }
2720 
2721 static int
compression_code_gzip(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)2722 compression_code_gzip(struct archive *a,
2723     struct la_zstream *lastrm, enum la_zaction action)
2724 {
2725 	z_stream *strm;
2726 	int r;
2727 
2728 	strm = (z_stream *)lastrm->real_stream;
2729 	/* zlib.h is not const-correct, so we need this one bit
2730 	 * of ugly hackery to convert a const * pointer to
2731 	 * a non-const pointer. */
2732 	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
2733 	strm->avail_in = (uInt)lastrm->avail_in;
2734 	strm->total_in = (uLong)lastrm->total_in;
2735 	strm->next_out = lastrm->next_out;
2736 	strm->avail_out = (uInt)lastrm->avail_out;
2737 	strm->total_out = (uLong)lastrm->total_out;
2738 	r = deflate(strm,
2739 	    (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
2740 	lastrm->next_in = strm->next_in;
2741 	lastrm->avail_in = strm->avail_in;
2742 	lastrm->total_in = strm->total_in;
2743 	lastrm->next_out = strm->next_out;
2744 	lastrm->avail_out = strm->avail_out;
2745 	lastrm->total_out = strm->total_out;
2746 	switch (r) {
2747 	case Z_OK:
2748 		return (ARCHIVE_OK);
2749 	case Z_STREAM_END:
2750 		return (ARCHIVE_EOF);
2751 	default:
2752 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
2753 		    "GZip compression failed:"
2754 		    " deflate() call returned status %d", r);
2755 		return (ARCHIVE_FATAL);
2756 	}
2757 }
2758 
2759 static int
compression_end_gzip(struct archive * a,struct la_zstream * lastrm)2760 compression_end_gzip(struct archive *a, struct la_zstream *lastrm)
2761 {
2762 	z_stream *strm;
2763 	int r;
2764 
2765 	strm = (z_stream *)lastrm->real_stream;
2766 	r = deflateEnd(strm);
2767 	free(strm);
2768 	lastrm->real_stream = NULL;
2769 	lastrm->valid = 0;
2770 	if (r != Z_OK) {
2771 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
2772 		    "Failed to clean up compressor");
2773 		return (ARCHIVE_FATAL);
2774 	}
2775 	return (ARCHIVE_OK);
2776 }
2777 
2778 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
2779 static int
compression_init_encoder_bzip2(struct archive * a,struct la_zstream * lastrm,int level)2780 compression_init_encoder_bzip2(struct archive *a,
2781     struct la_zstream *lastrm, int level)
2782 {
2783 	bz_stream *strm;
2784 
2785 	if (lastrm->valid)
2786 		compression_end(a, lastrm);
2787 	strm = calloc(1, sizeof(*strm));
2788 	if (strm == NULL) {
2789 		archive_set_error(a, ENOMEM,
2790 		    "Can't allocate memory for bzip2 stream");
2791 		return (ARCHIVE_FATAL);
2792 	}
2793 	/* bzlib.h is not const-correct, so we need this one bit
2794 	 * of ugly hackery to convert a const * pointer to
2795 	 * a non-const pointer. */
2796 	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2797 	strm->avail_in = (unsigned int)lastrm->avail_in;
2798 	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2799 	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2800 	strm->next_out = (char *)lastrm->next_out;
2801 	strm->avail_out = (unsigned int)lastrm->avail_out;
2802 	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2803 	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2804 	if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
2805 		free(strm);
2806 		lastrm->real_stream = NULL;
2807 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
2808 		    "Internal error initializing compression library");
2809 		return (ARCHIVE_FATAL);
2810 	}
2811 	lastrm->real_stream = strm;
2812 	lastrm->valid = 1;
2813 	lastrm->code = compression_code_bzip2;
2814 	lastrm->end = compression_end_bzip2;
2815 	return (ARCHIVE_OK);
2816 }
2817 
2818 static int
compression_code_bzip2(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)2819 compression_code_bzip2(struct archive *a,
2820     struct la_zstream *lastrm, enum la_zaction action)
2821 {
2822 	bz_stream *strm;
2823 	int r;
2824 
2825 	strm = (bz_stream *)lastrm->real_stream;
2826 	/* bzlib.h is not const-correct, so we need this one bit
2827 	 * of ugly hackery to convert a const * pointer to
2828 	 * a non-const pointer. */
2829 	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
2830 	strm->avail_in = (unsigned int)lastrm->avail_in;
2831 	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
2832 	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
2833 	strm->next_out = (char *)lastrm->next_out;
2834 	strm->avail_out = (unsigned int)lastrm->avail_out;
2835 	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
2836 	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
2837 	r = BZ2_bzCompress(strm,
2838 	    (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
2839 	lastrm->next_in = (const unsigned char *)strm->next_in;
2840 	lastrm->avail_in = strm->avail_in;
2841 	lastrm->total_in =
2842 	    (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
2843 	    + (uint64_t)(uint32_t)strm->total_in_lo32;
2844 	lastrm->next_out = (unsigned char *)strm->next_out;
2845 	lastrm->avail_out = strm->avail_out;
2846 	lastrm->total_out =
2847 	    (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
2848 	    + (uint64_t)(uint32_t)strm->total_out_lo32;
2849 	switch (r) {
2850 	case BZ_RUN_OK:     /* Non-finishing */
2851 	case BZ_FINISH_OK:  /* Finishing: There's more work to do */
2852 		return (ARCHIVE_OK);
2853 	case BZ_STREAM_END: /* Finishing: all done */
2854 		/* Only occurs in finishing case */
2855 		return (ARCHIVE_EOF);
2856 	default:
2857 		/* Any other return value indicates an error */
2858 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
2859 		    "Bzip2 compression failed:"
2860 		    " BZ2_bzCompress() call returned status %d", r);
2861 		return (ARCHIVE_FATAL);
2862 	}
2863 }
2864 
2865 static int
compression_end_bzip2(struct archive * a,struct la_zstream * lastrm)2866 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
2867 {
2868 	bz_stream *strm;
2869 	int r;
2870 
2871 	strm = (bz_stream *)lastrm->real_stream;
2872 	r = BZ2_bzCompressEnd(strm);
2873 	free(strm);
2874 	lastrm->real_stream = NULL;
2875 	lastrm->valid = 0;
2876 	if (r != BZ_OK) {
2877 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
2878 		    "Failed to clean up compressor");
2879 		return (ARCHIVE_FATAL);
2880 	}
2881 	return (ARCHIVE_OK);
2882 }
2883 
2884 #else
2885 static int
compression_init_encoder_bzip2(struct archive * a,struct la_zstream * lastrm,int level)2886 compression_init_encoder_bzip2(struct archive *a,
2887     struct la_zstream *lastrm, int level)
2888 {
2889 
2890 	(void) level; /* UNUSED */
2891 	if (lastrm->valid)
2892 		compression_end(a, lastrm);
2893 	return (compression_unsupported_encoder(a, lastrm, "bzip2"));
2894 }
2895 #endif
2896 
2897 #if defined(HAVE_LZMA_H)
2898 static int
compression_init_encoder_lzma(struct archive * a,struct la_zstream * lastrm,int level)2899 compression_init_encoder_lzma(struct archive *a,
2900     struct la_zstream *lastrm, int level)
2901 {
2902 	static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2903 	lzma_stream *strm;
2904 	lzma_options_lzma lzma_opt;
2905 	int r;
2906 
2907 	if (lastrm->valid)
2908 		compression_end(a, lastrm);
2909 	if (lzma_lzma_preset(&lzma_opt, level)) {
2910 		lastrm->real_stream = NULL;
2911 		archive_set_error(a, ENOMEM,
2912 		    "Internal error initializing compression library");
2913 		return (ARCHIVE_FATAL);
2914 	}
2915 	strm = calloc(1, sizeof(*strm));
2916 	if (strm == NULL) {
2917 		archive_set_error(a, ENOMEM,
2918 		    "Can't allocate memory for lzma stream");
2919 		return (ARCHIVE_FATAL);
2920 	}
2921 	*strm = lzma_init_data;
2922 	r = lzma_alone_encoder(strm, &lzma_opt);
2923 	switch (r) {
2924 	case LZMA_OK:
2925 		lastrm->real_stream = strm;
2926 		lastrm->valid = 1;
2927 		lastrm->code = compression_code_lzma;
2928 		lastrm->end = compression_end_lzma;
2929 		r = ARCHIVE_OK;
2930 		break;
2931 	case LZMA_MEM_ERROR:
2932 		free(strm);
2933 		lastrm->real_stream = NULL;
2934 		archive_set_error(a, ENOMEM,
2935 		    "Internal error initializing compression library: "
2936 		    "Cannot allocate memory");
2937 		r =  ARCHIVE_FATAL;
2938 		break;
2939         default:
2940 		free(strm);
2941 		lastrm->real_stream = NULL;
2942 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
2943 		    "Internal error initializing compression library: "
2944 		    "It's a bug in liblzma");
2945 		r =  ARCHIVE_FATAL;
2946 		break;
2947 	}
2948 	return (r);
2949 }
2950 
2951 static int
compression_init_encoder_xz(struct archive * a,struct la_zstream * lastrm,int level,int threads)2952 compression_init_encoder_xz(struct archive *a,
2953     struct la_zstream *lastrm, int level, int threads)
2954 {
2955 	static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
2956 	lzma_stream *strm;
2957 	lzma_filter *lzmafilters;
2958 	lzma_options_lzma lzma_opt;
2959 	int r;
2960 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
2961 	lzma_mt mt_options;
2962 #endif
2963 
2964 	(void)threads; /* UNUSED (if multi-threaded LZMA library not avail) */
2965 
2966 	if (lastrm->valid)
2967 		compression_end(a, lastrm);
2968 	strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
2969 	if (strm == NULL) {
2970 		archive_set_error(a, ENOMEM,
2971 		    "Can't allocate memory for xz stream");
2972 		return (ARCHIVE_FATAL);
2973 	}
2974 	lzmafilters = (lzma_filter *)(strm+1);
2975 	if (level > 9)
2976 		level = 9;
2977 	if (lzma_lzma_preset(&lzma_opt, level)) {
2978 		free(strm);
2979 		lastrm->real_stream = NULL;
2980 		archive_set_error(a, ENOMEM,
2981 		    "Internal error initializing compression library");
2982 		return (ARCHIVE_FATAL);
2983 	}
2984 	lzmafilters[0].id = LZMA_FILTER_LZMA2;
2985 	lzmafilters[0].options = &lzma_opt;
2986 	lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
2987 
2988 	*strm = lzma_init_data;
2989 #ifdef HAVE_LZMA_STREAM_ENCODER_MT
2990 	if (threads > 1) {
2991 		memset(&mt_options, 0, sizeof(mt_options));
2992 		mt_options.threads = threads;
2993 		mt_options.timeout = 300;
2994 		mt_options.filters = lzmafilters;
2995 		mt_options.check = LZMA_CHECK_CRC64;
2996 		r = lzma_stream_encoder_mt(strm, &mt_options);
2997 	} else
2998 #endif
2999 		r = lzma_stream_encoder(strm, lzmafilters, LZMA_CHECK_CRC64);
3000 	switch (r) {
3001 	case LZMA_OK:
3002 		lastrm->real_stream = strm;
3003 		lastrm->valid = 1;
3004 		lastrm->code = compression_code_lzma;
3005 		lastrm->end = compression_end_lzma;
3006 		r = ARCHIVE_OK;
3007 		break;
3008 	case LZMA_MEM_ERROR:
3009 		free(strm);
3010 		lastrm->real_stream = NULL;
3011 		archive_set_error(a, ENOMEM,
3012 		    "Internal error initializing compression library: "
3013 		    "Cannot allocate memory");
3014 		r =  ARCHIVE_FATAL;
3015 		break;
3016         default:
3017 		free(strm);
3018 		lastrm->real_stream = NULL;
3019 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
3020 		    "Internal error initializing compression library: "
3021 		    "It's a bug in liblzma");
3022 		r =  ARCHIVE_FATAL;
3023 		break;
3024 	}
3025 	return (r);
3026 }
3027 
3028 static int
compression_code_lzma(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)3029 compression_code_lzma(struct archive *a,
3030     struct la_zstream *lastrm, enum la_zaction action)
3031 {
3032 	lzma_stream *strm;
3033 	int r;
3034 
3035 	strm = (lzma_stream *)lastrm->real_stream;
3036 	strm->next_in = lastrm->next_in;
3037 	strm->avail_in = lastrm->avail_in;
3038 	strm->total_in = lastrm->total_in;
3039 	strm->next_out = lastrm->next_out;
3040 	strm->avail_out = lastrm->avail_out;
3041 	strm->total_out = lastrm->total_out;
3042 	r = lzma_code(strm,
3043 	    (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
3044 	lastrm->next_in = strm->next_in;
3045 	lastrm->avail_in = strm->avail_in;
3046 	lastrm->total_in = strm->total_in;
3047 	lastrm->next_out = strm->next_out;
3048 	lastrm->avail_out = strm->avail_out;
3049 	lastrm->total_out = strm->total_out;
3050 	switch (r) {
3051 	case LZMA_OK:
3052 		/* Non-finishing case */
3053 		return (ARCHIVE_OK);
3054 	case LZMA_STREAM_END:
3055 		/* This return can only occur in finishing case. */
3056 		return (ARCHIVE_EOF);
3057 	case LZMA_MEMLIMIT_ERROR:
3058 		archive_set_error(a, ENOMEM,
3059 		    "lzma compression error:"
3060 		    " %ju MiB would have been needed",
3061 		    (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
3062 			/ (1024 * 1024)));
3063 		return (ARCHIVE_FATAL);
3064 	default:
3065 		/* Any other return value indicates an error */
3066 		archive_set_error(a, ARCHIVE_ERRNO_MISC,
3067 		    "lzma compression failed:"
3068 		    " lzma_code() call returned status %d", r);
3069 		return (ARCHIVE_FATAL);
3070 	}
3071 }
3072 
3073 static int
compression_end_lzma(struct archive * a,struct la_zstream * lastrm)3074 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
3075 {
3076 	lzma_stream *strm;
3077 
3078 	(void)a; /* UNUSED */
3079 	strm = (lzma_stream *)lastrm->real_stream;
3080 	lzma_end(strm);
3081 	free(strm);
3082 	lastrm->valid = 0;
3083 	lastrm->real_stream = NULL;
3084 	return (ARCHIVE_OK);
3085 }
3086 #else
3087 static int
compression_init_encoder_lzma(struct archive * a,struct la_zstream * lastrm,int level)3088 compression_init_encoder_lzma(struct archive *a,
3089     struct la_zstream *lastrm, int level)
3090 {
3091 
3092 	(void) level; /* UNUSED */
3093 	if (lastrm->valid)
3094 		compression_end(a, lastrm);
3095 	return (compression_unsupported_encoder(a, lastrm, "lzma"));
3096 }
3097 static int
compression_init_encoder_xz(struct archive * a,struct la_zstream * lastrm,int level,int threads)3098 compression_init_encoder_xz(struct archive *a,
3099     struct la_zstream *lastrm, int level, int threads)
3100 {
3101 
3102 	(void) level; /* UNUSED */
3103 	(void) threads; /* UNUSED */
3104 	if (lastrm->valid)
3105 		compression_end(a, lastrm);
3106 	return (compression_unsupported_encoder(a, lastrm, "xz"));
3107 }
3108 #endif
3109 
3110 static int
xar_compression_init_encoder(struct archive_write * a)3111 xar_compression_init_encoder(struct archive_write *a)
3112 {
3113 	struct xar *xar;
3114 	int r;
3115 
3116 	xar = (struct xar *)a->format_data;
3117 	switch (xar->opt_compression) {
3118 	case GZIP:
3119 		r = compression_init_encoder_gzip(
3120 		    &(a->archive), &(xar->stream),
3121 		    xar->opt_compression_level, 1);
3122 		break;
3123 	case BZIP2:
3124 		r = compression_init_encoder_bzip2(
3125 		    &(a->archive), &(xar->stream),
3126 		    xar->opt_compression_level);
3127 		break;
3128 	case LZMA:
3129 		r = compression_init_encoder_lzma(
3130 		    &(a->archive), &(xar->stream),
3131 		    xar->opt_compression_level);
3132 		break;
3133 	case XZ:
3134 		r = compression_init_encoder_xz(
3135 		    &(a->archive), &(xar->stream),
3136 		    xar->opt_compression_level, xar->opt_threads);
3137 		break;
3138 	default:
3139 		r = ARCHIVE_OK;
3140 		break;
3141 	}
3142 	if (r == ARCHIVE_OK) {
3143 		xar->stream.total_in = 0;
3144 		xar->stream.next_out = xar->wbuff;
3145 		xar->stream.avail_out = sizeof(xar->wbuff);
3146 		xar->stream.total_out = 0;
3147 	}
3148 
3149 	return (r);
3150 }
3151 
3152 static int
compression_code(struct archive * a,struct la_zstream * lastrm,enum la_zaction action)3153 compression_code(struct archive *a, struct la_zstream *lastrm,
3154     enum la_zaction action)
3155 {
3156 	if (lastrm->valid)
3157 		return (lastrm->code(a, lastrm, action));
3158 	return (ARCHIVE_OK);
3159 }
3160 
3161 static int
compression_end(struct archive * a,struct la_zstream * lastrm)3162 compression_end(struct archive *a, struct la_zstream *lastrm)
3163 {
3164 	if (lastrm->valid)
3165 		return (lastrm->end(a, lastrm));
3166 	return (ARCHIVE_OK);
3167 }
3168 
3169 
3170 static int
save_xattrs(struct archive_write * a,struct file * file)3171 save_xattrs(struct archive_write *a, struct file *file)
3172 {
3173 	struct xar *xar;
3174 	const char *name;
3175 	const void *value;
3176 	struct heap_data *heap;
3177 	size_t size;
3178 	int count, r;
3179 
3180 	xar = (struct xar *)a->format_data;
3181 	count = archive_entry_xattr_reset(file->entry);
3182 	if (count == 0)
3183 		return (ARCHIVE_OK);
3184 	while (count--) {
3185 		archive_entry_xattr_next(file->entry,
3186 		    &name, &value, &size);
3187 		checksum_init(&(xar->a_sumwrk), xar->opt_sumalg);
3188 		checksum_init(&(xar->e_sumwrk), xar->opt_sumalg);
3189 
3190 		heap = calloc(1, sizeof(*heap));
3191 		if (heap == NULL) {
3192 			archive_set_error(&a->archive, ENOMEM,
3193 			    "Can't allocate memory for xattr");
3194 			return (ARCHIVE_FATAL);
3195 		}
3196 		heap->id = file->ea_idx++;
3197 		heap->temp_offset = xar->temp_offset;
3198 		heap->size = size;/* save a extracted size */
3199 		heap->compression = xar->opt_compression;
3200 		/* Get a extracted sumcheck value. */
3201 		checksum_update(&(xar->e_sumwrk), value, size);
3202 		checksum_final(&(xar->e_sumwrk), &(heap->e_sum));
3203 
3204 		/*
3205 		 * Not compression to xattr is simple way.
3206 		 */
3207 		if (heap->compression == NONE) {
3208 			checksum_update(&(xar->a_sumwrk), value, size);
3209 			checksum_final(&(xar->a_sumwrk), &(heap->a_sum));
3210 			if (write_to_temp(a, value, size)
3211 			    != ARCHIVE_OK) {
3212 				free(heap);
3213 				return (ARCHIVE_FATAL);
3214 			}
3215 			heap->length = size;
3216 			/* Add heap to the tail of file->xattr. */
3217 			heap->next = NULL;
3218 			*file->xattr.last = heap;
3219 			file->xattr.last = &(heap->next);
3220 			/* Next xattr */
3221 			continue;
3222 		}
3223 
3224 		/*
3225 		 * Init compression library.
3226 		 */
3227 		r = xar_compression_init_encoder(a);
3228 		if (r != ARCHIVE_OK) {
3229 			free(heap);
3230 			return (ARCHIVE_FATAL);
3231 		}
3232 
3233 		xar->stream.next_in = (const unsigned char *)value;
3234 		xar->stream.avail_in = size;
3235 		for (;;) {
3236 			r = compression_code(&(a->archive),
3237 			    &(xar->stream), ARCHIVE_Z_FINISH);
3238 			if (r != ARCHIVE_OK && r != ARCHIVE_EOF) {
3239 				free(heap);
3240 				return (ARCHIVE_FATAL);
3241 			}
3242 			size = sizeof(xar->wbuff) - xar->stream.avail_out;
3243 			checksum_update(&(xar->a_sumwrk),
3244 			    xar->wbuff, size);
3245 			if (write_to_temp(a, xar->wbuff, size)
3246 			    != ARCHIVE_OK) {
3247 				free(heap);
3248 				return (ARCHIVE_FATAL);
3249 			}
3250 			if (r == ARCHIVE_OK) {
3251 				xar->stream.next_out = xar->wbuff;
3252 				xar->stream.avail_out = sizeof(xar->wbuff);
3253 			} else {
3254 				checksum_final(&(xar->a_sumwrk),
3255 				    &(heap->a_sum));
3256 				heap->length = xar->stream.total_out;
3257 				/* Add heap to the tail of file->xattr. */
3258 				heap->next = NULL;
3259 				*file->xattr.last = heap;
3260 				file->xattr.last = &(heap->next);
3261 				break;
3262 			}
3263 		}
3264 		/* Clean up compression library. */
3265 		r = compression_end(&(a->archive), &(xar->stream));
3266 		if (r != ARCHIVE_OK)
3267 			return (ARCHIVE_FATAL);
3268 	}
3269 	return (ARCHIVE_OK);
3270 }
3271 
3272 static int
getalgsize(enum sumalg sumalg)3273 getalgsize(enum sumalg sumalg)
3274 {
3275 	switch (sumalg) {
3276 	default:
3277 	case CKSUM_NONE:
3278 		return (0);
3279 	case CKSUM_SHA1:
3280 		return (SHA1_SIZE);
3281 	case CKSUM_MD5:
3282 		return (MD5_SIZE);
3283 	}
3284 }
3285 
3286 static const char *
getalgname(enum sumalg sumalg)3287 getalgname(enum sumalg sumalg)
3288 {
3289 	switch (sumalg) {
3290 	default:
3291 	case CKSUM_NONE:
3292 		return (NULL);
3293 	case CKSUM_SHA1:
3294 		return (SHA1_NAME);
3295 	case CKSUM_MD5:
3296 		return (MD5_NAME);
3297 	}
3298 }
3299 
3300 #if HAVE_LIBXML_XMLWRITER_H
3301 
3302 #define BAD_CAST_CONST (const xmlChar *)
3303 
3304 struct xml_writer {
3305 	xmlTextWriterPtr writer;
3306 	xmlBufferPtr bp;
3307 	unsigned int indent;
3308 };
3309 
3310 static int
xml_writer_create(struct xml_writer ** pctx)3311 xml_writer_create(struct xml_writer **pctx)
3312 {
3313 	struct xml_writer *ctx = calloc(1, sizeof(struct xml_writer));
3314 	if (ctx == NULL) {
3315 		return (-1);
3316 	}
3317 
3318 	ctx->bp = xmlBufferCreate();
3319 	if (ctx->bp == NULL) {
3320 		free(ctx);
3321 		return (-1);
3322 	}
3323 
3324 	ctx->writer = xmlNewTextWriterMemory(ctx->bp, 0);
3325 	if (ctx->writer == NULL) {
3326 		xmlBufferFree(ctx->bp);
3327 		free(ctx);
3328 		return (-1);
3329 	}
3330 
3331 	*pctx = ctx;
3332 	return (0);
3333 }
3334 
3335 static int
xml_writer_destroy(struct xml_writer * ctx)3336 xml_writer_destroy(struct xml_writer *ctx)
3337 {
3338 	xmlFreeTextWriter(ctx->writer);
3339 	xmlBufferFree(ctx->bp);
3340 	free(ctx);
3341 	return (0);
3342 }
3343 
3344 static int
xml_writer_start_document(struct xml_writer * ctx)3345 xml_writer_start_document(struct xml_writer *ctx)
3346 {
3347 	int r;
3348 	r = xmlTextWriterStartDocument(ctx->writer, "1.0", "UTF-8", NULL);
3349 	if (r < 0) {
3350 		return (r);
3351 	}
3352 
3353 	r = xmlTextWriterSetIndent(ctx->writer, (int)ctx->indent);
3354 	return (r);
3355 }
3356 
3357 static int
xml_writer_end_document(struct xml_writer * ctx)3358 xml_writer_end_document(struct xml_writer *ctx)
3359 {
3360 	return (xmlTextWriterEndDocument(ctx->writer));
3361 }
3362 
3363 static int
xml_writer_set_indent(struct xml_writer * ctx,unsigned int indent)3364 xml_writer_set_indent(struct xml_writer *ctx, unsigned int indent)
3365 {
3366 	/* libxml2 only lets you set the indent after starting the document */
3367 	ctx->indent = indent;
3368 	return (0);
3369 }
3370 
3371 static int
xml_writer_start_element(struct xml_writer * ctx,const char * localName)3372 xml_writer_start_element(struct xml_writer *ctx, const char *localName)
3373 {
3374 	return (xmlTextWriterStartElement(ctx->writer,
3375 	    BAD_CAST_CONST(localName)));
3376 }
3377 
3378 static int
xml_writer_write_attribute(struct xml_writer * ctx,const char * key,const char * value)3379 xml_writer_write_attribute(struct xml_writer *ctx,
3380     const char *key, const char *value)
3381 {
3382 	return (xmlTextWriterWriteAttribute(ctx->writer,
3383 	    BAD_CAST_CONST(key), BAD_CAST_CONST(value)));
3384 }
3385 
3386 static int
xml_writer_write_attributef(struct xml_writer * ctx,const char * key,const char * format,...)3387 xml_writer_write_attributef(struct xml_writer *ctx,
3388     const char *key, const char *format, ...)
3389 {
3390 	va_list ap;
3391 	int ret;
3392 	va_start(ap, format);
3393 	ret = xmlTextWriterWriteVFormatAttribute(ctx->writer,
3394 	    BAD_CAST_CONST(key), format, ap);
3395 	va_end(ap);
3396 	return (ret);
3397 }
3398 
3399 static int
xml_writer_write_string(struct xml_writer * ctx,const char * string)3400 xml_writer_write_string(struct xml_writer *ctx, const char *string)
3401 {
3402 	return (xmlTextWriterWriteString(ctx->writer, BAD_CAST_CONST(string)));
3403 }
3404 
3405 static int
xml_writer_write_base64(struct xml_writer * ctx,const char * data,size_t start,size_t len)3406 xml_writer_write_base64(struct xml_writer* ctx,
3407     const char *data, size_t start, size_t len)
3408 {
3409 	return (xmlTextWriterWriteBase64(ctx->writer, data,
3410 	    (int)start, (int)len));
3411 }
3412 
3413 static int
xml_writer_end_element(struct xml_writer * ctx)3414 xml_writer_end_element(struct xml_writer *ctx)
3415 {
3416 	return (xmlTextWriterEndElement(ctx->writer));
3417 }
3418 
3419 static int
xml_writer_get_final_content_and_length(struct xml_writer * ctx,const char ** out,size_t * size)3420 xml_writer_get_final_content_and_length(struct xml_writer *ctx,
3421     const char **out, size_t *size)
3422 {
3423 	*out = (const char*)xmlBufferContent(ctx->bp);
3424 	*size = (size_t)xmlBufferLength(ctx->bp);
3425 	return (0);
3426 }
3427 
3428 #elif HAVE_XMLLITE_H
3429 
3430 struct xml_writer {
3431 	IXmlWriter *writer;
3432 	IStream *stream;
3433 	HGLOBAL global;
3434 };
3435 
3436 static int
xml_writer_create(struct xml_writer ** pctx)3437 xml_writer_create(struct xml_writer **pctx)
3438 {
3439 	struct xml_writer *ctx;
3440 	HRESULT hr;
3441 
3442 	ctx = calloc(1, sizeof(struct xml_writer));
3443 	if (ctx == NULL) {
3444 		return (E_OUTOFMEMORY);
3445 	}
3446 
3447 	hr = CreateStreamOnHGlobal(NULL, TRUE, &ctx->stream);
3448 	if (FAILED(hr)) {
3449 		free(ctx);
3450 		return (hr);
3451 	}
3452 
3453 	hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&ctx->writer, NULL);
3454 	if (FAILED(hr)) {
3455 		ctx->stream->lpVtbl->Release(ctx->stream);
3456 		free(ctx);
3457 		return (hr);
3458 	}
3459 
3460 	hr = ctx->writer->lpVtbl->SetOutput(ctx->writer,
3461 	    (IUnknown *)ctx->stream);
3462 	if (FAILED(hr)) {
3463 		ctx->writer->lpVtbl->Release(ctx->writer);
3464 		ctx->stream->lpVtbl->Release(ctx->stream);
3465 		free(ctx);
3466 		return (hr);
3467 	}
3468 
3469 	*pctx = ctx;
3470 	return (S_OK);
3471 }
3472 
3473 static int
xml_writer_destroy(struct xml_writer * ctx)3474 xml_writer_destroy(struct xml_writer *ctx)
3475 {
3476 	if (ctx->global)
3477 		GlobalUnlock(ctx->global);
3478 	ctx->writer->lpVtbl->Release(ctx->writer); /* Destroys only writer */
3479 	ctx->stream->lpVtbl->Release(ctx->stream); /* Destroys stream, global */
3480 	free(ctx);
3481 	return (S_OK);
3482 }
3483 
3484 static int
xml_writer_start_document(struct xml_writer * ctx)3485 xml_writer_start_document(struct xml_writer *ctx)
3486 {
3487 	return ctx->writer->lpVtbl->WriteStartDocument(ctx->writer,
3488 	    XmlStandalone_Omit);
3489 }
3490 
3491 static int
xml_writer_end_document(struct xml_writer * ctx)3492 xml_writer_end_document(struct xml_writer *ctx)
3493 {
3494 	return ctx->writer->lpVtbl->WriteEndDocument(ctx->writer);
3495 }
3496 
3497 static int
xml_writer_set_indent(struct xml_writer * ctx,unsigned int indent)3498 xml_writer_set_indent(struct xml_writer *ctx, unsigned int indent)
3499 {
3500 	/* Windows' xmllite does not support indent sizes; will always be 2 */
3501 	(void)indent;
3502 	return ctx->writer->lpVtbl->SetProperty(ctx->writer,
3503 	    XmlWriterProperty_Indent, (LONG_PTR)TRUE);
3504 }
3505 
3506 static int
xml_writer_start_element(struct xml_writer * ctx,const char * localName)3507 xml_writer_start_element(struct xml_writer *ctx, const char *localName)
3508 {
3509 	struct archive_wstring as;
3510 	HRESULT hr;
3511 	archive_string_init(&as);
3512 	if (archive_wstring_append_from_mbs(&as, localName,
3513 	    strlen(localName))) {
3514 		hr = E_OUTOFMEMORY;
3515 		goto exit_hr;
3516 	}
3517 	hr = ctx->writer->lpVtbl->WriteStartElement(ctx->writer, NULL,
3518 	    as.s, NULL);
3519 
3520 exit_hr:
3521 	archive_wstring_free(&as);
3522 	return hr;
3523 }
3524 
3525 static int
xml_writer_write_attribute(struct xml_writer * ctx,const char * key,const char * value)3526 xml_writer_write_attribute(struct xml_writer *ctx,
3527     const char *key, const char *value)
3528 {
3529 	struct archive_wstring ask, asv;
3530 	HRESULT hr;
3531 	archive_string_init(&ask);
3532 	archive_string_init(&asv);
3533 	if (archive_wstring_append_from_mbs(&ask, key, strlen(key))) {
3534 		hr = E_OUTOFMEMORY;
3535 		goto exit_hr;
3536 	}
3537 	if (archive_wstring_append_from_mbs(&asv, value, strlen(value))) {
3538 		hr = E_OUTOFMEMORY;
3539 		goto exit_hr;
3540 	}
3541 	hr = ctx->writer->lpVtbl->WriteAttributeString(ctx->writer, NULL,
3542 	    ask.s, NULL, asv.s);
3543 
3544 exit_hr:
3545 	archive_wstring_free(&asv);
3546 	archive_wstring_free(&ask);
3547 	return hr;
3548 }
3549 
3550 static int
xml_writer_write_attributef(struct xml_writer * ctx,const char * key,const char * format,...)3551 xml_writer_write_attributef(struct xml_writer *ctx,
3552     const char *key, const char *format, ...)
3553 {
3554 	struct archive_wstring ask, asv;
3555 	struct archive_string asf;
3556 	HRESULT hr;
3557 	va_list ap;
3558 
3559 	va_start(ap, format);
3560 	archive_string_init(&ask);
3561 	archive_string_init(&asv);
3562 	archive_string_init(&asf);
3563 
3564 	if (archive_wstring_append_from_mbs(&ask, key, strlen(key))) {
3565 		hr = E_OUTOFMEMORY;
3566 		goto exit_hr;
3567 	}
3568 
3569 	archive_string_vsprintf(&asf, format, ap);
3570 	if (archive_wstring_append_from_mbs(&asv, asf.s, asf.length)) {
3571 		hr = E_OUTOFMEMORY;
3572 		goto exit_hr;
3573 	}
3574 
3575 	hr = ctx->writer->lpVtbl->WriteAttributeString(ctx->writer, NULL,
3576 	    ask.s, NULL, asv.s);
3577 
3578 exit_hr:
3579 	archive_string_free(&asf);
3580 	archive_wstring_free(&asv);
3581 	archive_wstring_free(&ask);
3582 	va_end(ap);
3583 
3584 	return hr;
3585 }
3586 
3587 static int
xml_writer_write_string(struct xml_writer * ctx,const char * string)3588 xml_writer_write_string(struct xml_writer *ctx, const char *string)
3589 {
3590 	struct archive_wstring as;
3591 	HRESULT hr;
3592 	archive_string_init(&as);
3593 	if (archive_wstring_append_from_mbs(&as, string, strlen(string))) {
3594 		hr = E_OUTOFMEMORY;
3595 		goto exit_hr;
3596 	}
3597 	hr = ctx->writer->lpVtbl->WriteString(ctx->writer, as.s);
3598 
3599 exit_hr:
3600 	archive_wstring_free(&as);
3601 	return hr;
3602 }
3603 
3604 static const wchar_t base64[] = {
3605 	L'A', L'B', L'C', L'D', L'E', L'F', L'G', L'H',
3606 	L'I', L'J', L'K', L'L', L'M', L'N', L'O', L'P',
3607 	L'Q', L'R', L'S', L'T', L'U', L'V', L'W', L'X',
3608 	L'Y', L'Z', L'a', L'b', L'c', L'd', L'e', L'f',
3609 	L'g', L'h', L'i', L'j', L'k', L'l', L'm', L'n',
3610 	L'o', L'p', L'q', L'r', L's', L't', L'u', L'v',
3611 	L'w', L'x', L'y', L'z', L'0', L'1', L'2', L'3',
3612 	L'4', L'5', L'6', L'7', L'8', L'9', L'+', L'/'
3613 };
3614 
3615 static void
la_b64_wencode(struct archive_wstring * as,const unsigned char * p,size_t len)3616 la_b64_wencode(struct archive_wstring *as, const unsigned char *p, size_t len)
3617 {
3618 	int c;
3619 
3620 	for (; len >= 3; p += 3, len -= 3) {
3621 		c = p[0] >> 2;
3622 		archive_wstrappend_wchar(as, base64[c]);
3623 		c = ((p[0] & 0x03) << 4) | ((p[1] & 0xf0) >> 4);
3624 		archive_wstrappend_wchar(as, base64[c]);
3625 		c = ((p[1] & 0x0f) << 2) | ((p[2] & 0xc0) >> 6);
3626 		archive_wstrappend_wchar(as, base64[c]);
3627 		c = p[2] & 0x3f;
3628 		archive_wstrappend_wchar(as, base64[c]);
3629 	}
3630 	if (len > 0) {
3631 		c = p[0] >> 2;
3632 		archive_wstrappend_wchar(as, base64[c]);
3633 		c = (p[0] & 0x03) << 4;
3634 		if (len == 1) {
3635 			archive_wstrappend_wchar(as, base64[c]);
3636 			archive_wstrappend_wchar(as, '=');
3637 			archive_wstrappend_wchar(as, '=');
3638 		} else {
3639 			c |= (p[1] & 0xf0) >> 4;
3640 			archive_wstrappend_wchar(as, base64[c]);
3641 			c = (p[1] & 0x0f) << 2;
3642 			archive_wstrappend_wchar(as, base64[c]);
3643 			archive_wstrappend_wchar(as, '=');
3644 		}
3645 	}
3646 }
3647 
3648 static int
xml_writer_write_base64(struct xml_writer * ctx,const char * data,size_t start,size_t len)3649 xml_writer_write_base64(struct xml_writer* ctx,
3650     const char *data, size_t start, size_t len)
3651 {
3652 	struct archive_wstring as;
3653 	HRESULT hr;
3654 	archive_string_init(&as);
3655 	la_b64_wencode(&as, (const unsigned char *)data + start, len - start);
3656 	hr = ctx->writer->lpVtbl->WriteString(ctx->writer, as.s);
3657 	archive_wstring_free(&as);
3658 	return hr;
3659 }
3660 
3661 static int
xml_writer_end_element(struct xml_writer * ctx)3662 xml_writer_end_element(struct xml_writer *ctx)
3663 {
3664 	return ctx->writer->lpVtbl->WriteEndElement(ctx->writer);
3665 }
3666 
3667 static int
xml_writer_get_final_content_and_length(struct xml_writer * ctx,const char ** out,size_t * size)3668 xml_writer_get_final_content_and_length(struct xml_writer *ctx,
3669     const char **out, size_t *size)
3670 {
3671 	HGLOBAL gbl;
3672 	HRESULT hr;
3673 
3674 	hr = ctx->writer->lpVtbl->Flush(ctx->writer);
3675 	if (FAILED(hr)) {
3676 		return (hr);
3677 	}
3678 
3679 	hr = GetHGlobalFromStream(ctx->stream, &gbl);
3680 	if (FAILED(hr)) {
3681 		return (hr);
3682 	}
3683 
3684 	*out = (const char *)GlobalLock(gbl);
3685 	if (*out == NULL) {
3686 		hr = HRESULT_FROM_WIN32(GetLastError());
3687 		return (hr);
3688 	}
3689 
3690 	/* GlobalUnlock is called in
3691 	 * xml_writer_destroy.
3692 	 */
3693 	*size = (size_t)GlobalSize(gbl);
3694 	ctx->global = gbl;
3695 	return (hr);
3696 }
3697 
3698 #endif /* HAVE_LIBXML_XMLWRITER_H */
3699 
3700 #endif /* Support xar format */
3701