API cleanup (see ChangeLog)

--HG--
branch : HEAD
diff --git a/ChangeLog b/ChangeLog
index 0119f37..6fb2b82 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,31 @@
 2003-10-05  Dieter Baron  <dillo@danbala.tuwien.ac.at>
 
-	* lib/zip.h: (struct zip_error) new struct.
-	* lib/zip.h: (struct zip, struct zip_file) add new member error.
+	* lib/zip.h, lib/zipint.h: Don't expose struct zip, struc
+	zip_file.
+	* lib/zip_open.c (zip_open): new argument errp, use it to store
+	error code.
+	* lib/zip_error_str.c (zip_error_str): new function.
+	* lib/zip_error_sys_type.c (zip_error_sys_type): new function.
+	* lib/zip_get_num_files.c (zip_get_num_files): new function.
+	* src/zipcmp.c (compare_zip): adapt to new API.
+
+	* lib/zip.h, lib/zipint.h: Don't expose zip_err_str, rename to
+	_zip_err_str.  Adapt users.
+	
+	* lib/zip_error.c(_zip_error_get): new function.
+	* lib/zip_get_error.c (zip_get_error): new function.
+	* lib/zip_file_get_error.c (zip_file_get_error): new function.
+	
+	* lib/zip.h (struct zip_stat): new struct.
+	* lib/zip_stat.c (zip_stat): new function.
+	* lib/zip_stat_index.c (zip_stat_index) new function.
+
+	* lib/zip_error.c (_zip_error_set): new function.
+	* lib/zip_name_locate.c (zip_name_locate): set za->error if name
+	not found.
+	
+	* lib/zip.h: (struct zip_error): new struct.
+	* lib/zip.h: (struct zip, struct zip_file): add new member error.
 	* lib/zip.h, lib/zipint.h, lib/make_zip_err_str.sh: add
 	_zip_err_errno.
 	* lib/zip_error.c (_zip_error_fini, _zip_error_init): new
diff --git a/TODO b/TODO
index cfd0a7a..991e529 100644
--- a/TODO
+++ b/TODO
@@ -1,19 +1,17 @@
 ------------------------------------------------ showstopper
 * API cleanup
 	check function names (consistency, appropriateness)
-	error handling: errno member in struct zip, struct zip_file
-	error handling in zip_open?
 	file sizes, offsets: type big enough?
-	meta data: expose struct vs. accessor functions
-	don't expose struct zip, struct zip_file
-* needed functions:
-	get error code from struct zip, struct zip_file
-	get nentries from zip
-* documentation: zip_add*, zip_replace*,
+	don't expose struct zip, struct zip_file, struct zip_meta
+	clean up error handling and error code setting (get rid of zip_err)
+	zip_{add,replace}*: don't use struct zip_meta
+* documentation: zip_add*, zip_replace*, zip_{,_file}get_error,
+	zip_error_sys_type, zip_get_num_files, zip_error_str
 	[zip_free_meta, zip_meta_new]
+	zip_fopen, zip_name_locate: flags
+	zip_open: errp
 * regression tests
 * code review
-
 ------------------------------------------------ others
 * fix warnings in zipcmp
 * zipcmp: add option for file content comparison
diff --git a/configure.ac b/configure.ac
index 91a7e68..a3d31fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,7 @@
 		 man/zip_name_locate.3:man/zip_name_locate.${MANFMT}
 		 man/zip_open.3:man/zip_open.${MANFMT}
 		 man/zip_rename.3:man/zip_rename.${MANFMT}
+		 man/zip_stat.3:man/zip_stat.${MANFMT}
 		 man/zip_strerror.3:man/zip_strerror.${MANFMT}
 		 man/zip_unchange.3:man/zip_unchange.${MANFMT}
 		 man/zip_unchange_all.3:man/zip_unchange_all.${MANFMT}])
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 0fc78ee..53612c8 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -14,8 +14,10 @@
 	zip_delete.c \
 	zip_err_str.c \
 	zip_error.c \
+	zip_error_str.c \
 	zip_error_strerror.c \
 	zip_fclose.c \
+	zip_file_get_error.c \
 	zip_file_strerror.c \
 	zip_fopen.c \
 	zip_fopen_index.c \
