blob: 578c6ac940e62206c41a80050cb19cae063b980b [file] [log] [blame]
Dieter Baronbbb63691999-07-26 22:04:20 +00001/*
Thomas Klausner428ba432005-05-18 21:19:37 +00002 $NiH: zip_open.c,v 1.28 2005/01/11 19:01:53 dillo Exp $
Dieter Baron1c5ffe22002-06-06 09:27:17 +00003
Dieter Baronadaf98c2003-10-06 16:37:42 +00004 zip_open.c -- open zip archive
Dieter Baron2a8ad422004-04-16 09:40:31 +00005 Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner
Dieter Baronbbb63691999-07-26 22:04:20 +00006
Dieter Barondd9afca2003-10-02 14:13:37 +00007 This file is part of libzip, a library to manipulate ZIP archives.
Dieter Baronbbb63691999-07-26 22:04:20 +00008 The authors can be contacted at <nih@giga.or.at>
9
Dieter Barondd9afca2003-10-02 14:13:37 +000010 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions
12 are met:
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 2. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in
17 the documentation and/or other materials provided with the
18 distribution.
19 3. The names of the authors may not be used to endorse or promote
20 products derived from this software without specific prior
21 written permission.
22
23 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
24 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
31 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
33 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Dieter Baronbbb63691999-07-26 22:04:20 +000034*/
35
36
37
Dieter Baron2d6db591999-07-25 18:26:20 +000038#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <errno.h>
42#include <unistd.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45
46#include "zip.h"
47#include "zipint.h"
48
Dieter Baronb2ed74d2004-04-14 14:01:31 +000049static void set_error(int *, struct zip_error *, int);
50static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *);
51static int _zip_headercomp(struct zip_dirent *, int,
52 struct zip_dirent *, int);
Dieter Baronb3db4c12005-01-11 18:11:47 +000053static void *_zip_memdup(const void *, size_t, struct zip_error *);
Dieter Baronb2ed74d2004-04-14 14:01:31 +000054static unsigned char *_zip_memmem(const unsigned char *, int,
55 const unsigned char *, int);
56static struct zip_cdir *_zip_readcdir(FILE *, unsigned char *, unsigned char *,
57 int, struct zip_error *);
Dieter Baron2d6db591999-07-25 18:26:20 +000058
59
60
Thomas Klausnerb8ef4391999-07-25 19:44:00 +000061struct zip *
Dieter Baronb2ed74d2004-04-14 14:01:31 +000062zip_open(const char *fn, int flags, int *zep)
Dieter Baron2d6db591999-07-25 18:26:20 +000063{
64 FILE *fp;
65 unsigned char *buf, *match;
66 int a, i, buflen, best;
Dieter Baronb2ed74d2004-04-14 14:01:31 +000067 struct zip *za;
68 struct zip_cdir *cdir, *cdirnew;
Dieter Baron2d6db591999-07-25 18:26:20 +000069 long len;
70 struct stat st;
Dieter Baronb2ed74d2004-04-14 14:01:31 +000071 struct zip_error error, err2;
Dieter Baron2d6db591999-07-25 18:26:20 +000072
Thomas Klausnerb1b044e1999-07-26 03:59:58 +000073 if (fn == NULL) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +000074 set_error(zep, NULL, ZIP_ER_INVAL);
Dieter Baron2d6db591999-07-25 18:26:20 +000075 return NULL;
Thomas Klausnerb1b044e1999-07-26 03:59:58 +000076 }
Dieter Baron2d6db591999-07-25 18:26:20 +000077
78 if (stat(fn, &st) != 0) {
79 if (flags & ZIP_CREATE) {
Dieter Baronb2ed74d2004-04-14 14:01:31 +000080 if ((za=_zip_new(&error)) == NULL) {
81 set_error(zep, &error, 0);
Thomas Klausner8ec06071999-07-25 19:11:39 +000082 return NULL;
83 }
Dieter Baronb2ed74d2004-04-14 14:01:31 +000084
85 za->zn = strdup(fn);
86 if (!za->zn) {
87 _zip_free(za);
Thomas Klausnerd0147e92004-11-17 21:55:17 +000088 set_error(zep, NULL, ZIP_ER_MEMORY);
Dieter Baronb2ed74d2004-04-14 14:01:31 +000089 return NULL;
90 }
91 return za;
92 }
93 else {
Thomas Klausnerd0147e92004-11-17 21:55:17 +000094 set_error(zep, NULL, ZIP_ER_OPEN);
Dieter Baron2d6db591999-07-25 18:26:20 +000095 return NULL;
96 }
Dieter Baronb2ed74d2004-04-14 14:01:31 +000097 }
98 else if ((flags & ZIP_EXCL)) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +000099 set_error(zep, NULL, ZIP_ER_EXISTS);
Dieter Baron2d6db591999-07-25 18:26:20 +0000100 return NULL;
101 }
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000102 /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL,
Dieter Baron2d6db591999-07-25 18:26:20 +0000103 just like open() */
104
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000105 if ((fp=fopen(fn, "rb")) == NULL) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000106 set_error(zep, NULL, ZIP_ER_OPEN);
Dieter Baron2d6db591999-07-25 18:26:20 +0000107 return NULL;
108 }
109
110 clearerr(fp);
111 fseek(fp, 0, SEEK_END);
112 len = ftell(fp);
Dieter Baron81d8bb22004-04-19 11:49:13 +0000113 i = fseek(fp, -(len < CDBUFSIZE ? len : CDBUFSIZE), SEEK_END);
Dieter Baron2d6db591999-07-25 18:26:20 +0000114 if (i == -1 && errno != EFBIG) {
115 /* seek before start of file on my machine */
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000116 set_error(zep, NULL, ZIP_ER_SEEK);
Dieter Baron2d6db591999-07-25 18:26:20 +0000117 fclose(fp);
118 return NULL;
119 }
120
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000121 /* 64k is too much for stack */
Dieter Baron81d8bb22004-04-19 11:49:13 +0000122 if ((buf=(unsigned char *)malloc(CDBUFSIZE)) == NULL) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000123 set_error(zep, NULL, ZIP_ER_MEMORY);
Dieter Barone3f91ef2003-10-06 02:50:14 +0000124 fclose(fp);
Thomas Klausner8ec06071999-07-25 19:11:39 +0000125 return NULL;
126 }
Dieter Baron2d6db591999-07-25 18:26:20 +0000127
128 clearerr(fp);
Dieter Baron81d8bb22004-04-19 11:49:13 +0000129 buflen = fread(buf, 1, CDBUFSIZE, fp);
Dieter Baron2d6db591999-07-25 18:26:20 +0000130
131 if (ferror(fp)) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000132 set_error(zep, NULL, ZIP_ER_READ);
Dieter Baron2d6db591999-07-25 18:26:20 +0000133 free(buf);
134 fclose(fp);
135 return NULL;
136 }
137
138 best = -1;
139 cdir = NULL;
140 match = buf;
Thomas Klausnerb8ef4391999-07-25 19:44:00 +0000141 while ((match=_zip_memmem(match, buflen-(match-buf)-18,
142 EOCD_MAGIC, 4))!=NULL) {
Dieter Baron2d6db591999-07-25 18:26:20 +0000143 /* found match -- check, if good */
144 /* to avoid finding the same match all over again */
145 match++;
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000146 if ((cdirnew=_zip_readcdir(fp, buf, match-1, buflen, &err2)) == NULL)
Dieter Baron2d6db591999-07-25 18:26:20 +0000147 continue;
148
149 if (cdir) {
150 if (best <= 0)
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000151 best = _zip_checkcons(fp, cdir, &err2);
152 a = _zip_checkcons(fp, cdirnew, &err2);
Dieter Baron2d6db591999-07-25 18:26:20 +0000153 if (best < a) {
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000154 _zip_cdir_free(cdir);
Dieter Baron2d6db591999-07-25 18:26:20 +0000155 cdir = cdirnew;
156 best = a;
157 }
158 else
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000159 _zip_cdir_free(cdirnew);
Dieter Baron2d6db591999-07-25 18:26:20 +0000160 }
161 else {
162 cdir = cdirnew;
163 if (flags & ZIP_CHECKCONS)
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000164 best = _zip_checkcons(fp, cdir, &err2);
Dieter Baron2d6db591999-07-25 18:26:20 +0000165 else
166 best = 0;
167 }
168 cdirnew = NULL;
169 }
170
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000171 free(buf);
172
Dieter Baron2d6db591999-07-25 18:26:20 +0000173 if (best < 0) {
174 /* no consistent eocd found */
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000175 set_error(zep, NULL, ZIP_ER_NOZIP);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000176 _zip_cdir_free(cdir);
Dieter Baron2d6db591999-07-25 18:26:20 +0000177 fclose(fp);
178 return NULL;
179 }
180
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000181 if ((za=_zip_new(&error)) == NULL) {
182 set_error(zep, &error, 0);
183 _zip_cdir_free(cdir);
Dieter Barone3f91ef2003-10-06 02:50:14 +0000184 fclose(fp);
Thomas Klausner8ec06071999-07-25 19:11:39 +0000185 return NULL;
186 }
187
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000188 za->zp = fp;
189 za->cdir = cdir;
Dieter Baron2d6db591999-07-25 18:26:20 +0000190
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000191 if ((za->zn=strdup(fn)) == NULL) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000192 set_error(zep, NULL, ZIP_ER_MEMORY);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000193 _zip_free(za);
194 return NULL;
195 }
196
197 if ((za->entry=malloc(sizeof(*(za->entry))*cdir->nentry)) == NULL) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000198 set_error(zep, NULL, ZIP_ER_MEMORY);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000199 _zip_free(za);
200 return NULL;
201 }
202 for (i=0; i<cdir->nentry; i++)
Thomas Klausner73668b22004-11-30 21:42:24 +0000203 _zip_entry_new(za);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000204
205 return za;
Dieter Baron2d6db591999-07-25 18:26:20 +0000206}
207
208
209
Dieter Barone3f91ef2003-10-06 02:50:14 +0000210static void
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000211set_error(int *zep, struct zip_error *err, int ze)
Dieter Barone3f91ef2003-10-06 02:50:14 +0000212{
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000213 int se;
214
215 if (err) {
216 _zip_error_get(err, &ze, &se);
Thomas Klausnereb239572004-12-22 15:49:20 +0000217 if (zip_error_get_sys_type(ze) == ZIP_ET_SYS)
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000218 errno = se;
219 }
220
221 if (zep)
222 *zep = ze;
Dieter Barone3f91ef2003-10-06 02:50:14 +0000223}
224
225
226
Thomas Klausner8ec06071999-07-25 19:11:39 +0000227/* _zip_readcdir:
Dieter Baron2d6db591999-07-25 18:26:20 +0000228 tries to find a valid end-of-central-directory at the beginning of
229 buf, and then the corresponding central directory entries.
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000230 Returns a struct zip_cdir which contains the central directory
Dieter Baron2d6db591999-07-25 18:26:20 +0000231 entries, or NULL if unsuccessful. */
232
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000233static struct zip_cdir *
Dieter Baron549ac372003-10-06 22:44:07 +0000234_zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen,
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000235 struct zip_error *error)
Dieter Baron2d6db591999-07-25 18:26:20 +0000236{
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000237 struct zip_cdir *cd;
238 unsigned char *cdp, **bufp;
239 int i, comlen, nentry;
Dieter Baron2d6db591999-07-25 18:26:20 +0000240
241 comlen = buf + buflen - eocd - EOCDLEN;
242 if (comlen < 0) {
243 /* not enough bytes left for comment */
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000244 _zip_error_set(error, ZIP_ER_NOZIP, 0);
Dieter Baron2d6db591999-07-25 18:26:20 +0000245 return NULL;
246 }
247
248 /* check for end-of-central-dir magic */
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000249 if (memcmp(eocd, EOCD_MAGIC, 4) != 0) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000250 _zip_error_set(error, ZIP_ER_NOZIP, 0);
Dieter Baron2d6db591999-07-25 18:26:20 +0000251 return NULL;
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000252 }
Dieter Baron2d6db591999-07-25 18:26:20 +0000253
254 if (memcmp(eocd+4, "\0\0\0\0", 4) != 0) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000255 _zip_error_set(error, ZIP_ER_MULTIDISK, 0);
Dieter Baron2d6db591999-07-25 18:26:20 +0000256 return NULL;
257 }
258
Dieter Baron2d6db591999-07-25 18:26:20 +0000259 cdp = eocd + 8;
260 /* number of cdir-entries on this disk */
Thomas Klausner8ec06071999-07-25 19:11:39 +0000261 i = _zip_read2(&cdp);
Dieter Baron2d6db591999-07-25 18:26:20 +0000262 /* number of cdir-entries */
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000263 nentry = _zip_read2(&cdp);
264
265 if ((cd=_zip_cdir_new(nentry, error)) == NULL)
266 return NULL;
267
268 cd->size = _zip_read4(&cdp);
269 cd->offset = _zip_read4(&cdp);
270 cd->comment = NULL;
271 cd->comment_len = _zip_read2(&cdp);
Dieter Baron2d6db591999-07-25 18:26:20 +0000272
Dieter Baron5bec5e22005-01-11 19:01:53 +0000273 /* some zip files are broken; their internal comment length
Thomas Klausnerfe810f62001-10-20 14:04:27 +0000274 says 0, but they have 1 or 2 comment bytes */
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000275 if ((comlen-cd->comment_len < 0) || (comlen-cd->comment_len > 2)
276 || (cd->nentry != i)) {
Dieter Baron2d6db591999-07-25 18:26:20 +0000277 /* comment size wrong -- too few or too many left after central dir */
278 /* or number of cdir-entries on this disk != number of cdir-entries */
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000279 _zip_error_set(error, ZIP_ER_NOZIP, 0);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000280 free(cd);
Dieter Baron2d6db591999-07-25 18:26:20 +0000281 return NULL;
282 }
283
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000284 if (cd->comment_len)
Dieter Baronb3db4c12005-01-11 18:11:47 +0000285 if ((cd->comment=_zip_memdup(eocd+EOCDLEN, cd->comment_len, error))
286 == NULL) {
287 free(cd);
288 return NULL;
289 }
Dieter Baron2d6db591999-07-25 18:26:20 +0000290
291 cdp = eocd;
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000292 if (cd->size < eocd-buf) {
Dieter Baron2d6db591999-07-25 18:26:20 +0000293 /* if buffer already read in, use it */
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000294 cdp = eocd - cd->size;
295 bufp = &cdp;
Dieter Baron2d6db591999-07-25 18:26:20 +0000296 }
297 else {
298 /* go to start of cdir and read it entry by entry */
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000299 bufp = NULL;
Dieter Baron2d6db591999-07-25 18:26:20 +0000300 clearerr(fp);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000301 fseek(fp, -(cd->size+cd->comment_len+EOCDLEN), SEEK_END);
302 if (ferror(fp) || (ftell(fp) != cd->offset)) {
Dieter Baron2d6db591999-07-25 18:26:20 +0000303 /* seek error or offset of cdir wrong */
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000304 if (ferror(fp))
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000305 _zip_error_set(error, ZIP_ER_SEEK, errno);
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000306 else
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000307 _zip_error_set(error, ZIP_ER_NOZIP, 0);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000308 free(cd);
Dieter Baron2d6db591999-07-25 18:26:20 +0000309 return NULL;
310 }
311 }
312
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000313 for (i=0; i<cd->nentry; i++) {
314 if ((_zip_dirent_read(cd->entry+i, fp, bufp, eocd-cdp, 0,
315 error)) < 0) {
316 cd->nentry = i;
317 _zip_cdir_free(cd);
Thomas Klausneraf93f081999-07-26 01:39:56 +0000318 return NULL;
319 }
Dieter Baron2d6db591999-07-25 18:26:20 +0000320 }
321
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000322 return cd;
Dieter Baron2d6db591999-07-25 18:26:20 +0000323}
324
325
326
Thomas Klausner8ec06071999-07-25 19:11:39 +0000327/* _zip_checkcons:
Dieter Baron2d6db591999-07-25 18:26:20 +0000328 Checks the consistency of the central directory by comparing central
329 directory entries with local headers and checking for plausible
330 file and header offsets. Returns -1 if not plausible, else the
331 difference between the lowest and the highest fileposition reached */
332
333static int
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000334_zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error)
Dieter Baron2d6db591999-07-25 18:26:20 +0000335{
336 int min, max, i, j;
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000337 struct zip_dirent temp;
Dieter Baron2d6db591999-07-25 18:26:20 +0000338
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000339 if (cd->nentry) {
340 max = cd->entry[0].offset;
341 min = cd->entry[0].offset;
Dieter Baron2d6db591999-07-25 18:26:20 +0000342 }
Dieter Baron0a765162004-12-22 15:49:58 +0000343 else
344 min = max = 0;
Dieter Baron2d6db591999-07-25 18:26:20 +0000345
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000346 for (i=0; i<cd->nentry; i++) {
347 if (cd->entry[i].offset < min)
348 min = cd->entry[i].offset;
Thomas Klausneraf93f081999-07-26 01:39:56 +0000349 if (min < 0) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000350 _zip_error_set(error, ZIP_ER_NOZIP, 0);
Dieter Baron2d6db591999-07-25 18:26:20 +0000351 return -1;
Thomas Klausneraf93f081999-07-26 01:39:56 +0000352 }
353
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000354 j = cd->entry[i].offset + cd->entry[i].comp_size
355 + cd->entry[i].filename_len + LENTRYSIZE;
Dieter Baron2d6db591999-07-25 18:26:20 +0000356 if (j > max)
357 max = j;
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000358 if (max > cd->offset) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000359 _zip_error_set(error, ZIP_ER_NOZIP, 0);
Dieter Baron2d6db591999-07-25 18:26:20 +0000360 return -1;
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000361 }
362
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000363 if (fseek(fp, cd->entry[i].offset, SEEK_SET) != 0) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000364 _zip_error_set(error, ZIP_ER_SEEK, 0);
Dieter Baron2d6db591999-07-25 18:26:20 +0000365 return -1;
366 }
Thomas Klausneraf93f081999-07-26 01:39:56 +0000367
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000368 if (_zip_dirent_read(&temp, fp, NULL, 0, 1, error) == -1)
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000369 return -1;
Thomas Klausnerb1b044e1999-07-26 03:59:58 +0000370
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000371 if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) {
Thomas Klausnerd0147e92004-11-17 21:55:17 +0000372 _zip_error_set(error, ZIP_ER_NOZIP, 0);
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000373 _zip_dirent_finalize(&temp);
Dieter Baron2d6db591999-07-25 18:26:20 +0000374 return -1;
Thomas Klausneraf93f081999-07-26 01:39:56 +0000375 }
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000376 _zip_dirent_finalize(&temp);
Dieter Baron2d6db591999-07-25 18:26:20 +0000377 }
378
379 return max - min;
380}
381
382
383
Thomas Klausner8ec06071999-07-25 19:11:39 +0000384/* _zip_headercomp:
Dieter Baron2d6db591999-07-25 18:26:20 +0000385 compares two headers h1 and h2; if they are local headers, set
386 local1p or local2p respectively to 1, else 0. Return 0 if they
387 are identical, -1 if not. */
388
389static int
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000390_zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2,
Dieter Baron2d6db591999-07-25 18:26:20 +0000391 int local2p)
392{
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000393 if ((h1->version_needed != h2->version_needed)
Thomas Klausner0c53a3c1999-07-26 19:36:40 +0000394#if 0
395 /* some zip-files have different values in local
396 and global headers for the bitflags */
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000397 || (h1->bitflags != h2->bitflags)
Thomas Klausner0c53a3c1999-07-26 19:36:40 +0000398#endif
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000399 || (h1->comp_method != h2->comp_method)
400 || (h1->last_mod != h2->last_mod)
401 || (h1->crc != h2->crc)
402 || (h1->comp_size != h2->comp_size)
403 || (h1->uncomp_size != h2->uncomp_size)
404 || (h1->filename_len != h2->filename_len)
405 || !h1->filename || !h2->filename
406 || strcmp(h1->filename, h2->filename))
Dieter Baron2d6db591999-07-25 18:26:20 +0000407 return -1;
408
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000409 if ((local1p == local2p)
410 && ((h1->extrafield_len != h2->extrafield_len)
411 || (h1->extrafield_len && h2->extrafield
412 && memcmp(h1->extrafield, h2->extrafield,
413 h1->extrafield_len))))
414 return -1;
415
416 /* if either is local, nothing more to check */
417 if (local1p || local2p)
Dieter Baron2d6db591999-07-25 18:26:20 +0000418 return 0;
419
Dieter Baronb2ed74d2004-04-14 14:01:31 +0000420 if ((h1->version_madeby != h2->version_madeby)
421 || (h1->disk_number != h2->disk_number)
422 || (h1->int_attrib != h2->int_attrib)
423 || (h1->ext_attrib != h2->ext_attrib)
424 || (h1->offset != h2->offset)
425 || (h1->comment_len != h2->comment_len)
426 || (h1->comment_len && h2->comment
427 && memcmp(h1->comment, h2->comment, h1->comment_len)))
Dieter Baron2d6db591999-07-25 18:26:20 +0000428 return -1;
Dieter Baron2d6db591999-07-25 18:26:20 +0000429
430 return 0;
431}
Thomas Klausnerb8ef4391999-07-25 19:44:00 +0000432
433
434
Thomas Klausner13138a71999-07-25 20:15:13 +0000435static unsigned char *
436_zip_memmem(const unsigned char *big, int biglen, const unsigned char *little,
Thomas Klausnerb8ef4391999-07-25 19:44:00 +0000437 int littlelen)
438{
439 const unsigned char *p;
440
441 if ((biglen < littlelen) || (littlelen == 0))
442 return NULL;
443 p = big-1;
444 while ((p=memchr(p+1, little[0], big-(p+1)+biglen-littlelen+1))!=NULL) {
445 if (memcmp(p+1, little+1, littlelen-1)==0)
446 return (unsigned char *)p;
447 }
448
449 return NULL;
450}
451
452
453
Dieter Baronb3db4c12005-01-11 18:11:47 +0000454static void *
455_zip_memdup(const void *mem, size_t len, struct zip_error *error)
Thomas Klausnerb8ef4391999-07-25 19:44:00 +0000456{
457 void *ret;
458
459 ret = malloc(len);
460 if (!ret) {
Dieter Baronb3db4c12005-01-11 18:11:47 +0000461 _zip_error_set(error, ZIP_ER_MEMORY, 0);
Thomas Klausnerb8ef4391999-07-25 19:44:00 +0000462 return NULL;
463 }
464
465 memcpy(ret, mem, len);
466
467 return ret;
468}