static int add_data_comp(zip_source_callback cb, void *ud, struct zip_stat *st,FILE *ft, struct zip_error *error) { char buf[BUFSIZE]; ssize_t n; st->comp_size = 0; while ((n=cb(ud, buf, sizeof(buf), ZIP_SOURCE_READ)) > 0) { if (fwrite(buf, 1, n, ft) != (size_t)n) { _zip_error_set(error, ZIP_ER_WRITE, errno); return -1; } st->comp_size += n; } if (n < 0) { ch_set_error(error, cb, ud); return -1; } return 0; }
static int add_data_uncomp(struct zip *za, zip_source_callback cb, void *ud, struct zip_stat *st, FILE *ft) { char b1[BUFSIZE], b2[BUFSIZE]; int end, flush, ret; ssize_t n; size_t n2; z_stream zstr; int mem_level; st->comp_method = ZIP_CM_DEFLATE; st->comp_size = st->size = 0; st->crc = (unsigned int)crc32(0, NULL, 0); zstr.zalloc = Z_NULL; zstr.zfree = Z_NULL; zstr.opaque = NULL; zstr.avail_in = 0; zstr.avail_out = 0; if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) mem_level = TORRENT_MEM_LEVEL; else mem_level = MAX_MEM_LEVEL; /* -MAX_WBITS: undocumented feature of zlib to _not_ write a zlib header */ deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, mem_level, Z_DEFAULT_STRATEGY); zstr.next_out = (Bytef *)b2; zstr.avail_out = sizeof(b2); zstr.next_in = NULL; zstr.avail_in = 0; flush = 0; end = 0; while (!end) { if (zstr.avail_in == 0 && !flush) { if ((n=cb(ud, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) { ch_set_error(&za->error, cb, ud); deflateEnd(&zstr); return -1; } if (n > 0) { zstr.avail_in = (unsigned int)n; zstr.next_in = (Bytef *)b1; st->size += n; st->crc = (unsigned int)crc32(st->crc, (Bytef *)b1, (unsigned int)n); } else flush = Z_FINISH; } ret = deflate(&zstr, flush); if (ret != Z_OK && ret != Z_STREAM_END) { _zip_error_set(&za->error, ZIP_ER_ZLIB, ret); return -1; } if (zstr.avail_out != sizeof(b2)) { n2 = sizeof(b2) - zstr.avail_out; if (fwrite(b2, 1, n2, ft) != n2) { _zip_error_set(&za->error, ZIP_ER_WRITE, errno); return -1; } zstr.next_out = (Bytef *)b2; zstr.avail_out = sizeof(b2); st->comp_size += n2; } if (ret == Z_STREAM_END) { deflateEnd(&zstr); end = 1; } } return 0; }
static int add_data_uncomp(zip_source_callback cb, void *ud, struct zip_stat *st, FILE *ft, struct zip_error *error) { char b1[BUFSIZE], b2[BUFSIZE]; int end, flush, ret; ssize_t n; z_stream zstr; st->comp_method = ZIP_CM_DEFLATE; st->comp_size = st->size = 0; st->crc = crc32(0, NULL, 0); zstr.zalloc = Z_NULL; zstr.zfree = Z_NULL; zstr.opaque = NULL; zstr.avail_in = 0; zstr.avail_out = 0; /* -15: undocumented feature of zlib to _not_ write a zlib header */ deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY); zstr.next_out = (Bytef *)b2; zstr.avail_out = sizeof(b2); zstr.avail_in = 0; flush = 0; end = 0; while (!end) { if (zstr.avail_in == 0 && !flush) { if ((n=cb(ud, b1, sizeof(b1), ZIP_SOURCE_READ)) < 0) { ch_set_error(error, cb, ud); deflateEnd(&zstr); return -1; } if (n > 0) { zstr.avail_in = n; zstr.next_in = (Bytef *)b1; st->size += n; st->crc = crc32(st->crc, (Bytef *)b1, n); } else flush = Z_FINISH; } ret = deflate(&zstr, flush); if (ret != Z_OK && ret != Z_STREAM_END) { _zip_error_set(error, ZIP_ER_ZLIB, ret); return -1; } if (zstr.avail_out != sizeof(b2)) { n = sizeof(b2) - zstr.avail_out; if (fwrite(b2, 1, n, ft) != n) { _zip_error_set(error, ZIP_ER_WRITE, errno); return -1; } zstr.next_out = (Bytef *)b2; zstr.avail_out = sizeof(b2); st->comp_size += n; } if (ret == Z_STREAM_END) { deflateEnd(&zstr); end = 1; } } return 0; }
static int add_data(struct zip *za, struct zip_source *zs, struct zip_dirent *de, FILE *ft) { off_t offstart, offend; zip_source_callback cb; void *ud; struct zip_stat st; cb = zs->f; ud = zs->ud; if (cb(ud, &st, sizeof(st), ZIP_SOURCE_STAT) < (ssize_t)sizeof(st)) { ch_set_error(&za->error, cb, ud); return -1; } if (cb(ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) { ch_set_error(&za->error, cb, ud); return -1; } offstart = ftello(ft); if (_zip_dirent_write(de, ft, 1, &za->error) < 0) return -1; if (st.comp_method != ZIP_CM_STORE) { if (add_data_comp(cb, ud, &st, ft, &za->error) < 0) return -1; } else { if (add_data_uncomp(za, cb, ud, &st, ft) < 0) return -1; } if (cb(ud, NULL, 0, ZIP_SOURCE_CLOSE) < 0) { ch_set_error(&za->error, cb, ud); return -1; } offend = ftello(ft); if (fseeko(ft, offstart, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } de->last_mod = st.mtime; de->comp_method = st.comp_method; de->crc = st.crc; de->uncomp_size = (unsigned int)st.size; de->comp_size = (unsigned int)st.comp_size; if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0)) _zip_dirent_torrent_normalize(de); if (_zip_dirent_write(de, ft, 1, &za->error) < 0) return -1; if (fseeko(ft, offend, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } return 0; }
static int add_data(struct zip *za, int idx, struct zip_dirent *de, FILE *ft) { off_t offstart, offend; zip_source_callback cb; void *ud; struct zip_stat st; cb = za->entry[idx].source->f; ud = za->entry[idx].source->ud; if (cb(ud, &st, sizeof(st), ZIP_SOURCE_STAT) < sizeof(st)) { ch_set_error(&za->error, cb, ud); return -1; } if (cb(ud, NULL, 0, ZIP_SOURCE_OPEN) < 0) { ch_set_error(&za->error, cb, ud); return -1; } offstart = ftell(ft); if (_zip_dirent_write(de, ft, 1, &za->error) < 0) return -1; if (st.comp_method != ZIP_CM_STORE) { if (add_data_comp(cb, ud, &st, ft, &za->error) < 0) return -1; } else { if (add_data_uncomp(cb, ud, &st, ft, &za->error) < 0) return -1; } if (cb(ud, NULL, 0, ZIP_SOURCE_CLOSE) < 0) { ch_set_error(&za->error, cb, ud); return -1; } offend = ftell(ft); if (fseek(ft, offstart, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } de->comp_method = st.comp_method; de->last_mod = st.mtime; de->crc = st.crc; de->uncomp_size = st.size; de->comp_size = st.comp_size; if (_zip_dirent_write(de, ft, 1, &za->error) < 0) return -1; if (fseek(ft, offend, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } return 0; }