@@ -23,7 +25,9 @@
 	zip_free.c \
 	zip_free_entry.c \
 	zip_free_meta.c \
+	zip_get_error.c \
 	zip_get_meta.c \
+	zip_get_num_files.c \
 	zip_get_name.c \
 	zip_merge_meta.c \
 	zip_name_locate.c \
@@ -38,6 +42,8 @@
 	zip_replace_filep.c \
 	zip_replace_zip.c \
 	zip_set_name.c \
+	zip_stat.c \
+	zip_stat_index.c \
 	zip_strerror.c \
 	zip_unchange.c \
 	zip_unchange_all.c \
diff --git a/lib/make_zip_err_str.sh b/lib/make_zip_err_str.sh
index 162a6d8..1c8ce0c 100755
--- a/lib/make_zip_err_str.sh
+++ b/lib/make_zip_err_str.sh
@@ -22,7 +22,7 @@
 
 
 
-const char * const zip_err_str[] = {
+const char * const _zip_err_str[] = {
 EOF
 
 sed -n  '/^#define ZERR_/ s/.*\/\* . \([^*]*\) \*\//    "\1",/p' "$1" \
@@ -31,7 +31,7 @@
 cat <<EOF >> "$2.$$" || exit 1
 };
 
-const int zip_nerr_str = sizeof(zip_err_str)/sizeof(zip_err_str[0]);
+const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]);
 
 #define N ZIP_ET_NONE
 #define S ZIP_ET_SYS
diff --git a/lib/zip.h b/lib/zip.h
index e36de4b..6853136 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -2,7 +2,7 @@
 #define _HAD_ZIP_H
 
 /*
-  $NiH: zip.h,v 1.33 2003/10/04 07:40:59 dillo Exp $
+  $NiH: zip.h,v 1.34 2003/10/05 16:05:22 dillo Exp $
 
   zip.h -- exported declarations.
   Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
@@ -52,6 +52,10 @@
 #define ZIP_EXCL             2
 #define ZIP_CHECKCONS        4
 
+/* flags for zip_name_locate */
+#define ZIP_NAME_NOCASE		1
+#define ZIP_NAME_NODIR		2
+
 int zip_err; /* global variable for errors returned by the low-level
 		library */
 
@@ -78,70 +82,15 @@
 #define ZERR_INTERNAL        20  /* N Internal error */
 #define ZERR_INCONS	     21  /* N Zip archive inconsistent */
 
-extern const char * const zip_err_str[];
-extern const int zip_nerr_str;
+#define ZIP_ET_NONE	      0  /* sys_err unused */
+#define ZIP_ET_SYS	      1  /* sys_err is errno */
+#define ZIP_ET_ZIP	      2  /* sys_err is zlib error code */
 
 /* zip file */
 
 typedef int (*zip_read_func)(void *state, void *data,
 			     int len, enum zip_cmd cmd);
 
-struct zip_error {
-    int zip_err;	/* libzip error code (ZERR_*) */
-    int sys_err;	/* copy of errno (E*) */
-    char *str;		/* string representation or NULL */
-};
-
-struct zip {
-    char *zn;
-    FILE *zp;
-    struct zip_error error;
-    unsigned short comlen, changes;
-    unsigned int cd_size, cd_offset;
-    char *com;
-    int nentry, nentry_alloc;
-    struct zip_entry *entry;
-    int nfile, nfile_alloc;
-    struct zip_file **file;
-};
-
-/* file in zip file */
-
-struct zip_file {
-    struct zip *zf;
-    char *name;
-    struct zip_error error;
-    int flags; /* -1: eof, >0: error */
-
-    int method;
-    /* position within zip file (fread/fwrite) */
-    long fpos;
-    /* no of bytes left to read */
-    unsigned long bytes_left;
-    /* no of bytes of compressed data left */
-    unsigned long cbytes_left;
-    /* crc so far */
-    unsigned long crc, crc_orig;
-    
-    char *buffer;
-    z_stream *zstr;
-};
-
-/* entry in zip file directory */
-
-struct zip_entry {
-    struct zip_meta *meta;
-    char *fn;
-    char *fn_old;
-    unsigned int file_fnlen;
-
-    enum zip_state state;
-    zip_read_func ch_func;
-    void *ch_data;
-    int ch_comp;		/* 1: data returned by ch_func is compressed */
-    struct zip_meta *ch_meta;
-};
-
 struct zip_meta {
     unsigned short version_made, version_need, bitflags, comp_method,
 	disknrstart, int_attr;
@@ -151,6 +100,20 @@
     unsigned char *ef, *lef, *fc;
 };
 
