1 /*- 2 * Copyright (c) 2008 Anselm Strauss 3 * Copyright (c) 2009 Joerg Sonnenberger 4 * Copyright (c) 2011 Michihiro NAKAJIMA 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Development supported by Google Summer of Code 2008. 30 */ 31 32 /* 33 * The current implementation is very limited: 34 * 35 * - No encryption support. 36 * - No ZIP64 support. 37 * - No support for splitting and spanning. 38 * - Only supports regular file and folder entries. 39 * 40 * Note that generally data in ZIP files is little-endian encoded, 41 * with some exceptions. 42 * 43 * TODO: Since Libarchive is generally 64bit oriented, but this implementation 44 * does not yet support sizes exceeding 32bit, it is highly fragile for 45 * big archives. This should change when ZIP64 is finally implemented, otherwise 46 * some serious checking has to be done. 47 * 48 */ 49 50 #include "archive_platform.h" 51 __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_zip.c 201168 2009-12-29 06:15:32Z kientzle $"); 52 53 #ifdef HAVE_ERRNO_H 54 #include <errno.h> 55 #endif 56 #ifdef HAVE_LANGINFO_H 57 #include <langinfo.h> 58 #endif 59 #ifdef HAVE_STDLIB_H 60 #include <stdlib.h> 61 #endif 62 #ifdef HAVE_STRING_H 63 #include <string.h> 64 #endif 65 #ifdef HAVE_ZLIB_H 66 #include <zlib.h> 67 #endif 68 69 #include "archive.h" 70 #include "archive_endian.h" 71 #include "archive_entry.h" 72 #include "archive_entry_locale.h" 73 #include "archive_private.h" 74 #include "archive_write_private.h" 75 76 #ifndef HAVE_ZLIB_H 77 #include "archive_crc32.h" 78 #endif 79 80 #define ZIP_SIGNATURE_LOCAL_FILE_HEADER 0x04034b50 81 #define ZIP_SIGNATURE_DATA_DESCRIPTOR 0x08074b50 82 #define ZIP_SIGNATURE_FILE_HEADER 0x02014b50 83 #define ZIP_SIGNATURE_CENTRAL_DIRECTORY_END 0x06054b50 84 #define ZIP_SIGNATURE_EXTRA_TIMESTAMP 0x5455 85 #define ZIP_SIGNATURE_EXTRA_NEW_UNIX 0x7875 86 #define ZIP_VERSION_EXTRACT 0x0014 /* ZIP version 2.0 is needed. */ 87 #define ZIP_VERSION_BY 0x0314 /* Made by UNIX, using ZIP version 2.0. */ 88 #define ZIP_FLAGS 0x08 /* Flagging bit 3 (count from 0) for using data descriptor. */ 89 #define ZIP_FLAGS_UTF8_NAME (1 << 11) 90 91 enum compression { 92 COMPRESSION_STORE = 0 93 #ifdef HAVE_ZLIB_H 94 , 95 COMPRESSION_DEFLATE = 8 96 #endif 97 }; 98 99 static ssize_t archive_write_zip_data(struct archive_write *, 100 const void *buff, size_t s); 101 static int archive_write_zip_close(struct archive_write *); 102 static int archive_write_zip_free(struct archive_write *); 103 static int archive_write_zip_finish_entry(struct archive_write *); 104 static int archive_write_zip_header(struct archive_write *, 105 struct archive_entry *); 106 static int archive_write_zip_options(struct archive_write *, 107 const char *, const char *); 108 static unsigned int dos_time(const time_t); 109 static size_t path_length(struct archive_entry *); 110 static int write_path(struct archive_entry *, struct archive_write *); 111 112 struct zip_local_file_header { 113 char signature[4]; 114 char version[2]; 115 char flags[2]; 116 char compression[2]; 117 char timedate[4]; 118 char crc32[4]; 119 char compressed_size[4]; 120 char uncompressed_size[4]; 121 char filename_length[2]; 122 char extra_length[2]; 123 }; 124 125 struct zip_file_header { 126 char signature[4]; 127 char version_by[2]; 128 char version_extract[2]; 129 char flags[2]; 130 char compression[2]; 131 char timedate[4]; 132 char crc32[4]; 133 char compressed_size[4]; 134 char uncompressed_size[4]; 135 char filename_length[2]; 136 char extra_length[2]; 137 char comment_length[2]; 138 char disk_number[2]; 139 char attributes_internal[2]; 140 char attributes_external[4]; 141 char offset[4]; 142 }; 143 144 struct zip_data_descriptor { 145 char signature[4]; /* Not mandatory, but recommended by specification. */ 146 char crc32[4]; 147 char compressed_size[4]; 148 char uncompressed_size[4]; 149 }; 150 151 struct zip_extra_data_local { 152 char time_id[2]; 153 char time_size[2]; 154 char time_flag[1]; 155 char mtime[4]; 156 char atime[4]; 157 char ctime[4]; 158 char unix_id[2]; 159 char unix_size[2]; 160 char unix_version; 161 char unix_uid_size; 162 char unix_uid[4]; 163 char unix_gid_size; 164 char unix_gid[4]; 165 }; 166 167 struct zip_extra_data_central { 168 char time_id[2]; 169 char time_size[2]; 170 char time_flag[1]; 171 char mtime[4]; 172 char unix_id[2]; 173 char unix_size[2]; 174 }; 175 176 struct zip_file_header_link { 177 struct zip_file_header_link *next; 178 struct archive_entry *entry; 179 int64_t offset; 180 unsigned long crc32; 181 int64_t compressed_size; 182 enum compression compression; 183 int flags; 184 }; 185 186 struct zip { 187 struct zip_data_descriptor data_descriptor; 188 struct zip_file_header_link *central_directory; 189 struct zip_file_header_link *central_directory_end; 190 int64_t offset; 191 int64_t written_bytes; 192 int64_t remaining_data_bytes; 193 enum compression compression; 194 int flags; 195 struct archive_string_conv *opt_sconv; 196 struct archive_string_conv *sconv_default; 197 int init_default_conversion; 198 199 #ifdef HAVE_ZLIB_H 200 z_stream stream; 201 size_t len_buf; 202 unsigned char *buf; 203 #endif 204 }; 205 206 struct zip_central_directory_end { 207 char signature[4]; 208 char disk[2]; 209 char start_disk[2]; 210 char entries_disk[2]; 211 char entries[2]; 212 char size[4]; 213 char offset[4]; 214 char comment_length[2]; 215 }; 216 217 static int 218 archive_write_zip_options(struct archive_write *a, const char *key, 219 const char *val) 220 { 221 struct zip *zip = a->format_data; 222 int ret = ARCHIVE_FAILED; 223 224 if (strcmp(key, "compression") == 0) { 225 if (val == NULL || val[0] == 0) { 226 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 227 "%s: compression option needs a compression name", 228 a->format_name); 229 } else if (strcmp(val, "deflate") == 0) { 230 #ifdef HAVE_ZLIB_H 231 zip->compression = COMPRESSION_DEFLATE; 232 ret = ARCHIVE_OK; 233 #else 234 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 235 "deflate compression not supported"); 236 #endif 237 } else if (strcmp(val, "store") == 0) { 238 zip->compression = COMPRESSION_STORE; 239 ret = ARCHIVE_OK; 240 } 241 } else if (strcmp(key, "hdrcharset") == 0) { 242 if (val == NULL || val[0] == 0) { 243 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 244 "%s: hdrcharset option needs a character-set name", 245 a->format_name); 246 } else { 247 zip->opt_sconv = archive_string_conversion_to_charset( 248 &a->archive, val, 0); 249 if (zip->opt_sconv != NULL) 250 ret = ARCHIVE_OK; 251 else 252 ret = ARCHIVE_FATAL; 253 } 254 } else 255 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 256 "%s: unknown keyword ``%s''", a->format_name, key); 257 return (ret); 258 } 259 260 int 261 archive_write_set_format_zip(struct archive *_a) 262 { 263 struct archive_write *a = (struct archive_write *)_a; 264 struct zip *zip; 265 266 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 267 ARCHIVE_STATE_NEW, "archive_write_set_format_zip"); 268 269 /* If another format was already registered, unregister it. */ 270 if (a->format_free != NULL) 271 (a->format_free)(a); 272 273 zip = (struct zip *) calloc(1, sizeof(*zip)); 274 if (zip == NULL) { 275 archive_set_error(&a->archive, ENOMEM, 276 "Can't allocate zip data"); 277 return (ARCHIVE_FATAL); 278 } 279 zip->central_directory = NULL; 280 zip->central_directory_end = NULL; 281 zip->offset = 0; 282 zip->written_bytes = 0; 283 zip->remaining_data_bytes = 0; 284 285 #ifdef HAVE_ZLIB_H 286 zip->compression = COMPRESSION_DEFLATE; 287 zip->len_buf = 65536; 288 zip->buf = malloc(zip->len_buf); 289 if (zip->buf == NULL) { 290 archive_set_error(&a->archive, ENOMEM, 291 "Can't allocate compression buffer"); 292 return (ARCHIVE_FATAL); 293 } 294 #else 295 zip->compression = COMPRESSION_STORE; 296 #endif 297 298 a->format_data = zip; 299 a->format_name = "zip"; 300 a->format_options = archive_write_zip_options; 301 a->format_write_header = archive_write_zip_header; 302 a->format_write_data = archive_write_zip_data; 303 a->format_finish_entry = archive_write_zip_finish_entry; 304 a->format_close = archive_write_zip_close; 305 a->format_free = archive_write_zip_free; 306 a->archive.archive_format = ARCHIVE_FORMAT_ZIP; 307 a->archive.archive_format_name = "ZIP"; 308 309 archive_le32enc(&zip->data_descriptor.signature, 310 ZIP_SIGNATURE_DATA_DESCRIPTOR); 311 312 return (ARCHIVE_OK); 313 } 314 315 static int 316 is_all_ascii(const char *p) 317 { 318 const unsigned char *pp = (const unsigned char *)p; 319 320 while (*pp) { 321 if (*pp++ > 127) 322 return (0); 323 } 324 return (1); 325 } 326 327 static int 328 archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) 329 { 330 struct zip *zip; 331 struct zip_local_file_header h; 332 struct zip_extra_data_local e; 333 struct zip_data_descriptor *d; 334 struct zip_file_header_link *l; 335 struct archive_string_conv *sconv; 336 int ret, ret2 = ARCHIVE_OK; 337 int64_t size; 338 mode_t type; 339 340 /* Entries other than a regular file or a folder are skipped. */ 341 type = archive_entry_filetype(entry); 342 if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { 343 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 344 "Filetype not supported"); 345 return ARCHIVE_FAILED; 346 }; 347 348 /* Directory entries should have a size of 0. */ 349 if (type == AE_IFDIR) 350 archive_entry_set_size(entry, 0); 351 352 zip = a->format_data; 353 /* Setup default conversion. */ 354 if (zip->opt_sconv == NULL && !zip->init_default_conversion) { 355 zip->sconv_default = 356 archive_string_default_conversion_for_write(&(a->archive)); 357 zip->init_default_conversion = 1; 358 } 359 360 if (zip->flags == 0) { 361 /* Initialize the general purpose flags. */ 362 zip->flags = ZIP_FLAGS; 363 if (zip->opt_sconv != NULL) { 364 if (strcmp(archive_string_conversion_charset_name( 365 zip->opt_sconv), "UTF-8") == 0) 366 zip->flags |= ZIP_FLAGS_UTF8_NAME; 367 #if HAVE_NL_LANGINFO 368 } else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { 369 zip->flags |= ZIP_FLAGS_UTF8_NAME; 370 #endif 371 } 372 } 373 d = &zip->data_descriptor; 374 size = archive_entry_size(entry); 375 zip->remaining_data_bytes = size; 376 377 /* Append archive entry to the central directory data. */ 378 l = (struct zip_file_header_link *) malloc(sizeof(*l)); 379 if (l == NULL) { 380 archive_set_error(&a->archive, ENOMEM, 381 "Can't allocate zip header data"); 382 return (ARCHIVE_FATAL); 383 } 384 l->entry = archive_entry_clone(entry); 385 l->flags = zip->flags; 386 if (zip->opt_sconv != NULL) 387 sconv = zip->opt_sconv; 388 else 389 sconv = zip->sconv_default; 390 if (sconv != NULL) { 391 const char *p; 392 size_t len; 393 394 if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) { 395 if (errno == ENOMEM) { 396 archive_set_error(&a->archive, ENOMEM, 397 "Can't allocate memory for Pathname"); 398 return (ARCHIVE_FATAL); 399 } 400 archive_set_error(&a->archive, 401 ARCHIVE_ERRNO_FILE_FORMAT, 402 "Can't translate pathname '%s' to %s", 403 archive_entry_pathname(entry), 404 archive_string_conversion_charset_name(sconv)); 405 ret2 = ARCHIVE_WARN; 406 } 407 if (len > 0) 408 archive_entry_set_pathname(l->entry, p); 409 } 410 /* If all character of a filename is ASCII, Reset UTF-8 Name flag. */ 411 if ((l->flags & ZIP_FLAGS_UTF8_NAME) != 0 && 412 is_all_ascii(archive_entry_pathname(l->entry))) 413 l->flags &= ~ZIP_FLAGS_UTF8_NAME; 414 415 /* Initialize the CRC variable and potentially the local crc32(). */ 416 l->crc32 = crc32(0, NULL, 0); 417 if (type == AE_IFLNK) { 418 const char *p = archive_entry_symlink(l->entry); 419 if (p != NULL) 420 size = strlen(p); 421 else 422 size = 0; 423 zip->remaining_data_bytes = 0; 424 archive_entry_set_size(l->entry, size); 425 l->compression = COMPRESSION_STORE; 426 l->compressed_size = size; 427 } else { 428 l->compression = zip->compression; 429 l->compressed_size = 0; 430 } 431 l->next = NULL; 432 if (zip->central_directory == NULL) { 433 zip->central_directory = l; 434 } else { 435 zip->central_directory_end->next = l; 436 } 437 zip->central_directory_end = l; 438 439 /* Store the offset of this header for later use in central 440 * directory. */ 441 l->offset = zip->written_bytes; 442 443 memset(&h, 0, sizeof(h)); 444 archive_le32enc(&h.signature, ZIP_SIGNATURE_LOCAL_FILE_HEADER); 445 archive_le16enc(&h.version, ZIP_VERSION_EXTRACT); 446 archive_le16enc(&h.flags, l->flags); 447 archive_le16enc(&h.compression, l->compression); 448 archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(entry))); 449 archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry)); 450 451 switch (l->compression) { 452 case COMPRESSION_STORE: 453 /* Setting compressed and uncompressed sizes even when 454 * specification says to set to zero when using data 455 * descriptors. Otherwise the end of the data for an 456 * entry is rather difficult to find. */ 457 archive_le32enc(&h.compressed_size, size); 458 archive_le32enc(&h.uncompressed_size, size); 459 break; 460 #ifdef HAVE_ZLIB_H 461 case COMPRESSION_DEFLATE: 462 archive_le32enc(&h.uncompressed_size, size); 463 464 zip->stream.zalloc = Z_NULL; 465 zip->stream.zfree = Z_NULL; 466 zip->stream.opaque = Z_NULL; 467 zip->stream.next_out = zip->buf; 468 zip->stream.avail_out = zip->len_buf; 469 if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION, 470 Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { 471 archive_set_error(&a->archive, ENOMEM, 472 "Can't init deflate compressor"); 473 return (ARCHIVE_FATAL); 474 } 475 break; 476 #endif 477 } 478 479 /* Formatting extra data. */ 480 archive_le16enc(&h.extra_length, sizeof(e)); 481 archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP); 482 archive_le16enc(&e.time_size, sizeof(e.time_flag) + 483 sizeof(e.mtime) + sizeof(e.atime) + sizeof(e.ctime)); 484 e.time_flag[0] = 0x07; 485 archive_le32enc(&e.mtime, archive_entry_mtime(entry)); 486 archive_le32enc(&e.atime, archive_entry_atime(entry)); 487 archive_le32enc(&e.ctime, archive_entry_ctime(entry)); 488 489 archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX); 490 archive_le16enc(&e.unix_size, sizeof(e.unix_version) + 491 sizeof(e.unix_uid_size) + sizeof(e.unix_uid) + 492 sizeof(e.unix_gid_size) + sizeof(e.unix_gid)); 493 e.unix_version = 1; 494 e.unix_uid_size = 4; 495 archive_le32enc(&e.unix_uid, archive_entry_uid(entry)); 496 e.unix_gid_size = 4; 497 archive_le32enc(&e.unix_gid, archive_entry_gid(entry)); 498 499 archive_le32enc(&d->uncompressed_size, size); 500 501 ret = __archive_write_output(a, &h, sizeof(h)); 502 if (ret != ARCHIVE_OK) 503 return (ARCHIVE_FATAL); 504 zip->written_bytes += sizeof(h); 505 506 ret = write_path(l->entry, a); 507 if (ret <= ARCHIVE_OK) 508 return (ARCHIVE_FATAL); 509 zip->written_bytes += ret; 510 511 ret = __archive_write_output(a, &e, sizeof(e)); 512 if (ret != ARCHIVE_OK) 513 return (ARCHIVE_FATAL); 514 zip->written_bytes += sizeof(e); 515 516 if (type == AE_IFLNK) { 517 const unsigned char *p; 518 519 p = (const unsigned char *)archive_entry_symlink(l->entry); 520 ret = __archive_write_output(a, p, size); 521 if (ret != ARCHIVE_OK) 522 return (ARCHIVE_FATAL); 523 zip->written_bytes += size; 524 l->crc32 = crc32(l->crc32, p, size); 525 } 526 527 if (ret2 != ARCHIVE_OK) 528 return (ret2); 529 return (ARCHIVE_OK); 530 } 531 532 static ssize_t 533 archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) 534 { 535 int ret; 536 struct zip *zip = a->format_data; 537 struct zip_file_header_link *l = zip->central_directory_end; 538 539 if ((int64_t)s > zip->remaining_data_bytes) 540 s = (size_t)zip->remaining_data_bytes; 541 542 if (s == 0) return 0; 543 544 switch (l->compression) { 545 case COMPRESSION_STORE: 546 ret = __archive_write_output(a, buff, s); 547 if (ret != ARCHIVE_OK) return (ret); 548 zip->written_bytes += s; 549 zip->remaining_data_bytes -= s; 550 l->compressed_size += s; 551 l->crc32 = crc32(l->crc32, buff, s); 552 return (s); 553 #if HAVE_ZLIB_H 554 case COMPRESSION_DEFLATE: 555 zip->stream.next_in = (unsigned char*)(uintptr_t)buff; 556 zip->stream.avail_in = s; 557 do { 558 ret = deflate(&zip->stream, Z_NO_FLUSH); 559 if (ret == Z_STREAM_ERROR) 560 return (ARCHIVE_FATAL); 561 if (zip->stream.avail_out == 0) { 562 ret = __archive_write_output(a, zip->buf, 563 zip->len_buf); 564 if (ret != ARCHIVE_OK) 565 return (ret); 566 l->compressed_size += zip->len_buf; 567 zip->written_bytes += zip->len_buf; 568 zip->stream.next_out = zip->buf; 569 zip->stream.avail_out = zip->len_buf; 570 } 571 } while (zip->stream.avail_in != 0); 572 zip->remaining_data_bytes -= s; 573 /* If we have it, use zlib's fast crc32() */ 574 l->crc32 = crc32(l->crc32, buff, s); 575 return (s); 576 #endif 577 578 default: 579 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 580 "Invalid ZIP compression type"); 581 return ARCHIVE_FATAL; 582 } 583 } 584 585 static int 586 archive_write_zip_finish_entry(struct archive_write *a) 587 { 588 /* Write the data descripter after file data has been written. */ 589 int ret; 590 struct zip *zip = a->format_data; 591 struct zip_data_descriptor *d = &zip->data_descriptor; 592 struct zip_file_header_link *l = zip->central_directory_end; 593 #if HAVE_ZLIB_H 594 size_t reminder; 595 #endif 596 597 switch(l->compression) { 598 case COMPRESSION_STORE: 599 break; 600 #if HAVE_ZLIB_H 601 case COMPRESSION_DEFLATE: 602 for (;;) { 603 ret = deflate(&zip->stream, Z_FINISH); 604 if (ret == Z_STREAM_ERROR) 605 return (ARCHIVE_FATAL); 606 reminder = zip->len_buf - zip->stream.avail_out; 607 ret = __archive_write_output(a, zip->buf, reminder); 608 if (ret != ARCHIVE_OK) 609 return (ret); 610 l->compressed_size += reminder; 611 zip->written_bytes += reminder; 612 zip->stream.next_out = zip->buf; 613 if (zip->stream.avail_out != 0) 614 break; 615 zip->stream.avail_out = zip->len_buf; 616 } 617 deflateEnd(&zip->stream); 618 break; 619 #endif 620 } 621 622 archive_le32enc(&d->crc32, l->crc32); 623 archive_le32enc(&d->compressed_size, l->compressed_size); 624 ret = __archive_write_output(a, d, sizeof(*d)); 625 if (ret != ARCHIVE_OK) 626 return (ARCHIVE_FATAL); 627 zip->written_bytes += sizeof(*d); 628 return (ARCHIVE_OK); 629 } 630 631 static int 632 archive_write_zip_close(struct archive_write *a) 633 { 634 struct zip *zip; 635 struct zip_file_header_link *l; 636 struct zip_file_header h; 637 struct zip_central_directory_end end; 638 struct zip_extra_data_central e; 639 int64_t offset_start, offset_end; 640 int entries; 641 int ret; 642 643 zip = a->format_data; 644 l = zip->central_directory; 645 646 /* 647 * Formatting central directory file header fields that are 648 * fixed for all entries. 649 * Fields not used (and therefor 0) are: 650 * 651 * - comment_length 652 * - disk_number 653 * - attributes_internal 654 */ 655 memset(&h, 0, sizeof(h)); 656 archive_le32enc(&h.signature, ZIP_SIGNATURE_FILE_HEADER); 657 archive_le16enc(&h.version_by, ZIP_VERSION_BY); 658 archive_le16enc(&h.version_extract, ZIP_VERSION_EXTRACT); 659 660 entries = 0; 661 offset_start = zip->written_bytes; 662 663 /* Formatting individual header fields per entry and 664 * writing each entry. */ 665 while (l != NULL) { 666 archive_le16enc(&h.flags, l->flags); 667 archive_le16enc(&h.compression, l->compression); 668 archive_le32enc(&h.timedate, 669 dos_time(archive_entry_mtime(l->entry))); 670 archive_le32enc(&h.crc32, l->crc32); 671 archive_le32enc(&h.compressed_size, l->compressed_size); 672 archive_le32enc(&h.uncompressed_size, 673 archive_entry_size(l->entry)); 674 archive_le16enc(&h.filename_length, 675 (uint16_t)path_length(l->entry)); 676 archive_le16enc(&h.extra_length, sizeof(e)); 677 archive_le16enc(&h.attributes_external[2], 678 archive_entry_mode(l->entry)); 679 archive_le32enc(&h.offset, l->offset); 680 681 /* Formatting extra data. */ 682 archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP); 683 archive_le16enc(&e.time_size, 684 sizeof(e.mtime) + sizeof(e.time_flag)); 685 e.time_flag[0] = 0x07; 686 archive_le32enc(&e.mtime, archive_entry_mtime(l->entry)); 687 archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX); 688 archive_le16enc(&e.unix_size, 0x0000); 689 690 ret = __archive_write_output(a, &h, sizeof(h)); 691 if (ret != ARCHIVE_OK) 692 return (ARCHIVE_FATAL); 693 zip->written_bytes += sizeof(h); 694 695 ret = write_path(l->entry, a); 696 if (ret <= ARCHIVE_OK) 697 return (ARCHIVE_FATAL); 698 zip->written_bytes += ret; 699 700 ret = __archive_write_output(a, &e, sizeof(e)); 701 if (ret != ARCHIVE_OK) 702 return (ARCHIVE_FATAL); 703 zip->written_bytes += sizeof(e); 704 705 l = l->next; 706 entries++; 707 } 708 offset_end = zip->written_bytes; 709 710 /* Formatting end of central directory. */ 711 memset(&end, 0, sizeof(end)); 712 archive_le32enc(&end.signature, ZIP_SIGNATURE_CENTRAL_DIRECTORY_END); 713 archive_le16enc(&end.entries_disk, entries); 714 archive_le16enc(&end.entries, entries); 715 archive_le32enc(&end.size, offset_end - offset_start); 716 archive_le32enc(&end.offset, offset_start); 717 718 /* Writing end of central directory. */ 719 ret = __archive_write_output(a, &end, sizeof(end)); 720 if (ret != ARCHIVE_OK) 721 return (ARCHIVE_FATAL); 722 zip->written_bytes += sizeof(end); 723 return (ARCHIVE_OK); 724 } 725 726 static int 727 archive_write_zip_free(struct archive_write *a) 728 { 729 struct zip *zip; 730 struct zip_file_header_link *l; 731 732 zip = a->format_data; 733 while (zip->central_directory != NULL) { 734 l = zip->central_directory; 735 zip->central_directory = l->next; 736 archive_entry_free(l->entry); 737 free(l); 738 } 739 #ifdef HAVE_ZLIB_H 740 free(zip->buf); 741 #endif 742 free(zip); 743 a->format_data = NULL; 744 return (ARCHIVE_OK); 745 } 746 747 /* Convert into MSDOS-style date/time. */ 748 static unsigned int 749 dos_time(const time_t unix_time) 750 { 751 struct tm *t; 752 unsigned int dt; 753 754 /* This will not preserve time when creating/extracting the archive 755 * on two systems with different time zones. */ 756 t = localtime(&unix_time); 757 758 /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */ 759 if (t->tm_year < 1980 - 1900) 760 /* Set minimum date/time '1980-01-01 00:00:00'. */ 761 dt = 0x00210000U; 762 else if (t->tm_year > 2107 - 1900) 763 /* Set maximum date/time '2107-12-31 23:59:58'. */ 764 dt = 0xff9fbf7dU; 765 else { 766 dt = 0; 767 dt += ((t->tm_year - 80) & 0x7f) << 9; 768 dt += ((t->tm_mon + 1) & 0x0f) << 5; 769 dt += (t->tm_mday & 0x1f); 770 dt <<= 16; 771 dt += (t->tm_hour & 0x1f) << 11; 772 dt += (t->tm_min & 0x3f) << 5; 773 dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ 774 } 775 return dt; 776 } 777 778 static size_t 779 path_length(struct archive_entry *entry) 780 { 781 mode_t type; 782 const char *path; 783 784 type = archive_entry_filetype(entry); 785 path = archive_entry_pathname(entry); 786 787 if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { 788 return strlen(path) + 1; 789 } else { 790 return strlen(path); 791 } 792 } 793 794 static int 795 write_path(struct archive_entry *entry, struct archive_write *archive) 796 { 797 int ret; 798 const char *path; 799 mode_t type; 800 size_t written_bytes; 801 802 path = archive_entry_pathname(entry); 803 type = archive_entry_filetype(entry); 804 written_bytes = 0; 805 806 ret = __archive_write_output(archive, path, strlen(path)); 807 if (ret != ARCHIVE_OK) 808 return (ARCHIVE_FATAL); 809 written_bytes += strlen(path); 810 811 /* Folders are recognized by a traling slash. */ 812 if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { 813 ret = __archive_write_output(archive, "/", 1); 814 if (ret != ARCHIVE_OK) 815 return (ARCHIVE_FATAL); 816 written_bytes += 1; 817 } 818 819 return ((int)written_bytes); 820 } 821