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