+struct zip_stat {
+    const char *name;			/* name of the file */
+    int index;				/* index within archive */
+    unsigned int crc;			/* crc of file data */
+    unsigned int size;			/* size of file (uncompressed) */
+    time_t mtime;			/* modification time */
+    unsigned int comp_size;		/* size of file (compressed) */
+    unsigned short comp_method;		/* compression method used */
+    /* unsigned short bitflags; */
+};
+
+struct zip;
+struct zip_file;
+
 
 
 int zip_add(struct zip *, const char *, struct zip_meta *,
@@ -165,17 +128,22 @@
 		struct zip *, int, int, int);
 int zip_close(struct zip *);
 int zip_delete(struct zip *, int);
+int zip_error_str(char *, int, int, int);
+int zip_error_sys_type(int);
 int zip_fclose(struct zip_file *);
+void zip_file_get_error(struct zip_file *, int *, int *);
 const char *zip_file_strerror(struct zip_file *);
 struct zip_file *zip_fopen(struct zip *, const char *, int);
 struct zip_file *zip_fopen_index(struct zip *, int);
 int zip_fread(struct zip_file *, char *, int);
 void zip_free_meta(struct zip_meta *);
+void zip_get_error(struct zip *, int *, int *);
 struct zip_meta *zip_get_meta(struct zip *, int);
 const char *zip_get_name(struct zip *, int);
+int zip_get_num_files(struct zip *);
 int zip_name_locate(struct zip *, const char *, int);
 struct zip_meta *zip_new_meta(void);
-struct zip *zip_open(const char *, int);
+struct zip *zip_open(const char *, int, int *);
 int zip_rename(struct zip *, int, const char *);
 int zip_replace(struct zip *, int, const char *, struct zip_meta *,
 		zip_read_func, void *, int);
@@ -187,6 +155,8 @@
 		     FILE *, int, int);
 int zip_replace_zip(struct zip *, int, const char *, struct zip_meta *,
 		    struct zip *, int, int, int);
+int zip_stat(struct zip *, const char *, int, struct zip_stat *);
+int zip_stat_index(struct zip *, int, struct zip_stat *);
 const char *zip_strerror(struct zip *);
 int zip_unchange(struct zip *, int);
 int zip_unchange_all(struct zip *);
diff --git a/lib/zip_error.c b/lib/zip_error.c
index 5891321..2e28a8c 100644
--- a/lib/zip_error.c
+++ b/lib/zip_error.c
@@ -1,5 +1,5 @@
 /*
-  $NiH$
+  $NiH: zip_error.c,v 1.1 2003/10/05 16:05:22 dillo Exp $
 
   zip_error.c -- struct zip_error helper functions
   Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
@@ -51,10 +51,31 @@
 
 
 
+void
+_zip_error_get(struct zip_error *err, int *zep, int *sep)
+{
+    if (zep)
+	*zep = err->zip_err;
+    /* XXX: only if valid? */
+    if (sep)
+	*sep = err->sys_err;
+}
 
-void _zip_error_init(struct zip_error *err)
+
+
+void
+_zip_error_init(struct zip_error *err)
 {
     err->zip_err = 0;
     err->sys_err = 0;
     err->str = NULL;
 }
