Beispiel #1
0
static bool
start(void *ud) {
    struct ctx *ctx = (struct ctx *)ud;
    int ret;

    ctx->zstr.avail_in = 0;
    ctx->zstr.next_in = NULL;
    ctx->zstr.avail_out = 0;
    ctx->zstr.next_out = NULL;

    if (ctx->compress) {
	ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30);

    }
    else {
	ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0);
    }

    if (ret != BZ_OK) {
	zip_error_set(ctx->error, map_error(ret), 0);
	return false;
    }

    return true;
}
Beispiel #2
0
zip_t *
_zip_new(zip_error_t *error)
{
    zip_t *za;

    za = (zip_t *)malloc(sizeof(struct zip));
    if (!za) {
	zip_error_set(error, ZIP_ER_MEMORY, 0);
	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);
    za->flags = za->ch_flags = 0;
    za->default_password = NULL;
    za->comment_orig = za->comment_changes = NULL;
    za->comment_changed = 0;
    za->nentry = za->nentry_alloc = 0;
    za->entry = NULL;
    za->nopen_source = za->nopen_source_alloc = 0;
    za->open_source = NULL;
    za->tempdir = NULL;
    
    return za;
}
Beispiel #3
0
int
zip_source_stat(zip_source_t *src, zip_stat_t *st)
{
    if (src->source_closed) {
        return -1;
    }
    if (st == NULL) {
        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
	return -1;
    }

    zip_stat_init(st);
    
    if (ZIP_SOURCE_IS_LAYERED(src)) {
        if (zip_source_stat(src->src, st) < 0) {
            _zip_error_set_from_source(&src->error, src->src);
            return -1;
        }
    }

    if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) {
	return -1;
    }

    return 0;
}
ZIP_EXTERN int
zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len) {
    if (len < 0 || len > ZIP_UINT16_MAX) {
	zip_error_set(&za->error, ZIP_ER_INVAL, 0);
	return -1;
    }
    return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
}
static int
_zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error)
{
    if (offset > ZIP_INT64_MAX) {
	zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
	return -1;
    }
    return _zip_seek_win32(h, (zip_int64_t)offset, whence, error);
}
static int
_zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error)
{
    if (offset > ZIP_INT64_MAX) {
	zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
	return -1;
    }
    return _zip_fseek(f, (zip_int64_t)offset, whence, error);
}
Beispiel #7
0
ZIP_EXTERN zip_int64_t
zip_file_add(zip_t *za, const char *name, zip_source_t *source, zip_flags_t flags) {
    if (name == NULL || source == NULL) {
	zip_error_set(&za->error, ZIP_ER_INVAL, 0);
	return -1;
    }

    return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);
}
ZIP_EXTERN const zip_uint8_t *
zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags)
{
    static const zip_uint8_t empty[1] = { '\0' };

    zip_dirent_t *de;
    zip_extra_field_t *ef;
    int i;

    if ((flags & ZIP_EF_BOTH) == 0) {
	zip_error_set(&za->error, ZIP_ER_INVAL, 0);
	return NULL;
    }

    if ((de=_zip_get_dirent(za, idx, flags, &za->error)) == NULL)
	return NULL;

    if (flags & ZIP_FL_LOCAL)
	if (_zip_read_local_ef(za, idx) < 0)
	    return NULL;

    i = 0;
    for (ef=de->extra_fields; ef; ef=ef->next) {
	if (ef->flags & flags & ZIP_EF_BOTH) {
	    if (i < ef_idx) {
		i++;
		continue;
	    }

	    if (idp)
		*idp = ef->id;
	    if (lenp)
		*lenp = ef->size;
	    if (ef->size > 0)
		return ef->data;
	    else
		return empty;
	}
    }

    zip_error_set(&za->error, ZIP_ER_NOENT, 0);
    return NULL;

}
static int
create_temp_output(struct read_file *ctx)
{
    char *temp;
    int tfd;
    mode_t mask;
    FILE *tfp;
    
    if ((temp=(char *)malloc(strlen(ctx->fname)+8)) == NULL) {
	zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
	return -1;
    }
    sprintf(temp, "%s.XXXXXX", ctx->fname);

    mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
    if ((tfd=mkstemp(temp)) == -1) {
        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
	umask(mask);
        free(temp);
        return -1;
    }
    umask(mask);

    if ((tfp=fdopen(tfd, "r+b")) == NULL) {
        zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
        close(tfd);
        (void)remove(temp);
        free(temp);
        return -1;
    }
    
#ifdef _WIN32
    /*
     According to Pierre Joye, Windows in some environments per
     default creates text files, so force binary mode.
     */
    _setmode(_fileno(tfp), _O_BINARY );
#endif
    
    ctx->fout = tfp;
    ctx->tmpname = temp;
    
    return 0;
}
Beispiel #10
0
zip_int64_t
_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error) {
    int (*cmp)(const char *, const char *);
    const char *fn, *p;
    zip_uint64_t i;

    if (za == NULL)
	return -1;

    if (fname == NULL) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return -1;
    }

    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;
	    }

	    if (cmp(fname, fn) == 0) {
		_zip_error_clear(error);
		return (zip_int64_t)i;
	    }
	}

	zip_error_set(error, ZIP_ER_NOENT, 0);
	return -1;
    }
    else {
	return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
    }
}
ZIP_EXTERN zip_source_t *
zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
{
    if (h == INVALID_HANDLE_VALUE || length < -1) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return NULL;
    }

    return _zip_source_win32_handle_or_name(NULL, h, start, length, 1, NULL, NULL, error);
}
Beispiel #12
0
zip_uint8_t *
_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error)
{
    zip_uint8_t *r;
    
    if (length == 0 && !nulp) {
	return NULL;
    }

    r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
    if (!r) {
	zip_error_set(error, ZIP_ER_MEMORY, 0);
	return NULL;
    }

    if (buffer) {
        zip_uint8_t *data = _zip_buffer_get(buffer, length);
        
        if (data == NULL) {
            zip_error_set(error, ZIP_ER_MEMORY, 0);
            free(r);
            return NULL;
        }
	memcpy(r, data, length);
    }
    else {
	if (_zip_read(src, r, length, error) < 0) {
	    free(r);
	    return NULL;
	}
    }

    if (nulp) {
	zip_uint8_t *o;
	/* replace any in-string NUL characters with spaces */
	r[length] = 0;
	for (o=r; o<r+length; o++)
	    if (*o == '\0')
		*o = ' ';
    }

    return r;
}
Beispiel #13
0
ZIP_EXTERN zip_source_t *
zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
{
    if (fname == NULL || length < -1) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return NULL;
    }

    return _zip_source_file_or_p(fname, NULL, start, length, NULL, error);
}
Beispiel #14
0
ZIP_EXTERN zip_source_t *
zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
{
    if (file == NULL || length < -1) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return NULL;
    }

    return _zip_source_file_or_p(NULL, file, start, length, NULL, error);
}
Beispiel #15
0
static int
buffer_to_file(buffer_t *buffer, const char *fname, zip_error_t *error)
{
    FILE *f = fopen(fname, "wb");
    zip_uint64_t i;
    zip_uint64_t nul_run;

    if (f == NULL) {
        zip_error_set(error, ZIP_ER_OPEN, errno);
        return -1;
    }

    fwrite(MARK_BEGIN, 4, 1, f);
    write_u64(buffer->fragment_size, f);
    write_u64(buffer->size, f);

    nul_run = 0;
    for (i=0; i * buffer->fragment_size <buffer->size; i++) {
        if (buffer->fragment[i] == NULL || only_nul(buffer->fragment[i], buffer->fragment_size)) {
            nul_run++;
        }
        else {
            if (nul_run > 0) {
                write_nuls(nul_run, f);
                nul_run = 0;
            }
            fwrite(MARK_DATA, 4, 1, f);

            fwrite(buffer->fragment[i], 1, buffer->fragment_size, f);
        }
    }

    if (nul_run > 0) {
        write_nuls(nul_run, f);
    }

    if (fclose(f) != 0) {
        zip_error_set(error, ZIP_ER_WRITE, errno);
        return -1;
    }

    return 0;
}
Beispiel #16
0
ZIP_EXTERN zip_source_t *
zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
{
    if (fname == NULL || length < -1) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
	return NULL;
    }

    return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_w, error);
}
Beispiel #17
0
/* 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;
}
static int
_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx)
{
    FILETIME mtimeft;
    time_t mtime;
    LARGE_INTEGER size;
    int regularp;

    if (!GetFileTime(h, NULL, NULL, &mtimeft)) {
	zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
	return -1;
    }
    if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) {
	zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
	return -1;
    }

    regularp = 0;
    if (GetFileType(h) == FILE_TYPE_DISK) {
	regularp = 1;
    }

    if (!GetFileSizeEx(h, &size)) {
	zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
	return -1;
    }

    zip_stat_init(st);
    st->mtime = mtime;
    st->valid |= ZIP_STAT_MTIME;
    if (ctx->end != 0) {
	st->size = ctx->end - ctx->start;
	st->valid |= ZIP_STAT_SIZE;
    }
    else if (regularp) {
	st->size = (zip_uint64_t)size.QuadPart;
	st->valid |= ZIP_STAT_SIZE;
    }

    return 0;
}
Beispiel #19
0
zip_int64_t
_zip_add_entry(zip_t *za)
{
    zip_uint64_t idx;

    if (za->nentry+1 >= za->nentry_alloc) {
	zip_entry_t *rentries;
	zip_uint64_t nalloc = za->nentry_alloc;
	zip_uint64_t additional_entries = 2 * nalloc;
	zip_uint64_t realloc_size;

	if (additional_entries < 16) {
	    additional_entries = 16;
	}
	else if (additional_entries > 1024) {
	    additional_entries = 1024;
	}
	/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
	nalloc += additional_entries;
	realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;

	if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
	    zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
	    return -1;
	}
	rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
	if (!rentries) {
	    zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
	    return -1;
	}
	za->entry = rentries;
	za->nentry_alloc = nalloc;
    }

    idx = za->nentry++;

    _zip_entry_init(za->entry+idx);

    return (zip_int64_t)idx;
}
Beispiel #20
0
zip_t *
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
{
    zip_t *za;
    zip_cdir_t *cdir;
    struct zip_stat st;
    zip_uint64_t len;

    zip_stat_init(&st);
    if (zip_source_stat(src, &st) < 0) {
	_zip_error_set_from_source(error, src);
	return NULL;
    }
    if ((st.valid & ZIP_STAT_SIZE) == 0) {
	zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP);
	return NULL;
    }
    len = st.size;

    /* treat empty files as empty archives */
    if (len == 0) {
	if ((za=_zip_allocate_new(src, flags, error)) == NULL) {
	    zip_source_free(src);
	    return NULL;
	}

	return za;
    }

    if ((za=_zip_allocate_new(src, flags, error)) == NULL) {
        return NULL;
    }
    
    if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
        _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->entry = cdir->entry;
    za->nentry = cdir->nentry;
    za->nentry_alloc = cdir->nentry_alloc;
    za->comment_orig = cdir->comment;
    
    za->ch_flags = za->flags;

    free(cdir);

    return za;
}
Beispiel #21
0
zip_int64_t
zip_source_read(zip_source_t *src, void *data, zip_uint64_t len)
{
    if (src->source_closed) {
        return -1;
    }
    if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) {
        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
	return -1;
    }

    return _zip_source_call(src, data, len, ZIP_SOURCE_READ);
}
Beispiel #22
0
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
    struct ctx *ctx = (struct ctx *)ud;

    if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
	zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
	return false;
    }

    ctx->zstr.avail_in = (unsigned int)length;
    ctx->zstr.next_in = (char *)data;

    return true;
}
Beispiel #23
0
ZIP_EXTERN int
zip_get_num_files(zip_t *za)
{
    if (za == NULL)
	return -1;

    if (za->nentry > INT_MAX) {
	zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
	return -1;
    }

    return (int)za->nentry;
}
Beispiel #24
0
int
_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error)
{
    zip_int64_t n;

    if (length > ZIP_INT64_MAX) {
	zip_error_set(error, ZIP_ER_INTERNAL, 0);
	return -1;
    }

    if ((n = zip_source_read(src, b, length)) < 0) {
	_zip_error_set_from_source(error, src);
	return -1;
    }

    if (n < (zip_int64_t)length) {
	zip_error_set(error, ZIP_ER_EOF, 0);
	return -1;
    }

    return 0;
}
Beispiel #25
0
ZIP_EXTERN int zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
{
    zip_entry_t *e;
    int changed;

    if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
        return -1;

    if (ZIP_IS_RDONLY(za)) {
        zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
        return -1;
    }

    e = za->entry+idx;

    changed = e->orig == NULL || mtime != e->orig->last_mod;

    if (changed) {
        if (e->changes == NULL) {
            if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                return -1;
            }
        }
        e->changes->last_mod = mtime;
        e->changes->changed |= ZIP_DIRENT_LAST_MOD;
    }
    else {
        if (e->changes) {
            e->changes->changed &= ~ZIP_DIRENT_LAST_MOD;
            if (e->changes->changed == 0) {
		_zip_dirent_free(e->changes);
                e->changes = NULL;
            }
        }
    }

    return 0;
}
Beispiel #26
0
ZIP_EXTERN zip_int64_t
zip_source_tell(zip_source_t *src)
{
    if (src->source_closed) {
        return -1;
    }
    if (!ZIP_SOURCE_IS_OPEN_READING(src)) {
        zip_error_set(&src->error, ZIP_ER_INVAL, 0);
        return -1;
    }
    
    return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL);
}
Beispiel #27
0
ZIP_EXTERN int
zip_source_open(zip_source_t *src) {
    if (src->source_closed) {
	return -1;
    }
    if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
	zip_error_set(&src->error, ZIP_ER_DELETED, 0);
	return -1;
    }

    if (ZIP_SOURCE_IS_OPEN_READING(src)) {
	if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) {
	    zip_error_set(&src->error, ZIP_ER_INUSE, 0);
	    return -1;
	}
    }
    else {
	if (ZIP_SOURCE_IS_LAYERED(src)) {
	    if (zip_source_open(src->src) < 0) {
		_zip_error_set_from_source(&src->error, src->src);
		return -1;
	    }
	}

	if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) {
	    if (ZIP_SOURCE_IS_LAYERED(src)) {
		zip_source_close(src->src);
	    }
	    return -1;
	}
    }

    src->eof = false;
    src->had_read_error = false;
    _zip_error_clear(&src->error);
    src->open_count++;

    return 0;
}
Beispiel #28
0
static zip_cdir_t *
_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
{
    zip_cdir_t *cd;
    zip_uint64_t i, nentry, size, offset, eocd_offset;

    if (_zip_buffer_left(buffer) < EOCDLEN) {
	zip_error_set(error, ZIP_ER_INCONS, 0);
	return NULL;
    }

    eocd_offset = _zip_buffer_offset(buffer);

    _zip_buffer_get(buffer, 4); /* magic already verified */

    if (_zip_buffer_get_32(buffer) != 0) {
	zip_error_set(error, ZIP_ER_MULTIDISK, 0);
	return NULL;
    }

    /* number of cdir-entries on this disk */
    i = _zip_buffer_get_16(buffer);
    /* number of cdir-entries */
    nentry = _zip_buffer_get_16(buffer);

    if (nentry != i) {
	zip_error_set(error, ZIP_ER_NOZIP, 0);
	return NULL;
    }

    size = _zip_buffer_get_32(buffer);
    offset = _zip_buffer_get_32(buffer);

    if (offset+size < offset) {
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
        return NULL;
    }

    if (offset+size > buf_offset + eocd_offset) {
	/* cdir spans past EOCD record */
	zip_error_set(error, ZIP_ER_INCONS, 0);
	return NULL;
    }

    if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + eocd_offset) {
	zip_error_set(error, ZIP_ER_INCONS, 0);
	return NULL;
    }

    if ((cd=_zip_cdir_new(nentry, error)) == NULL)
	return NULL;

    cd->is_zip64 = false;
    cd->size = size;
    cd->offset = offset;

    return cd;
}
ZIP_EXTERN int
zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence) {
    zip_source_args_seek_t args;

    if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) {
	zip_error_set(&src->error, ZIP_ER_INVAL, 0);
	return -1;
    }

    args.offset = offset;
    args.whence = whence;

    return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK_WRITE) < 0 ? -1 : 0);
}
Beispiel #30
0
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;
}