summaryrefslogtreecommitdiffstats
path: root/contrib/libarchive/libarchive/archive_write_set_format_zip.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libarchive/libarchive/archive_write_set_format_zip.c')
-rw-r--r--contrib/libarchive/libarchive/archive_write_set_format_zip.c336
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;
OpenPOWER on IntegriCloud