+
+
+
+void
+_zip_error_set(struct zip_error *err, int ze, int se)
+{
+    err->zip_err = ze;
+    err->sys_err = se;
+}
diff --git a/lib/zip_error_str.c b/lib/zip_error_str.c
new file mode 100644
index 0000000..548b2c0
--- /dev/null
+++ b/lib/zip_error_str.c
@@ -0,0 +1,73 @@
+/*
+  $NiH$
+
+  zip_error_str.c -- get string representation of zip error code
+  Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <nih@giga.or.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+ 
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_error_str(char *buf, int len, int ze, int se)
+{
+    const char *zs, *ss;
+
+    if (ze < 0 || ze >= _zip_nerr_str)
+	return snprintf(buf, len, "Unknown error %d", ze);
+
+    zs = _zip_err_str[ze];
+	
+    switch (_zip_err_type[ze]) {
+    case ZIP_ET_SYS:
+	ss = strerror(se);
+	break;
+	
+    case ZIP_ET_ZIP:
+	ss = zError(se);
+	break;
+	
+    default:
+	ss = NULL;
+    }
+
+    return snprintf(buf, len, "%s%s%s",
+		    zs, (ss ? ": " : ""), (ss ? ss : ""));
+}
diff --git a/lib/zip_error_strerror.c b/lib/zip_error_strerror.c
index 7e8791a..fae7c1c 100644
--- a/lib/zip_error_strerror.c
+++ b/lib/zip_error_strerror.c
@@ -1,5 +1,5 @@
 /*
-  $NiH$
+  $NiH: zip_error_strerror.c,v 1.1 2003/10/05 16:05:22 dillo Exp $
 
   zip_error_sterror.c -- get string representation of struct zip_error
   Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
@@ -48,28 +48,45 @@
 const char *
 _zip_error_strerror(struct zip_error *err)
 {
+    const char *zs, *ss;
+    char buf[128], *s;
+
     _zip_error_fini(err);
 
-    if (err->zip_err < 0 || err->zip_err >= zip_nerr_str) {
-	/* XXX */
-	asprintf(&err->str, "Unknown error %d", err->zip_err);
-	return err->str;
+    if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) {
+	sprintf(buf, "Unknown error %d", err->zip_err);
+	zs = NULL;
+	ss = buf;
+    }
+    else {
+	zs = _zip_err_str[err->zip_err];
+	
+	switch (_zip_err_type[err->zip_err]) {
+	case ZIP_ET_SYS:
+	    ss = strerror(err->sys_err);
+	    break;
+
+	case ZIP_ET_ZIP:
+	    ss = zError(err->sys_err);
+	    break;
+
+	default:
+	    ss = NULL;
+	}
     }
 
-    switch (_zip_err_type[err->zip_err]) {
-    case ZIP_ET_SYS:
-	/* XXX */
-	asprintf(&err->str, "%s: %s",
-		 zip_err_str[err->zip_err], strerror(err->sys_err));
-	return err->str;
+    if (ss == NULL)
+	return zs;
+    else {
+	if ((s=malloc(strlen(ss) + (zs ? strlen(zs)+2 : 0) + 1)) == NULL)
+	    return _zip_err_str[ZERR_MEMORY];
+	
+	sprintf(s, "%s%s%s",
+		(zs ? zs : ""),
+		(zs ? ": " : ""),
+		ss);
+	err->str = s;
 
-    case ZIP_ET_ZIP:
-	/* XXX */
-	asprintf(&err->str, "%s: %s",
-		 zip_err_str[err->zip_err], zError(err->sys_err));
-	return err->str;
-
-    default:
-	return zip_err_str[err->zip_err];
+	return ss;
     }
 }
