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