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