diff --git a/lib/zip_error_sys_type.c b/lib/zip_error_sys_type.c
new file mode 100644
index 0000000..7c1c899
--- /dev/null
+++ b/lib/zip_error_sys_type.c
@@ -0,0 +1,50 @@
+/*
+  $NiH$
+
+  zip_error_sys_type.c -- return type of system error code
+  Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <nih@giga.or.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+ 
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_error_sys_type(int ze)
+{
+    if (ze < 0 || ze >= _zip_nerr_str)
+	return 0;
+
+    return _zip_err_type[ze];
+}
diff --git a/lib/zip_file_get_error.c b/lib/zip_file_get_error.c
new file mode 100644
index 0000000..f9f36a6
--- /dev/null
+++ b/lib/zip_file_get_error.c
@@ -0,0 +1,47 @@
+/*
+  $NiH$
+
+  zip_file_get_error.c -- get zip file error
+  Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <nih@giga.or.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+ 
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+void
+zip_file_get_error(struct zip_file *zf, int *zep, int *sep)
+{
+    _zip_error_get(&zf->error, zep, sep);
+}
diff --git a/lib/zip_get_error.c b/lib/zip_get_error.c
new file mode 100644
index 0000000..5545565
--- /dev/null
+++ b/lib/zip_get_error.c
@@ -0,0 +1,47 @@
+/*
+  $NiH$
+
+  zip_get_error.c -- get zip error
+  Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <nih@giga.or.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+ 
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+void
+zip_get_error(struct zip *za, int *zep, int *sep)
+{
+    _zip_error_get(&za->error, zep, sep);
+}
diff --git a/lib/zip_get_num_files.c b/lib/zip_get_num_files.c
new file mode 100644
index 0000000..9b399cc
--- /dev/null
+++ b/lib/zip_get_num_files.c
@@ -0,0 +1,47 @@
+/*
+  $NiH$
+
+  zip_get_num_files.c -- get number of files in archive
+  Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <nih@giga.or.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+ 
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_get_num_files(struct zip *za)
+{
+    return za->nentry;
+}
diff --git a/lib/zip_name_locate.c b/lib/zip_name_locate.c
index 32f6ebe..eb7c9a9 100644
--- a/lib/zip_name_locate.c
+++ b/lib/zip_name_locate.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_name_locate.c,v 1.7 2003/10/01 09:51:00 dillo Exp $
+  $NiH: zip_name_locate.c,v 1.8 2003/10/02 14:13:30 dillo Exp $
 
   zip_name_locate.c -- get index by name
   Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
@@ -43,13 +43,27 @@
 
 
 int
-zip_name_locate(struct zip *zf, const char *fname, int case_sens)
+zip_name_locate(struct zip *za, const char *fname, int flags)
 {
+    int (*cmp)();
+    const char *fn;
     int i;
 
-    for (i=0; i<zf->nentry; i++)
-	if ((case_sens ? strcmp : strcasecmp)(fname, zf->entry[i].fn) == 0)
-	    return i;
+    cmp = (flags & ZIP_NAME_NOCASE) ? strcmp : strcasecmp;
 
+    for (i=0; i<za->nentry; i++) {
+	if (flags & ZIP_NAME_NODIR) {
+	    /* XXX: handle '\' */
+	    if ((fn=strrchr(za->entry[i].fn, '/')) == NULL)
+		fn = za->entry[i].fn;
+	}
+	else 
+	    fn = za->entry[i].fn;
+
+	if (cmp(fname, fn) == 0)
+	    return i;
+    }
+
+    _zip_error_set(&za->error, ZERR_NOENT, 0);
     return -1;
 }
diff --git a/lib/zip_open.c b/lib/zip_open.c
index ee89a79..3323e11 100644
--- a/lib/zip_open.c
+++ b/lib/zip_open.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_open.c,v 1.15 2003/10/01 09:51:00 dillo Exp $
+  $NiH: zip_open.c,v 1.16 2003/10/02 14:13:31 dillo Exp $
 
   zip_open.c -- open zip file
   Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
@@ -46,6 +46,7 @@
 #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);
 static int _zip_read2(unsigned char **a);
@@ -69,7 +70,7 @@
    zipfile struct, or NULL if unsuccessful, setting zip_err. */
 
 struct zip *
