Hash file names to speed up some operations.
In particular, zip_file_add and zip_name_locate.
Add consistency check for duplicate file names,
now that it's cheap.
diff --git a/TODO b/TODO
index 124d79e..bbdb9d5 100644
--- a/TODO
+++ b/TODO
@@ -101,6 +101,7 @@
Test Case Issues
================
+* unchange on added file
* test seek in zip_source_crc
* test cases for set_extra*, delete_extra*, *extra_field*
* test cases for in memory archives
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 3bfc622..2a0962f 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -100,6 +100,7 @@
zip_get_name.c
zip_get_num_entries.c
zip_get_num_files.c
+ zip_hash.c
zip_io_util.c
zip_memdup.c
zip_name_locate.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c43ed4b..8cd2e6e 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -58,6 +58,7 @@
zip_get_num_entries.c \
zip_get_num_files.c \
zip_get_name.c \
+ zip_hash.c \
zip_io_util.c \
zip_memdup.c \
zip_name_locate.c \
diff --git a/lib/zip_delete.c b/lib/zip_delete.c
index b3e7abb..7be0926 100644
--- a/lib/zip_delete.c
+++ b/lib/zip_delete.c
@@ -38,6 +38,8 @@
ZIP_EXTERN int
zip_delete(zip_t *za, zip_uint64_t idx)
{
+ const char *name;
+
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
@@ -48,6 +50,14 @@
return -1;
}
+ if ((name=_zip_get_name(za, idx, 0, &za->error)) == NULL) {
+ return -1;
+ }
+
+ if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
+ return -1;
+ }
+
/* allow duplicate file names, because the file will
* be removed directly afterwards */
if (_zip_unchange(za, idx, 1) != 0)
diff --git a/lib/zip_discard.c b/lib/zip_discard.c
index db22370..cf12215 100644
--- a/lib/zip_discard.c
+++ b/lib/zip_discard.c
@@ -58,6 +58,8 @@
_zip_string_free(za->comment_orig);
_zip_string_free(za->comment_changes);
+ _zip_hash_free(za->names);
+
if (za->entry) {
for (i=0; i<za->nentry; i++)
_zip_entry_finalize(za->entry+i);
diff --git a/lib/zip_hash.c b/lib/zip_hash.c
new file mode 100644
index 0000000..ec6e336
--- /dev/null
+++ b/lib/zip_hash.c
@@ -0,0 +1,263 @@
+/*
+ zip_hash.c -- hash table string -> uint64
+ Copyright (C) 2015 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.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 <stdlib.h>
+#include <string.h>
+#include "zipint.h"
+
+struct zip_hash_entry {
+ const zip_uint8_t *name;
+ zip_int64_t orig_index;
+ zip_int64_t current_index;
+ struct zip_hash_entry *next;
+};
+typedef struct zip_hash_entry zip_hash_entry_t;
+
+struct zip_hash {
+ zip_uint16_t table_size;
+ zip_hash_entry_t **table;
+};
+
+zip_hash_t *
+_zip_hash_new(zip_uint16_t table_size, zip_error_t *error)
+{
+ zip_hash_t *hash;
+
+ if (table_size == 0) {
+ zip_error_set(error, ZIP_ER_INTERNAL, 0);
+ return NULL;
+ }
+
+ if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
+ }
+ hash->table_size = table_size;
+ if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) {
+ free(hash);
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
+ }
+
+ return hash;
+}
+
+static void
+_free_list(zip_hash_entry_t *entry)
+{
+ zip_hash_entry_t *next;
+ do {
+ next = entry->next;
+ free(entry);
+ entry = next;
+ } while (entry != NULL);
+}
+
+void
+_zip_hash_free(zip_hash_t *hash)
+{
+ zip_uint16_t i;
+
+ if (hash == NULL) {
+ return;
+ }
+
+ for (i=0; i<hash->table_size; i++) {
+ if (hash->table[i] != NULL) {
+ _free_list(hash->table[i]);
+ }
+ }
+ free(hash->table);
+ free(hash);
+}
+
+static zip_uint16_t
+_hash_string(const zip_uint8_t *name, zip_uint16_t size)
+{
+#define HASH_MULTIPLIER 33
+ zip_uint16_t value = 5381;
+
+ if (name == NULL)
+ return 0;
+
+ while (*name != 0) {
+ value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size);
+ name++;
+ }
+
+ return value;
+}
+
+/* insert into hash, return error on existence or memory issues */
+bool
+_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error)
+{
+ zip_uint16_t hash_value;
+ zip_hash_entry_t *entry;
+
+ if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return false;
+ }
+
+ hash_value = _hash_string(name, hash->table_size);
+ for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
+ if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+ if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
+ zip_error_set(error, ZIP_ER_EXISTS, 0);
+ return false;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ if (entry == NULL) {
+ if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return false;
+ }
+ entry->name = name;
+ entry->next = hash->table[hash_value];
+ hash->table[hash_value] = entry;
+ entry->orig_index = -1;
+ }
+
+ if (flags & ZIP_FL_UNCHANGED) {
+ entry->orig_index = (zip_int64_t)index;
+ }
+ entry->current_index = (zip_int64_t)index;
+
+ return true;
+}
+
+/* remove entry from hash, error if not found */
+bool
+_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
+{
+ zip_uint16_t hash_value;
+ zip_hash_entry_t *entry, *previous;
+
+ if (hash == NULL || name == NULL) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return false;
+ }
+
+ hash_value = _hash_string(name, hash->table_size);
+ previous = NULL;
+ entry = hash->table[hash_value];
+ while (entry) {
+ if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+ if (entry->orig_index == -1) {
+ if (previous) {
+ previous->next = entry->next;
+ }
+ else {
+ hash->table[hash_value] = entry->next;
+ }
+ free(entry);
+ }
+ else {
+ entry->current_index = -1;
+ }
+ return true;
+ }
+ previous = entry;
+ entry = entry->next;
+ };
+
+ zip_error_set(error, ZIP_ER_NOENT, 0);
+ return false;
+}
+
+/* find value for entry in hash, -1 if not found */
+zip_int64_t
+_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error)
+{
+ zip_uint16_t hash_value;
+ zip_hash_entry_t *entry;
+
+ if (hash == NULL || name == NULL) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return -1;
+ }
+
+ hash_value = _hash_string(name, hash->table_size);
+ for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
+ if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+ if (flags & ZIP_FL_UNCHANGED) {
+ if (entry->orig_index != -1) {
+ return entry->orig_index;
+ }
+ }
+ else {
+ if (entry->current_index != -1) {
+ return entry->current_index;
+ }
+ }
+ break;
+ }
+ }
+
+ zip_error_set(error, ZIP_ER_NOENT, 0);
+ return -1;
+}
+
+void
+_zip_hash_revert(zip_hash_t *hash)
+{
+ zip_uint16_t i;
+ zip_hash_entry_t *entry, *previous;
+
+ for (i = 0; i < hash->table_size; i++) {
+ previous = NULL;
+ entry = hash->table[i];
+ while (entry) {
+ if (entry->orig_index == -1) {
+ if (previous) {
+ previous->next = entry->next;
+ }
+ else {
+ hash->table[i] = entry->next;
+ }
+ free(entry);
+ }
+ else {
+ entry->current_index = entry->orig_index;
+ }
+ previous = entry;
+ entry = entry->next;
+ }
+ }
+}
diff --git a/lib/zip_name_locate.c b/lib/zip_name_locate.c
index 820ea0c..896132c 100644
--- a/lib/zip_name_locate.c
+++ b/lib/zip_name_locate.c
@@ -62,27 +62,33 @@
return -1;
}
- cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
+ if (flags & (ZIP_FL_NOCASE|ZIP_FL_NODIR|ZIP_FL_ENC_CP437)) {
+ /* can't use hash table */
+ cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
- for (i=0; i<za->nentry; i++) {
- fn = _zip_get_name(za, i, flags, error);
-
- /* newly added (partially filled) entry or error */
- if (fn == NULL)
- continue;
-
- if (flags & ZIP_FL_NODIR) {
- p = strrchr(fn, '/');
- if (p)
- fn = p+1;
+ for (i=0; i<za->nentry; i++) {
+ fn = _zip_get_name(za, i, flags, error);
+
+ /* newly added (partially filled) entry or error */
+ if (fn == NULL)
+ continue;
+
+ if (flags & ZIP_FL_NODIR) {
+ p = strrchr(fn, '/');
+ if (p)
+ fn = p+1;
+ }
+
+ if (cmp(fname, fn) == 0) {
+ _zip_error_clear(error);
+ return (zip_int64_t)i;
+ }
}
- if (cmp(fname, fn) == 0) {
- _zip_error_clear(error);
- return (zip_int64_t)i;
- }
+ zip_error_set(error, ZIP_ER_NOENT, 0);
+ return -1;
}
-
- zip_error_set(error, ZIP_ER_NOENT, 0);
- return -1;
+ else {
+ return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
+ }
}
diff --git a/lib/zip_new.c b/lib/zip_new.c
index d54a247..905e45c 100644
--- a/lib/zip_new.c
+++ b/lib/zip_new.c
@@ -52,6 +52,11 @@
return NULL;
}
+ if ((za->names = _zip_hash_new(ZIP_HASH_TABLE_SIZE, error)) == NULL) {
+ free(za);
+ return NULL;
+ }
+
za->src = NULL;
za->open_flags = 0;
zip_error_init(&za->error);
diff --git a/lib/zip_open.c b/lib/zip_open.c
index 1f5e4d8..3f866a9 100644
--- a/lib/zip_open.c
+++ b/lib/zip_open.c
@@ -183,7 +183,7 @@
zip_t *za;
zip_cdir_t *cdir;
struct zip_stat st;
- zip_uint64_t len;
+ zip_uint64_t len, idx;
zip_stat_init(&st);
if (zip_source_stat(src, &st) < 0) {
@@ -222,11 +222,31 @@
za->nentry = cdir->nentry;
za->nentry_alloc = cdir->nentry_alloc;
za->comment_orig = cdir->comment;
-
- za->ch_flags = za->flags;
free(cdir);
+ for (idx = 0; idx < za->nentry; idx++) {
+ const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
+ if (name == NULL) {
+ /* keep src so discard does not get rid of it */
+ zip_source_keep(src);
+ zip_discard(za);
+ return NULL;
+ }
+
+ if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
+ if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
+ _zip_error_copy(error, &za->error);
+ /* keep src so discard does not get rid of it */
+ zip_source_keep(src);
+ zip_discard(za);
+ return NULL;
+ }
+ }
+ }
+
+ za->ch_flags = za->flags;
+
return za;
}
diff --git a/lib/zip_set_name.c b/lib/zip_set_name.c
index 5a10381..fd60e16 100644
--- a/lib/zip_set_name.c
+++ b/lib/zip_set_name.c
@@ -43,8 +43,10 @@
{
zip_entry_t *e;
zip_string_t *str;
- int changed;
+ bool same_as_orig;
zip_int64_t i;
+ const zip_uint8_t *old_name, *new_name;
+ zip_string_t *old_str;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -81,35 +83,76 @@
e = za->entry+idx;
- if (e->changes) {
- _zip_string_free(e->changes->filename);
- e->changes->filename = NULL;
- e->changes->changed &= ~ZIP_DIRENT_FILENAME;
+ if (e->orig)
+ same_as_orig = _zip_string_equal(e->orig->filename, str);
+ else
+ same_as_orig = false;
+
+ if (!same_as_orig && e->changes == NULL) {
+ if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ _zip_string_free(str);
+ return -1;
+ }
}
- if (e->orig)
- changed = !_zip_string_equal(e->orig->filename, str);
- else
- changed = 1;
-
- if (changed) {
- if (e->changes == NULL) {
- if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- _zip_string_free(str);
- return -1;
- }
- }
- e->changes->filename = str;
- e->changes->changed |= ZIP_DIRENT_FILENAME;
+ if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
+ _zip_string_free(str);
+ return -1;
+ }
+
+ if (e->changes) {
+ old_str = e->changes->filename;
+ }
+ else if (e->orig) {
+ old_str = e->orig->filename;
}
else {
- _zip_string_free(str);
- if (e->changes && e->changes->changed == 0) {
- _zip_dirent_free(e->changes);
- e->changes = NULL;
+ old_str = NULL;
+ }
+
+ if (old_str) {
+ if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
+ _zip_string_free(str);
+ return -1;
}
}
+ else {
+ old_name = NULL;
+ }
+
+ if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
+ _zip_string_free(str);
+ return -1;
+ }
+ if (old_name) {
+ _zip_hash_delete(za->names, old_name, NULL);
+ }
+
+ if (same_as_orig) {
+ if (e->changes) {
+ if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+ _zip_string_free(e->changes->filename);
+ e->changes->changed &= ~ZIP_DIRENT_FILENAME;
+ if (e->changes->changed == 0) {
+ _zip_dirent_free(e->changes);
+ e->changes = NULL;
+ }
+ else {
+ /* TODO: what if not cloned? can that happen? */
+ e->changes->filename = e->orig->filename;
+ }
+ }
+ }
+ _zip_string_free(str);
+ }
+ else {
+ if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+ _zip_string_free(e->changes->filename);
+ }
+ e->changes->changed |= ZIP_DIRENT_FILENAME;
+ e->changes->filename = str;
+ }
return 0;
}
diff --git a/lib/zip_unchange.c b/lib/zip_unchange.c
index 6c8a495..c753712 100644
--- a/lib/zip_unchange.c
+++ b/lib/zip_unchange.c
@@ -48,6 +48,7 @@
_zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates)
{
zip_int64_t i;
+ const char *orig_name, *changed_name;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -55,9 +56,32 @@
}
if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) {
- i = _zip_name_locate(za, _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), 0, NULL);
- if (i >= 0 && (zip_uint64_t)i != idx) {
- zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+ if (za->entry[idx].orig != NULL) {
+ if ((orig_name=_zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) {
+ return -1;
+ }
+
+ i = _zip_name_locate(za, orig_name, 0, NULL);
+ if (i >= 0 && (zip_uint64_t)i != idx) {
+ zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+ return -1;
+ }
+ }
+ else {
+ orig_name = NULL;
+ }
+
+ if ((changed_name=_zip_get_name(za, idx, 0, &za->error)) == NULL) {
+ return -1;
+ }
+
+ if (orig_name) {
+ if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) {
+ return -1;
+ }
+ }
+ if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) {
+ _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL);
return -1;
}
}
diff --git a/lib/zip_unchange_all.c b/lib/zip_unchange_all.c
index 6007683..a72c068 100644
--- a/lib/zip_unchange_all.c
+++ b/lib/zip_unchange_all.c
@@ -43,6 +43,8 @@
int ret;
zip_uint64_t i;
+ _zip_hash_revert(za->names);
+
ret = 0;
for (i=0; i<za->nentry; i++)
ret |= _zip_unchange(za, i, 1);
diff --git a/lib/zipint.h b/lib/zipint.h
index a53d62c..91ae88b 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -266,13 +266,19 @@
typedef enum zip_encoding_type zip_encoding_type_t;
+#ifndef ZIP_HASH_TABLE_SIZE
+#define ZIP_HASH_TABLE_SIZE 8192
+#endif
+
+struct zip_hash;
+
typedef struct zip_cdir zip_cdir_t;
typedef struct zip_dirent zip_dirent_t;
typedef struct zip_entry zip_entry_t;
typedef struct zip_extra_field zip_extra_field_t;
typedef struct zip_string zip_string_t;
typedef struct zip_buffer zip_buffer_t;
-
+typedef struct zip_hash zip_hash_t;
/* zip archive, part of API */
@@ -287,7 +293,7 @@
char *default_password; /* password used when no other supplied */
zip_string_t *comment_orig; /* archive comment */
- zip_string_t *comment_changes; /* changed archive comment */
+ zip_string_t *comment_changes; /* changed archive comment */
bool comment_changed; /* whether archive comment was changed */
zip_uint64_t nentry; /* number of entries */
@@ -297,6 +303,8 @@
unsigned int nopen_source; /* number of open sources using archive */
unsigned int nopen_source_alloc; /* number of sources allocated */
zip_source_t **open_source; /* open sources using archive */
+
+ zip_hash_t *names; /* hash table for name lookup */
char *tempdir; /* custom temp dir (needed e.g. for OS X sandboxing) */
};
@@ -323,7 +331,7 @@
struct zip_dirent {
zip_uint32_t changed;
bool local_extra_fields_read; /* whether we already read in local header extra fields */
- bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */
+ bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */
zip_uint16_t version_madeby; /* (c) version of creator */
zip_uint16_t version_needed; /* (cl) version needed to extract */
@@ -516,6 +524,13 @@
enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type);
zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, zip_uint32_t *, zip_error_t *);
+bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error);
+bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *key, zip_error_t *error);
+void _zip_hash_free(zip_hash_t *hash);
+zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error);
+zip_hash_t *_zip_hash_new(zip_uint16_t hash_size, zip_error_t *error);
+void _zip_hash_revert(zip_hash_t *hash);
+
zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *);
int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error);
diff --git a/regress/Makefile.am b/regress/Makefile.am
index fdccb90..338516f 100644
--- a/regress/Makefile.am
+++ b/regress/Makefile.am
@@ -223,10 +223,6 @@
zip64_creation.test \
zip64_stored_creation.test
-XFAIL_TESTS= \
- open_filename_duplicate_consistency.test \
- open_filename_duplicate_empty_consistency.test
-
AM_CPPFLAGS=-I${top_srcdir}/lib -I../lib -I${top_srcdir}/src
LDADD=${top_builddir}/lib/libzip.la
diff --git a/regress/open_filename_duplicate.test b/regress/open_filename_duplicate.test
index c8cc727..5204db6 100644
--- a/regress/open_filename_duplicate.test
+++ b/regress/open_filename_duplicate.test
@@ -1,6 +1,6 @@
# zip_open: file opens fine even though same file name appears twice
program tryopen
-args filename_duplicate.zip
+args filename_duplicate.zzip
return 0
-file filename_duplicate.zip filename_duplicate.zip filename_duplicate.zip
-stdout opening 'filename_duplicate.zip' succeeded, 2 entries
+file filename_duplicate.zzip filename_duplicate.zip filename_duplicate.zip
+stdout opening 'filename_duplicate.zzip' succeeded, 2 entries
diff --git a/regress/open_filename_duplicate_consistency.test b/regress/open_filename_duplicate_consistency.test
index a997972..e82cf75 100644
--- a/regress/open_filename_duplicate_consistency.test
+++ b/regress/open_filename_duplicate_consistency.test
@@ -1,6 +1,7 @@
# zip_open: file opens fine even though same file name appears twice
program tryopen
-args -c filename_duplicate.zip
-return 0
-file filename_duplicate.zip filename_duplicate.zip filename_duplicate.zip
-stderr some error about a duplicate file name
+args -c filename_duplicate.zzip
+return 1
+file filename_duplicate.zzip filename_duplicate.zip filename_duplicate.zip
+stdout opening 'filename_duplicate.zzip' returned error 10
+stderr 1 errors
diff --git a/regress/open_filename_duplicate_empty.test b/regress/open_filename_duplicate_empty.test
index 505916b..ea143b6 100644
--- a/regress/open_filename_duplicate_empty.test
+++ b/regress/open_filename_duplicate_empty.test
@@ -1,6 +1,6 @@
# zip_open: file opens fine even though same file name (empty file name) appears twice
program tryopen
-args filename_duplicate_empty.zip
+args filename_duplicate_empty.zzip
return 0
-file filename_duplicate_empty.zip filename_duplicate_empty.zip filename_duplicate_empty.zip
-stdout opening 'filename_duplicate_empty.zip' succeeded, 2 entries
+file filename_duplicate_empty.zzip filename_duplicate_empty.zip filename_duplicate_empty.zip
+stdout opening 'filename_duplicate_empty.zzip' succeeded, 2 entries
diff --git a/regress/open_filename_duplicate_empty_consistency.test b/regress/open_filename_duplicate_empty_consistency.test
index 43bb43e..6570195 100644
--- a/regress/open_filename_duplicate_empty_consistency.test
+++ b/regress/open_filename_duplicate_empty_consistency.test
@@ -1,6 +1,7 @@
# zip_open: file opens fine even though same file name (empty file name) appears twice
program tryopen
-args -c filename_duplicate_empty.zip
+args -c filename_duplicate_empty.zzip
return 1
-file filename_duplicate_empty.zip filename_duplicate_empty.zip filename_duplicate_empty.zip
-stdout some error about duplicate file names
+file filename_duplicate_empty.zzip filename_duplicate_empty.zip filename_duplicate_empty.zip
+stdout opening 'filename_duplicate_empty.zzip' returned error 10
+stderr 1 errors