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