-zip_open(const char *fn, int flags)
+zip_open(const char *fn, int flags, int *errp)
 {
     FILE *fp;
     unsigned char *buf, *match;
@@ -79,32 +80,34 @@
     struct stat st;
 
     if (fn == NULL) {
-	zip_err = ZERR_INVAL;
+	set_error(errp, ZERR_INVAL);
 	return NULL;
     }
     
     if (stat(fn, &st) != 0) {
 	if (flags & ZIP_CREATE) {
 	    cdir = _zip_new();
+	    /* XXX: check cdir != NULL */
 	    cdir->zn = strdup(fn);
 	    if (!cdir->zn) {
-		zip_err = ZERR_MEMORY;
+		/* XXX: free cdir */
+		set_error(errp, ZERR_MEMORY);
 		return NULL;
 	    }
 	    return cdir;
 	} else {
-	    zip_err = ZERR_NOENT;
+	    set_error(errp, ZERR_NOENT);
 	    return NULL;
 	}
     } else if ((flags & ZIP_EXCL)) {
-	zip_err = ZERR_EXISTS;
+	set_error(errp, ZERR_EXISTS);
 	return NULL;
     }
     /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL,
        just like open() */
     
     if ((fp=fopen(fn, "rb"))==NULL) {
-	zip_err = ZERR_OPEN;
+	set_error(errp, ZERR_OPEN);
 	return NULL;
     }
     
@@ -114,14 +117,16 @@
     i = fseek(fp, -(len < BUFSIZE ? len : BUFSIZE), SEEK_END);
     if (i == -1 && errno != EFBIG) {
 	/* seek before start of file on my machine */
-	zip_err = ZERR_SEEK;
+	set_error(errp, ZERR_SEEK);
 	fclose(fp);
 	return NULL;
     }
 
+    /* XXX: why not allocate statically? */
     buf = (unsigned char *)malloc(BUFSIZE);
     if (!buf) {
-	zip_err = ZERR_MEMORY;
+	set_error(errp, ZERR_MEMORY);
+	fclose(fp);
 	return NULL;
     }
 
@@ -129,7 +134,7 @@
     buflen = fread(buf, 1, BUFSIZE, fp);
 
     if (ferror(fp)) {
-	zip_err = ZERR_READ;
+	set_error(errp, ZERR_READ);
 	free(buf);
 	fclose(fp);
 	return NULL;
@@ -170,7 +175,7 @@
 
     if (best < 0) {
 	/* no consistent eocd found */
-	zip_err = ZERR_NOZIP;
+	set_error(errp, ZERR_NOZIP);
 	free(buf);
 	_zip_free(cdir);
 	fclose(fp);
@@ -181,7 +186,9 @@
 
     cdir->zn = strdup(fn);
     if (!cdir->zn) {
-	zip_err = ZERR_MEMORY;
+	set_error(errp, ZERR_MEMORY);
+	_zip_free(cdir);
+	fclose(fp);
 	return NULL;
     }
 
@@ -192,6 +199,15 @@
 
 
 
+static void
+set_error(int *errp, int err)
+{
+    if (errp)
+	*errp = err;
+}
+
+
+
 /* _zip_readcdir:
    tries to find a valid end-of-central-directory at the beginning of
    buf, and then the corresponding central directory entries.
diff --git a/lib/zip_stat.c b/lib/zip_stat.c
new file mode 100644
index 0000000..44a1113
--- /dev/null
+++ b/lib/zip_stat.c
@@ -0,0 +1,52 @@
+/*
+  $NiH$
+
+  zip_stat.c -- get information about file by name
+  Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <nih@giga.or.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+ 
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_stat(struct zip *za, const char *fname, int flags, struct zip_stat *st)
+{
+    int idx;
+
+    if ((idx=zip_name_locate(za, fname, flags)) < 0)
+	return -1;
+
+    return zip_stat_index(za, idx, st);
+}
diff --git a/lib/zip_stat_index.c b/lib/zip_stat_index.c
new file mode 100644
index 0000000..06bda6e
--- /dev/null
+++ b/lib/zip_stat_index.c
@@ -0,0 +1,61 @@
+/*
+  $NiH$
+
+  zip_stat_index.c -- get information about file by index
+  Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <nih@giga.or.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+ 
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_stat_index(struct zip *za, int index, struct zip_stat *st)
+{
+    if (index < 0 || index >= za->nentry) {
+	_zip_error_set(&za->error, ZERR_INVAL, 0);
+	return -1;
+    }
+
+    st->name = za->entry[index].fn;
+    st->index = index;
+    st->crc = za->entry[index].meta->crc;
+    st->size = za->entry[index].meta->uncomp_size;
+    st->mtime = za->entry[index].meta->last_mod;
+    st->comp_size = za->entry[index].meta->comp_size;
+    st->comp_method = za->entry[index].meta->comp_method;
+    /* st->bitflags = za->entry[index].meta->bitflags; */
+
+    return 0;
+}
diff --git a/lib/zipint.h b/lib/zipint.h
index 37ea3a9..69fb693 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -2,7 +2,7 @@
 #define _HAD_ZIPINT_H
 
 /*
-  $NiH: zipint.h,v 1.18 2003/10/02 14:13:33 dillo Exp $
+  $NiH: zipint.h,v 1.19 2003/10/05 16:05:22 dillo Exp $
 
   zipint.h -- internal declarations.
   Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner
@@ -48,8 +48,68 @@
 #define CDENTRYSIZE         46
 #define LENTRYSIZE          30
 
-enum { ZIP_ET_NONE, ZIP_ET_SYS, ZIP_ET_ZIP };
+
 
+struct zip_error {
+    int zip_err;	/* libzip error code (ZERR_*) */
+    int sys_err;	/* copy of errno (E*) or zlib error code */
+    char *str;		/* string representation or NULL */
+};
+
+struct zip {
+    char *zn;
+    FILE *zp;
+    struct zip_error error;
+    unsigned short comlen, changes;
+    unsigned int cd_size, cd_offset;
+    char *com;
+    int nentry, nentry_alloc;
+    struct zip_entry *entry;
+    int nfile, nfile_alloc;
+    struct zip_file **file;
+};
+
+/* file in zip file */
+
+struct zip_file {
+    struct zip *zf;
+    char *name;
+    struct zip_error error;
+    int flags; /* -1: eof, >0: error */
+
+    int method;
+    /* position within zip file (fread/fwrite) */
+    long fpos;
+    /* no of bytes left to read */
+    unsigned long bytes_left;
+    /* no of bytes of compressed data left */
+    unsigned long cbytes_left;
+    /* crc so far */
+    unsigned long crc, crc_orig;
+    
+    char *buffer;
+    z_stream *zstr;
+};
+
+/* entry in zip file directory */
+
+struct zip_entry {
+    struct zip_meta *meta;
+    char *fn;
+    char *fn_old;
+    unsigned int file_fnlen;
+
+    enum zip_state state;
+    zip_read_func ch_func;
+    void *ch_data;
+    int ch_comp;		/* 1: data returned by ch_func is compressed */
+    struct zip_meta *ch_meta;
+};
+
+
+
+extern const char * const _zip_err_str[];
+extern const int _zip_nerr_str;
 extern const int _zip_err_type[];
 
 
@@ -57,7 +117,9 @@
 void _zip_entry_init(struct zip *, int);
 const char *_zip_error_strerror(struct zip_error *);
 void _zip_error_fini(struct zip_error *);
+void _zip_error_get(struct zip_error *, int *, int *);
 void _zip_error_init(struct zip_error *);
+void _zip_error_set(struct zip_error *, int, int);
 int _zip_file_fillbuf(char *, int, struct zip_file *);
 int _zip_free(struct zip *);
 int _zip_free_entry(struct zip_entry *);
diff --git a/man/Makefile.am b/man/Makefile.am
index 4225793..c6a792a 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -14,6 +14,8 @@
 	zip_name_locate.3 \
 	zip_open.3 \
 	zip_rename.3 \
+	zip_stat.3 \
+	zip_stat_index.3 \
 	zip_strerror.3 \
 	zip_unchange.3 \
 	zip_unchange_all.3
@@ -25,6 +27,8 @@
 link-man3: install-man3
 	-rm -f ${man3dir}/zip_fopen_index.3
 	${LN} ${man3dir}/zip_fopen.3 ${man3dir}/zip_fopen_index.3
+	-rm -f ${man3dir}/zip_stat_index.3
+	${LN} ${man3dir}/zip_stat.3 ${man3dir}/zip_stat_index.3
 
 MANDOC=${MAN1:.1=.mdoc} ${MAN3:.3=.mdoc}
 MAN=${MANDOC:.mdoc=.man}
diff --git a/man/zip_stat.mdoc b/man/zip_stat.mdoc
new file mode 100644
index 0000000..795d6be
--- /dev/null
+++ b/man/zip_stat.mdoc
@@ -0,0 +1,101 @@
+.\" $NiH$
+.\"
+.\" zip_stat.mdoc -- get information about file
+.\" Copyright (C) 2003 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP archives.
+.\" The authors can be contacted at <nih@giga.or.at>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in
+.\"    the documentation and/or other materials provided with the
+.\"    distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\"    products derived from this software without specific prior
+.\"    written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd October 3, 2003
+.Dt ZIP_STAT 3
+.Os
+.Sh NAME
+.Nm zip_stat ,
+.Nm zip_stat_index
+.Nd get information about file
+.Sh LIBRARY
+libzip (-lzip)
+.Sh SYNOPSIS
+.In zip.h
+.Ft int
+.Fn zip_stat "struct zip *archive" "const char *fname" "int case_sens" "struct zip_stat *sb"
+.Ft int
+.Fn zip_stat_index "struct zip *archive" "int index" "struct zip_stat *sb"
+.Sh DESCRIPTION
+The
+.Fn zip_stat
+function obtains information about the file named
+.Ar fname
+in
+.Ar archive .
+The
+.Ar flags
+argument specifies how the name lookup should be done.
+Its values are described in
+.Xr zip_name_locate 3 .
+.Pp
+The
+.Fn zip_stat_index
+function obtains information about the file at position
+.Ar index .
+.Pp
+The
+.Ar sb
+argument is a pointer to a
+.Ft struct zip_stat
+(shown below), into which information about the file is placed.
+.Bd -literal
+struct zip_stat {
+    const char *name;			/* name of the file */
+    int index;				/* index within archive */
+    unsigned int crc;			/* crc of file data */
+    unsigned int size;			/* size of file (uncompressed) */
+    time_t mtime;			/* modification time */
+    unsigned int comp_size;		/* size of file (compressed) */
+    unsigned short comp_method;		/* compression method used */
+};
+.Sh RETURN VALUES
+Upon successful completion 0 is returned.
+Otherwise, \-1 is returned and the error information in
+.Ar archive
+is set to indicate the error.
+.Sh ERRORS
+The function
+.Fn zip_stat
+can fail for any of the errors specified for the routine
+.Xr zip_name_locate 3 .
+.Pp
+The function
+.Fn zip_stata_index
+fails and sets the error information to
+.Er ZERR_INVAL
+if
+.Ar index
+is invalid.
+.Sh SEE ALSO
+.Xr zip_name_locate 3
diff --git a/src/zipcmp.c b/src/zipcmp.c
index 1d9e6c7..3e9a0fb 100644
--- a/src/zipcmp.c
+++ b/src/zipcmp.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zipcmp.c,v 1.4 2003/10/02 14:13:37 dillo Exp $
+  $NiH: zipcmp.c,v 1.5 2003/10/03 23:54:32 dillo Exp $
 
   cmpzip.c -- compare zip files
   Copyright (C) 2003 Dieter Baron and Thomas Klausner
@@ -35,6 +35,7 @@
 
 
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -141,18 +142,22 @@
 compare_zip(const char *zn[], int verbose)
 {
     struct zip *z;
+    struct zip_stat st;
     struct entry *e[2];
     int n[2];
     int i, j;
+    int err;
+    char errstr[1024];
 
     for (i=0; i<2; i++) {
-	if ((z=zip_open(zn[i], ZIP_CHECKCONS)) == NULL) {
+	if ((z=zip_open(zn[i], ZIP_CHECKCONS, &err)) == NULL) {
+	    zip_error_str(errstr, sizeof(errstr), err, errno);
 	    fprintf(stderr, "%s: cannot open zip file `%s': %s\n",
-		    prg, zn[i], zip_err_str[zip_err]);
+		    prg, zn[i], errstr);
 	    return -1;
 	}
 
-	n[i] = z->nentry;
+	n[i] = zip_get_num_files(z);
 
 	if ((e[i]=malloc(sizeof(*e[i]) * n[i])) == NULL) {
 	    fprintf(stderr, "%s: malloc failure\n", prg);
@@ -160,9 +165,10 @@
 	}
 
 	for (j=0; j<n[i]; j++) {
-	    e[i][j].name = strdup(z->entry[j].fn);
-	    e[i][j].size = z->entry[j].meta->uncomp_size;
-	    e[i][j].crc = z->entry[j].meta->crc;
+	    zip_stat_index(z, i, &st);
+	    e[i][j].name = strdup(st.name);
+	    e[i][j].size = st.size;
+	    e[i][j].crc = st.crc;
 	}
 
 	zip_close(z);