2 * Copyright (c) 2008 Anselm Strauss
3 * Copyright (c) 2009 Joerg Sonnenberger
4 * Copyright (c) 2011 Michihiro NAKAJIMA
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
29 * Development supported by Google Summer of Code 2008.
33 * The current implementation is very limited:
35 * - No encryption support.
37 * - No support for splitting and spanning.
38 * - Only supports regular file and folder entries.
40 * Note that generally data in ZIP files is little-endian encoded,
41 * with some exceptions.
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.
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 $");
56 #ifdef HAVE_LANGINFO_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"
77 #include "archive_crc32.h"
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)
95 COMPRESSION_DEFLATE = 8
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 *);
112 struct zip_local_file_header {
119 char compressed_size[4];
120 char uncompressed_size[4];
121 char filename_length[2];
122 char extra_length[2];
125 struct zip_file_header {
128 char version_extract[2];
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];
139 char attributes_internal[2];
140 char attributes_external[4];
144 struct zip_data_descriptor {
145 char signature[4]; /* Not mandatory, but recommended by specification. */
147 char compressed_size[4];
148 char uncompressed_size[4];
151 struct zip_extra_data_local {
167 struct zip_extra_data_central {
176 struct zip_file_header_link {
177 struct zip_file_header_link *next;
178 struct archive_entry *entry;
181 int64_t compressed_size;
182 enum compression compression;
187 struct zip_data_descriptor data_descriptor;
188 struct zip_file_header_link *central_directory;
189 struct zip_file_header_link *central_directory_end;
191 int64_t written_bytes;
192 int64_t remaining_data_bytes;
193 enum compression compression;
195 struct archive_string_conv *opt_sconv;
196 struct archive_string_conv *sconv_default;
197 int init_default_conversion;
206 struct zip_central_directory_end {
210 char entries_disk[2];
214 char comment_length[2];
218 archive_write_zip_options(struct archive_write *a, const char *key,
221 struct zip *zip = a->format_data;
222 int ret = ARCHIVE_FAILED;
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",
229 } else if (strcmp(val, "deflate") == 0) {
231 zip->compression = COMPRESSION_DEFLATE;
234 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
235 "deflate compression not supported");
237 } else if (strcmp(val, "store") == 0) {
238 zip->compression = COMPRESSION_STORE;
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",
247 zip->opt_sconv = archive_string_conversion_to_charset(
248 &a->archive, val, 0);
249 if (zip->opt_sconv != NULL)
255 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
256 "%s: unknown keyword ``%s''", a->format_name, key);
261 archive_write_set_format_zip(struct archive *_a)
263 struct archive_write *a = (struct archive_write *)_a;
266 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
267 ARCHIVE_STATE_NEW, "archive_write_set_format_zip");
269 /* If another format was already registered, unregister it. */
270 if (a->format_free != NULL)
273 zip = (struct zip *) calloc(1, sizeof(*zip));
275 archive_set_error(&a->archive, ENOMEM,
276 "Can't allocate zip data");
277 return (ARCHIVE_FATAL);
279 zip->central_directory = NULL;
280 zip->central_directory_end = NULL;
282 zip->written_bytes = 0;
283 zip->remaining_data_bytes = 0;
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);
295 zip->compression = COMPRESSION_STORE;
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";
309 archive_le32enc(&zip->data_descriptor.signature,
310 ZIP_SIGNATURE_DATA_DESCRIPTOR);
316 is_all_ascii(const char *p)
318 const unsigned char *pp = (const unsigned char *)p;
328 archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
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;
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;
348 /* Directory entries should have a size of 0. */
349 if (type == AE_IFDIR)
350 archive_entry_set_size(entry, 0);
352 zip = a->format_data;
353 /* Setup default conversion. */
354 if (zip->opt_sconv == NULL && !zip->init_default_conversion) {
356 archive_string_default_conversion_for_write(&(a->archive));
357 zip->init_default_conversion = 1;
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;
368 } else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) {
369 zip->flags |= ZIP_FLAGS_UTF8_NAME;
373 d = &zip->data_descriptor;
374 size = archive_entry_size(entry);
375 zip->remaining_data_bytes = size;
377 /* Append archive entry to the central directory data. */
378 l = (struct zip_file_header_link *) malloc(sizeof(*l));
380 archive_set_error(&a->archive, ENOMEM,
381 "Can't allocate zip header data");
382 return (ARCHIVE_FATAL);
384 l->entry = archive_entry_clone(entry);
385 l->flags = zip->flags;
386 if (zip->opt_sconv != NULL)
387 sconv = zip->opt_sconv;
389 sconv = zip->sconv_default;
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);
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));
408 archive_entry_set_pathname(l->entry, p);
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;
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);
423 zip->remaining_data_bytes = 0;
424 archive_entry_set_size(l->entry, size);
425 l->compression = COMPRESSION_STORE;
426 l->compressed_size = size;
428 l->compression = zip->compression;
429 l->compressed_size = 0;
432 if (zip->central_directory == NULL) {
433 zip->central_directory = l;
435 zip->central_directory_end->next = l;
437 zip->central_directory_end = l;
439 /* Store the offset of this header for later use in central
441 l->offset = zip->written_bytes;
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));
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);
461 case COMPRESSION_DEFLATE:
462 archive_le32enc(&h.uncompressed_size, size);
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);
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));
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));
495 archive_le32enc(&e.unix_uid, archive_entry_uid(entry));
497 archive_le32enc(&e.unix_gid, archive_entry_gid(entry));
499 archive_le32enc(&d->uncompressed_size, size);
501 ret = __archive_write_output(a, &h, sizeof(h));
502 if (ret != ARCHIVE_OK)
503 return (ARCHIVE_FATAL);
504 zip->written_bytes += sizeof(h);
506 ret = write_path(l->entry, a);
507 if (ret <= ARCHIVE_OK)
508 return (ARCHIVE_FATAL);
509 zip->written_bytes += ret;
511 ret = __archive_write_output(a, &e, sizeof(e));
512 if (ret != ARCHIVE_OK)
513 return (ARCHIVE_FATAL);
514 zip->written_bytes += sizeof(e);
516 if (type == AE_IFLNK) {
517 const unsigned char *p;
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);
527 if (ret2 != ARCHIVE_OK)
533 archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
536 struct zip *zip = a->format_data;
537 struct zip_file_header_link *l = zip->central_directory_end;
539 if ((int64_t)s > zip->remaining_data_bytes)
540 s = (size_t)zip->remaining_data_bytes;
542 if (s == 0) return 0;
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);
554 case COMPRESSION_DEFLATE:
555 zip->stream.next_in = (unsigned char*)(uintptr_t)buff;
556 zip->stream.avail_in = s;
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,
564 if (ret != ARCHIVE_OK)
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;
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);
579 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
580 "Invalid ZIP compression type");
581 return ARCHIVE_FATAL;
586 archive_write_zip_finish_entry(struct archive_write *a)
588 /* Write the data descripter after file data has been written. */
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;
597 switch(l->compression) {
598 case COMPRESSION_STORE:
601 case COMPRESSION_DEFLATE:
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)
610 l->compressed_size += reminder;
611 zip->written_bytes += reminder;
612 zip->stream.next_out = zip->buf;
613 if (zip->stream.avail_out != 0)
615 zip->stream.avail_out = zip->len_buf;
617 deflateEnd(&zip->stream);
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);
632 archive_write_zip_close(struct archive_write *a)
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;
643 zip = a->format_data;
644 l = zip->central_directory;
647 * Formatting central directory file header fields that are
648 * fixed for all entries.
649 * Fields not used (and therefor 0) are:
653 * - attributes_internal
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);
661 offset_start = zip->written_bytes;
663 /* Formatting individual header fields per entry and
664 * writing each entry. */
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);
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);
690 ret = __archive_write_output(a, &h, sizeof(h));
691 if (ret != ARCHIVE_OK)
692 return (ARCHIVE_FATAL);
693 zip->written_bytes += sizeof(h);
695 ret = write_path(l->entry, a);
696 if (ret <= ARCHIVE_OK)
697 return (ARCHIVE_FATAL);
698 zip->written_bytes += ret;
700 ret = __archive_write_output(a, &e, sizeof(e));
701 if (ret != ARCHIVE_OK)
702 return (ARCHIVE_FATAL);
703 zip->written_bytes += sizeof(e);
708 offset_end = zip->written_bytes;
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);
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);
727 archive_write_zip_free(struct archive_write *a)
730 struct zip_file_header_link *l;
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);
743 a->format_data = NULL;
747 /* Convert into MSDOS-style date/time. */
749 dos_time(const time_t unix_time)
754 /* This will not preserve time when creating/extracting the archive
755 * on two systems with different time zones. */
756 t = localtime(&unix_time);
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'. */
762 else if (t->tm_year > 2107 - 1900)
763 /* Set maximum date/time '2107-12-31 23:59:58'. */
767 dt += ((t->tm_year - 80) & 0x7f) << 9;
768 dt += ((t->tm_mon + 1) & 0x0f) << 5;
769 dt += (t->tm_mday & 0x1f);
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. */
779 path_length(struct archive_entry *entry)
784 type = archive_entry_filetype(entry);
785 path = archive_entry_pathname(entry);
787 if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) {
788 return strlen(path) + 1;
795 write_path(struct archive_entry *entry, struct archive_write *archive)
800 size_t written_bytes;
802 path = archive_entry_pathname(entry);
803 type = archive_entry_filetype(entry);
806 ret = __archive_write_output(archive, path, strlen(path));
807 if (ret != ARCHIVE_OK)
808 return (ARCHIVE_FATAL);
809 written_bytes += strlen(path);
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);
819 return ((int)written_bytes);