Merge no-meta branch

--HG--
branch : HEAD
diff --git a/lib/zip_open.c b/lib/zip_open.c
index 163ef28..4341258 100644
--- a/lib/zip_open.c
+++ b/lib/zip_open.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_open.c,v 1.18 2003/10/06 16:37:41 dillo Exp $
+  $NiH: zip_open.c,v 1.19.4.6 2004/04/13 19:47:59 dillo Exp $
 
   zip_open.c -- open zip archive
   Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
@@ -46,69 +46,63 @@
 #include "zip.h"
 #include "zipint.h"
 
-static void set_error(int *errp, int err);
-static struct zip *_zip_readcdir(FILE *fp, unsigned char *buf,
-			   unsigned char *eocd, int buflen, int *errp);
-static int _zip_read2(unsigned char **a);
-static int _zip_read4(unsigned char **a);
-static char *_zip_readstr(unsigned char **buf, int len, int nulp);
-static char *_zip_readfpstr(FILE *fp, int len, int nulp);
-static int _zip_checkcons(FILE *fp, struct zip *zf);
-static int _zip_headercomp(struct zip_entry *h1, int local1p,
-			   struct zip_entry *h2, int local2p);
-static unsigned char *_zip_memmem(const unsigned char *big, int biglen,
-				  const unsigned char *little, int littlelen);
-static time_t _zip_d2u_time(int dtime, int ddate);
+static void set_error(int *, struct zip_error *, int);
+static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *);
+static int _zip_headercomp(struct zip_dirent *, int,
+			   struct zip_dirent *, int);
+static unsigned char *_zip_memmem(const unsigned char *, int,
+				  const unsigned char *, int);
+static struct zip_cdir *_zip_readcdir(FILE *, unsigned char *, unsigned char *,
+				 int, struct zip_error *);
 
 
 
-/* zip_open:
-   Tries to open the file 'fn' as a zipfile. If flags & ZIP_CHECKCONS,
-   also does some consistency checks (comparing local headers to
-   central directory entries). If flags & ZIP_CREATE, make a new file
-   (if flags & ZIP_EXCL, error if already existing).  Returns a
-   zipfile struct, or NULL if unsuccessful, setting zip_err. */
-
 struct zip *
