gp_container *gp_open_zip(const char *path) { struct zip_priv *priv; gp_container *ret; gp_io *io; int err; io = open_zip(path); if (!io) return NULL; ret = malloc(sizeof(gp_container) + sizeof(struct zip_priv)); if (!ret) { err = ENOMEM; goto err0; } GP_DEBUG(1, "ZIP Container initialized"); ret->img_count = -1; ret->cur_img = 0; ret->ops = &zip_ops; priv = GP_CONTAINER_PRIV(ret); priv->io = io; priv->table.next = NULL; priv->table.prev = NULL; /* Cache for current table for seeks */ priv->cur_table = &priv->table; priv->cur_table_pos = 0; /* Current position */ priv->cur_pos = 0; /* Last table, used for insertion */ priv->tables_used = 0; priv->table_used = 0; priv->last_table = &priv->table; return ret; err0: gp_io_close(io); errno = err; return NULL; }
static YogVal compress(YogEnv* env, YogVal self, YogVal pkg, YogVal args, YogVal kw, YogVal block) { SAVE_ARGS5(env, self, pkg, args, kw, block); YogVal path = YUNDEF; YogVal files = YUNDEF; PUSH_LOCALS2(env, path, files); YogCArg params[] = { { "path", &path }, { "*", &files }, { NULL, NULL } }; YogGetArgs_parse_args(env, "compress", params, args, kw); if (!IS_PTR(path) || (BASIC_OBJ_TYPE(path) != TYPE_STRING)) { YogError_raise_TypeError(env, "path must be String"); } struct zip* archive = open_zip(env, pkg, path, ZIP_CREATE); int n = zip_get_num_files(archive); int i; for (i = 0; i < n; i++) { if (zip_delete(archive, i) != 0) { raise_ZipError(env, pkg, zip_strerror(archive)); } } uint_t size = YogArray_size(env, files); uint_t j; for (j = 0; j < size; j++) { YogHandle* name = VAL2HDL(env, YogArray_at(env, files, j)); YogMisc_check_String(env, name, "Filename"); YogVal bin = YogString_to_bin_in_default_encoding(env, name); const char* fname = BINARY_CSTR(bin); struct zip_source* source = zip_source_file(archive, fname, 0, 0); if (source == NULL) { raise_ZipError(env, pkg, zip_strerror(archive)); } if (zip_add(archive, fname, source) < 0) { raise_ZipError(env, pkg, zip_strerror(archive)); } } close_zip(env, pkg, archive); RETURN(env, YNIL); }
static YogVal decompress(YogEnv* env, YogVal self, YogVal pkg, YogVal args, YogVal kw, YogVal block) { SAVE_ARGS5(env, self, pkg, args, kw, block); YogVal zip = YUNDEF; YogVal dest = YNIL; YogVal s = YUNDEF; PUSH_LOCALS3(env, zip, dest, s); YogCArg params[] = { { "zip", &zip }, { "|", NULL }, { "dest", &dest }, { NULL, NULL } }; YogGetArgs_parse_args(env, "decompress", params, args, kw); if (!IS_PTR(zip) || (BASIC_OBJ_TYPE(zip) != TYPE_STRING)) { YogError_raise_TypeError(env, "zip must be String"); } if (!IS_NIL(dest) && (!IS_PTR(dest) || (BASIC_OBJ_TYPE(dest) != TYPE_STRING))) { YogError_raise_TypeError(env, "dest must be nil or String"); } struct zip* archive = open_zip(env, pkg, zip, 0); int n = zip_get_num_files(archive); YogHandle* h = VAL2HDL(env, dest); int i; for (i = 0; i < n; i++) { const char* name = zip_get_name(archive, i, 0); if (name == NULL) { close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } YogVal bin = YogString_to_bin_in_default_encoding(env, h); char* path = (char*)YogSysdeps_alloca(strlen(BINARY_CSTR(bin)) + strlen(name) + 2); strcpy(path, BINARY_CSTR(bin)); strcat(path, "/"); strcat(path, name); char* dir = (char*)YogSysdeps_alloca(strlen(path) + 1); strcpy(dir, path); dirname(dir); make_dirs(env, dir); struct zip_file* file = zip_fopen_index(archive, i, 0); if (file == NULL) { close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } FILE* fp = fopen(path, "wb"); if (fp == NULL) { zip_fclose(file); close_zip(env, pkg, archive); s = YogString_from_string(env, path); YogError_raise_sys_err(env, errno, s); } while (1) { char buf[1024]; int len = zip_fread(file, buf, array_sizeof(buf)); if (len < 0) { zip_fclose(file); close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } else if (len == 0) { break; } fwrite(buf, sizeof(char), len, fp); if (ferror(fp)) { zip_fclose(file); close_zip(env, pkg, archive); YogError_raise_IOError(env, name); } } fclose(fp); if (zip_fclose(file) != 0) { close_zip(env, pkg, archive); raise_ZipError(env, pkg, zip_strerror(archive)); } } close_zip(env, pkg, archive); RETURN(env, YNIL); }