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