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