diff options
author | mm <mm@FreeBSD.org> | 2012-02-25 10:58:02 +0000 |
---|---|---|
committer | mm <mm@FreeBSD.org> | 2012-02-25 10:58:02 +0000 |
commit | 6132589d7bb05bbf0c9033cc9f5cf79bafdc0b0f (patch) | |
tree | 117e869a99c6fa7f789c6d9a87cf7eac26ae69e3 /contrib/libarchive/libarchive/archive_write_set_format_zip.c | |
parent | 87f7f0cfe8d3d17bc154ca2c0dcd51bca1444006 (diff) | |
parent | 2f6e434fe4c652da1969314fa57ae21936cec85d (diff) | |
download | FreeBSD-src-6132589d7bb05bbf0c9033cc9f5cf79bafdc0b0f.zip FreeBSD-src-6132589d7bb05bbf0c9033cc9f5cf79bafdc0b0f.tar.gz |
Update libarchive to 3.0.3
Some of new features:
- New readers: RAR, LHA/LZH, CAB reader, 7-Zip
- New writers: ISO9660, XAR
- Improvements to many formats, especially including ISO9660 and Zip
- Stackable write filters to write, e.g., tar.gz.uu in a single pass
- Exploit seekable input; new "seekable" Zip reader can exploit the Zip
Central Directory when it's available; the old "streamable" Zip reader
is still fully supported for cases where seeking is not possible.
Full release notes available at:
https://github.com/libarchive/libarchive/wiki/ReleaseNotes
Diffstat (limited to 'contrib/libarchive/libarchive/archive_write_set_format_zip.c')
-rw-r--r-- | contrib/libarchive/libarchive/archive_write_set_format_zip.c | 336 |
1 files changed, 252 insertions, 84 deletions
diff --git a/contrib/libarchive/libarchive/archive_write_set_format_zip.c b/contrib/libarchive/libarchive/archive_write_set_format_zip.c index 1bbbb6a..57835fc 100644 --- a/contrib/libarchive/libarchive/archive_write_set_format_zip.c +++ b/contrib/libarchive/libarchive/archive_write_set_format_zip.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2008 Anselm Strauss * Copyright (c) 2009 Joerg Sonnenberger + * Copyright (c) 2011-2012 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +53,9 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_ERRNO_H #include <errno.h> #endif -#include <stdio.h> +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -66,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include "archive.h" #include "archive_endian.h" #include "archive_entry.h" +#include "archive_entry_locale.h" #include "archive_private.h" #include "archive_write_private.h" @@ -78,10 +82,11 @@ __FBSDID("$FreeBSD$"); #define ZIP_SIGNATURE_FILE_HEADER 0x02014b50 #define ZIP_SIGNATURE_CENTRAL_DIRECTORY_END 0x06054b50 #define ZIP_SIGNATURE_EXTRA_TIMESTAMP 0x5455 -#define ZIP_SIGNATURE_EXTRA_UNIX 0x7855 +#define ZIP_SIGNATURE_EXTRA_NEW_UNIX 0x7875 #define ZIP_VERSION_EXTRACT 0x0014 /* ZIP version 2.0 is needed. */ #define ZIP_VERSION_BY 0x0314 /* Made by UNIX, using ZIP version 2.0. */ #define ZIP_FLAGS 0x08 /* Flagging bit 3 (count from 0) for using data descriptor. */ +#define ZIP_FLAGS_UTF8_NAME (1 << 11) enum compression { COMPRESSION_STORE = 0 @@ -91,11 +96,15 @@ enum compression { #endif }; -static ssize_t archive_write_zip_data(struct archive_write *, const void *buff, size_t s); -static int archive_write_zip_finish(struct archive_write *); -static int archive_write_zip_destroy(struct archive_write *); +static ssize_t archive_write_zip_data(struct archive_write *, + const void *buff, size_t s); +static int archive_write_zip_close(struct archive_write *); +static int archive_write_zip_free(struct archive_write *); static int archive_write_zip_finish_entry(struct archive_write *); -static int archive_write_zip_header(struct archive_write *, struct archive_entry *); +static int archive_write_zip_header(struct archive_write *, + struct archive_entry *); +static int archive_write_zip_options(struct archive_write *, + const char *, const char *); static unsigned int dos_time(const time_t); static size_t path_length(struct archive_entry *); static int write_path(struct archive_entry *, struct archive_write *); @@ -148,8 +157,11 @@ struct zip_extra_data_local { char ctime[4]; char unix_id[2]; char unix_size[2]; - char unix_uid[2]; - char unix_gid[2]; + char unix_version; + char unix_uid_size; + char unix_uid[4]; + char unix_gid_size; + char unix_gid[4]; }; struct zip_extra_data_central { @@ -164,10 +176,11 @@ struct zip_extra_data_central { struct zip_file_header_link { struct zip_file_header_link *next; struct archive_entry *entry; - off_t offset; + int64_t offset; unsigned long crc32; - off_t compressed_size; + int64_t compressed_size; enum compression compression; + int flags; }; struct zip { @@ -178,6 +191,10 @@ struct zip { int64_t written_bytes; int64_t remaining_data_bytes; enum compression compression; + int flags; + struct archive_string_conv *opt_sconv; + struct archive_string_conv *sconv_default; + int init_default_conversion; #ifdef HAVE_ZLIB_H z_stream stream; @@ -199,25 +216,48 @@ struct zip_central_directory_end { static int archive_write_zip_options(struct archive_write *a, const char *key, - const char *value) + const char *val) { struct zip *zip = a->format_data; + int ret = ARCHIVE_FAILED; if (strcmp(key, "compression") == 0) { - if (strcmp(value, "deflate") == 0) { + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: compression option needs a compression name", + a->format_name); + } else if (strcmp(val, "deflate") == 0) { #ifdef HAVE_ZLIB_H zip->compression = COMPRESSION_DEFLATE; + ret = ARCHIVE_OK; #else archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "deflate compression not supported"); - return ARCHIVE_WARN; #endif - } else if (strcmp(value, "store") == 0) + } else if (strcmp(val, "store") == 0) { zip->compression = COMPRESSION_STORE; - else - return (ARCHIVE_WARN); - return (ARCHIVE_OK); + ret = ARCHIVE_OK; + } + return (ret); + } else if (strcmp(key, "hdrcharset") == 0) { + if (val == NULL || val[0] == 0) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "%s: hdrcharset option needs a character-set name", + a->format_name); + } else { + zip->opt_sconv = archive_string_conversion_to_charset( + &a->archive, val, 0); + if (zip->opt_sconv != NULL) + ret = ARCHIVE_OK; + else + ret = ARCHIVE_FATAL; + } + return (ret); } + + /* Note: The "warn" return is just to inform the options + * supervisor that we didn't handle it. It will generate + * a suitable error if no one used this option. */ return (ARCHIVE_WARN); } @@ -227,13 +267,17 @@ archive_write_set_format_zip(struct archive *_a) struct archive_write *a = (struct archive_write *)_a; struct zip *zip; + archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, + ARCHIVE_STATE_NEW, "archive_write_set_format_zip"); + /* If another format was already registered, unregister it. */ - if (a->format_destroy != NULL) - (a->format_destroy)(a); + if (a->format_free != NULL) + (a->format_free)(a); zip = (struct zip *) calloc(1, sizeof(*zip)); if (zip == NULL) { - archive_set_error(&a->archive, ENOMEM, "Can't allocate zip data"); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip data"); return (ARCHIVE_FATAL); } zip->central_directory = NULL; @@ -247,7 +291,8 @@ archive_write_set_format_zip(struct archive *_a) zip->len_buf = 65536; zip->buf = malloc(zip->len_buf); if (zip->buf == NULL) { - archive_set_error(&a->archive, ENOMEM, "Can't allocate compression buffer"); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate compression buffer"); return (ARCHIVE_FATAL); } #else @@ -255,15 +300,13 @@ archive_write_set_format_zip(struct archive *_a) #endif a->format_data = zip; - - a->pad_uncompressed = 0; /* Actually not needed for now, since no compression support yet. */ a->format_name = "zip"; a->format_options = archive_write_zip_options; a->format_write_header = archive_write_zip_header; a->format_write_data = archive_write_zip_data; a->format_finish_entry = archive_write_zip_finish_entry; - a->format_finish = archive_write_zip_finish; - a->format_destroy = archive_write_zip_destroy; + a->format_close = archive_write_zip_close; + a->format_free = archive_write_zip_free; a->archive.archive_format = ARCHIVE_FORMAT_ZIP; a->archive.archive_format_name = "ZIP"; @@ -274,6 +317,18 @@ archive_write_set_format_zip(struct archive *_a) } static int +is_all_ascii(const char *p) +{ + const unsigned char *pp = (const unsigned char *)p; + + while (*pp) { + if (*pp++ > 127) + return (0); + } + return (1); +} + +static int archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) { struct zip *zip; @@ -281,22 +336,44 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) struct zip_extra_data_local e; struct zip_data_descriptor *d; struct zip_file_header_link *l; - int ret; + struct archive_string_conv *sconv; + int ret, ret2 = ARCHIVE_OK; int64_t size; mode_t type; /* Entries other than a regular file or a folder are skipped. */ type = archive_entry_filetype(entry); - if ((type != AE_IFREG) & (type != AE_IFDIR)) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Filetype not supported"); + if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Filetype not supported"); return ARCHIVE_FAILED; - }; + }; /* Directory entries should have a size of 0. */ if (type == AE_IFDIR) archive_entry_set_size(entry, 0); zip = a->format_data; + /* Setup default conversion. */ + if (zip->opt_sconv == NULL && !zip->init_default_conversion) { + zip->sconv_default = + archive_string_default_conversion_for_write(&(a->archive)); + zip->init_default_conversion = 1; + } + + if (zip->flags == 0) { + /* Initialize the general purpose flags. */ + zip->flags = ZIP_FLAGS; + if (zip->opt_sconv != NULL) { + if (strcmp(archive_string_conversion_charset_name( + zip->opt_sconv), "UTF-8") == 0) + zip->flags |= ZIP_FLAGS_UTF8_NAME; +#if HAVE_NL_LANGINFO + } else if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { + zip->flags |= ZIP_FLAGS_UTF8_NAME; +#endif + } + } d = &zip->data_descriptor; size = archive_entry_size(entry); zip->remaining_data_bytes = size; @@ -304,14 +381,71 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) /* Append archive entry to the central directory data. */ l = (struct zip_file_header_link *) malloc(sizeof(*l)); if (l == NULL) { - archive_set_error(&a->archive, ENOMEM, "Can't allocate zip header data"); + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip header data"); return (ARCHIVE_FATAL); } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Make sure the path separators in pahtname, hardlink and symlink + * are all slash '/', not the Windows path separator '\'. */ + l->entry = __la_win_entry_in_posix_pathseparator(entry); + if (l->entry == entry) + l->entry = archive_entry_clone(entry); +#else l->entry = archive_entry_clone(entry); +#endif + if (l->entry == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate zip header data"); + free(l); + return (ARCHIVE_FATAL); + } + l->flags = zip->flags; + if (zip->opt_sconv != NULL) + sconv = zip->opt_sconv; + else + sconv = zip->sconv_default; + if (sconv != NULL) { + const char *p; + size_t len; + + if (archive_entry_pathname_l(entry, &p, &len, sconv) != 0) { + if (errno == ENOMEM) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for Pathname"); + return (ARCHIVE_FATAL); + } + archive_set_error(&a->archive, + ARCHIVE_ERRNO_FILE_FORMAT, + "Can't translate pathname '%s' to %s", + archive_entry_pathname(entry), + archive_string_conversion_charset_name(sconv)); + ret2 = ARCHIVE_WARN; + } + if (len > 0) + archive_entry_set_pathname(l->entry, p); + } + /* If all character of a filename is ASCII, Reset UTF-8 Name flag. */ + if ((l->flags & ZIP_FLAGS_UTF8_NAME) != 0 && + is_all_ascii(archive_entry_pathname(l->entry))) + l->flags &= ~ZIP_FLAGS_UTF8_NAME; + /* Initialize the CRC variable and potentially the local crc32(). */ l->crc32 = crc32(0, NULL, 0); - l->compression = zip->compression; - l->compressed_size = 0; + if (type == AE_IFLNK) { + const char *p = archive_entry_symlink(l->entry); + if (p != NULL) + size = strlen(p); + else + size = 0; + zip->remaining_data_bytes = 0; + archive_entry_set_size(l->entry, size); + l->compression = COMPRESSION_STORE; + l->compressed_size = size; + } else { + l->compression = zip->compression; + l->compressed_size = 0; + } l->next = NULL; if (zip->central_directory == NULL) { zip->central_directory = l; @@ -320,22 +454,24 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) } zip->central_directory_end = l; - /* Store the offset of this header for later use in central directory. */ + /* Store the offset of this header for later use in central + * directory. */ l->offset = zip->written_bytes; memset(&h, 0, sizeof(h)); archive_le32enc(&h.signature, ZIP_SIGNATURE_LOCAL_FILE_HEADER); archive_le16enc(&h.version, ZIP_VERSION_EXTRACT); - archive_le16enc(&h.flags, ZIP_FLAGS); - archive_le16enc(&h.compression, zip->compression); + archive_le16enc(&h.flags, l->flags); + archive_le16enc(&h.compression, l->compression); archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(entry))); - archive_le16enc(&h.filename_length, (uint16_t)path_length(entry)); + archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry)); - switch (zip->compression) { + switch (l->compression) { case COMPRESSION_STORE: - /* Setting compressed and uncompressed sizes even when specification says - * to set to zero when using data descriptors. Otherwise the end of the - * data for an entry is rather difficult to find. */ + /* Setting compressed and uncompressed sizes even when + * specification says to set to zero when using data + * descriptors. Otherwise the end of the data for an + * entry is rather difficult to find. */ archive_le32enc(&h.compressed_size, size); archive_le32enc(&h.uncompressed_size, size); break; @@ -348,9 +484,10 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) zip->stream.opaque = Z_NULL; zip->stream.next_out = zip->buf; zip->stream.avail_out = zip->len_buf; - if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, - -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { - archive_set_error(&a->archive, ENOMEM, "Can't init deflate compressor"); + if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION, + Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) { + archive_set_error(&a->archive, ENOMEM, + "Can't init deflate compressor"); return (ARCHIVE_FATAL); } break; @@ -366,29 +503,47 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry) archive_le32enc(&e.mtime, archive_entry_mtime(entry)); archive_le32enc(&e.atime, archive_entry_atime(entry)); archive_le32enc(&e.ctime, archive_entry_ctime(entry)); - - archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_UNIX); - archive_le16enc(&e.unix_size, sizeof(e.unix_uid) + sizeof(e.unix_gid)); - archive_le16enc(&e.unix_uid, archive_entry_uid(entry)); - archive_le16enc(&e.unix_gid, archive_entry_gid(entry)); + + archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX); + archive_le16enc(&e.unix_size, sizeof(e.unix_version) + + sizeof(e.unix_uid_size) + sizeof(e.unix_uid) + + sizeof(e.unix_gid_size) + sizeof(e.unix_gid)); + e.unix_version = 1; + e.unix_uid_size = 4; + archive_le32enc(&e.unix_uid, archive_entry_uid(entry)); + e.unix_gid_size = 4; + archive_le32enc(&e.unix_gid, archive_entry_gid(entry)); archive_le32enc(&d->uncompressed_size, size); - ret = (a->compressor.write)(a, &h, sizeof(h)); + ret = __archive_write_output(a, &h, sizeof(h)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(h); - ret = write_path(entry, a); + ret = write_path(l->entry, a); if (ret <= ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += ret; - ret = (a->compressor.write)(a, &e, sizeof(e)); + ret = __archive_write_output(a, &e, sizeof(e)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(e); + if (type == AE_IFLNK) { + const unsigned char *p; + + p = (const unsigned char *)archive_entry_symlink(l->entry); + ret = __archive_write_output(a, p, size); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + zip->written_bytes += size; + l->crc32 = crc32(l->crc32, p, size); + } + + if (ret2 != ARCHIVE_OK) + return (ret2); return (ARCHIVE_OK); } @@ -404,9 +559,9 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) if (s == 0) return 0; - switch (zip->compression) { + switch (l->compression) { case COMPRESSION_STORE: - ret = (a->compressor.write)(a, buff, s); + ret = __archive_write_output(a, buff, s); if (ret != ARCHIVE_OK) return (ret); zip->written_bytes += s; zip->remaining_data_bytes -= s; @@ -422,7 +577,8 @@ archive_write_zip_data(struct archive_write *a, const void *buff, size_t s) if (ret == Z_STREAM_ERROR) return (ARCHIVE_FATAL); if (zip->stream.avail_out == 0) { - ret = (a->compressor.write)(a, zip->buf, zip->len_buf); + ret = __archive_write_output(a, zip->buf, + zip->len_buf); if (ret != ARCHIVE_OK) return (ret); l->compressed_size += zip->len_buf; @@ -456,7 +612,7 @@ archive_write_zip_finish_entry(struct archive_write *a) size_t reminder; #endif - switch(zip->compression) { + switch(l->compression) { case COMPRESSION_STORE: break; #if HAVE_ZLIB_H @@ -466,7 +622,7 @@ archive_write_zip_finish_entry(struct archive_write *a) if (ret == Z_STREAM_ERROR) return (ARCHIVE_FATAL); reminder = zip->len_buf - zip->stream.avail_out; - ret = (a->compressor.write)(a, zip->buf, reminder); + ret = __archive_write_output(a, zip->buf, reminder); if (ret != ARCHIVE_OK) return (ret); l->compressed_size += reminder; @@ -483,7 +639,7 @@ archive_write_zip_finish_entry(struct archive_write *a) archive_le32enc(&d->crc32, l->crc32); archive_le32enc(&d->compressed_size, l->compressed_size); - ret = (a->compressor.write)(a, d, sizeof(*d)); + ret = __archive_write_output(a, d, sizeof(*d)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(*d); @@ -491,25 +647,23 @@ archive_write_zip_finish_entry(struct archive_write *a) } static int -archive_write_zip_finish(struct archive_write *a) +archive_write_zip_close(struct archive_write *a) { struct zip *zip; struct zip_file_header_link *l; struct zip_file_header h; struct zip_central_directory_end end; struct zip_extra_data_central e; - off_t offset_start, offset_end; + int64_t offset_start, offset_end; int entries; int ret; - if (a->compressor.write == NULL) - return (ARCHIVE_OK); - zip = a->format_data; l = zip->central_directory; /* - * Formatting central directory file header fields that are fixed for all entries. + * Formatting central directory file header fields that are + * fixed for all entries. * Fields not used (and therefor 0) are: * * - comment_length @@ -520,7 +674,6 @@ archive_write_zip_finish(struct archive_write *a) archive_le32enc(&h.signature, ZIP_SIGNATURE_FILE_HEADER); archive_le16enc(&h.version_by, ZIP_VERSION_BY); archive_le16enc(&h.version_extract, ZIP_VERSION_EXTRACT); - archive_le16enc(&h.flags, ZIP_FLAGS); entries = 0; offset_start = zip->written_bytes; @@ -528,25 +681,31 @@ archive_write_zip_finish(struct archive_write *a) /* Formatting individual header fields per entry and * writing each entry. */ while (l != NULL) { + archive_le16enc(&h.flags, l->flags); archive_le16enc(&h.compression, l->compression); - archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(l->entry))); + archive_le32enc(&h.timedate, + dos_time(archive_entry_mtime(l->entry))); archive_le32enc(&h.crc32, l->crc32); archive_le32enc(&h.compressed_size, l->compressed_size); - archive_le32enc(&h.uncompressed_size, archive_entry_size(l->entry)); - archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry)); + archive_le32enc(&h.uncompressed_size, + archive_entry_size(l->entry)); + archive_le16enc(&h.filename_length, + (uint16_t)path_length(l->entry)); archive_le16enc(&h.extra_length, sizeof(e)); - archive_le16enc(&h.attributes_external[2], archive_entry_mode(l->entry)); + archive_le16enc(&h.attributes_external[2], + archive_entry_mode(l->entry)); archive_le32enc(&h.offset, l->offset); /* Formatting extra data. */ archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP); - archive_le16enc(&e.time_size, sizeof(e.mtime) + sizeof(e.time_flag)); + archive_le16enc(&e.time_size, + sizeof(e.mtime) + sizeof(e.time_flag)); e.time_flag[0] = 0x07; archive_le32enc(&e.mtime, archive_entry_mtime(l->entry)); - archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_UNIX); + archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_NEW_UNIX); archive_le16enc(&e.unix_size, 0x0000); - ret = (a->compressor.write)(a, &h, sizeof(h)); + ret = __archive_write_output(a, &h, sizeof(h)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(h); @@ -556,7 +715,7 @@ archive_write_zip_finish(struct archive_write *a) return (ARCHIVE_FATAL); zip->written_bytes += ret; - ret = (a->compressor.write)(a, &e, sizeof(e)); + ret = __archive_write_output(a, &e, sizeof(e)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(e); @@ -575,7 +734,7 @@ archive_write_zip_finish(struct archive_write *a) archive_le32enc(&end.offset, offset_start); /* Writing end of central directory. */ - ret = (a->compressor.write)(a, &end, sizeof(end)); + ret = __archive_write_output(a, &end, sizeof(end)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); zip->written_bytes += sizeof(end); @@ -583,7 +742,7 @@ archive_write_zip_finish(struct archive_write *a) } static int -archive_write_zip_destroy(struct archive_write *a) +archive_write_zip_free(struct archive_write *a) { struct zip *zip; struct zip_file_header_link *l; @@ -614,14 +773,23 @@ dos_time(const time_t unix_time) * on two systems with different time zones. */ t = localtime(&unix_time); - dt = 0; - dt += ((t->tm_year - 80) & 0x7f) << 9; - dt += ((t->tm_mon + 1) & 0x0f) << 5; - dt += (t->tm_mday & 0x1f); - dt <<= 16; - dt += (t->tm_hour & 0x1f) << 11; - dt += (t->tm_min & 0x3f) << 5; - dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ + /* MSDOS-style date/time is only between 1980-01-01 and 2107-12-31 */ + if (t->tm_year < 1980 - 1900) + /* Set minimum date/time '1980-01-01 00:00:00'. */ + dt = 0x00210000U; + else if (t->tm_year > 2107 - 1900) + /* Set maximum date/time '2107-12-31 23:59:58'. */ + dt = 0xff9fbf7dU; + else { + dt = 0; + dt += ((t->tm_year - 80) & 0x7f) << 9; + dt += ((t->tm_mon + 1) & 0x0f) << 5; + dt += (t->tm_mday & 0x1f); + dt <<= 16; + dt += (t->tm_hour & 0x1f) << 11; + dt += (t->tm_min & 0x3f) << 5; + dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */ + } return dt; } @@ -653,14 +821,14 @@ write_path(struct archive_entry *entry, struct archive_write *archive) type = archive_entry_filetype(entry); written_bytes = 0; - ret = (archive->compressor.write)(archive, path, strlen(path)); + ret = __archive_write_output(archive, path, strlen(path)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); written_bytes += strlen(path); /* Folders are recognized by a traling slash. */ if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) { - ret = (archive->compressor.write)(archive, "/", 1); + ret = __archive_write_output(archive, "/", 1); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); written_bytes += 1; |