const char * _zip_get_name(struct zip *za, zip_uint64_t idx, zip_flags_t flags, struct zip_error *error) { struct zip_dirent *de; const zip_uint8_t *str; if ((de=_zip_get_dirent(za, idx, flags, error)) == NULL) return NULL; if ((str=_zip_string_get(de->filename, NULL, flags, error)) == NULL) return NULL; return (const char *)str; }
ZIP_EXTERN const char * zip_file_get_comment(struct zip *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags) { struct zip_dirent *de; zip_uint32_t len; const zip_uint8_t *str; if ((de=_zip_get_dirent(za, idx, flags, NULL)) == NULL) return NULL; if ((str=_zip_string_get(de->comment, &len, flags, &za->error)) == NULL) return NULL; if (lenp) *lenp = len; return (const char *)str; }
int _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { zip_entry_t *e; zip_string_t *str; 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); return -1; } if (ZIP_IS_RDONLY(za)) { zip_error_set(&za->error, ZIP_ER_RDONLY, 0); return -1; } if (name && name[0] != '\0') { /* TODO: check for string too long */ if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) return -1; if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) str->encoding = ZIP_ENCODING_UTF8_KNOWN; } else str = NULL; /* TODO: encoding flags needed for CP437? */ if ((i=_zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { _zip_string_free(str); zip_error_set(&za->error, ZIP_ER_EXISTS, 0); return -1; } /* no effective name change */ if (i>=0 && (zip_uint64_t)i == idx) { _zip_string_free(str); return 0; } e = za->entry+idx; 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 ((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 { 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; }
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, idx; 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; free(cdir); _zip_hash_reserve_capacity(za->names, za->nentry, &za->error); 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; }