160b4ad09SPeter Avalos /*-
260b4ad09SPeter Avalos  * Copyright (c) 2004 Tim Kientzle
3*59bf7050SPeter Avalos  * Copyright (c) 2011-2012 Michihiro NAKAJIMA
460b4ad09SPeter Avalos  * All rights reserved.
560b4ad09SPeter Avalos  *
660b4ad09SPeter Avalos  * Redistribution and use in source and binary forms, with or without
760b4ad09SPeter Avalos  * modification, are permitted provided that the following conditions
860b4ad09SPeter Avalos  * are met:
960b4ad09SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
1060b4ad09SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
1160b4ad09SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1260b4ad09SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1360b4ad09SPeter Avalos  *    documentation and/or other materials provided with the distribution.
1460b4ad09SPeter Avalos  *
1560b4ad09SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
1660b4ad09SPeter Avalos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1760b4ad09SPeter Avalos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1860b4ad09SPeter Avalos  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
1960b4ad09SPeter Avalos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2060b4ad09SPeter Avalos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2160b4ad09SPeter Avalos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2260b4ad09SPeter Avalos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2360b4ad09SPeter Avalos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2460b4ad09SPeter Avalos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2560b4ad09SPeter Avalos  */
2660b4ad09SPeter Avalos 
2760b4ad09SPeter Avalos #include "archive_platform.h"
289c82a63eSPeter Avalos __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 2009-12-28 03:11:36Z kientzle $");
2960b4ad09SPeter Avalos 
3060b4ad09SPeter Avalos #ifdef HAVE_ERRNO_H
3160b4ad09SPeter Avalos #include <errno.h>
3260b4ad09SPeter Avalos #endif
3360b4ad09SPeter Avalos #ifdef HAVE_STDLIB_H
3460b4ad09SPeter Avalos #include <stdlib.h>
3560b4ad09SPeter Avalos #endif
3660b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H
3760b4ad09SPeter Avalos #include <zlib.h>
3860b4ad09SPeter Avalos #endif
3960b4ad09SPeter Avalos 
4060b4ad09SPeter Avalos #include "archive.h"
41*59bf7050SPeter Avalos #include "archive_endian.h"
4260b4ad09SPeter Avalos #include "archive_entry.h"
43c09f92d2SPeter Avalos #include "archive_entry_locale.h"
4460b4ad09SPeter Avalos #include "archive_private.h"
45*59bf7050SPeter Avalos #include "archive_rb.h"
4660b4ad09SPeter Avalos #include "archive_read_private.h"
4760b4ad09SPeter Avalos 
489c82a63eSPeter Avalos #ifndef HAVE_ZLIB_H
499c82a63eSPeter Avalos #include "archive_crc32.h"
509c82a63eSPeter Avalos #endif
519c82a63eSPeter Avalos 
52c09f92d2SPeter Avalos struct zip_entry {
53*59bf7050SPeter Avalos 	struct archive_rb_node	node;
54c09f92d2SPeter Avalos 	int64_t			local_header_offset;
55c09f92d2SPeter Avalos 	int64_t			compressed_size;
56c09f92d2SPeter Avalos 	int64_t			uncompressed_size;
57c09f92d2SPeter Avalos 	int64_t			gid;
58c09f92d2SPeter Avalos 	int64_t			uid;
59c09f92d2SPeter Avalos 	struct archive_entry	*entry;
60c09f92d2SPeter Avalos 	time_t			mtime;
61c09f92d2SPeter Avalos 	time_t			atime;
62c09f92d2SPeter Avalos 	time_t			ctime;
63c09f92d2SPeter Avalos 	uint32_t		crc32;
64c09f92d2SPeter Avalos 	uint16_t		mode;
65c09f92d2SPeter Avalos 	uint16_t		flags;
66c09f92d2SPeter Avalos 	char			compression;
67c09f92d2SPeter Avalos 	char			system;
68c09f92d2SPeter Avalos };
69c09f92d2SPeter Avalos 
7060b4ad09SPeter Avalos struct zip {
71c09f92d2SPeter Avalos 	/* Structural information about the archive. */
72c09f92d2SPeter Avalos 	int64_t			central_directory_offset;
73c09f92d2SPeter Avalos 	size_t			central_directory_size;
74c09f92d2SPeter Avalos 	size_t			central_directory_entries;
75c09f92d2SPeter Avalos 	char			have_central_directory;
76*59bf7050SPeter Avalos 	int64_t			offset;
77c09f92d2SPeter Avalos 
78c09f92d2SPeter Avalos 	/* List of entries (seekable Zip only) */
79c09f92d2SPeter Avalos 	size_t			entries_remaining;
80c09f92d2SPeter Avalos 	struct zip_entry	*zip_entries;
81c09f92d2SPeter Avalos 	struct zip_entry	*entry;
82*59bf7050SPeter Avalos 	struct archive_rb_tree	tree;
83c09f92d2SPeter Avalos 
84c09f92d2SPeter Avalos 	size_t			unconsumed;
85c09f92d2SPeter Avalos 
8660b4ad09SPeter Avalos 	/* entry_bytes_remaining is the number of bytes we expect. */
8760b4ad09SPeter Avalos 	int64_t			entry_bytes_remaining;
8860b4ad09SPeter Avalos 
8960b4ad09SPeter Avalos 	/* These count the number of bytes actually read for the entry. */
9060b4ad09SPeter Avalos 	int64_t			entry_compressed_bytes_read;
9160b4ad09SPeter Avalos 	int64_t			entry_uncompressed_bytes_read;
9260b4ad09SPeter Avalos 
938029ab02SPeter Avalos 	/* Running CRC32 of the decompressed data */
948029ab02SPeter Avalos 	unsigned long		entry_crc32;
958029ab02SPeter Avalos 
9660b4ad09SPeter Avalos 	/* Flags to mark progress of decompression. */
9760b4ad09SPeter Avalos 	char			decompress_init;
9860b4ad09SPeter Avalos 	char			end_of_entry;
9960b4ad09SPeter Avalos 
10060b4ad09SPeter Avalos 	ssize_t			filename_length;
10160b4ad09SPeter Avalos 	ssize_t			extra_length;
10260b4ad09SPeter Avalos 
10360b4ad09SPeter Avalos 	unsigned char 		*uncompressed_buffer;
10460b4ad09SPeter Avalos 	size_t 			uncompressed_buffer_size;
10560b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H
10660b4ad09SPeter Avalos 	z_stream		stream;
10760b4ad09SPeter Avalos 	char			stream_valid;
10860b4ad09SPeter Avalos #endif
10960b4ad09SPeter Avalos 
11060b4ad09SPeter Avalos 	struct archive_string	extra;
111c09f92d2SPeter Avalos 	struct archive_string_conv *sconv;
112c09f92d2SPeter Avalos 	struct archive_string_conv *sconv_default;
113c09f92d2SPeter Avalos 	struct archive_string_conv *sconv_utf8;
114c09f92d2SPeter Avalos 	int			init_default_conversion;
11560b4ad09SPeter Avalos 	char	format_name[64];
11660b4ad09SPeter Avalos };
11760b4ad09SPeter Avalos 
11860b4ad09SPeter Avalos #define ZIP_LENGTH_AT_END	8
119c09f92d2SPeter Avalos #define ZIP_ENCRYPTED		(1<<0)
120c09f92d2SPeter Avalos #define ZIP_STRONG_ENCRYPTED	(1<<6)
121c09f92d2SPeter Avalos #define ZIP_UTF8_NAME		(1<<11)
12260b4ad09SPeter Avalos 
123c09f92d2SPeter Avalos static int	archive_read_format_zip_streamable_bid(struct archive_read *, int);
124c09f92d2SPeter Avalos static int	archive_read_format_zip_seekable_bid(struct archive_read *, int);
125c09f92d2SPeter Avalos static int	archive_read_format_zip_options(struct archive_read *,
126c09f92d2SPeter Avalos 		    const char *, const char *);
12760b4ad09SPeter Avalos static int	archive_read_format_zip_cleanup(struct archive_read *);
12860b4ad09SPeter Avalos static int	archive_read_format_zip_read_data(struct archive_read *,
129c09f92d2SPeter Avalos 		    const void **, size_t *, int64_t *);
13060b4ad09SPeter Avalos static int	archive_read_format_zip_read_data_skip(struct archive_read *a);
131c09f92d2SPeter Avalos static int	archive_read_format_zip_seekable_read_header(struct archive_read *,
13260b4ad09SPeter Avalos 		    struct archive_entry *);
133c09f92d2SPeter Avalos static int	archive_read_format_zip_streamable_read_header(struct archive_read *,
134c09f92d2SPeter Avalos 		    struct archive_entry *);
135c09f92d2SPeter Avalos #ifdef HAVE_ZLIB_H
13660b4ad09SPeter Avalos static int	zip_read_data_deflate(struct archive_read *a, const void **buff,
137c09f92d2SPeter Avalos 		    size_t *size, int64_t *offset);
138c09f92d2SPeter Avalos #endif
13960b4ad09SPeter Avalos static int	zip_read_data_none(struct archive_read *a, const void **buff,
140c09f92d2SPeter Avalos 		    size_t *size, int64_t *offset);
141c09f92d2SPeter Avalos static int	zip_read_local_file_header(struct archive_read *a,
142c09f92d2SPeter Avalos     struct archive_entry *entry, struct zip *);
14360b4ad09SPeter Avalos static time_t	zip_time(const char *);
144c09f92d2SPeter Avalos static const char *compression_name(int compression);
145c09f92d2SPeter Avalos static void process_extra(const char *, size_t, struct zip_entry *);
14660b4ad09SPeter Avalos 
147*59bf7050SPeter Avalos int	archive_read_support_format_zip_streamable(struct archive *);
148*59bf7050SPeter Avalos int	archive_read_support_format_zip_seekable(struct archive *);
149*59bf7050SPeter Avalos 
15060b4ad09SPeter Avalos int
151c09f92d2SPeter Avalos archive_read_support_format_zip_streamable(struct archive *_a)
15260b4ad09SPeter Avalos {
15360b4ad09SPeter Avalos 	struct archive_read *a = (struct archive_read *)_a;
15460b4ad09SPeter Avalos 	struct zip *zip;
15560b4ad09SPeter Avalos 	int r;
15660b4ad09SPeter Avalos 
157c09f92d2SPeter Avalos 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
158c09f92d2SPeter Avalos 	    ARCHIVE_STATE_NEW, "archive_read_support_format_zip");
159c09f92d2SPeter Avalos 
16060b4ad09SPeter Avalos 	zip = (struct zip *)malloc(sizeof(*zip));
16160b4ad09SPeter Avalos 	if (zip == NULL) {
162c09f92d2SPeter Avalos 		archive_set_error(&a->archive, ENOMEM,
163c09f92d2SPeter Avalos 		    "Can't allocate zip data");
16460b4ad09SPeter Avalos 		return (ARCHIVE_FATAL);
16560b4ad09SPeter Avalos 	}
16660b4ad09SPeter Avalos 	memset(zip, 0, sizeof(*zip));
16760b4ad09SPeter Avalos 
16860b4ad09SPeter Avalos 	r = __archive_read_register_format(a,
16960b4ad09SPeter Avalos 	    zip,
1708029ab02SPeter Avalos 	    "zip",
171c09f92d2SPeter Avalos 	    archive_read_format_zip_streamable_bid,
172c09f92d2SPeter Avalos 	    archive_read_format_zip_options,
173c09f92d2SPeter Avalos 	    archive_read_format_zip_streamable_read_header,
17460b4ad09SPeter Avalos 	    archive_read_format_zip_read_data,
17560b4ad09SPeter Avalos 	    archive_read_format_zip_read_data_skip,
17660b4ad09SPeter Avalos 	    archive_read_format_zip_cleanup);
17760b4ad09SPeter Avalos 
17860b4ad09SPeter Avalos 	if (r != ARCHIVE_OK)
17960b4ad09SPeter Avalos 		free(zip);
18060b4ad09SPeter Avalos 	return (ARCHIVE_OK);
18160b4ad09SPeter Avalos }
18260b4ad09SPeter Avalos 
183c09f92d2SPeter Avalos int
184c09f92d2SPeter Avalos archive_read_support_format_zip_seekable(struct archive *_a)
185c09f92d2SPeter Avalos {
186c09f92d2SPeter Avalos 	struct archive_read *a = (struct archive_read *)_a;
187c09f92d2SPeter Avalos 	struct zip *zip;
188c09f92d2SPeter Avalos 	int r;
189c09f92d2SPeter Avalos 
190c09f92d2SPeter Avalos 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
191c09f92d2SPeter Avalos 	    ARCHIVE_STATE_NEW, "archive_read_support_format_zip_seekable");
192c09f92d2SPeter Avalos 
193c09f92d2SPeter Avalos 	zip = (struct zip *)malloc(sizeof(*zip));
194c09f92d2SPeter Avalos 	if (zip == NULL) {
195c09f92d2SPeter Avalos 		archive_set_error(&a->archive, ENOMEM,
196c09f92d2SPeter Avalos 		    "Can't allocate zip data");
197c09f92d2SPeter Avalos 		return (ARCHIVE_FATAL);
198c09f92d2SPeter Avalos 	}
199c09f92d2SPeter Avalos 	memset(zip, 0, sizeof(*zip));
200c09f92d2SPeter Avalos 
201c09f92d2SPeter Avalos 	r = __archive_read_register_format(a,
202c09f92d2SPeter Avalos 	    zip,
203c09f92d2SPeter Avalos 	    "zip",
204c09f92d2SPeter Avalos 	    archive_read_format_zip_seekable_bid,
205c09f92d2SPeter Avalos 	    archive_read_format_zip_options,
206c09f92d2SPeter Avalos 	    archive_read_format_zip_seekable_read_header,
207c09f92d2SPeter Avalos 	    archive_read_format_zip_read_data,
208c09f92d2SPeter Avalos 	    archive_read_format_zip_read_data_skip,
209c09f92d2SPeter Avalos 	    archive_read_format_zip_cleanup);
210c09f92d2SPeter Avalos 
211c09f92d2SPeter Avalos 	if (r != ARCHIVE_OK)
212c09f92d2SPeter Avalos 		free(zip);
213c09f92d2SPeter Avalos 	return (ARCHIVE_OK);
214c09f92d2SPeter Avalos }
215c09f92d2SPeter Avalos 
216c09f92d2SPeter Avalos int
217c09f92d2SPeter Avalos archive_read_support_format_zip(struct archive *a)
218c09f92d2SPeter Avalos {
219c09f92d2SPeter Avalos 	int r;
220c09f92d2SPeter Avalos 	r = archive_read_support_format_zip_streamable(a);
221c09f92d2SPeter Avalos 	if (r != ARCHIVE_OK)
222c09f92d2SPeter Avalos 		return r;
223c09f92d2SPeter Avalos 	return (archive_read_support_format_zip_seekable(a));
224c09f92d2SPeter Avalos }
225c09f92d2SPeter Avalos 
226c09f92d2SPeter Avalos /*
227*59bf7050SPeter Avalos  * TODO: This is a performance sink because it forces the read core to
228*59bf7050SPeter Avalos  * drop buffered data from the start of file, which will then have to
229*59bf7050SPeter Avalos  * be re-read again if this bidder loses.
230c09f92d2SPeter Avalos  *
231*59bf7050SPeter Avalos  * We workaround this a little by passing in the best bid so far so
232*59bf7050SPeter Avalos  * that later bidders can do nothing if they know they'll never
233*59bf7050SPeter Avalos  * outbid.  But we can certainly do better...
234c09f92d2SPeter Avalos  */
235c09f92d2SPeter Avalos static int
236c09f92d2SPeter Avalos archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
237c09f92d2SPeter Avalos {
238c09f92d2SPeter Avalos 	struct zip *zip = (struct zip *)a->format->data;
239c09f92d2SPeter Avalos 	int64_t filesize;
240c09f92d2SPeter Avalos 	const char *p;
241c09f92d2SPeter Avalos 
242c09f92d2SPeter Avalos 	/* If someone has already bid more than 32, then avoid
243c09f92d2SPeter Avalos 	   trashing the look-ahead buffers with a seek. */
244c09f92d2SPeter Avalos 	if (best_bid > 32)
245c09f92d2SPeter Avalos 		return (-1);
246c09f92d2SPeter Avalos 
247c09f92d2SPeter Avalos 	filesize = __archive_read_seek(a, -22, SEEK_END);
248c09f92d2SPeter Avalos 	/* If we can't seek, then we can't bid. */
249c09f92d2SPeter Avalos 	if (filesize <= 0)
250c09f92d2SPeter Avalos 		return 0;
251c09f92d2SPeter Avalos 
252c09f92d2SPeter Avalos 	/* TODO: More robust search for end of central directory record. */
253c09f92d2SPeter Avalos 	if ((p = __archive_read_ahead(a, 22, NULL)) == NULL)
254c09f92d2SPeter Avalos 		return 0;
255c09f92d2SPeter Avalos 	/* First four bytes are signature for end of central directory
256c09f92d2SPeter Avalos 	   record.  Four zero bytes ensure this isn't a multi-volume
257c09f92d2SPeter Avalos 	   Zip file (which we don't yet support). */
258c09f92d2SPeter Avalos 	if (memcmp(p, "PK\005\006\000\000\000\000", 8) != 0)
259c09f92d2SPeter Avalos 		return 0;
260c09f92d2SPeter Avalos 
261c09f92d2SPeter Avalos 	/* Since we've already done the hard work of finding the
262c09f92d2SPeter Avalos 	   end of central directory record, let's save the important
263c09f92d2SPeter Avalos 	   information. */
264c09f92d2SPeter Avalos 	zip->central_directory_entries = archive_le16dec(p + 10);
265c09f92d2SPeter Avalos 	zip->central_directory_size = archive_le32dec(p + 12);
266c09f92d2SPeter Avalos 	zip->central_directory_offset = archive_le32dec(p + 16);
267c09f92d2SPeter Avalos 
268c09f92d2SPeter Avalos 	/* Just one volume, so central dir must all be on this volume. */
269c09f92d2SPeter Avalos 	if (zip->central_directory_entries != archive_le16dec(p + 8))
270c09f92d2SPeter Avalos 		return 0;
271c09f92d2SPeter Avalos 	/* Central directory can't extend beyond end of this file. */
272*59bf7050SPeter Avalos 	if (zip->central_directory_offset + (int64_t)zip->central_directory_size > filesize)
273c09f92d2SPeter Avalos 		return 0;
274c09f92d2SPeter Avalos 
275c09f92d2SPeter Avalos 	/* This is just a tiny bit higher than the maximum returned by
276c09f92d2SPeter Avalos 	   the streaming Zip bidder.  This ensures that the more accurate
277c09f92d2SPeter Avalos 	   seeking Zip parser wins whenever seek is available. */
278c09f92d2SPeter Avalos 	return 32;
279c09f92d2SPeter Avalos }
28060b4ad09SPeter Avalos 
28160b4ad09SPeter Avalos static int
282*59bf7050SPeter Avalos cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2)
283*59bf7050SPeter Avalos {
284*59bf7050SPeter Avalos 	const struct zip_entry *e1 = (const struct zip_entry *)n1;
285*59bf7050SPeter Avalos 	const struct zip_entry *e2 = (const struct zip_entry *)n2;
286*59bf7050SPeter Avalos 
287*59bf7050SPeter Avalos 	return ((int)(e2->local_header_offset - e1->local_header_offset));
288*59bf7050SPeter Avalos }
289*59bf7050SPeter Avalos 
290*59bf7050SPeter Avalos static int
291*59bf7050SPeter Avalos cmp_key(const struct archive_rb_node *n, const void *key)
292*59bf7050SPeter Avalos {
293*59bf7050SPeter Avalos 	/* This function won't be called */
294*59bf7050SPeter Avalos 	(void)n; /* UNUSED */
295*59bf7050SPeter Avalos 	(void)key; /* UNUSED */
296*59bf7050SPeter Avalos 	return 1;
297*59bf7050SPeter Avalos }
298*59bf7050SPeter Avalos 
299*59bf7050SPeter Avalos static int
300c09f92d2SPeter Avalos slurp_central_directory(struct archive_read *a, struct zip *zip)
301c09f92d2SPeter Avalos {
302c09f92d2SPeter Avalos 	unsigned i;
303*59bf7050SPeter Avalos 	static const struct archive_rb_tree_ops rb_ops = {
304*59bf7050SPeter Avalos 		&cmp_node, &cmp_key
305*59bf7050SPeter Avalos 	};
306c09f92d2SPeter Avalos 
307c09f92d2SPeter Avalos 	__archive_read_seek(a, zip->central_directory_offset, SEEK_SET);
308*59bf7050SPeter Avalos 	zip->offset = zip->central_directory_offset;
309*59bf7050SPeter Avalos 	__archive_rb_tree_init(&zip->tree, &rb_ops);
310c09f92d2SPeter Avalos 
311*59bf7050SPeter Avalos 	zip->zip_entries = calloc(zip->central_directory_entries,
312*59bf7050SPeter Avalos 				sizeof(struct zip_entry));
313c09f92d2SPeter Avalos 	for (i = 0; i < zip->central_directory_entries; ++i) {
314c09f92d2SPeter Avalos 		struct zip_entry *zip_entry = &zip->zip_entries[i];
315c09f92d2SPeter Avalos 		size_t filename_length, extra_length, comment_length;
316c09f92d2SPeter Avalos 		uint32_t external_attributes;
317c09f92d2SPeter Avalos 		const char *p;
318c09f92d2SPeter Avalos 
319c09f92d2SPeter Avalos 		if ((p = __archive_read_ahead(a, 46, NULL)) == NULL)
320c09f92d2SPeter Avalos 			return ARCHIVE_FATAL;
321c09f92d2SPeter Avalos 		if (memcmp(p, "PK\001\002", 4) != 0) {
322c09f92d2SPeter Avalos 			archive_set_error(&a->archive,
323c09f92d2SPeter Avalos 			    -1, "Invalid central directory signature");
324c09f92d2SPeter Avalos 			return ARCHIVE_FATAL;
325c09f92d2SPeter Avalos 		}
326c09f92d2SPeter Avalos 		zip->have_central_directory = 1;
327c09f92d2SPeter Avalos 		/* version = p[4]; */
328c09f92d2SPeter Avalos 		zip_entry->system = p[5];
329c09f92d2SPeter Avalos 		/* version_required = archive_le16dec(p + 6); */
330c09f92d2SPeter Avalos 		zip_entry->flags = archive_le16dec(p + 8);
331*59bf7050SPeter Avalos 		zip_entry->compression = (char)archive_le16dec(p + 10);
332c09f92d2SPeter Avalos 		zip_entry->mtime = zip_time(p + 12);
333c09f92d2SPeter Avalos 		zip_entry->crc32 = archive_le32dec(p + 16);
334c09f92d2SPeter Avalos 		zip_entry->compressed_size = archive_le32dec(p + 20);
335c09f92d2SPeter Avalos 		zip_entry->uncompressed_size = archive_le32dec(p + 24);
336c09f92d2SPeter Avalos 		filename_length = archive_le16dec(p + 28);
337c09f92d2SPeter Avalos 		extra_length = archive_le16dec(p + 30);
338c09f92d2SPeter Avalos 		comment_length = archive_le16dec(p + 32);
339c09f92d2SPeter Avalos 		/* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */
340c09f92d2SPeter Avalos 		/* internal_attributes = archive_le16dec(p + 36); */ /* text bit */
341c09f92d2SPeter Avalos 		external_attributes = archive_le32dec(p + 38);
342c09f92d2SPeter Avalos 		zip_entry->local_header_offset = archive_le32dec(p + 42);
343c09f92d2SPeter Avalos 
344*59bf7050SPeter Avalos 		/* If we can't guess the mode, leave it zero here;
345*59bf7050SPeter Avalos 		   when we read the local file header we might get
346*59bf7050SPeter Avalos 		   more information. */
347*59bf7050SPeter Avalos 		zip_entry->mode = 0;
348c09f92d2SPeter Avalos 		if (zip_entry->system == 3) {
349c09f92d2SPeter Avalos 			zip_entry->mode = external_attributes >> 16;
350c09f92d2SPeter Avalos 		}
351*59bf7050SPeter Avalos 		/* Register an entry to RB tree to sort it by file offset. */
352*59bf7050SPeter Avalos 		__archive_rb_tree_insert_node(&zip->tree, &zip_entry->node);
353c09f92d2SPeter Avalos 
354*59bf7050SPeter Avalos 		/* We don't read the filename until we get to the
355*59bf7050SPeter Avalos 		   local file header.  Reading it here would speed up
356*59bf7050SPeter Avalos 		   table-of-contents operations (removing the need to
357*59bf7050SPeter Avalos 		   find and read local file header to get the
358*59bf7050SPeter Avalos 		   filename) at the cost of requiring a lot of extra
359*59bf7050SPeter Avalos 		   space. */
360*59bf7050SPeter Avalos 		/* We don't read the extra block here.  We assume it
361*59bf7050SPeter Avalos 		   will be duplicated at the local file header. */
362c09f92d2SPeter Avalos 		__archive_read_consume(a,
363c09f92d2SPeter Avalos 		    46 + filename_length + extra_length + comment_length);
364c09f92d2SPeter Avalos 	}
365c09f92d2SPeter Avalos 
366c09f92d2SPeter Avalos 	return ARCHIVE_OK;
367c09f92d2SPeter Avalos }
368c09f92d2SPeter Avalos 
369*59bf7050SPeter Avalos static int64_t
370*59bf7050SPeter Avalos zip_read_consume(struct archive_read *a, int64_t bytes)
371*59bf7050SPeter Avalos {
372*59bf7050SPeter Avalos 	struct zip *zip = (struct zip *)a->format->data;
373*59bf7050SPeter Avalos 	int64_t skip;
374*59bf7050SPeter Avalos 
375*59bf7050SPeter Avalos 	skip = __archive_read_consume(a, bytes);
376*59bf7050SPeter Avalos 	if (skip > 0)
377*59bf7050SPeter Avalos 		zip->offset += skip;
378*59bf7050SPeter Avalos 	return (skip);
379*59bf7050SPeter Avalos }
380*59bf7050SPeter Avalos 
381c09f92d2SPeter Avalos static int
382c09f92d2SPeter Avalos archive_read_format_zip_seekable_read_header(struct archive_read *a,
383c09f92d2SPeter Avalos 	struct archive_entry *entry)
384c09f92d2SPeter Avalos {
385c09f92d2SPeter Avalos 	struct zip *zip = (struct zip *)a->format->data;
386*59bf7050SPeter Avalos 	int r, ret = ARCHIVE_OK;
387c09f92d2SPeter Avalos 
388c09f92d2SPeter Avalos 	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
389c09f92d2SPeter Avalos 	if (a->archive.archive_format_name == NULL)
390c09f92d2SPeter Avalos 		a->archive.archive_format_name = "ZIP";
391c09f92d2SPeter Avalos 
392c09f92d2SPeter Avalos 	if (zip->zip_entries == NULL) {
393c09f92d2SPeter Avalos 		r = slurp_central_directory(a, zip);
394c09f92d2SPeter Avalos 		zip->entries_remaining = zip->central_directory_entries;
395c09f92d2SPeter Avalos 		if (r != ARCHIVE_OK)
396c09f92d2SPeter Avalos 			return r;
397*59bf7050SPeter Avalos 		/* Get first entry whose local header offset is lower than
398*59bf7050SPeter Avalos 		 * other entries in the archive file. */
399*59bf7050SPeter Avalos 		zip->entry =
400*59bf7050SPeter Avalos 		    (struct zip_entry *)ARCHIVE_RB_TREE_MIN(&zip->tree);
401*59bf7050SPeter Avalos 	} else if (zip->entry != NULL) {
402*59bf7050SPeter Avalos 		/* Get next entry in local header offset order. */
403*59bf7050SPeter Avalos 		zip->entry = (struct zip_entry *)__archive_rb_tree_iterate(
404*59bf7050SPeter Avalos 		    &zip->tree, &zip->entry->node, ARCHIVE_RB_DIR_RIGHT);
405c09f92d2SPeter Avalos 	}
406c09f92d2SPeter Avalos 
407*59bf7050SPeter Avalos 	if (zip->entries_remaining <= 0 || zip->entry == NULL)
408c09f92d2SPeter Avalos 		return ARCHIVE_EOF;
409c09f92d2SPeter Avalos 	--zip->entries_remaining;
410c09f92d2SPeter Avalos 
411*59bf7050SPeter Avalos 	if (zip->offset != zip->entry->local_header_offset) {
412*59bf7050SPeter Avalos 		__archive_read_seek(a, zip->entry->local_header_offset,
413*59bf7050SPeter Avalos 			SEEK_SET);
414*59bf7050SPeter Avalos 		zip->offset = zip->entry->local_header_offset;
415*59bf7050SPeter Avalos 	}
416c09f92d2SPeter Avalos 	zip->unconsumed = 0;
417c09f92d2SPeter Avalos 	r = zip_read_local_file_header(a, entry, zip);
418c09f92d2SPeter Avalos 	if (r != ARCHIVE_OK)
419c09f92d2SPeter Avalos 		return r;
420c09f92d2SPeter Avalos 	if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) {
421c09f92d2SPeter Avalos 		const void *p;
422*59bf7050SPeter Avalos 		struct archive_string_conv *sconv;
423*59bf7050SPeter Avalos 		size_t linkname_length = (size_t)archive_entry_size(entry);
424c09f92d2SPeter Avalos 
425c09f92d2SPeter Avalos 		archive_entry_set_size(entry, 0);
426c09f92d2SPeter Avalos 		p = __archive_read_ahead(a, linkname_length, NULL);
427c09f92d2SPeter Avalos 		if (p == NULL) {
428c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
429c09f92d2SPeter Avalos 			    "Truncated Zip file");
430c09f92d2SPeter Avalos 			return ARCHIVE_FATAL;
431c09f92d2SPeter Avalos 		}
432c09f92d2SPeter Avalos 
433*59bf7050SPeter Avalos 		sconv = zip->sconv;
434*59bf7050SPeter Avalos 		if (sconv == NULL && (zip->entry->flags & ZIP_UTF8_NAME))
435*59bf7050SPeter Avalos 			sconv = zip->sconv_utf8;
436*59bf7050SPeter Avalos 		if (sconv == NULL)
437*59bf7050SPeter Avalos 			sconv = zip->sconv_default;
438c09f92d2SPeter Avalos 		if (archive_entry_copy_symlink_l(entry, p, linkname_length,
439*59bf7050SPeter Avalos 		    sconv) != 0) {
440*59bf7050SPeter Avalos 			if (errno != ENOMEM && sconv == zip->sconv_utf8 &&
441*59bf7050SPeter Avalos 			    (zip->entry->flags & ZIP_UTF8_NAME))
442*59bf7050SPeter Avalos 			    archive_entry_copy_symlink_l(entry, p,
443*59bf7050SPeter Avalos 				linkname_length, NULL);
444*59bf7050SPeter Avalos 			if (errno == ENOMEM) {
445c09f92d2SPeter Avalos 				archive_set_error(&a->archive, ENOMEM,
446c09f92d2SPeter Avalos 				    "Can't allocate memory for Symlink");
447c09f92d2SPeter Avalos 				return (ARCHIVE_FATAL);
448c09f92d2SPeter Avalos 			}
449*59bf7050SPeter Avalos 			/*
450*59bf7050SPeter Avalos 			 * Since there is no character-set regulation for
451*59bf7050SPeter Avalos 			 * symlink name, do not report the conversion error
452*59bf7050SPeter Avalos 			 * in an automatic conversion.
453*59bf7050SPeter Avalos 			 */
454*59bf7050SPeter Avalos 			if (sconv != zip->sconv_utf8 ||
455*59bf7050SPeter Avalos 			    (zip->entry->flags & ZIP_UTF8_NAME) == 0) {
456*59bf7050SPeter Avalos 				archive_set_error(&a->archive,
457*59bf7050SPeter Avalos 				    ARCHIVE_ERRNO_FILE_FORMAT,
458*59bf7050SPeter Avalos 				    "Symlink cannot be converted "
459*59bf7050SPeter Avalos 				    "from %s to current locale.",
460*59bf7050SPeter Avalos 				    archive_string_conversion_charset_name(
461*59bf7050SPeter Avalos 					sconv));
462*59bf7050SPeter Avalos 				ret = ARCHIVE_WARN;
463c09f92d2SPeter Avalos 			}
464*59bf7050SPeter Avalos 		}
465*59bf7050SPeter Avalos 	}
466*59bf7050SPeter Avalos 	return (ret);
467c09f92d2SPeter Avalos }
468c09f92d2SPeter Avalos 
469c09f92d2SPeter Avalos static int
470c09f92d2SPeter Avalos archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid)
47160b4ad09SPeter Avalos {
47260b4ad09SPeter Avalos 	const char *p;
473c09f92d2SPeter Avalos 
474c09f92d2SPeter Avalos 	(void)best_bid; /* UNUSED */
47560b4ad09SPeter Avalos 
4768029ab02SPeter Avalos 	if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
47760b4ad09SPeter Avalos 		return (-1);
47860b4ad09SPeter Avalos 
47960b4ad09SPeter Avalos 	/*
48060b4ad09SPeter Avalos 	 * Bid of 30 here is: 16 bits for "PK",
48160b4ad09SPeter Avalos 	 * next 16-bit field has four options (-2 bits).
48260b4ad09SPeter Avalos 	 * 16 + 16-2 = 30.
48360b4ad09SPeter Avalos 	 */
48460b4ad09SPeter Avalos 	if (p[0] == 'P' && p[1] == 'K') {
48560b4ad09SPeter Avalos 		if ((p[2] == '\001' && p[3] == '\002')
48660b4ad09SPeter Avalos 		    || (p[2] == '\003' && p[3] == '\004')
48760b4ad09SPeter Avalos 		    || (p[2] == '\005' && p[3] == '\006')
48860b4ad09SPeter Avalos 		    || (p[2] == '\007' && p[3] == '\010')
48960b4ad09SPeter Avalos 		    || (p[2] == '0' && p[3] == '0'))
49060b4ad09SPeter Avalos 			return (30);
49160b4ad09SPeter Avalos 	}
49260b4ad09SPeter Avalos 
493*59bf7050SPeter Avalos 	/* TODO: It's worth looking ahead a little bit for a valid
494*59bf7050SPeter Avalos 	 * PK signature.  In particular, that would make it possible
495*59bf7050SPeter Avalos 	 * to read some UUEncoded SFX files or SFX files coming from
496*59bf7050SPeter Avalos 	 * a network socket. */
497*59bf7050SPeter Avalos 
49860b4ad09SPeter Avalos 	return (0);
49960b4ad09SPeter Avalos }
50060b4ad09SPeter Avalos 
50160b4ad09SPeter Avalos static int
502c09f92d2SPeter Avalos archive_read_format_zip_options(struct archive_read *a,
503c09f92d2SPeter Avalos     const char *key, const char *val)
50460b4ad09SPeter Avalos {
505c09f92d2SPeter Avalos 	struct zip *zip;
506c09f92d2SPeter Avalos 	int ret = ARCHIVE_FAILED;
50760b4ad09SPeter Avalos 
508c09f92d2SPeter Avalos 	zip = (struct zip *)(a->format->data);
509c09f92d2SPeter Avalos 	if (strcmp(key, "compat-2x")  == 0) {
510c09f92d2SPeter Avalos 		/* Handle filnames as libarchive 2.x */
511c09f92d2SPeter Avalos 		zip->init_default_conversion = (val != NULL) ? 1 : 0;
512*59bf7050SPeter Avalos 		return (ARCHIVE_OK);
513c09f92d2SPeter Avalos 	} else if (strcmp(key, "hdrcharset")  == 0) {
514c09f92d2SPeter Avalos 		if (val == NULL || val[0] == 0)
515c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
516c09f92d2SPeter Avalos 			    "zip: hdrcharset option needs a character-set name");
517c09f92d2SPeter Avalos 		else {
518c09f92d2SPeter Avalos 			zip->sconv = archive_string_conversion_from_charset(
519c09f92d2SPeter Avalos 			    &a->archive, val, 0);
520c09f92d2SPeter Avalos 			if (zip->sconv != NULL) {
521c09f92d2SPeter Avalos 				if (strcmp(val, "UTF-8") == 0)
522c09f92d2SPeter Avalos 					zip->sconv_utf8 = zip->sconv;
523c09f92d2SPeter Avalos 				ret = ARCHIVE_OK;
524c09f92d2SPeter Avalos 			} else
525c09f92d2SPeter Avalos 				ret = ARCHIVE_FATAL;
526c09f92d2SPeter Avalos 		}
527c09f92d2SPeter Avalos 		return (ret);
52860b4ad09SPeter Avalos 	}
52960b4ad09SPeter Avalos 
530*59bf7050SPeter Avalos 	/* Note: The "warn" return is just to inform the options
531*59bf7050SPeter Avalos 	 * supervisor that we didn't handle it.  It will generate
532*59bf7050SPeter Avalos 	 * a suitable error if no one used this option. */
533*59bf7050SPeter Avalos 	return (ARCHIVE_WARN);
534*59bf7050SPeter Avalos }
535*59bf7050SPeter Avalos 
53660b4ad09SPeter Avalos static int
537c09f92d2SPeter Avalos archive_read_format_zip_streamable_read_header(struct archive_read *a,
53860b4ad09SPeter Avalos     struct archive_entry *entry)
53960b4ad09SPeter Avalos {
54060b4ad09SPeter Avalos 	struct zip *zip;
54160b4ad09SPeter Avalos 
54260b4ad09SPeter Avalos 	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
54360b4ad09SPeter Avalos 	if (a->archive.archive_format_name == NULL)
54460b4ad09SPeter Avalos 		a->archive.archive_format_name = "ZIP";
54560b4ad09SPeter Avalos 
54660b4ad09SPeter Avalos 	zip = (struct zip *)(a->format->data);
547c09f92d2SPeter Avalos 
548c09f92d2SPeter Avalos 	/* Make sure we have a zip_entry structure to use. */
549c09f92d2SPeter Avalos 	if (zip->zip_entries == NULL) {
550c09f92d2SPeter Avalos 		zip->zip_entries = malloc(sizeof(struct zip_entry));
551c09f92d2SPeter Avalos 		if (zip->zip_entries == NULL) {
552c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ENOMEM, "Out  of memory");
553c09f92d2SPeter Avalos 			return ARCHIVE_FATAL;
554c09f92d2SPeter Avalos 		}
555c09f92d2SPeter Avalos 	}
556c09f92d2SPeter Avalos 	zip->entry = zip->zip_entries;
557c09f92d2SPeter Avalos 	memset(zip->entry, 0, sizeof(struct zip_entry));
558c09f92d2SPeter Avalos 
559c09f92d2SPeter Avalos 	/* Search ahead for the next local file header. */
560*59bf7050SPeter Avalos 	zip_read_consume(a, zip->unconsumed);
561c09f92d2SPeter Avalos 	zip->unconsumed = 0;
562c09f92d2SPeter Avalos 	for (;;) {
563c09f92d2SPeter Avalos 		int64_t skipped = 0;
564c09f92d2SPeter Avalos 		const char *p, *end;
565c09f92d2SPeter Avalos 		ssize_t bytes;
566c09f92d2SPeter Avalos 
567c09f92d2SPeter Avalos 		p = __archive_read_ahead(a, 4, &bytes);
568c09f92d2SPeter Avalos 		if (p == NULL)
569c09f92d2SPeter Avalos 			return (ARCHIVE_FATAL);
570c09f92d2SPeter Avalos 		end = p + bytes;
571c09f92d2SPeter Avalos 
572c09f92d2SPeter Avalos 		while (p + 4 <= end) {
573c09f92d2SPeter Avalos 			if (p[0] == 'P' && p[1] == 'K') {
574c09f92d2SPeter Avalos 				if (p[2] == '\001' && p[3] == '\002')
575c09f92d2SPeter Avalos 					/* Beginning of central directory. */
576c09f92d2SPeter Avalos 					return (ARCHIVE_EOF);
577c09f92d2SPeter Avalos 
578c09f92d2SPeter Avalos 				if (p[2] == '\003' && p[3] == '\004') {
579c09f92d2SPeter Avalos 					/* Regular file entry. */
580*59bf7050SPeter Avalos 					zip_read_consume(a, skipped);
581c09f92d2SPeter Avalos 					return zip_read_local_file_header(a, entry, zip);
582c09f92d2SPeter Avalos 				}
583c09f92d2SPeter Avalos 
584c09f92d2SPeter Avalos 				if (p[2] == '\005' && p[3] == '\006')
585c09f92d2SPeter Avalos 					/* End of central directory. */
586c09f92d2SPeter Avalos 					return (ARCHIVE_EOF);
587c09f92d2SPeter Avalos 			}
588c09f92d2SPeter Avalos 			++p;
589c09f92d2SPeter Avalos 			++skipped;
590c09f92d2SPeter Avalos 		}
591*59bf7050SPeter Avalos 		zip_read_consume(a, skipped);
592c09f92d2SPeter Avalos 	}
593c09f92d2SPeter Avalos }
594c09f92d2SPeter Avalos 
595c09f92d2SPeter Avalos /*
596c09f92d2SPeter Avalos  * Assumes file pointer is at beginning of local file header.
597c09f92d2SPeter Avalos  */
598c09f92d2SPeter Avalos static int
599c09f92d2SPeter Avalos zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
600c09f92d2SPeter Avalos     struct zip *zip)
601c09f92d2SPeter Avalos {
602c09f92d2SPeter Avalos 	const char *p;
603c09f92d2SPeter Avalos 	const void *h;
604c09f92d2SPeter Avalos 	const wchar_t *wp;
605c09f92d2SPeter Avalos 	const char *cp;
606c09f92d2SPeter Avalos 	size_t len, filename_length, extra_length;
607c09f92d2SPeter Avalos 	struct archive_string_conv *sconv;
608c09f92d2SPeter Avalos 	struct zip_entry *zip_entry = zip->entry;
609c09f92d2SPeter Avalos 	uint32_t local_crc32;
610c09f92d2SPeter Avalos 	int64_t compressed_size, uncompressed_size;
611c09f92d2SPeter Avalos 	int ret = ARCHIVE_OK;
612c09f92d2SPeter Avalos 	char version;
613c09f92d2SPeter Avalos 
61460b4ad09SPeter Avalos 	zip->decompress_init = 0;
61560b4ad09SPeter Avalos 	zip->end_of_entry = 0;
61660b4ad09SPeter Avalos 	zip->entry_uncompressed_bytes_read = 0;
61760b4ad09SPeter Avalos 	zip->entry_compressed_bytes_read = 0;
6188029ab02SPeter Avalos 	zip->entry_crc32 = crc32(0, NULL, 0);
61960b4ad09SPeter Avalos 
620c09f92d2SPeter Avalos 	/* Setup default conversion. */
621c09f92d2SPeter Avalos 	if (zip->sconv == NULL && !zip->init_default_conversion) {
622c09f92d2SPeter Avalos 		zip->sconv_default =
623c09f92d2SPeter Avalos 		    archive_string_default_conversion_for_read(&(a->archive));
624c09f92d2SPeter Avalos 		zip->init_default_conversion = 1;
62560b4ad09SPeter Avalos 	}
62660b4ad09SPeter Avalos 
627c09f92d2SPeter Avalos 	if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) {
62860b4ad09SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
62960b4ad09SPeter Avalos 		    "Truncated ZIP file header");
63060b4ad09SPeter Avalos 		return (ARCHIVE_FATAL);
63160b4ad09SPeter Avalos 	}
63260b4ad09SPeter Avalos 
633c09f92d2SPeter Avalos 	if (memcmp(p, "PK\003\004", 4) != 0) {
634c09f92d2SPeter Avalos 		archive_set_error(&a->archive, -1, "Damaged Zip archive");
635c09f92d2SPeter Avalos 		return ARCHIVE_FATAL;
636c09f92d2SPeter Avalos 	}
637c09f92d2SPeter Avalos 	version = p[4];
638c09f92d2SPeter Avalos 	zip_entry->system = p[5];
639c09f92d2SPeter Avalos 	zip_entry->flags = archive_le16dec(p + 6);
640*59bf7050SPeter Avalos 	zip_entry->compression = (char)archive_le16dec(p + 8);
641c09f92d2SPeter Avalos 	zip_entry->mtime = zip_time(p + 10);
642c09f92d2SPeter Avalos 	local_crc32 = archive_le32dec(p + 14);
643c09f92d2SPeter Avalos 	compressed_size = archive_le32dec(p + 18);
644c09f92d2SPeter Avalos 	uncompressed_size = archive_le32dec(p + 22);
645c09f92d2SPeter Avalos 	filename_length = archive_le16dec(p + 26);
646c09f92d2SPeter Avalos 	extra_length = archive_le16dec(p + 28);
64760b4ad09SPeter Avalos 
648*59bf7050SPeter Avalos 	zip_read_consume(a, 30);
64960b4ad09SPeter Avalos 
650c09f92d2SPeter Avalos 	if (zip->have_central_directory) {
651c09f92d2SPeter Avalos 		/* If we read the central dir entry, we must have size information
652c09f92d2SPeter Avalos 		   as well, so ignore the length-at-end flag. */
653c09f92d2SPeter Avalos 		zip_entry->flags &= ~ZIP_LENGTH_AT_END;
654c09f92d2SPeter Avalos 		/* If we have values from both the local file header
655c09f92d2SPeter Avalos 		   and the central directory, warn about mismatches
656c09f92d2SPeter Avalos 		   which might indicate a damaged file.  But some
657c09f92d2SPeter Avalos 		   writers always put zero in the local header; don't
658c09f92d2SPeter Avalos 		   bother warning about that. */
659c09f92d2SPeter Avalos 		if (local_crc32 != 0 && local_crc32 != zip_entry->crc32) {
660c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
661c09f92d2SPeter Avalos 			    "Inconsistent CRC32 values");
662c09f92d2SPeter Avalos 			ret = ARCHIVE_WARN;
663c09f92d2SPeter Avalos 		}
664c09f92d2SPeter Avalos 		if (compressed_size != 0
665c09f92d2SPeter Avalos 		    && compressed_size != zip_entry->compressed_size) {
666c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
667c09f92d2SPeter Avalos 			    "Inconsistent compressed size");
668c09f92d2SPeter Avalos 			ret = ARCHIVE_WARN;
669c09f92d2SPeter Avalos 		}
670c09f92d2SPeter Avalos 		if (uncompressed_size != 0
671c09f92d2SPeter Avalos 		    && uncompressed_size != zip_entry->uncompressed_size) {
672c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
673c09f92d2SPeter Avalos 			    "Inconsistent uncompressed size");
674c09f92d2SPeter Avalos 			ret = ARCHIVE_WARN;
675c09f92d2SPeter Avalos 		}
676c09f92d2SPeter Avalos 	} else {
677c09f92d2SPeter Avalos 		/* If we don't have the CD info, use whatever we do have. */
678c09f92d2SPeter Avalos 		zip_entry->crc32 = local_crc32;
679c09f92d2SPeter Avalos 		zip_entry->compressed_size = compressed_size;
680c09f92d2SPeter Avalos 		zip_entry->uncompressed_size = uncompressed_size;
681c09f92d2SPeter Avalos 	}
68260b4ad09SPeter Avalos 
68360b4ad09SPeter Avalos 	/* Read the filename. */
684c09f92d2SPeter Avalos 	if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) {
68560b4ad09SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
68660b4ad09SPeter Avalos 		    "Truncated ZIP file header");
68760b4ad09SPeter Avalos 		return (ARCHIVE_FATAL);
68860b4ad09SPeter Avalos 	}
689c09f92d2SPeter Avalos 	if (zip_entry->flags & ZIP_UTF8_NAME) {
690c09f92d2SPeter Avalos 		/* The filename is stored to be UTF-8. */
691c09f92d2SPeter Avalos 		if (zip->sconv_utf8 == NULL) {
692c09f92d2SPeter Avalos 			zip->sconv_utf8 =
693c09f92d2SPeter Avalos 			    archive_string_conversion_from_charset(
694c09f92d2SPeter Avalos 				&a->archive, "UTF-8", 1);
695c09f92d2SPeter Avalos 			if (zip->sconv_utf8 == NULL)
696c09f92d2SPeter Avalos 				return (ARCHIVE_FATAL);
697c09f92d2SPeter Avalos 		}
698c09f92d2SPeter Avalos 		sconv = zip->sconv_utf8;
699c09f92d2SPeter Avalos 	} else if (zip->sconv != NULL)
700c09f92d2SPeter Avalos 		sconv = zip->sconv;
70160b4ad09SPeter Avalos 	else
702c09f92d2SPeter Avalos 		sconv = zip->sconv_default;
703c09f92d2SPeter Avalos 
704c09f92d2SPeter Avalos 	if (archive_entry_copy_pathname_l(entry,
705c09f92d2SPeter Avalos 	    h, filename_length, sconv) != 0) {
706c09f92d2SPeter Avalos 		if (errno == ENOMEM) {
707c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ENOMEM,
708c09f92d2SPeter Avalos 			    "Can't allocate memory for Pathname");
709c09f92d2SPeter Avalos 			return (ARCHIVE_FATAL);
710c09f92d2SPeter Avalos 		}
711c09f92d2SPeter Avalos 		archive_set_error(&a->archive,
712c09f92d2SPeter Avalos 		    ARCHIVE_ERRNO_FILE_FORMAT,
713c09f92d2SPeter Avalos 		    "Pathname cannot be converted "
714c09f92d2SPeter Avalos 		    "from %s to current locale.",
715c09f92d2SPeter Avalos 		    archive_string_conversion_charset_name(sconv));
716c09f92d2SPeter Avalos 		ret = ARCHIVE_WARN;
717c09f92d2SPeter Avalos 	}
718*59bf7050SPeter Avalos 	zip_read_consume(a, filename_length);
719c09f92d2SPeter Avalos 
720c09f92d2SPeter Avalos 	if (zip_entry->mode == 0) {
721c09f92d2SPeter Avalos 		/* Especially in streaming mode, we can end up
722c09f92d2SPeter Avalos 		   here without having seen any mode information.
723c09f92d2SPeter Avalos 		   Guess from the filename. */
724c09f92d2SPeter Avalos 		wp = archive_entry_pathname_w(entry);
725c09f92d2SPeter Avalos 		if (wp != NULL) {
726c09f92d2SPeter Avalos 			len = wcslen(wp);
727c09f92d2SPeter Avalos 			if (len > 0 && wp[len - 1] == L'/')
728c09f92d2SPeter Avalos 				zip_entry->mode = AE_IFDIR | 0777;
729c09f92d2SPeter Avalos 			else
730*59bf7050SPeter Avalos 				zip_entry->mode = AE_IFREG | 0666;
731c09f92d2SPeter Avalos 		} else {
732c09f92d2SPeter Avalos 			cp = archive_entry_pathname(entry);
733c09f92d2SPeter Avalos 			len = (cp != NULL)?strlen(cp):0;
734c09f92d2SPeter Avalos 			if (len > 0 && cp[len - 1] == '/')
735c09f92d2SPeter Avalos 				zip_entry->mode = AE_IFDIR | 0777;
736c09f92d2SPeter Avalos 			else
737*59bf7050SPeter Avalos 				zip_entry->mode = AE_IFREG | 0666;
738c09f92d2SPeter Avalos 		}
739c09f92d2SPeter Avalos 	}
74060b4ad09SPeter Avalos 
74160b4ad09SPeter Avalos 	/* Read the extra data. */
742c09f92d2SPeter Avalos 	if ((h = __archive_read_ahead(a, extra_length, NULL)) == NULL) {
74360b4ad09SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
74460b4ad09SPeter Avalos 		    "Truncated ZIP file header");
74560b4ad09SPeter Avalos 		return (ARCHIVE_FATAL);
74660b4ad09SPeter Avalos 	}
747c09f92d2SPeter Avalos 	process_extra(h, extra_length, zip_entry);
748*59bf7050SPeter Avalos 	zip_read_consume(a, extra_length);
74960b4ad09SPeter Avalos 
75060b4ad09SPeter Avalos 	/* Populate some additional entry fields: */
751c09f92d2SPeter Avalos 	archive_entry_set_mode(entry, zip_entry->mode);
752c09f92d2SPeter Avalos 	archive_entry_set_uid(entry, zip_entry->uid);
753c09f92d2SPeter Avalos 	archive_entry_set_gid(entry, zip_entry->gid);
754c09f92d2SPeter Avalos 	archive_entry_set_mtime(entry, zip_entry->mtime, 0);
755c09f92d2SPeter Avalos 	archive_entry_set_ctime(entry, zip_entry->ctime, 0);
756c09f92d2SPeter Avalos 	archive_entry_set_atime(entry, zip_entry->atime, 0);
7578029ab02SPeter Avalos 	/* Set the size only if it's meaningful. */
758c09f92d2SPeter Avalos 	if (0 == (zip_entry->flags & ZIP_LENGTH_AT_END))
759c09f92d2SPeter Avalos 		archive_entry_set_size(entry, zip_entry->uncompressed_size);
76060b4ad09SPeter Avalos 
761c09f92d2SPeter Avalos 	zip->entry_bytes_remaining = zip_entry->compressed_size;
76260b4ad09SPeter Avalos 
76360b4ad09SPeter Avalos 	/* If there's no body, force read_data() to return EOF immediately. */
764c09f92d2SPeter Avalos 	if (0 == (zip_entry->flags & ZIP_LENGTH_AT_END)
76560b4ad09SPeter Avalos 	    && zip->entry_bytes_remaining < 1)
76660b4ad09SPeter Avalos 		zip->end_of_entry = 1;
76760b4ad09SPeter Avalos 
76860b4ad09SPeter Avalos 	/* Set up a more descriptive format name. */
76960b4ad09SPeter Avalos 	sprintf(zip->format_name, "ZIP %d.%d (%s)",
770c09f92d2SPeter Avalos 	    version / 10, version % 10,
771c09f92d2SPeter Avalos 	    compression_name(zip->entry->compression));
77260b4ad09SPeter Avalos 	a->archive.archive_format_name = zip->format_name;
77360b4ad09SPeter Avalos 
774c09f92d2SPeter Avalos 	return (ret);
775c09f92d2SPeter Avalos }
776c09f92d2SPeter Avalos 
777c09f92d2SPeter Avalos static const char *
778c09f92d2SPeter Avalos compression_name(int compression)
779c09f92d2SPeter Avalos {
780c09f92d2SPeter Avalos 	static const char *compression_names[] = {
781c09f92d2SPeter Avalos 		"uncompressed",
782c09f92d2SPeter Avalos 		"shrinking",
783c09f92d2SPeter Avalos 		"reduced-1",
784c09f92d2SPeter Avalos 		"reduced-2",
785c09f92d2SPeter Avalos 		"reduced-3",
786c09f92d2SPeter Avalos 		"reduced-4",
787c09f92d2SPeter Avalos 		"imploded",
788c09f92d2SPeter Avalos 		"reserved",
789c09f92d2SPeter Avalos 		"deflation"
790c09f92d2SPeter Avalos 	};
791c09f92d2SPeter Avalos 
792*59bf7050SPeter Avalos 	if (0 <= compression && compression <
793*59bf7050SPeter Avalos 	    (int)(sizeof(compression_names)/sizeof(compression_names[0])))
794c09f92d2SPeter Avalos 		return compression_names[compression];
795c09f92d2SPeter Avalos 	else
796c09f92d2SPeter Avalos 		return "??";
79760b4ad09SPeter Avalos }
79860b4ad09SPeter Avalos 
79960b4ad09SPeter Avalos /* Convert an MSDOS-style date/time into Unix-style time. */
80060b4ad09SPeter Avalos static time_t
80160b4ad09SPeter Avalos zip_time(const char *p)
80260b4ad09SPeter Avalos {
80360b4ad09SPeter Avalos 	int msTime, msDate;
80460b4ad09SPeter Avalos 	struct tm ts;
80560b4ad09SPeter Avalos 
80660b4ad09SPeter Avalos 	msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]);
80760b4ad09SPeter Avalos 	msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]);
80860b4ad09SPeter Avalos 
80960b4ad09SPeter Avalos 	memset(&ts, 0, sizeof(ts));
81060b4ad09SPeter Avalos 	ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
81160b4ad09SPeter Avalos 	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
81260b4ad09SPeter Avalos 	ts.tm_mday = msDate & 0x1f; /* Day of month. */
81360b4ad09SPeter Avalos 	ts.tm_hour = (msTime >> 11) & 0x1f;
81460b4ad09SPeter Avalos 	ts.tm_min = (msTime >> 5) & 0x3f;
81560b4ad09SPeter Avalos 	ts.tm_sec = (msTime << 1) & 0x3e;
81660b4ad09SPeter Avalos 	ts.tm_isdst = -1;
81760b4ad09SPeter Avalos 	return mktime(&ts);
81860b4ad09SPeter Avalos }
81960b4ad09SPeter Avalos 
82060b4ad09SPeter Avalos static int
82160b4ad09SPeter Avalos archive_read_format_zip_read_data(struct archive_read *a,
822c09f92d2SPeter Avalos     const void **buff, size_t *size, int64_t *offset)
82360b4ad09SPeter Avalos {
82460b4ad09SPeter Avalos 	int r;
825c09f92d2SPeter Avalos 	struct zip *zip = (struct zip *)(a->format->data);
82660b4ad09SPeter Avalos 
82760b4ad09SPeter Avalos 	*offset = zip->entry_uncompressed_bytes_read;
82860b4ad09SPeter Avalos 	*size = 0;
82960b4ad09SPeter Avalos 	*buff = NULL;
830c09f92d2SPeter Avalos 
831c09f92d2SPeter Avalos 	/* If we hit end-of-entry last time, return ARCHIVE_EOF. */
832c09f92d2SPeter Avalos 	if (zip->end_of_entry)
83360b4ad09SPeter Avalos 		return (ARCHIVE_EOF);
834c09f92d2SPeter Avalos 
835c09f92d2SPeter Avalos 	/* Return EOF immediately if this is a non-regular file. */
836c09f92d2SPeter Avalos 	if (AE_IFREG != (zip->entry->mode & AE_IFMT))
837c09f92d2SPeter Avalos 		return (ARCHIVE_EOF);
838c09f92d2SPeter Avalos 
839c09f92d2SPeter Avalos 	if (zip->entry->flags & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)) {
840c09f92d2SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
841c09f92d2SPeter Avalos 		    "Encrypted file is unsupported");
842c09f92d2SPeter Avalos 		return (ARCHIVE_FAILED);
84360b4ad09SPeter Avalos 	}
84460b4ad09SPeter Avalos 
845*59bf7050SPeter Avalos 	zip_read_consume(a, zip->unconsumed);
846c09f92d2SPeter Avalos 	zip->unconsumed = 0;
847c09f92d2SPeter Avalos 
848c09f92d2SPeter Avalos 	switch(zip->entry->compression) {
84960b4ad09SPeter Avalos 	case 0:  /* No compression. */
85060b4ad09SPeter Avalos 		r =  zip_read_data_none(a, buff, size, offset);
85160b4ad09SPeter Avalos 		break;
852c09f92d2SPeter Avalos #ifdef HAVE_ZLIB_H
85360b4ad09SPeter Avalos 	case 8: /* Deflate compression. */
85460b4ad09SPeter Avalos 		r =  zip_read_data_deflate(a, buff, size, offset);
85560b4ad09SPeter Avalos 		break;
856c09f92d2SPeter Avalos #endif
85760b4ad09SPeter Avalos 	default: /* Unsupported compression. */
85860b4ad09SPeter Avalos 		/* Return a warning. */
85960b4ad09SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
86060b4ad09SPeter Avalos 		    "Unsupported ZIP compression method (%s)",
861c09f92d2SPeter Avalos 		    compression_name(zip->entry->compression));
86260b4ad09SPeter Avalos 		/* We can't decompress this entry, but we will
86360b4ad09SPeter Avalos 		 * be able to skip() it and try the next entry. */
864c09f92d2SPeter Avalos 		return (ARCHIVE_FAILED);
86560b4ad09SPeter Avalos 		break;
86660b4ad09SPeter Avalos 	}
8678029ab02SPeter Avalos 	if (r != ARCHIVE_OK)
86860b4ad09SPeter Avalos 		return (r);
8698029ab02SPeter Avalos 	/* Update checksum */
8708029ab02SPeter Avalos 	if (*size)
8719c82a63eSPeter Avalos 		zip->entry_crc32 = crc32(zip->entry_crc32, *buff, *size);
8728029ab02SPeter Avalos 	/* If we hit the end, swallow any end-of-data marker. */
8738029ab02SPeter Avalos 	if (zip->end_of_entry) {
8748029ab02SPeter Avalos 		/* Check file size, CRC against these values. */
875c09f92d2SPeter Avalos 		if (zip->entry->compressed_size != zip->entry_compressed_bytes_read) {
8768029ab02SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
877c09f92d2SPeter Avalos 			    "ZIP compressed data is wrong size (read %jd, expected %jd)",
878c09f92d2SPeter Avalos 			    (intmax_t)zip->entry_compressed_bytes_read,
879c09f92d2SPeter Avalos 			    (intmax_t)zip->entry->compressed_size);
8808029ab02SPeter Avalos 			return (ARCHIVE_WARN);
8818029ab02SPeter Avalos 		}
882c09f92d2SPeter Avalos 		/* Size field only stores the lower 32 bits of the actual
883c09f92d2SPeter Avalos 		 * size. */
884c09f92d2SPeter Avalos 		if ((zip->entry->uncompressed_size & UINT32_MAX)
8858029ab02SPeter Avalos 		    != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
8868029ab02SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
887c09f92d2SPeter Avalos 			    "ZIP uncompressed data is wrong size (read %jd, expected %jd)",
888c09f92d2SPeter Avalos 			    (intmax_t)zip->entry_uncompressed_bytes_read,
889c09f92d2SPeter Avalos 			    (intmax_t)zip->entry->uncompressed_size);
8908029ab02SPeter Avalos 			return (ARCHIVE_WARN);
8918029ab02SPeter Avalos 		}
8928029ab02SPeter Avalos 		/* Check computed CRC against header */
893c09f92d2SPeter Avalos 		if (zip->entry->crc32 != zip->entry_crc32) {
8948029ab02SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
8958029ab02SPeter Avalos 			    "ZIP bad CRC: 0x%lx should be 0x%lx",
896c09f92d2SPeter Avalos 			    (unsigned long)zip->entry_crc32,
897c09f92d2SPeter Avalos 			    (unsigned long)zip->entry->crc32);
8988029ab02SPeter Avalos 			return (ARCHIVE_WARN);
8998029ab02SPeter Avalos 		}
9008029ab02SPeter Avalos 	}
9018029ab02SPeter Avalos 
9028029ab02SPeter Avalos 	return (ARCHIVE_OK);
90360b4ad09SPeter Avalos }
90460b4ad09SPeter Avalos 
90560b4ad09SPeter Avalos /*
906c09f92d2SPeter Avalos  * Read "uncompressed" data.  There are three cases:
907c09f92d2SPeter Avalos  *  1) We know the size of the data.  This is always true for the
908c09f92d2SPeter Avalos  * seeking reader (we've examined the Central Directory already).
909c09f92d2SPeter Avalos  *  2) ZIP_LENGTH_AT_END was set, but only the CRC was deferred.
910c09f92d2SPeter Avalos  * Info-ZIP seems to do this; we know the size but have to grab
911c09f92d2SPeter Avalos  * the CRC from the data descriptor afterwards.
912c09f92d2SPeter Avalos  *  3) We're streaming and ZIP_LENGTH_AT_END was specified and
913c09f92d2SPeter Avalos  * we have no size information.  In this case, we can do pretty
914c09f92d2SPeter Avalos  * well by watching for the data descriptor record.  The data
915c09f92d2SPeter Avalos  * descriptor is 16 bytes and includes a computed CRC that should
916c09f92d2SPeter Avalos  * provide a strong check.
917c09f92d2SPeter Avalos  *
918c09f92d2SPeter Avalos  * TODO: Technically, the PK\007\010 signature is optional.
919c09f92d2SPeter Avalos  * In the original spec, the data descriptor contained CRC
920c09f92d2SPeter Avalos  * and size fields but had no leading signature.  In practice,
921c09f92d2SPeter Avalos  * newer writers seem to provide the signature pretty consistently,
922c09f92d2SPeter Avalos  * but we might need to do something more complex here if
923c09f92d2SPeter Avalos  * we want to handle older archives that lack that signature.
92460b4ad09SPeter Avalos  *
92560b4ad09SPeter Avalos  * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets
92660b4ad09SPeter Avalos  * zip->end_of_entry if it consumes all of the data.
92760b4ad09SPeter Avalos  */
92860b4ad09SPeter Avalos static int
929c09f92d2SPeter Avalos zip_read_data_none(struct archive_read *a, const void **_buff,
930c09f92d2SPeter Avalos     size_t *size, int64_t *offset)
93160b4ad09SPeter Avalos {
93260b4ad09SPeter Avalos 	struct zip *zip;
933c09f92d2SPeter Avalos 	const char *buff;
93460b4ad09SPeter Avalos 	ssize_t bytes_avail;
93560b4ad09SPeter Avalos 
936*59bf7050SPeter Avalos 	(void)offset; /* UNUSED */
937*59bf7050SPeter Avalos 
93860b4ad09SPeter Avalos 	zip = (struct zip *)(a->format->data);
93960b4ad09SPeter Avalos 
940c09f92d2SPeter Avalos 	if (zip->entry->flags & ZIP_LENGTH_AT_END) {
941c09f92d2SPeter Avalos 		const char *p;
942c09f92d2SPeter Avalos 
943c09f92d2SPeter Avalos 		/* Grab at least 16 bytes. */
944c09f92d2SPeter Avalos 		buff = __archive_read_ahead(a, 16, &bytes_avail);
945c09f92d2SPeter Avalos 		if (bytes_avail < 16) {
946c09f92d2SPeter Avalos 			/* Zip archives have end-of-archive markers
947c09f92d2SPeter Avalos 			   that are longer than this, so a failure to get at
948c09f92d2SPeter Avalos 			   least 16 bytes really does indicate a truncated
949c09f92d2SPeter Avalos 			   file. */
950c09f92d2SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
951c09f92d2SPeter Avalos 			    "Truncated ZIP file data");
952c09f92d2SPeter Avalos 			return (ARCHIVE_FATAL);
953c09f92d2SPeter Avalos 		}
954c09f92d2SPeter Avalos 		/* Check for a complete PK\007\010 signature. */
955c09f92d2SPeter Avalos 		p = buff;
956c09f92d2SPeter Avalos 		if (p[0] == 'P' && p[1] == 'K'
957c09f92d2SPeter Avalos 		    && p[2] == '\007' && p[3] == '\010'
958c09f92d2SPeter Avalos 		    && archive_le32dec(p + 4) == zip->entry_crc32
959c09f92d2SPeter Avalos 		    && archive_le32dec(p + 8) == zip->entry_compressed_bytes_read
960c09f92d2SPeter Avalos 		    && archive_le32dec(p + 12) == zip->entry_uncompressed_bytes_read) {
961c09f92d2SPeter Avalos 			zip->entry->crc32 = archive_le32dec(p + 4);
962c09f92d2SPeter Avalos 			zip->entry->compressed_size = archive_le32dec(p + 8);
963c09f92d2SPeter Avalos 			zip->entry->uncompressed_size = archive_le32dec(p + 12);
964c09f92d2SPeter Avalos 			zip->end_of_entry = 1;
965c09f92d2SPeter Avalos 			zip->unconsumed = 16;
966c09f92d2SPeter Avalos 			return (ARCHIVE_OK);
967c09f92d2SPeter Avalos 		}
968c09f92d2SPeter Avalos 		/* If not at EOF, ensure we consume at least one byte. */
969c09f92d2SPeter Avalos 		++p;
970c09f92d2SPeter Avalos 
971c09f92d2SPeter Avalos 		/* Scan forward until we see where a PK\007\010 signature might be. */
972c09f92d2SPeter Avalos 		/* Return bytes up until that point.  On the next call, the code
973c09f92d2SPeter Avalos 		   above will verify the data descriptor. */
974c09f92d2SPeter Avalos 		while (p < buff + bytes_avail - 4) {
975c09f92d2SPeter Avalos 			if (p[3] == 'P') { p += 3; }
976c09f92d2SPeter Avalos 			else if (p[3] == 'K') { p += 2; }
977c09f92d2SPeter Avalos 			else if (p[3] == '\007') { p += 1; }
978c09f92d2SPeter Avalos 			else if (p[3] == '\010' && p[2] == '\007'
979c09f92d2SPeter Avalos 			    && p[1] == 'K' && p[0] == 'P') {
980c09f92d2SPeter Avalos 				break;
981c09f92d2SPeter Avalos 			} else { p += 4; }
982c09f92d2SPeter Avalos 		}
983c09f92d2SPeter Avalos 		bytes_avail = p - buff;
984c09f92d2SPeter Avalos 	} else {
98560b4ad09SPeter Avalos 		if (zip->entry_bytes_remaining == 0) {
98660b4ad09SPeter Avalos 			zip->end_of_entry = 1;
98760b4ad09SPeter Avalos 			return (ARCHIVE_OK);
98860b4ad09SPeter Avalos 		}
989c09f92d2SPeter Avalos 		/* Grab a bunch of bytes. */
990c09f92d2SPeter Avalos 		buff = __archive_read_ahead(a, 1, &bytes_avail);
99160b4ad09SPeter Avalos 		if (bytes_avail <= 0) {
99260b4ad09SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
99360b4ad09SPeter Avalos 			    "Truncated ZIP file data");
99460b4ad09SPeter Avalos 			return (ARCHIVE_FATAL);
99560b4ad09SPeter Avalos 		}
99660b4ad09SPeter Avalos 		if (bytes_avail > zip->entry_bytes_remaining)
997*59bf7050SPeter Avalos 			bytes_avail = (ssize_t)zip->entry_bytes_remaining;
998c09f92d2SPeter Avalos 	}
99960b4ad09SPeter Avalos 	*size = bytes_avail;
1000c09f92d2SPeter Avalos 	zip->entry_bytes_remaining -= bytes_avail;
1001c09f92d2SPeter Avalos 	zip->entry_uncompressed_bytes_read += bytes_avail;
1002c09f92d2SPeter Avalos 	zip->entry_compressed_bytes_read += bytes_avail;
1003c09f92d2SPeter Avalos 	zip->unconsumed += bytes_avail;
1004c09f92d2SPeter Avalos 	*_buff = buff;
100560b4ad09SPeter Avalos 	return (ARCHIVE_OK);
100660b4ad09SPeter Avalos }
100760b4ad09SPeter Avalos 
100860b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H
100960b4ad09SPeter Avalos static int
101060b4ad09SPeter Avalos zip_read_data_deflate(struct archive_read *a, const void **buff,
1011c09f92d2SPeter Avalos     size_t *size, int64_t *offset)
101260b4ad09SPeter Avalos {
101360b4ad09SPeter Avalos 	struct zip *zip;
101460b4ad09SPeter Avalos 	ssize_t bytes_avail;
101560b4ad09SPeter Avalos 	const void *compressed_buff;
101660b4ad09SPeter Avalos 	int r;
101760b4ad09SPeter Avalos 
1018*59bf7050SPeter Avalos 	(void)offset; /* UNUSED */
1019*59bf7050SPeter Avalos 
102060b4ad09SPeter Avalos 	zip = (struct zip *)(a->format->data);
102160b4ad09SPeter Avalos 
102260b4ad09SPeter Avalos 	/* If the buffer hasn't been allocated, allocate it now. */
102360b4ad09SPeter Avalos 	if (zip->uncompressed_buffer == NULL) {
1024c09f92d2SPeter Avalos 		zip->uncompressed_buffer_size = 256 * 1024;
102560b4ad09SPeter Avalos 		zip->uncompressed_buffer
102660b4ad09SPeter Avalos 		    = (unsigned char *)malloc(zip->uncompressed_buffer_size);
102760b4ad09SPeter Avalos 		if (zip->uncompressed_buffer == NULL) {
102860b4ad09SPeter Avalos 			archive_set_error(&a->archive, ENOMEM,
102960b4ad09SPeter Avalos 			    "No memory for ZIP decompression");
103060b4ad09SPeter Avalos 			return (ARCHIVE_FATAL);
103160b4ad09SPeter Avalos 		}
103260b4ad09SPeter Avalos 	}
103360b4ad09SPeter Avalos 
103460b4ad09SPeter Avalos 	/* If we haven't yet read any data, initialize the decompressor. */
103560b4ad09SPeter Avalos 	if (!zip->decompress_init) {
103660b4ad09SPeter Avalos 		if (zip->stream_valid)
103760b4ad09SPeter Avalos 			r = inflateReset(&zip->stream);
103860b4ad09SPeter Avalos 		else
103960b4ad09SPeter Avalos 			r = inflateInit2(&zip->stream,
104060b4ad09SPeter Avalos 			    -15 /* Don't check for zlib header */);
104160b4ad09SPeter Avalos 		if (r != Z_OK) {
104260b4ad09SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
104360b4ad09SPeter Avalos 			    "Can't initialize ZIP decompression.");
104460b4ad09SPeter Avalos 			return (ARCHIVE_FATAL);
104560b4ad09SPeter Avalos 		}
104660b4ad09SPeter Avalos 		/* Stream structure has been set up. */
104760b4ad09SPeter Avalos 		zip->stream_valid = 1;
104860b4ad09SPeter Avalos 		/* We've initialized decompression for this stream. */
104960b4ad09SPeter Avalos 		zip->decompress_init = 1;
105060b4ad09SPeter Avalos 	}
105160b4ad09SPeter Avalos 
105260b4ad09SPeter Avalos 	/*
105360b4ad09SPeter Avalos 	 * Note: '1' here is a performance optimization.
105460b4ad09SPeter Avalos 	 * Recall that the decompression layer returns a count of
105560b4ad09SPeter Avalos 	 * available bytes; asking for more than that forces the
105660b4ad09SPeter Avalos 	 * decompressor to combine reads by copying data.
105760b4ad09SPeter Avalos 	 */
10588029ab02SPeter Avalos 	compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
1059c09f92d2SPeter Avalos 	if (0 == (zip->entry->flags & ZIP_LENGTH_AT_END)
1060c09f92d2SPeter Avalos 	    && bytes_avail > zip->entry_bytes_remaining) {
1061*59bf7050SPeter Avalos 		bytes_avail = (ssize_t)zip->entry_bytes_remaining;
1062c09f92d2SPeter Avalos 	}
106360b4ad09SPeter Avalos 	if (bytes_avail <= 0) {
106460b4ad09SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
106560b4ad09SPeter Avalos 		    "Truncated ZIP file body");
106660b4ad09SPeter Avalos 		return (ARCHIVE_FATAL);
106760b4ad09SPeter Avalos 	}
106860b4ad09SPeter Avalos 
106960b4ad09SPeter Avalos 	/*
107060b4ad09SPeter Avalos 	 * A bug in zlib.h: stream.next_in should be marked 'const'
107160b4ad09SPeter Avalos 	 * but isn't (the library never alters data through the
107260b4ad09SPeter Avalos 	 * next_in pointer, only reads it).  The result: this ugly
107360b4ad09SPeter Avalos 	 * cast to remove 'const'.
107460b4ad09SPeter Avalos 	 */
107560b4ad09SPeter Avalos 	zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff;
107660b4ad09SPeter Avalos 	zip->stream.avail_in = bytes_avail;
107760b4ad09SPeter Avalos 	zip->stream.total_in = 0;
107860b4ad09SPeter Avalos 	zip->stream.next_out = zip->uncompressed_buffer;
107960b4ad09SPeter Avalos 	zip->stream.avail_out = zip->uncompressed_buffer_size;
108060b4ad09SPeter Avalos 	zip->stream.total_out = 0;
108160b4ad09SPeter Avalos 
108260b4ad09SPeter Avalos 	r = inflate(&zip->stream, 0);
108360b4ad09SPeter Avalos 	switch (r) {
108460b4ad09SPeter Avalos 	case Z_OK:
108560b4ad09SPeter Avalos 		break;
108660b4ad09SPeter Avalos 	case Z_STREAM_END:
108760b4ad09SPeter Avalos 		zip->end_of_entry = 1;
108860b4ad09SPeter Avalos 		break;
108960b4ad09SPeter Avalos 	case Z_MEM_ERROR:
109060b4ad09SPeter Avalos 		archive_set_error(&a->archive, ENOMEM,
109160b4ad09SPeter Avalos 		    "Out of memory for ZIP decompression");
109260b4ad09SPeter Avalos 		return (ARCHIVE_FATAL);
109360b4ad09SPeter Avalos 	default:
109460b4ad09SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
109560b4ad09SPeter Avalos 		    "ZIP decompression failed (%d)", r);
109660b4ad09SPeter Avalos 		return (ARCHIVE_FATAL);
109760b4ad09SPeter Avalos 	}
109860b4ad09SPeter Avalos 
109960b4ad09SPeter Avalos 	/* Consume as much as the compressor actually used. */
110060b4ad09SPeter Avalos 	bytes_avail = zip->stream.total_in;
1101*59bf7050SPeter Avalos 	zip_read_consume(a, bytes_avail);
110260b4ad09SPeter Avalos 	zip->entry_bytes_remaining -= bytes_avail;
110360b4ad09SPeter Avalos 	zip->entry_compressed_bytes_read += bytes_avail;
110460b4ad09SPeter Avalos 
110560b4ad09SPeter Avalos 	*size = zip->stream.total_out;
1106c09f92d2SPeter Avalos 	zip->entry_uncompressed_bytes_read += zip->stream.total_out;
110760b4ad09SPeter Avalos 	*buff = zip->uncompressed_buffer;
1108c09f92d2SPeter Avalos 
1109c09f92d2SPeter Avalos 	if (zip->end_of_entry && (zip->entry->flags & ZIP_LENGTH_AT_END)) {
1110c09f92d2SPeter Avalos 		const char *p;
1111c09f92d2SPeter Avalos 
1112c09f92d2SPeter Avalos 		if (NULL == (p = __archive_read_ahead(a, 16, NULL))) {
1113c09f92d2SPeter Avalos 			archive_set_error(&a->archive,
1114c09f92d2SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
1115c09f92d2SPeter Avalos 			    "Truncated ZIP end-of-file record");
111660b4ad09SPeter Avalos 			return (ARCHIVE_FATAL);
111760b4ad09SPeter Avalos 		}
1118c09f92d2SPeter Avalos 		/* Consume the optional PK\007\010 marker. */
1119c09f92d2SPeter Avalos 		if (p[0] == 'P' && p[1] == 'K' && p[2] == '\007' && p[3] == '\010') {
1120c09f92d2SPeter Avalos 			zip->entry->crc32 = archive_le32dec(p + 4);
1121c09f92d2SPeter Avalos 			zip->entry->compressed_size = archive_le32dec(p + 8);
1122c09f92d2SPeter Avalos 			zip->entry->uncompressed_size = archive_le32dec(p + 12);
1123c09f92d2SPeter Avalos 			zip->unconsumed = 16;
1124c09f92d2SPeter Avalos 		}
1125c09f92d2SPeter Avalos 	}
1126c09f92d2SPeter Avalos 
1127c09f92d2SPeter Avalos 	return (ARCHIVE_OK);
1128c09f92d2SPeter Avalos }
112960b4ad09SPeter Avalos #endif
113060b4ad09SPeter Avalos 
113160b4ad09SPeter Avalos static int
113260b4ad09SPeter Avalos archive_read_format_zip_read_data_skip(struct archive_read *a)
113360b4ad09SPeter Avalos {
113460b4ad09SPeter Avalos 	struct zip *zip;
113560b4ad09SPeter Avalos 
113660b4ad09SPeter Avalos 	zip = (struct zip *)(a->format->data);
113760b4ad09SPeter Avalos 
113860b4ad09SPeter Avalos 	/* If we've already read to end of data, we're done. */
11398029ab02SPeter Avalos 	if (zip->end_of_entry)
114060b4ad09SPeter Avalos 		return (ARCHIVE_OK);
114160b4ad09SPeter Avalos 
1142c09f92d2SPeter Avalos 	/* So we know we're streaming... */
1143c09f92d2SPeter Avalos 	if (0 == (zip->entry->flags & ZIP_LENGTH_AT_END)) {
1144c09f92d2SPeter Avalos 		/* We know the compressed length, so we can just skip. */
1145*59bf7050SPeter Avalos 		int64_t bytes_skipped = zip_read_consume(a,
1146c09f92d2SPeter Avalos 		    zip->entry_bytes_remaining + zip->unconsumed);
114760b4ad09SPeter Avalos 		if (bytes_skipped < 0)
114860b4ad09SPeter Avalos 			return (ARCHIVE_FATAL);
1149c09f92d2SPeter Avalos 		zip->unconsumed = 0;
115060b4ad09SPeter Avalos 		return (ARCHIVE_OK);
115160b4ad09SPeter Avalos 	}
115260b4ad09SPeter Avalos 
1153c09f92d2SPeter Avalos 	/* We're streaming and we don't know the length. */
1154c09f92d2SPeter Avalos 	/* If the body is compressed and we know the format, we can
1155c09f92d2SPeter Avalos 	 * find an exact end-of-entry by decompressing it. */
1156c09f92d2SPeter Avalos 	switch (zip->entry->compression) {
1157c09f92d2SPeter Avalos #ifdef HAVE_ZLIB_H
1158c09f92d2SPeter Avalos 	case 8: /* Deflate compression. */
1159c09f92d2SPeter Avalos 		while (!zip->end_of_entry) {
1160c09f92d2SPeter Avalos 			int64_t offset = 0;
1161c09f92d2SPeter Avalos 			const void *buff = NULL;
1162c09f92d2SPeter Avalos 			size_t size = 0;
1163c09f92d2SPeter Avalos 			int r;
1164c09f92d2SPeter Avalos 			r =  zip_read_data_deflate(a, &buff, &size, &offset);
1165c09f92d2SPeter Avalos 			if (r != ARCHIVE_OK)
1166c09f92d2SPeter Avalos 				return (r);
1167c09f92d2SPeter Avalos 		}
1168*59bf7050SPeter Avalos 		return ARCHIVE_OK;
1169c09f92d2SPeter Avalos #endif
1170c09f92d2SPeter Avalos 	default: /* Uncompressed or unknown. */
1171c09f92d2SPeter Avalos 		/* Scan for a PK\007\010 signature. */
1172*59bf7050SPeter Avalos 		zip_read_consume(a, zip->unconsumed);
1173c09f92d2SPeter Avalos 		zip->unconsumed = 0;
1174c09f92d2SPeter Avalos 		for (;;) {
1175c09f92d2SPeter Avalos 			const char *p, *buff;
1176c09f92d2SPeter Avalos 			ssize_t bytes_avail;
1177c09f92d2SPeter Avalos 			buff = __archive_read_ahead(a, 16, &bytes_avail);
1178c09f92d2SPeter Avalos 			if (bytes_avail < 16) {
1179c09f92d2SPeter Avalos 				archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1180c09f92d2SPeter Avalos 				    "Truncated ZIP file data");
1181c09f92d2SPeter Avalos 				return (ARCHIVE_FATAL);
1182c09f92d2SPeter Avalos 			}
1183c09f92d2SPeter Avalos 			p = buff;
1184*59bf7050SPeter Avalos 			while (p <= buff + bytes_avail - 16) {
1185c09f92d2SPeter Avalos 				if (p[3] == 'P') { p += 3; }
1186c09f92d2SPeter Avalos 				else if (p[3] == 'K') { p += 2; }
1187c09f92d2SPeter Avalos 				else if (p[3] == '\007') { p += 1; }
1188c09f92d2SPeter Avalos 				else if (p[3] == '\010' && p[2] == '\007'
1189c09f92d2SPeter Avalos 				    && p[1] == 'K' && p[0] == 'P') {
1190*59bf7050SPeter Avalos 					zip_read_consume(a, p - buff + 16);
1191c09f92d2SPeter Avalos 					return ARCHIVE_OK;
1192c09f92d2SPeter Avalos 				} else { p += 4; }
1193c09f92d2SPeter Avalos 			}
1194*59bf7050SPeter Avalos 			zip_read_consume(a, p - buff);
1195c09f92d2SPeter Avalos 		}
1196c09f92d2SPeter Avalos 	}
1197c09f92d2SPeter Avalos }
1198c09f92d2SPeter Avalos 
119960b4ad09SPeter Avalos static int
120060b4ad09SPeter Avalos archive_read_format_zip_cleanup(struct archive_read *a)
120160b4ad09SPeter Avalos {
120260b4ad09SPeter Avalos 	struct zip *zip;
120360b4ad09SPeter Avalos 
120460b4ad09SPeter Avalos 	zip = (struct zip *)(a->format->data);
120560b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H
120660b4ad09SPeter Avalos 	if (zip->stream_valid)
120760b4ad09SPeter Avalos 		inflateEnd(&zip->stream);
120860b4ad09SPeter Avalos #endif
1209c09f92d2SPeter Avalos 	free(zip->zip_entries);
121060b4ad09SPeter Avalos 	free(zip->uncompressed_buffer);
121160b4ad09SPeter Avalos 	archive_string_free(&(zip->extra));
121260b4ad09SPeter Avalos 	free(zip);
121360b4ad09SPeter Avalos 	(a->format->data) = NULL;
121460b4ad09SPeter Avalos 	return (ARCHIVE_OK);
121560b4ad09SPeter Avalos }
121660b4ad09SPeter Avalos 
121760b4ad09SPeter Avalos /*
121860b4ad09SPeter Avalos  * The extra data is stored as a list of
121960b4ad09SPeter Avalos  *	id1+size1+data1 + id2+size2+data2 ...
122060b4ad09SPeter Avalos  *  triplets.  id and size are 2 bytes each.
122160b4ad09SPeter Avalos  */
122260b4ad09SPeter Avalos static void
1223c09f92d2SPeter Avalos process_extra(const char *p, size_t extra_length, struct zip_entry* zip_entry)
122460b4ad09SPeter Avalos {
1225c09f92d2SPeter Avalos 	unsigned offset = 0;
1226c09f92d2SPeter Avalos 
1227c09f92d2SPeter Avalos 	while (offset < extra_length - 4)
122860b4ad09SPeter Avalos 	{
122960b4ad09SPeter Avalos 		unsigned short headerid = archive_le16dec(p + offset);
123060b4ad09SPeter Avalos 		unsigned short datasize = archive_le16dec(p + offset + 2);
123160b4ad09SPeter Avalos 		offset += 4;
1232c09f92d2SPeter Avalos 		if (offset + datasize > extra_length)
123360b4ad09SPeter Avalos 			break;
123460b4ad09SPeter Avalos #ifdef DEBUG
1235c09f92d2SPeter Avalos 		fprintf(stderr, "Header id 0x%x, length %d\n",
123660b4ad09SPeter Avalos 		    headerid, datasize);
123760b4ad09SPeter Avalos #endif
123860b4ad09SPeter Avalos 		switch (headerid) {
123960b4ad09SPeter Avalos 		case 0x0001:
124060b4ad09SPeter Avalos 			/* Zip64 extended information extra field. */
124160b4ad09SPeter Avalos 			if (datasize >= 8)
1242c09f92d2SPeter Avalos 				zip_entry->uncompressed_size =
1243c09f92d2SPeter Avalos 				    archive_le64dec(p + offset);
124460b4ad09SPeter Avalos 			if (datasize >= 16)
1245c09f92d2SPeter Avalos 				zip_entry->compressed_size =
1246c09f92d2SPeter Avalos 				    archive_le64dec(p + offset + 8);
124760b4ad09SPeter Avalos 			break;
124860b4ad09SPeter Avalos 		case 0x5455:
124960b4ad09SPeter Avalos 		{
125060b4ad09SPeter Avalos 			/* Extended time field "UT". */
125160b4ad09SPeter Avalos 			int flags = p[offset];
125260b4ad09SPeter Avalos 			offset++;
125360b4ad09SPeter Avalos 			datasize--;
125460b4ad09SPeter Avalos 			/* Flag bits indicate which dates are present. */
125560b4ad09SPeter Avalos 			if (flags & 0x01)
125660b4ad09SPeter Avalos 			{
125760b4ad09SPeter Avalos #ifdef DEBUG
125860b4ad09SPeter Avalos 				fprintf(stderr, "mtime: %lld -> %d\n",
1259c09f92d2SPeter Avalos 				    (long long)zip_entry->mtime,
126060b4ad09SPeter Avalos 				    archive_le32dec(p + offset));
126160b4ad09SPeter Avalos #endif
126260b4ad09SPeter Avalos 				if (datasize < 4)
126360b4ad09SPeter Avalos 					break;
1264c09f92d2SPeter Avalos 				zip_entry->mtime = archive_le32dec(p + offset);
126560b4ad09SPeter Avalos 				offset += 4;
126660b4ad09SPeter Avalos 				datasize -= 4;
126760b4ad09SPeter Avalos 			}
126860b4ad09SPeter Avalos 			if (flags & 0x02)
126960b4ad09SPeter Avalos 			{
127060b4ad09SPeter Avalos 				if (datasize < 4)
127160b4ad09SPeter Avalos 					break;
1272c09f92d2SPeter Avalos 				zip_entry->atime = archive_le32dec(p + offset);
127360b4ad09SPeter Avalos 				offset += 4;
127460b4ad09SPeter Avalos 				datasize -= 4;
127560b4ad09SPeter Avalos 			}
127660b4ad09SPeter Avalos 			if (flags & 0x04)
127760b4ad09SPeter Avalos 			{
127860b4ad09SPeter Avalos 				if (datasize < 4)
127960b4ad09SPeter Avalos 					break;
1280c09f92d2SPeter Avalos 				zip_entry->ctime = archive_le32dec(p + offset);
128160b4ad09SPeter Avalos 				offset += 4;
128260b4ad09SPeter Avalos 				datasize -= 4;
128360b4ad09SPeter Avalos 			}
128460b4ad09SPeter Avalos 			break;
128560b4ad09SPeter Avalos 		}
1286c09f92d2SPeter Avalos 		case 0x5855:
1287c09f92d2SPeter Avalos 		{
1288c09f92d2SPeter Avalos 			/* Info-ZIP Unix Extra Field (old version) "UX". */
1289c09f92d2SPeter Avalos 			if (datasize >= 8) {
1290c09f92d2SPeter Avalos 				zip_entry->atime = archive_le32dec(p + offset);
1291c09f92d2SPeter Avalos 				zip_entry->mtime = archive_le32dec(p + offset + 4);
1292c09f92d2SPeter Avalos 			}
1293c09f92d2SPeter Avalos 			if (datasize >= 12) {
1294c09f92d2SPeter Avalos 				zip_entry->uid = archive_le16dec(p + offset + 8);
1295c09f92d2SPeter Avalos 				zip_entry->gid = archive_le16dec(p + offset + 10);
1296c09f92d2SPeter Avalos 			}
1297c09f92d2SPeter Avalos 			break;
1298c09f92d2SPeter Avalos 		}
129960b4ad09SPeter Avalos 		case 0x7855:
130060b4ad09SPeter Avalos 			/* Info-ZIP Unix Extra Field (type 2) "Ux". */
130160b4ad09SPeter Avalos #ifdef DEBUG
130260b4ad09SPeter Avalos 			fprintf(stderr, "uid %d gid %d\n",
130360b4ad09SPeter Avalos 			    archive_le16dec(p + offset),
130460b4ad09SPeter Avalos 			    archive_le16dec(p + offset + 2));
130560b4ad09SPeter Avalos #endif
130660b4ad09SPeter Avalos 			if (datasize >= 2)
1307c09f92d2SPeter Avalos 				zip_entry->uid = archive_le16dec(p + offset);
130860b4ad09SPeter Avalos 			if (datasize >= 4)
1309c09f92d2SPeter Avalos 				zip_entry->gid = archive_le16dec(p + offset + 2);
131060b4ad09SPeter Avalos 			break;
1311c09f92d2SPeter Avalos 		case 0x7875:
1312c09f92d2SPeter Avalos 		{
1313c09f92d2SPeter Avalos 			/* Info-Zip Unix Extra Field (type 3) "ux". */
1314c09f92d2SPeter Avalos 			int uidsize = 0, gidsize = 0;
1315c09f92d2SPeter Avalos 
1316c09f92d2SPeter Avalos 			if (datasize >= 1 && p[offset] == 1) {/* version=1 */
1317c09f92d2SPeter Avalos 				if (datasize >= 4) {
1318c09f92d2SPeter Avalos 					/* get a uid size. */
1319c09f92d2SPeter Avalos 					uidsize = p[offset+1];
1320c09f92d2SPeter Avalos 					if (uidsize == 2)
1321c09f92d2SPeter Avalos 						zip_entry->uid = archive_le16dec(
1322c09f92d2SPeter Avalos 						     p + offset + 2);
1323c09f92d2SPeter Avalos 					else if (uidsize == 4 && datasize >= 6)
1324c09f92d2SPeter Avalos 						zip_entry->uid = archive_le32dec(
1325c09f92d2SPeter Avalos 						     p + offset + 2);
1326c09f92d2SPeter Avalos 				}
1327c09f92d2SPeter Avalos 				if (datasize >= (2 + uidsize + 3)) {
1328c09f92d2SPeter Avalos 					/* get a gid size. */
1329c09f92d2SPeter Avalos 					gidsize = p[offset+2+uidsize];
1330c09f92d2SPeter Avalos 					if (gidsize == 2)
1331c09f92d2SPeter Avalos 						zip_entry->gid = archive_le16dec(
1332c09f92d2SPeter Avalos 						    p+offset+2+uidsize+1);
1333c09f92d2SPeter Avalos 					else if (gidsize == 4 &&
1334c09f92d2SPeter Avalos 					    datasize >= (2 + uidsize + 5))
1335c09f92d2SPeter Avalos 						zip_entry->gid = archive_le32dec(
1336c09f92d2SPeter Avalos 						    p+offset+2+uidsize+1);
1337c09f92d2SPeter Avalos 				}
1338c09f92d2SPeter Avalos 			}
1339c09f92d2SPeter Avalos 			break;
1340c09f92d2SPeter Avalos 		}
134160b4ad09SPeter Avalos 		default:
134260b4ad09SPeter Avalos 			break;
134360b4ad09SPeter Avalos 		}
134460b4ad09SPeter Avalos 		offset += datasize;
134560b4ad09SPeter Avalos 	}
134660b4ad09SPeter Avalos #ifdef DEBUG
1347c09f92d2SPeter Avalos 	if (offset != extra_length)
134860b4ad09SPeter Avalos 	{
134960b4ad09SPeter Avalos 		fprintf(stderr,
1350c09f92d2SPeter Avalos 		    "Extra data field contents do not match reported size!\n");
135160b4ad09SPeter Avalos 	}
135260b4ad09SPeter Avalos #endif
135360b4ad09SPeter Avalos }
1354