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