-zip_open(const char *fn, int flags, int *errp)
+zip_open(const char *fn, int flags, int *zep)
 {
     FILE *fp;
     unsigned char *buf, *match;
     int a, i, buflen, best;
-    struct zip *cdir, *cdirnew;
+    struct zip *za;
+    struct zip_cdir *cdir, *cdirnew;
     long len;
     struct stat st;
+    struct zip_error error, err2;
 
     if (fn == NULL) {
-	set_error(errp, ZERR_INVAL);
+	set_error(zep, NULL, ZERR_INVAL);
 	return NULL;
     }
     
     if (stat(fn, &st) != 0) {
 	if (flags & ZIP_CREATE) {
-	    if ((cdir=_zip_new(errp)) == NULL)
-		return NULL;
-	    
-	    cdir->zn = strdup(fn);
-	    if (!cdir->zn) {
-		_zip_free(cdir);
-		set_error(errp, ZERR_MEMORY);
+	    if ((za=_zip_new(&error)) == NULL) {
+		set_error(zep, &error, 0);
 		return NULL;
 	    }
-	    return cdir;
-	} else {
-	    set_error(errp, ZERR_NOENT);
+	    
+	    za->zn = strdup(fn);
+	    if (!za->zn) {
+		_zip_free(za);
+		set_error(zep, NULL, ZERR_MEMORY);
+		return NULL;
+	    }
+	    return za;
+	}
+	else {
+	    set_error(zep, NULL, ZERR_OPEN);
 	    return NULL;
 	}
-    } else if ((flags & ZIP_EXCL)) {
-	set_error(errp, ZERR_EXISTS);
+    }
+    else if ((flags & ZIP_EXCL)) {
+	set_error(zep, NULL, ZERR_EXISTS);
 	return NULL;
     }
     /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL,
        just like open() */
     
-    if ((fp=fopen(fn, "rb"))==NULL) {
-	set_error(errp, ZERR_OPEN);
+    if ((fp=fopen(fn, "rb")) == NULL) {
+	set_error(zep, NULL, ZERR_OPEN);
 	return NULL;
     }
     
@@ -118,15 +112,14 @@
     i = fseek(fp, -(len < BUFSIZE ? len : BUFSIZE), SEEK_END);
     if (i == -1 && errno != EFBIG) {
 	/* seek before start of file on my machine */
-	set_error(errp, ZERR_SEEK);
+	set_error(zep, NULL, ZERR_SEEK);
 	fclose(fp);
 	return NULL;
     }
 
-    /* XXX: why not allocate statically? */
-    buf = (unsigned char *)malloc(BUFSIZE);
-    if (!buf) {
-	set_error(errp, ZERR_MEMORY);
+    /* 64k is too much for stack */
+    if ((buf=(unsigned char *)malloc(BUFSIZE)) == NULL) {
+	set_error(zep, NULL, ZERR_MEMORY);
 	fclose(fp);
 	return NULL;
     }
@@ -135,7 +128,7 @@
     buflen = fread(buf, 1, BUFSIZE, fp);
 
     if (ferror(fp)) {
-	set_error(errp, ZERR_READ);
+	set_error(zep, NULL, ZERR_READ);
 	free(buf);
 	fclose(fp);
 	return NULL;
@@ -149,62 +142,83 @@
 	/* found match -- check, if good */
 	/* to avoid finding the same match all over again */
 	match++;
-	if ((cdirnew=_zip_readcdir(fp, buf, match-1, buflen, errp)) == NULL)
+	if ((cdirnew=_zip_readcdir(fp, buf, match-1, buflen, &err2)) == NULL)
 	    continue;	    
 
 	if (cdir) {
 	    if (best <= 0)
-		best = _zip_checkcons(fp, cdir);
-	    a = _zip_checkcons(fp, cdirnew);
+		best = _zip_checkcons(fp, cdir, &err2);
+	    a = _zip_checkcons(fp, cdirnew, &err2);
 	    if (best < a) {
-		_zip_free(cdir);
+		_zip_cdir_free(cdir);
 		cdir = cdirnew;
 		best = a;
 	    }
 	    else
-		_zip_free(cdirnew);
+		_zip_cdir_free(cdirnew);
 	}
 	else {
 	    cdir = cdirnew;
 	    if (flags & ZIP_CHECKCONS)
-		best = _zip_checkcons(fp, cdir);
+		best = _zip_checkcons(fp, cdir, &err2);
 	    else
 		best = 0;
 	}
 	cdirnew = NULL;
     }
 
+    free(buf);
+    
     if (best < 0) {
 	/* no consistent eocd found */
-	set_error(errp, ZERR_NOZIP);
-	free(buf);
-	_zip_free(cdir);
+	set_error(zep, NULL, ZERR_NOZIP);
+	_zip_cdir_free(cdir);
 	fclose(fp);
 	return NULL;
     }
 
-    free(buf);
-
-    cdir->zn = strdup(fn);
-    if (!cdir->zn) {
-	set_error(errp, ZERR_MEMORY);
-	_zip_free(cdir);
+    if ((za=_zip_new(&error)) == NULL) {
+	set_error(zep, &error, 0);
+	_zip_cdir_free(cdir);
 	fclose(fp);
 	return NULL;
     }
 
-    cdir->zp = fp;
+    za->zp = fp;
+    za->cdir = cdir;
     
-    return cdir;
+    if ((za->zn=strdup(fn)) == NULL) {
+	set_error(zep, NULL, ZERR_MEMORY);
+	_zip_free(za);
+	return NULL;
+    }
+
+    if ((za->entry=malloc(sizeof(*(za->entry))*cdir->nentry)) == NULL) {
+	set_error(zep, NULL, ZERR_MEMORY);
+	_zip_free(za);
+	return NULL;
+    }
+    for (i=0; i<cdir->nentry; i++)
+	_zip_new_entry(za);
+
+    return za;
 }
 
 
 
 static void
-set_error(int *errp, int err)
+set_error(int *zep, struct zip_error *err, int ze)
 {
-    if (errp)
-	*errp = err;
+    int se;
+
+    if (err) {
+	_zip_error_get(err, &ze, &se);
+	if (zip_error_sys_type(ze) == ZIP_ET_SYS)
+	    errno = se;
+    }
+
+    if (zep)
+	*zep = ze;
 }
 
 
@@ -212,357 +226,95 @@
 /* _zip_readcdir:
    tries to find a valid end-of-central-directory at the beginning of
    buf, and then the corresponding central directory entries.
-   Returns a struct zip which contains the central directory 
+   Returns a struct zip_cdir which contains the central directory 
    entries, or NULL if unsuccessful. */
 
-static struct zip *
+static struct zip_cdir *
 _zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen,
-	      int *errp)
+	      struct zip_error *error)
 {
-    struct zip *zf;
-    unsigned char *cdp;
-    int i, comlen, readp;
-    int entries;
+    struct zip_cdir *cd;
+    unsigned char *cdp, **bufp;
+    int i, comlen, nentry;
 
     comlen = buf + buflen - eocd - EOCDLEN;
     if (comlen < 0) {
 	/* not enough bytes left for comment */
-	set_error(errp, ZERR_NOZIP);
+	_zip_error_set(error, ZERR_NOZIP, 0);
 	return NULL;
     }
 
     /* check for end-of-central-dir magic */
     if (memcmp(eocd, EOCD_MAGIC, 4) != 0) {
-	set_error(errp, ZERR_NOZIP);
+	_zip_error_set(error, ZERR_NOZIP, 0);
 	return NULL;
     }
 
     if (memcmp(eocd+4, "\0\0\0\0", 4) != 0) {
-	set_error(errp, ZERR_MULTIDISK);
+	_zip_error_set(error, ZERR_MULTIDISK, 0);
 	return NULL;
     }
 
-    if ((zf=_zip_new(errp)) == NULL)
-	return NULL;
-
     cdp = eocd + 8;
     /* number of cdir-entries on this disk */
     i = _zip_read2(&cdp);
     /* number of cdir-entries */
-    entries = _zip_read2(&cdp);
-    zf->cd_size = _zip_read4(&cdp);
-    zf->cd_offset = _zip_read4(&cdp);
-    zf->comlen = _zip_read2(&cdp);
-    zf->entry = NULL;
+    nentry = _zip_read2(&cdp);
+
+    if ((cd=_zip_cdir_new(nentry, error)) == NULL)
+	return NULL;
+
+    cd->size = _zip_read4(&cdp);
+    cd->offset = _zip_read4(&cdp);
+    cd->comment = NULL;
+    cd->comment_len = _zip_read2(&cdp);
 
     /* XXX: some zip files are broken; their internal comment length
        says 0, but they have 1 or 2 comment bytes */
-    if (((zf->comlen != comlen) && (zf->comlen != comlen-1) &&
-	 (zf->comlen != comlen-2)) || (entries != i)) {
+    if ((comlen-cd->comment_len < 0) || (comlen-cd->comment_len > 2)
+	|| (cd->nentry != i)) {
 	/* comment size wrong -- too few or too many left after central dir */
 	/* or number of cdir-entries on this disk != number of cdir-entries */
-	set_error(errp, ZERR_NOZIP);
-	_zip_free(zf);
+	_zip_error_set(error, ZERR_NOZIP, 0);
+	free(cd);
 	return NULL;
     }
 
-    zf->com = (unsigned char *)_zip_memdup(eocd+EOCDLEN, zf->comlen);
+    if (cd->comment_len)
+	cd->comment = _zip_memdup(eocd+EOCDLEN, cd->comment_len);
 
     cdp = eocd;
-    if (zf->cd_size < eocd-buf) {
+    if (cd->size < eocd-buf) {
 	/* if buffer already read in, use it */
-	readp = 0;
-	cdp = eocd - zf->cd_size;
+	cdp = eocd - cd->size;
+	bufp = &cdp;
     }
     else {
 	/* go to start of cdir and read it entry by entry */
-	readp = 1;
+	bufp = NULL;
 	clearerr(fp);
-	fseek(fp, -(zf->cd_size+zf->comlen+EOCDLEN), SEEK_END);
-	if (ferror(fp) || (ftell(fp) != zf->cd_offset)) {
+	fseek(fp, -(cd->size+cd->comment_len+EOCDLEN), SEEK_END);
+	if (ferror(fp) || (ftell(fp) != cd->offset)) {
 	    /* seek error or offset of cdir wrong */
 	    if (ferror(fp))
-		set_error(errp, ZERR_SEEK);
+		_zip_error_set(error, ZERR_SEEK, errno);
 	    else
-		set_error(errp, ZERR_NOZIP);
-	    _zip_free(zf);
+		_zip_error_set(error, ZERR_NOZIP, 0);
+	    free(cd);
 	    return NULL;
 	}
     }
 
-    zf->entry = (struct zip_entry *)malloc(sizeof(struct zip_entry)
-					   *entries);
-    if (!zf->entry) {
-	set_error(errp, ZERR_MEMORY);
-	_zip_free(zf);
-	return NULL;
-    }
-
-    zf->nentry_alloc = entries;
-
-    for (i=0; i<entries; i++) {
-	if (_zip_new_entry(zf) == NULL) {
-	    /* shouldn't happen, since space already has been malloc'd */
-	    _zip_error_get(&zf->error, errp, NULL);
-	    _zip_free(zf);
+    for (i=0; i<cd->nentry; i++) {
+	if ((_zip_dirent_read(cd->entry+i, fp, bufp, eocd-cdp, 0,
+			      error)) < 0) {
+	    cd->nentry = i;
+	    _zip_cdir_free(cd);
 	    return NULL;
 	}
     }
     
-    for (i=0; i<zf->nentry; i++) {
-	if ((_zip_readcdentry(fp, zf->entry+i, &cdp, eocd-cdp,
-			      readp, 0)) < 0) {
-	    _zip_free(zf);
-	    return NULL;
-	}
-    }
-    
-    return zf;
-}
-
-
-
-/* _zip_readcdentry:
-   fills the zipfile entry zfe with data from the buffer *cdpp, not reading
-   more than 'left' bytes from it; if readp != 0, it also reads more data
-   from fp, if necessary. If localp != 0, it reads a local header instead
-   of a central directory entry. Returns 0 if successful, -1 if not,
-   advancing *cdpp for each byte read. */
-
-int
-_zip_readcdentry(FILE *fp, struct zip_entry *zfe, unsigned char **cdpp, 
-		 int left, int readp, int localp)
-{
-    unsigned char buf[CDENTRYSIZE];
-    unsigned char *cur;
-    unsigned short dostime, dosdate;
-    int size;
-
-    if (localp)
-	size = LENTRYSIZE;
-    else
-	size = CDENTRYSIZE;
-    
-    if (readp) {
-	/* read entry from disk */
-	if ((fread(buf, 1, size, fp)<size)) {
-	    zip_err = ZERR_READ;
-	    return -1;
-	}
-	left = size;
-	cur = buf;
-    }
-    else {
-	cur = *cdpp;
-	if (left < size) {
-	    zip_err = ZERR_NOZIP;
-	    return -1;
-	}
-    }
-
-    if (localp) {
-	if (memcmp(cur, LOCAL_MAGIC, 4)!=0) {
-	    zip_err = ZERR_NOZIP;
-	    return -1;
-	}
-    }
-    else
-	if (memcmp(cur, CENTRAL_MAGIC, 4)!=0) {
-	    zip_err = ZERR_NOZIP;
-	    return -1;
-	}
-
-    cur += 4;
-
-    /* convert buffercontents to zf_entry */
-    if (!localp)
-	zfe->meta->version_made = _zip_read2(&cur);
-    else
-	zfe->meta->version_made = 0;
-    zfe->meta->version_need = _zip_read2(&cur);
-    zfe->meta->bitflags = _zip_read2(&cur);
-    zfe->meta->comp_method = _zip_read2(&cur);
-    /* convert to time_t */
-    dostime = _zip_read2(&cur);
-    dosdate = _zip_read2(&cur);
-
-    zfe->meta->last_mod = _zip_d2u_time(dostime, dosdate);
-    
-    zfe->meta->crc = _zip_read4(&cur);
-    zfe->meta->comp_size = _zip_read4(&cur);
-    zfe->meta->uncomp_size = _zip_read4(&cur);
-    
-    zfe->file_fnlen = _zip_read2(&cur);
-    if (localp) {
-	zfe->meta->ef_len = 0;
-	zfe->meta->lef_len = _zip_read2(&cur);
-	zfe->meta->fc_len = zfe->meta->disknrstart = zfe->meta->int_attr = 0;
-	zfe->meta->ext_attr = zfe->meta->local_offset = 0;
-    } else {
-	zfe->meta->ef_len = _zip_read2(&cur);
-	zfe->meta->lef_len = 0;
-	zfe->meta->fc_len = _zip_read2(&cur);
-	zfe->meta->disknrstart = _zip_read2(&cur);
-	zfe->meta->int_attr = _zip_read2(&cur);
-
-	zfe->meta->ext_attr = _zip_read4(&cur);
-	zfe->meta->local_offset = _zip_read4(&cur);
-    }
-
-    if (left < CDENTRYSIZE+zfe->file_fnlen+zfe->meta->ef_len
-	+zfe->meta->lef_len+zfe->meta->fc_len) {
-	if (readp) {
-	    if (zfe->file_fnlen)
-		zfe->fn = _zip_readfpstr(fp, zfe->file_fnlen, 1);
-	    else
-		zfe->fn = strdup("");
-
-	    if (!zfe->fn) {
-		zip_err = ZERR_MEMORY;
-		return -1;
-	    }
-
-	    /* only set for local headers */
-	    if (zfe->meta->lef_len) {
-		zfe->meta->lef = _zip_readfpstr(fp, zfe->meta->lef_len, 0);
-		if (!zfe->meta->lef)
-		    return -1;
-	    }
-
-	    /* only set for central directory entries */
-	    if (zfe->meta->ef_len) {
-		zfe->meta->ef = _zip_readfpstr(fp, zfe->meta->ef_len, 0);
-		if (!zfe->meta->ef)
-		    return -1;
-	    }
-
-	    /* only set for central directory entries */
-	    if (zfe->meta->fc_len) {
-		zfe->meta->fc = _zip_readfpstr(fp, zfe->meta->fc_len, 0);
-		if (!zfe->meta->fc)
-		    return -1;
-	    }
-	}
-	else {
-	    /* can't get more bytes if not allowed to read */
-	    zip_err = ZERR_NOZIP;
-	    return -1;
-	}
-    }
-    else {
-        if (zfe->file_fnlen) {
-	    zfe->fn = _zip_readstr(&cur, zfe->file_fnlen, 1);
-	    if (!zfe->fn)
-		return -1;
-	}
-
-	/* only set for local headers */
-	if (zfe->meta->lef_len) {
-	    zfe->meta->lef = _zip_readstr(&cur, zfe->meta->lef_len, 0);
-	    if (!zfe->meta->lef)
-		return -1;
-	}
-
-	/* only set for central directory entries */
-	if (zfe->meta->ef_len) {
-	    zfe->meta->ef = _zip_readstr(&cur, zfe->meta->ef_len, 0);
-	    if (!zfe->meta->ef)
-		return -1;
-	}
-
-	/* only set for central directory entries */
-        if (zfe->meta->fc_len) {
-	    zfe->meta->fc = _zip_readstr(&cur, zfe->meta->fc_len, 0);
-	    if (!zfe->meta->fc)
-		return -1;
-	}
-    }
-    if (!readp)
-      *cdpp = cur;
-
-    return 0;
-}
-
-
-
-static int
-_zip_read2(unsigned char **a)
-{
-    int ret;
-
-    ret = (*a)[0]+((*a)[1]<<8);
-    *a += 2;
-
-    return ret;
-}
-
-
-
-static int
-_zip_read4(unsigned char **a)
-{
-    int ret;
-
-    ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
-    *a += 4;
-
-    return ret;
-}
-
-
-
-static char *
-_zip_readstr(unsigned char **buf, int len, int nulp)
-{
-    char *r, *o;
-
-    r = (char *)malloc(nulp?len+1:len);
-    if (!r) {
-	zip_err = ZERR_MEMORY;
-	return NULL;
-    }
-    
-    memcpy(r, *buf, len);
-    *buf += len;
-
-    if (nulp) {
-	/* elephant */
-	r[len] = 0;
-	o = r-1;
-	while (((o=memchr(o+1, 0, r+len-(o+1))) < r+len) && o)
-	       *o = ' ';
-    }
-
-    return r;
-}
-
-
-
-static char *
-_zip_readfpstr(FILE *fp, int len, int nulp)
-{
-    char *r, *o;
-
-    r = (char *)malloc(nulp?len+1:len);
-    if (!r) {
-	zip_err = ZERR_MEMORY;
-	return NULL;
-    }
-
-    if (fread(r, 1, len, fp)<len) {
-	free(r);
-	return NULL;
-    }
-
-    if (nulp) {
-	/* elephant */
-	r[len] = 0;
-	o = r-1;
-	while (((o=memchr(o+1, 0, r+len-(o+1))) < r+len) && o)
-	       *o = ' ';
-    }
-    
-    return r;
+    return cd;
 }
 
 
@@ -574,60 +326,51 @@
    difference between the lowest and the highest fileposition reached */
 
 static int
-_zip_checkcons(FILE *fp, struct zip *zf)
+_zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error)
 {
     int min, max, i, j;
-    struct zip_entry *temp;
+    struct zip_dirent temp;
     unsigned char *buf;
 
     buf = NULL;
-    if (zf->nentry) {
-	max = zf->entry[0].meta->local_offset;
-	min = zf->entry[0].meta->local_offset;
+    if (cd->nentry) {
+	max = cd->entry[0].offset;
+	min = cd->entry[0].offset;
     }
 
-    if ((temp=_zip_new_entry(NULL))==NULL)
-	return -1;
-    
-    for (i=0; i<zf->nentry; i++) {
-	if (zf->entry[i].meta->local_offset < min)
-	    min = zf->entry[i].meta->local_offset;
+    for (i=0; i<cd->nentry; i++) {
+	if (cd->entry[i].offset < min)
+	    min = cd->entry[i].offset;
 	if (min < 0) {
-	    zip_err = ZERR_NOZIP;
-	    _zip_free_entry(temp);
+	    _zip_error_set(error, ZERR_NOZIP, 0);
 	    return -1;
 	}
 	
-	j = zf->entry[i].meta->local_offset + zf->entry[i].meta->comp_size
-	    + zf->entry[i].file_fnlen + zf->entry[i].meta->ef_len
-	    + zf->entry[i].meta->fc_len + LENTRYSIZE;
+	j = cd->entry[i].offset + cd->entry[i].comp_size
+	    + cd->entry[i].filename_len + LENTRYSIZE;
 	if (j > max)
 	    max = j;
-	if (max > zf->cd_offset) {
-	    zip_err = ZERR_NOZIP;
-	    _zip_free_entry(temp);
+	if (max > cd->offset) {
+	    _zip_error_set(error, ZERR_NOZIP, 0);
 	    return -1;
 	}
 	
-	if (fseek(fp, zf->entry[i].meta->local_offset, SEEK_SET) != 0) {
-	    zip_err = ZERR_SEEK;
-	    _zip_free_entry(temp);
+	if (fseek(fp, cd->entry[i].offset, SEEK_SET) != 0) {
+	    _zip_error_set(error, ZERR_SEEK, 0);
 	    return -1;
 	}
 	
-	if (_zip_readcdentry(fp, temp, &buf, 0, 1, 1) == -1) {
-	    _zip_free_entry(temp);
+	if (_zip_dirent_read(&temp, fp, NULL, 0, 1, error) == -1)
 	    return -1;
-	}
 	
-	if (_zip_headercomp(zf->entry+i, 0, temp, 1) != 0) {
-	    zip_err = ZERR_NOZIP;
-	    _zip_free_entry(temp);
+	if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) {
+	    _zip_error_set(error, ZERR_NOZIP, 0);
+	    _zip_dirent_finalize(&temp);
 	    return -1;
 	}
+	_zip_dirent_finalize(&temp);
     }
 
-    _zip_free_entry(temp);
     return max - min;
 }
 
@@ -639,42 +382,45 @@
    are identical, -1 if not. */
 
 static int
-_zip_headercomp(struct zip_entry *h1, int local1p, struct zip_entry *h2,
+_zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2,
 	   int local2p)
 {
-    if ((h1->meta->version_need != h2->meta->version_need)
+    if ((h1->version_needed != h2->version_needed)
 #if 0
 	/* some zip-files have different values in local
 	   and global headers for the bitflags */
-	|| (h1->meta->bitflags != h2->meta->bitflags)
+	|| (h1->bitflags != h2->bitflags)
 #endif
-	|| (h1->meta->comp_method != h2->meta->comp_method)
-	|| (h1->meta->last_mod != h2->meta->last_mod)
-	|| (h1->meta->crc != h2->meta->crc)
-	|| (h1->meta->comp_size != h2->meta->comp_size)
-	|| (h1->meta->uncomp_size != h2->meta->uncomp_size)
-	|| !h1->fn
-	|| !h2->fn
-	|| strcmp(h1->fn, h2->fn))
+	|| (h1->comp_method != h2->comp_method)
+	|| (h1->last_mod != h2->last_mod)
+	|| (h1->crc != h2->crc)
+	|| (h1->comp_size != h2->comp_size)
+	|| (h1->uncomp_size != h2->uncomp_size)
+	|| (h1->filename_len != h2->filename_len)
+	|| !h1->filename || !h2->filename
+	|| strcmp(h1->filename, h2->filename))
 	return -1;
 
-    /* if they are different type, nothing more to check */
-    if (local1p != local2p)
+    if ((local1p == local2p)
+	&& ((h1->extrafield_len != h2->extrafield_len)
+	    || (h1->extrafield_len && h2->extrafield
+		&& memcmp(h1->extrafield, h2->extrafield,
+			  h1->extrafield_len))))
+	return -1;
+
+    /* if either is local, nothing more to check */
+    if (local1p || local2p)
 	return 0;
 
-    if ((h1->meta->version_made != h2->meta->version_made)
-	|| (h1->meta->disknrstart != h2->meta->disknrstart)
-	|| (h1->meta->int_attr != h2->meta->int_attr)
-	|| (h1->meta->ext_attr != h2->meta->ext_attr)
-	|| (h1->meta->local_offset != h2->meta->local_offset)
-	|| (h1->meta->ef_len != h2->meta->ef_len)
-	|| (h1->meta->ef_len && memcmp(h1->meta->ef, h2->meta->ef,
-				       h1->meta->ef_len))
-	|| (h1->meta->fc_len != h2->meta->fc_len)
-	|| (h1->meta->fc_len && memcmp(h1->meta->fc, h2->meta->fc,
-				       h1->meta->fc_len))) {
+    if ((h1->version_madeby != h2->version_madeby)
+	|| (h1->disk_number != h2->disk_number)
+	|| (h1->int_attrib != h2->int_attrib)
+	|| (h1->ext_attrib != h2->ext_attrib)
+	|| (h1->offset != h2->offset)
+	|| (h1->comment_len != h2->comment_len)
+	|| (h1->comment_len && h2->comment
+	    && memcmp(h1->comment, h2->comment, h1->comment_len)))
 	return -1;
-    }
 
     return 0;
 }
@@ -707,7 +453,7 @@
 
     ret = malloc(len);
     if (!ret) {
-	zip_err = ZERR_MEMORY;
+	/* XXX: zip_err = ZERR_MEMORY; */
 	return NULL;
     }
 
@@ -715,25 +461,3 @@
 
     return ret;
 }
-
-
-
-static time_t
-_zip_d2u_time(int dtime, int ddate)
-{
-    struct tm *tm;
-    time_t now;
-
-    now = time(NULL);
-    tm = localtime(&now);
-    
-    tm->tm_year = ((ddate>>9)&127) + 1980 - 1900;
-    tm->tm_mon = ((ddate>>5)&15) - 1;
-    tm->tm_mday = ddate&31;
-
-    tm->tm_hour = (dtime>>11)&31;
-    tm->tm_min = (dtime>>5)&63;
-    tm->tm_sec = (dtime<<1)&62;
-
-    return mktime(tm);
-}