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