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