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