10#define __STDC_WANT_LIB_EXT1__ 1
16#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
21#define HAS_DEVICE(P) \
22 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \
24#define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0)
43#define ftruncate(fd, sz) (-(_chsize_s((fd), (sz)) != 0))
47#if defined(__TINYC__) && (defined(_WIN32) || defined(_WIN64))
50#define ftruncate(fd, sz) (-(_chsize_s((fd), (sz)) != 0))
55#define HAS_DEVICE(P) 0
58#ifndef FILESYSTEM_PREFIX_LEN
59#define FILESYSTEM_PREFIX_LEN(P) 0
63#define ISSLASH(C) ((C) == '/' || (C) == '\\')
74#define UNX_IFDIR 0040000
75#define UNX_IFREG 0100000
76#define UNX_IFSOCK 0140000
77#define UNX_IFLNK 0120000
78#define UNX_IFBLK 0060000
79#define UNX_IFCHR 0020000
80#define UNX_IFIFO 0010000
85 mz_uint64 uncomp_size;
87 mz_uint32 uncomp_crc32;
89 mz_uint8 header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
90 mz_uint64 header_offset;
94 mz_uint32 external_attr;
112 enum zip_modify_t type;
113 mz_uint64 m_local_header_ofs;
117static const char *
const zip_errlist[33] = {
120 "invalid entry name\0",
122 "invalid zip mode\0",
123 "invalid compression level\0",
124 "no zip 64 support\0",
126 "cannot write data to entry\0",
127 "cannot initialize tdefl compressor\0",
129 "header not found\0",
130 "cannot flush tdefl buffer\0",
131 "cannot write entry header\0",
132 "cannot create entry header\0",
133 "cannot write to central dir\0",
134 "cannot open file\0",
135 "invalid entry type\0",
136 "extracting data using no memory allocation\0",
140 "invalid zip archive name\0",
143 "close archive error\0",
144 "capacity size too small\0",
148 "cannot initialize reader\0",
149 "cannot initialize writer\0",
150 "cannot initialize writer from reader\0",
155 if (errnum <= 0 || errnum >= 33) {
159 return zip_errlist[errnum];
162static const char *zip_basename(
const char *name) {
164 char const *base = name += FILESYSTEM_PREFIX_LEN(name);
167 for (p = name; *p; p++) {
175 if (*base ==
'\0' && ISSLASH(*name) && all_slashes)
181static int zip_mkpath(
char *path) {
183 char npath[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE + 1];
185 int has_device = HAS_DEVICE(path);
187 memset(npath, 0, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE + 1);
194 for (p = path + len; *p && len < MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE; p++) {
195 if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) {
196#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
204 if (MZ_MKDIR(npath) == -1) {
205 if (errno != EEXIST) {
216static char *zip_strclone(
const char *str,
size_t n) {
219 char *rpl = (
char *)calloc((1 + n),
sizeof(char));
225 for (i = 0; (i < n) && (c = *str++); ++i) {
232static char *zip_strrpl(
const char *str,
size_t n,
char oldchar,
char newchar) {
235 char *rpl = (
char *)calloc((1 + n),
sizeof(char));
241 for (i = 0; (i < n) && (c = *str++); ++i) {
251static inline int zip_strchr_match(
const char *
const str,
size_t len,
char c) {
253 for (i = 0; i < len; ++i) {
262static char *zip_name_normalize(
char *name,
char *
const nname,
size_t len) {
263 size_t offn = 0, ncpy = 0;
266 if (name == NULL || nname == NULL || len <= 0) {
270 while (ISSLASH(*name)) {
274 while ((c = *name++)) {
276 if (ncpy > 0 && !zip_strchr_match(&nname[offn], ncpy,
'.')) {
282 nname[offn + ncpy] = c;
289 if (!zip_strchr_match(&nname[offn], ncpy,
'.')) {
290 nname[offn + ncpy] =
'\0';
299 mz_zip_internal_state *pState = pzip->m_pState;
300 mz_uint64 file_size = pzip->m_archive_size;
301 if ((pzip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
304 if (pzip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED) {
305 if (pState->m_pFile) {
306 int fd = fileno(pState->m_pFile);
307 return ftruncate(fd, pState->m_file_archive_start_ofs + file_size);
313static int zip_archive_extract(
mz_zip_archive *zip_archive,
const char *dir,
314 int (*on_extract)(
const char *filename,
319 char path[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE + 1];
320 char symlink_to[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE + 1];
322 size_t dirlen = 0, filename_size = MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE;
325 memset(path, 0,
sizeof(path));
326 memset(symlink_to, 0,
sizeof(symlink_to));
328 dirlen = strlen(dir);
329 if (dirlen + 1 > MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE) {
330 return ZIP_EINVENTNAME;
336 strcpy_s(path, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE, dir);
338 strncpy(path, dir, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE);
341 if (!ISSLASH(path[dirlen - 1])) {
342#if defined(_WIN32) || defined(__WIN32__)
350 if (filename_size > MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - dirlen) {
351 filename_size = MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - dirlen;
354 n = mz_zip_reader_get_num_files(zip_archive);
355 for (i = 0; i < n; ++i) {
356 if (!mz_zip_reader_file_stat(zip_archive, i, &info)) {
362 if (!zip_name_normalize(info.m_filename, info.m_filename,
363 strlen(info.m_filename))) {
365 err = ZIP_EINVENTNAME;
370 strncpy_s(&path[dirlen], filename_size, info.m_filename, filename_size);
372 strncpy(&path[dirlen], info.m_filename, filename_size);
374 err = zip_mkpath(path);
380 if ((((info.m_version_made_by >> 8) == 3) ||
381 ((info.m_version_made_by >> 8) ==
384 && info.m_external_attr &
387#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
390 if (info.m_uncomp_size > MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE ||
391 !mz_zip_reader_extract_to_mem_no_alloc(
392 zip_archive, i, symlink_to, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE, 0,
394 err = ZIP_EMEMNOALLOC;
397 symlink_to[info.m_uncomp_size] =
'\0';
398 if (symlink(symlink_to, path) != 0) {
404 if (!mz_zip_reader_is_file_a_directory(zip_archive, i)) {
405 if (!mz_zip_reader_extract_to_file(zip_archive, i, path, 0)) {
412#if defined(_MSC_VER) || defined(PS4)
415 xattr = (info.m_external_attr >> 16) & 0xFFFF;
416 if (xattr > 0 && xattr <= MZ_UINT16_MAX) {
417 if (CHMOD(path, (mode_t)xattr) < 0) {
426 if (on_extract(path, arg) < 0) {
434 if (!mz_zip_reader_end(zip_archive)) {
442 mz_zip_writer_finalize_archive(pzip);
443 zip_archive_truncate(pzip);
446static ssize_t zip_entry_mark(
struct zip_t *zip,
448 const ssize_t n,
char *
const entries[],
452 if (!zip || !entry_mark || !entries) {
457 mz_uint64 d_pos = UINT64_MAX;
458 for (i = 0; i < n; ++i) {
463 mz_bool name_matches = MZ_FALSE;
466 for (j = 0; j < len; ++j) {
467 if (strcmp(zip->entry.name, entries[j]) == 0) {
468 name_matches = MZ_TRUE;
474 entry_mark[i].type = MZ_DELETE;
476 entry_mark[i].type = MZ_KEEP;
479 if (!mz_zip_reader_file_stat(&zip->archive, i, &file_stat)) {
485 entry_mark[i].m_local_header_ofs = file_stat.m_local_header_ofs;
486 entry_mark[i].file_index = (ssize_t)-1;
487 entry_mark[i].lf_length = 0;
488 if ((entry_mark[i].type) == MZ_DELETE &&
489 (d_pos > entry_mark[i].m_local_header_ofs)) {
490 d_pos = entry_mark[i].m_local_header_ofs;
494 for (i = 0; i < n; ++i) {
495 if ((entry_mark[i].m_local_header_ofs > d_pos) &&
496 (entry_mark[i].type != MZ_DELETE)) {
497 entry_mark[i].type = MZ_MOVE;
503static ssize_t zip_entry_markbyindex(
struct zip_t *zip,
505 const ssize_t n,
size_t entries[],
509 if (!zip || !entry_mark || !entries) {
514 mz_uint64 d_pos = UINT64_MAX;
515 for (i = 0; i < n; ++i) {
520 mz_bool matches = MZ_FALSE;
523 for (j = 0; j < len; ++j) {
524 if ((
size_t)i == entries[j]) {
531 entry_mark[i].type = MZ_DELETE;
533 entry_mark[i].type = MZ_KEEP;
536 if (!mz_zip_reader_file_stat(&zip->archive, i, &file_stat)) {
542 entry_mark[i].m_local_header_ofs = file_stat.m_local_header_ofs;
543 entry_mark[i].file_index = (ssize_t)-1;
544 entry_mark[i].lf_length = 0;
545 if ((entry_mark[i].type) == MZ_DELETE &&
546 (d_pos > entry_mark[i].m_local_header_ofs)) {
547 d_pos = entry_mark[i].m_local_header_ofs;
551 for (i = 0; i < n; ++i) {
552 if ((entry_mark[i].m_local_header_ofs > d_pos) &&
553 (entry_mark[i].type != MZ_DELETE)) {
554 entry_mark[i].type = MZ_MOVE;
559static ssize_t zip_index_next(mz_uint64 *local_header_ofs_array,
561 ssize_t new_index = 0, i;
562 for (i = cur_index - 1; i >= 0; --i) {
563 if (local_header_ofs_array[cur_index] > local_header_ofs_array[i]) {
571static ssize_t zip_sort(mz_uint64 *local_header_ofs_array, ssize_t cur_index) {
572 ssize_t nxt_index = zip_index_next(local_header_ofs_array, cur_index);
574 if (nxt_index != cur_index) {
575 mz_uint64 temp = local_header_ofs_array[cur_index];
577 for (i = cur_index; i > nxt_index; i--) {
578 local_header_ofs_array[i] = local_header_ofs_array[i - 1];
580 local_header_ofs_array[nxt_index] = temp;
586 ssize_t last_index, ssize_t nxt_index) {
588 for (j = 0; j < last_index; j++) {
589 if (entry_mark[j].file_index >= nxt_index) {
590 entry_mark[j].file_index += 1;
593 entry_mark[nxt_index].file_index = last_index;
597static int zip_entry_finalize(
struct zip_t *zip,
601 mz_uint64 *local_header_ofs_array = (mz_uint64 *)calloc(n,
sizeof(mz_uint64));
602 if (!local_header_ofs_array) {
606 for (i = 0; i < n; ++i) {
607 local_header_ofs_array[i] = entry_mark[i].m_local_header_ofs;
608 ssize_t index = zip_sort(local_header_ofs_array, i);
611 zip_index_update(entry_mark, i, index);
613 entry_mark[i].file_index = index;
616 size_t *length = (
size_t *)calloc(n,
sizeof(
size_t));
618 CLEANUP(local_header_ofs_array);
621 for (i = 0; i < n - 1; i++) {
623 (size_t)(local_header_ofs_array[i + 1] - local_header_ofs_array[i]);
626 (size_t)(zip->archive.m_archive_size - local_header_ofs_array[n - 1]);
628 for (i = 0; i < n; i++) {
629 entry_mark[i].lf_length = length[entry_mark[i].file_index];
633 CLEANUP(local_header_ofs_array);
637static ssize_t zip_entry_set(
struct zip_t *zip,
639 char *
const entries[],
const size_t len) {
642 if ((err = zip_entry_mark(zip, entry_mark, n, entries, len)) < 0) {
645 if ((err = zip_entry_finalize(zip, entry_mark, n)) < 0) {
651static ssize_t zip_entry_setbyindex(
struct zip_t *zip,
653 ssize_t n,
size_t entries[],
657 if ((err = zip_entry_markbyindex(zip, entry_mark, n, entries, len)) < 0) {
660 if ((err = zip_entry_finalize(zip, entry_mark, n)) < 0) {
666static ssize_t zip_mem_move(
void *pBuf,
size_t bufSize,
const mz_uint64 to,
667 const mz_uint64 from,
const size_t length) {
668 uint8_t *dst = NULL, *src = NULL, *end = NULL;
674 end = (uint8_t *)pBuf + bufSize;
680 if (from > bufSize) {
684 dst = (uint8_t *)pBuf + to;
685 src = (uint8_t *)pBuf + from;
687 if (((dst + length) > end) || ((src + length) > end)) {
691 memmove(dst, src, length);
695static ssize_t zip_file_move(MZ_FILE *m_pFile,
const mz_uint64 to,
696 const mz_uint64 from,
const size_t length,
697 mz_uint8 *move_buf,
const size_t capacity_size) {
698 if (length > capacity_size) {
701 if (MZ_FSEEK64(m_pFile, from, SEEK_SET)) {
704 if (fread(move_buf, 1, length, m_pFile) != length) {
707 if (MZ_FSEEK64(m_pFile, to, SEEK_SET)) {
710 if (fwrite(move_buf, 1, length, m_pFile) != length) {
713 return (ssize_t)length;
716static ssize_t zip_files_move(
struct zip_t *zip, mz_uint64 writen_num,
717 mz_uint64 read_num,
size_t length) {
719 const size_t page_size = 1 << 12;
720 mz_zip_internal_state *pState = zip->archive.m_pState;
722 mz_uint8 *move_buf = (mz_uint8 *)calloc(1, page_size);
727 ssize_t moved_length = 0;
728 ssize_t move_count = 0;
729 while ((mz_int64)length > 0) {
730 move_count = (length >= page_size) ? page_size : length;
732 if (pState->m_pFile) {
733 n = zip_file_move(pState->m_pFile, writen_num, read_num, move_count,
734 move_buf, page_size);
735 }
else if (pState->m_pMem) {
736 n = zip_mem_move(pState->m_pMem, pState->m_mem_size, writen_num, read_num,
747 if (n != move_count) {
751 writen_num += move_count;
752 read_num += move_count;
753 length -= move_count;
754 moved_length += move_count;
762static int zip_central_dir_move(mz_zip_internal_state *pState,
int begin,
763 int end,
int entry_num) {
764 if (begin == entry_num) {
770 mz_uint32 d_size = 0;
771 mz_uint8 *next = NULL;
772 mz_uint8 *deleted = &MZ_ZIP_ARRAY_ELEMENT(
773 &pState->m_central_dir, mz_uint8,
774 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, begin));
775 l_size = (size_t)(deleted - (mz_uint8 *)(pState->m_central_dir.m_p));
776 if (end == entry_num) {
779 next = &MZ_ZIP_ARRAY_ELEMENT(
780 &pState->m_central_dir, mz_uint8,
781 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, end));
782 r_size = pState->m_central_dir.m_size -
783 (mz_uint32)(next - (mz_uint8 *)(pState->m_central_dir.m_p));
784 d_size = (mz_uint32)(next - deleted);
787 if (next && l_size == 0) {
788 memmove(pState->m_central_dir.m_p, next, r_size);
789 pState->m_central_dir.m_p = MZ_REALLOC(pState->m_central_dir.m_p, r_size);
792 for (i = end; i < entry_num; i++) {
793 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i) -=
799 if (next && l_size * r_size != 0) {
800 memmove(deleted, next, r_size);
803 for (i = end; i < entry_num; i++) {
804 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i) -=
810 pState->m_central_dir.m_size = l_size + r_size;
814static int zip_central_dir_delete(mz_zip_internal_state *pState,
815 int *deleted_entry_index_array,
821 while (i < entry_num) {
822 while ((i < entry_num) && (!deleted_entry_index_array[i])) {
827 while ((i < entry_num) && (deleted_entry_index_array[i])) {
831 zip_central_dir_move(pState, begin, end, entry_num);
835 while (i < entry_num) {
836 while ((i < entry_num) && (!deleted_entry_index_array[i])) {
840 if (begin == entry_num) {
843 while ((i < entry_num) && (deleted_entry_index_array[i])) {
848 for (j = end; j < entry_num; j++) {
849 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32,
851 (mz_uint32)MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets,
855 d_num += end - begin;
858 pState->m_central_dir_offsets.m_size =
859 sizeof(mz_uint32) * (entry_num - d_num);
863static ssize_t zip_entries_delete_mark(
struct zip_t *zip,
866 mz_uint64 writen_num = 0;
867 mz_uint64 read_num = 0;
868 size_t deleted_length = 0;
869 size_t move_length = 0;
871 size_t deleted_entry_num = 0;
874 mz_bool *deleted_entry_flag_array =
875 (mz_bool *)calloc(entry_num,
sizeof(mz_bool));
876 if (deleted_entry_flag_array == NULL) {
880 mz_zip_internal_state *pState = zip->archive.m_pState;
881 zip->archive.m_zip_mode = MZ_ZIP_MODE_WRITING;
883 if (pState->m_pFile) {
884 if (MZ_FSEEK64(pState->m_pFile, 0, SEEK_SET)) {
885 CLEANUP(deleted_entry_flag_array);
890 while (i < entry_num) {
891 while ((i < entry_num) && (entry_mark[i].type == MZ_KEEP)) {
892 writen_num += entry_mark[i].lf_length;
893 read_num = writen_num;
897 while ((i < entry_num) && (entry_mark[i].type == MZ_DELETE)) {
898 deleted_entry_flag_array[i] = MZ_TRUE;
899 read_num += entry_mark[i].lf_length;
900 deleted_length += entry_mark[i].lf_length;
905 while ((i < entry_num) && (entry_mark[i].type == MZ_MOVE)) {
906 move_length += entry_mark[i].lf_length;
907 mz_uint8 *p = &MZ_ZIP_ARRAY_ELEMENT(
908 &pState->m_central_dir, mz_uint8,
909 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i));
911 CLEANUP(deleted_entry_flag_array);
914 mz_uint32 offset = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
915 offset -= (mz_uint32)deleted_length;
916 MZ_WRITE_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS, offset);
920 n = zip_files_move(zip, writen_num, read_num, move_length);
921 if (n != (ssize_t)move_length) {
922 CLEANUP(deleted_entry_flag_array);
925 writen_num += move_length;
926 read_num += move_length;
929 zip->archive.m_archive_size -= (mz_uint64)deleted_length;
930 zip->archive.m_total_files =
931 (mz_uint32)entry_num - (mz_uint32)deleted_entry_num;
933 zip_central_dir_delete(pState, deleted_entry_flag_array, entry_num);
934 CLEANUP(deleted_entry_flag_array);
936 return (ssize_t)deleted_entry_num;
946 struct zip_t *zip = NULL;
949 if (!zipname || strlen(zipname) < 1) {
951 *errnum = ZIP_EINVZIPNAME;
956 level = MZ_DEFAULT_LEVEL;
957 if ((level & 0xF) > MZ_UBER_COMPRESSION) {
959 *errnum = ZIP_EINVLVL;
963 zip = (
struct zip_t *)calloc((
size_t)1,
sizeof(
struct zip_t));
966 *errnum = ZIP_EOOMEM;
970 zip->level = (mz_uint)level;
971 zip->entry.index = -1;
975 if (!mz_zip_writer_init_file_v2(&(zip->archive), zipname, 0,
976 MZ_ZIP_FLAG_WRITE_ZIP64)) {
978 *errnum = ZIP_EWINIT;
984 if (!mz_zip_reader_init_file_v2(
985 &(zip->archive), zipname,
986 zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) {
989 *errnum = ZIP_ERINIT;
996 MZ_FILE *fp = MZ_FOPEN(zipname,
"r+b");
998 *errnum = ZIP_EOPNFILE;
1001 if (!mz_zip_reader_init_cfile(
1002 &(zip->archive), fp, 0,
1003 zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) {
1006 *errnum = ZIP_ERINIT;
1010 if (!mz_zip_writer_init_from_reader_v2(&(zip->archive), zipname, 0)) {
1011 *errnum = ZIP_EWRINIT;
1013 mz_zip_reader_end(&(zip->archive));
1017 zip->archive.m_zip_type = MZ_ZIP_TYPE_FILE;
1021 *errnum = ZIP_EINVMODE;
1037 if (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) {
1038 mz_zip_writer_finalize_archive(pZip);
1041 if (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING ||
1042 pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED) {
1043 zip_archive_truncate(pZip);
1044 mz_zip_writer_end(pZip);
1046 if (pZip->m_zip_mode == MZ_ZIP_MODE_READING) {
1047 mz_zip_reader_end(pZip);
1055 if (!zip || !zip->archive.m_pState) {
1060 return (
int)zip->archive.m_pState->m_zip64;
1064 if (!zip || !zip->archive.m_pState) {
1069 *offset = mz_zip_get_archive_file_start_offset(&zip->archive);
1073static int _zip_entry_open(
struct zip_t *zip,
const char *entryname,
1074 int case_sensitive) {
1075 size_t entrylen = 0;
1077 mz_uint num_alignment_padding_bytes, level;
1080 mz_uint16 dos_time = 0, dos_date = 0;
1081 mz_uint32 extra_size = 0;
1082 mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
1083 mz_uint64 local_dir_header_ofs = 0;
1089 local_dir_header_ofs = zip->archive.m_archive_size;
1092 return ZIP_EINVENTNAME;
1095 entrylen = strlen(entryname);
1096 if (entrylen == 0) {
1097 return ZIP_EINVENTNAME;
1100 if (zip->entry.name) {
1101 CLEANUP(zip->entry.name);
1104 pzip = &(zip->archive);
1105 if (pzip->m_zip_mode == MZ_ZIP_MODE_READING) {
1106 zip->entry.name = zip_strclone(entryname, entrylen);
1107 if (!zip->entry.name) {
1109 return ZIP_EINVENTNAME;
1112 zip->entry.index = (ssize_t)mz_zip_reader_locate_file(
1113 pzip, zip->entry.name, NULL,
1114 case_sensitive ? MZ_ZIP_FLAG_CASE_SENSITIVE : 0);
1115 if (zip->entry.index < (ssize_t)0) {
1120 if (!mz_zip_reader_file_stat(pzip, (mz_uint)zip->entry.index, &stats)) {
1125 zip->entry.comp_size = stats.m_comp_size;
1126 zip->entry.uncomp_size = stats.m_uncomp_size;
1127 zip->entry.uncomp_crc32 = stats.m_crc32;
1128 zip->entry.dir_offset = stats.m_central_dir_ofs;
1129 zip->entry.header_offset = stats.m_local_header_ofs;
1130 zip->entry.method = stats.m_method;
1131 zip->entry.external_attr = stats.m_external_attr;
1132#ifndef MINIZ_NO_TIME
1133 zip->entry.m_time = stats.m_time;
1150 zip->entry.name = zip_strrpl(entryname, entrylen,
'\\',
'/');
1151 if (!zip->entry.name) {
1153 return ZIP_EINVENTNAME;
1156 level = zip->level & 0xF;
1158 zip->entry.index = (ssize_t)zip->archive.m_total_files;
1159 zip->entry.comp_size = 0;
1160 zip->entry.uncomp_size = 0;
1161 zip->entry.uncomp_crc32 = MZ_CRC32_INIT;
1162 zip->entry.dir_offset = zip->archive.m_archive_size;
1163 zip->entry.header_offset = zip->archive.m_archive_size;
1164 memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE *
sizeof(mz_uint8));
1165 zip->entry.method = level ? MZ_DEFLATED : 0;
1168#if MZ_PLATFORM == 3 || MZ_PLATFORM == 19
1170 zip->entry.external_attr = (mz_uint32)(0100644) << 16;
1172 zip->entry.external_attr = 0;
1175 num_alignment_padding_bytes =
1176 mz_zip_writer_compute_padding_needed_for_file_alignment(pzip);
1178 if (!pzip->m_pState || (pzip->m_zip_mode != MZ_ZIP_MODE_WRITING)) {
1183 if (zip->level & MZ_ZIP_FLAG_COMPRESSED_DATA) {
1189 if (!mz_zip_writer_write_zeros(pzip, zip->entry.dir_offset,
1190 num_alignment_padding_bytes)) {
1195 local_dir_header_ofs += num_alignment_padding_bytes;
1197 zip->entry.m_time = time(NULL);
1198#ifndef MINIZ_NO_TIME
1199 mz_zip_time_t_to_dos_time(zip->entry.m_time, &dos_time, &dos_date);
1204 extra_size = mz_zip_writer_create_zip64_extra_data(
1205 extra_data, NULL, NULL,
1206 (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
1208 if (!mz_zip_writer_create_local_dir_header(
1209 pzip, zip->entry.header, entrylen, (mz_uint16)extra_size, 0, 0, 0,
1211 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 |
1212 MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR,
1213 dos_time, dos_date)) {
1219 zip->entry.header_offset =
1220 zip->entry.dir_offset + num_alignment_padding_bytes;
1222 if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.header_offset,
1224 sizeof(zip->entry.header)) !=
sizeof(zip->entry.header)) {
1230 if (pzip->m_file_offset_alignment) {
1232 (zip->entry.header_offset & (pzip->m_file_offset_alignment - 1)) == 0);
1234 zip->entry.dir_offset +=
1235 num_alignment_padding_bytes +
sizeof(zip->entry.header);
1237 if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.dir_offset, zip->entry.name,
1238 entrylen) != entrylen) {
1244 zip->entry.dir_offset += entrylen;
1246 if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.dir_offset, extra_data,
1247 extra_size) != extra_size) {
1252 zip->entry.dir_offset += extra_size;
1255 zip->entry.state.m_pZip = pzip;
1256 zip->entry.state.m_cur_archive_file_ofs = zip->entry.dir_offset;
1257 zip->entry.state.m_comp_size = 0;
1259 if (tdefl_init(&(zip->entry.comp), mz_zip_writer_add_put_buf_callback,
1260 &(zip->entry.state),
1261 (
int)tdefl_create_comp_flags_from_zip_params(
1262 (
int)level, -15, MZ_DEFAULT_STRATEGY)) !=
1263 TDEFL_STATUS_OKAY) {
1265 err = ZIP_ETDEFLINIT;
1273 CLEANUP(zip->entry.name);
1278 return _zip_entry_open(zip, entryname, 0);
1282 return _zip_entry_open(zip, entryname, 1);
1289 const mz_uint8 *pHeader;
1290 const char *pFilename;
1297 pZip = &(zip->archive);
1298 if (pZip->m_zip_mode != MZ_ZIP_MODE_READING) {
1300 return ZIP_EINVMODE;
1303 if (index >= (
size_t)pZip->m_total_files) {
1308 if (!(pHeader = &MZ_ZIP_ARRAY_ELEMENT(
1309 &pZip->m_pState->m_central_dir, mz_uint8,
1310 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets,
1311 mz_uint32, index)))) {
1316 namelen = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1317 pFilename = (
const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1319 if (zip->entry.name) {
1320 CLEANUP(zip->entry.name);
1323 zip->entry.name = zip_strclone(pFilename, namelen);
1324 if (!zip->entry.name) {
1326 return ZIP_EINVENTNAME;
1329 if (!mz_zip_reader_file_stat(pZip, (mz_uint)index, &stats)) {
1333 zip->entry.index = (ssize_t)index;
1334 zip->entry.comp_size = stats.m_comp_size;
1335 zip->entry.uncomp_size = stats.m_uncomp_size;
1336 zip->entry.uncomp_crc32 = stats.m_crc32;
1337 zip->entry.dir_offset = stats.m_central_dir_ofs;
1338 zip->entry.header_offset = stats.m_local_header_ofs;
1339 zip->entry.method = stats.m_method;
1340 zip->entry.external_attr = stats.m_external_attr;
1341#ifndef MINIZ_NO_TIME
1342 zip->entry.m_time = stats.m_time;
1353 mz_uint16 dos_time = 0, dos_date = 0;
1355 mz_uint8 *pExtra_data = NULL;
1356 mz_uint32 extra_size = 0;
1357 mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
1358 mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
1359 mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
1367 pzip = &(zip->archive);
1368 if (pzip->m_zip_mode == MZ_ZIP_MODE_READING) {
1372 level = zip->level & 0xF;
1374 done = tdefl_compress_buffer(&(zip->entry.comp),
"", 0, TDEFL_FINISH);
1375 if (done != TDEFL_STATUS_DONE && done != TDEFL_STATUS_OKAY) {
1377 err = ZIP_ETDEFLBUF;
1380 zip->entry.comp_size = zip->entry.state.m_comp_size;
1381 zip->entry.dir_offset = zip->entry.state.m_cur_archive_file_ofs;
1382 zip->entry.method = MZ_DEFLATED;
1385 entrylen = (mz_uint16)strlen(zip->entry.name);
1386#ifndef MINIZ_NO_TIME
1387 mz_zip_time_t_to_dos_time(zip->entry.m_time, &dos_time, &dos_date);
1390 MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
1391 MZ_WRITE_LE32(local_dir_footer + 4, zip->entry.uncomp_crc32);
1392 MZ_WRITE_LE64(local_dir_footer + 8, zip->entry.comp_size);
1393 MZ_WRITE_LE64(local_dir_footer + 16, zip->entry.uncomp_size);
1395 if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.dir_offset,
1397 local_dir_footer_size) != local_dir_footer_size) {
1402 zip->entry.dir_offset += local_dir_footer_size;
1404 pExtra_data = extra_data;
1405 extra_size = mz_zip_writer_create_zip64_extra_data(
1407 (zip->entry.uncomp_size >= MZ_UINT32_MAX) ? &zip->entry.uncomp_size
1409 (zip->entry.comp_size >= MZ_UINT32_MAX) ? &zip->entry.comp_size : NULL,
1410 (zip->entry.header_offset >= MZ_UINT32_MAX) ? &zip->entry.header_offset
1413 if ((entrylen) && ISSLASH(zip->entry.name[entrylen - 1]) &&
1414 !zip->entry.uncomp_size) {
1416 zip->entry.external_attr |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
1419 if (!mz_zip_writer_add_to_central_dir(
1420 pzip, zip->entry.name, entrylen, pExtra_data, (mz_uint16)extra_size,
1421 "", 0, zip->entry.uncomp_size, zip->entry.comp_size,
1422 zip->entry.uncomp_crc32, zip->entry.method,
1423 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 |
1424 MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR,
1425 dos_time, dos_date, zip->entry.header_offset,
1426 zip->entry.external_attr, NULL, 0)) {
1432 pzip->m_total_files++;
1433 pzip->m_archive_size = zip->entry.dir_offset;
1437 zip->entry.m_time = 0;
1438 zip->entry.index = -1;
1439 CLEANUP(zip->entry.name);
1449 return zip->entry.name;
1458 return zip->entry.index;
1468 if (zip->entry.index < (ssize_t)0) {
1473 entrylen = (mz_uint16)strlen(zip->entry.name);
1474 return ISSLASH(zip->entry.name[entrylen - 1]);
1482 return zip ? zip->entry.uncomp_size : 0;
1486 return zip ? zip->entry.comp_size : 0;
1490 return zip ? zip->entry.uncomp_crc32 : 0;
1494 return zip ? zip->entry.dir_offset : 0;
1498 return zip ? zip->entry.header_offset : 0;
1504 tdefl_status status;
1511 pzip = &(zip->archive);
1512 if (buf && bufsize > 0) {
1513 zip->entry.uncomp_size += bufsize;
1514 zip->entry.uncomp_crc32 = (mz_uint32)mz_crc32(
1515 zip->entry.uncomp_crc32, (
const mz_uint8 *)buf, bufsize);
1517 level = zip->level & 0xF;
1519 if ((pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.dir_offset, buf,
1520 bufsize) != bufsize)) {
1524 zip->entry.dir_offset += bufsize;
1525 zip->entry.comp_size += bufsize;
1527 status = tdefl_compress_buffer(&(zip->entry.comp), buf, bufsize,
1529 if (status != TDEFL_STATUS_DONE && status != TDEFL_STATUS_OKAY) {
1531 return ZIP_ETDEFLBUF;
1542 MZ_FILE *stream = NULL;
1543 mz_uint8 buf[MZ_ZIP_MAX_IO_BUF_SIZE];
1544 struct MZ_FILE_STAT_STRUCT file_stat;
1552 memset(buf, 0, MZ_ZIP_MAX_IO_BUF_SIZE);
1553 memset((
void *)&file_stat, 0,
sizeof(
struct MZ_FILE_STAT_STRUCT));
1554 if (MZ_FILE_STAT(filename, &file_stat) != 0) {
1559#if defined(_WIN32) || defined(__WIN32__) || defined(DJGPP)
1563 modes = file_stat.st_mode &
1564 (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
1565 if (S_ISDIR(file_stat.st_mode))
1567 if (S_ISREG(file_stat.st_mode))
1569 if (S_ISLNK(file_stat.st_mode))
1571 if (S_ISBLK(file_stat.st_mode))
1573 if (S_ISCHR(file_stat.st_mode))
1575 if (S_ISFIFO(file_stat.st_mode))
1577 if (S_ISSOCK(file_stat.st_mode))
1578 modes |= UNX_IFSOCK;
1579 zip->entry.external_attr = (modes << 16) | !(file_stat.st_mode & S_IWUSR);
1580 if ((file_stat.st_mode & S_IFMT) == S_IFDIR) {
1581 zip->entry.external_attr |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
1585 zip->entry.m_time = file_stat.st_mtime;
1587 if (!(stream = MZ_FOPEN(filename,
"rb"))) {
1589 return ZIP_EOPNFILE;
1592 while ((n = fread(buf,
sizeof(mz_uint8), MZ_ZIP_MAX_IO_BUF_SIZE, stream)) >
1614 pzip = &(zip->archive);
1615 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING ||
1616 zip->entry.index < (ssize_t)0) {
1618 return (ssize_t)ZIP_ENOENT;
1621 idx = (mz_uint)zip->entry.index;
1622 if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
1624 return (ssize_t)ZIP_EINVENTTYPE;
1627 *buf = mz_zip_reader_extract_to_heap(pzip, idx, &size, 0);
1628 if (*buf && bufsize) {
1631 return (ssize_t)size;
1642 pzip = &(zip->archive);
1643 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING ||
1644 zip->entry.index < (ssize_t)0) {
1646 return (ssize_t)ZIP_ENOENT;
1649 if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index,
1650 buf, bufsize, 0, NULL, 0)) {
1651 return (ssize_t)ZIP_EMEMNOALLOC;
1654 return (ssize_t)zip->entry.uncomp_size;
1660 mz_uint32 xattr = 0;
1669 pzip = &(zip->archive);
1670 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING ||
1671 zip->entry.index < (ssize_t)0) {
1676 idx = (mz_uint)zip->entry.index;
1677 if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
1679 return ZIP_EINVENTTYPE;
1682 if (!mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) {
1686#if defined(_MSC_VER) || defined(PS4)
1689 if (!mz_zip_reader_file_stat(pzip, idx, &info)) {
1694 xattr = (info.m_external_attr >> 16) & 0xFFFF;
1695 if (xattr > 0 && xattr <= MZ_UINT16_MAX) {
1696 if (CHMOD(filename, (mode_t)xattr) < 0) {
1705int zip_entry_extract(
struct zip_t *zip,
1706 size_t (*on_extract)(
void *arg, uint64_t offset,
1707 const void *buf,
size_t bufsize),
1717 pzip = &(zip->archive);
1718 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING ||
1719 zip->entry.index < (ssize_t)0) {
1724 idx = (mz_uint)zip->entry.index;
1725 return (mz_zip_reader_extract_to_callback(pzip, idx, on_extract, arg, 0))
1736 return (ssize_t)zip->archive.m_total_files;
1745 if (zip == NULL || (entries == NULL && len != 0)) {
1749 if (entries == NULL && len == 0) {
1761 zip->archive.m_zip_mode = MZ_ZIP_MODE_READING;
1763 err = zip_entry_set(zip, entry_mark, n, entries, len);
1765 CLEANUP(entry_mark);
1769 err = zip_entries_delete_mark(zip, entry_mark, (
int)n);
1770 CLEANUP(entry_mark);
1780 if (zip == NULL || (entries == NULL && len != 0)) {
1784 if (entries == NULL && len == 0) {
1796 zip->archive.m_zip_mode = MZ_ZIP_MODE_READING;
1798 err = zip_entry_setbyindex(zip, entry_mark, n, entries, len);
1800 CLEANUP(entry_mark);
1804 err = zip_entries_delete_mark(zip, entry_mark, (
int)n);
1805 CLEANUP(entry_mark);
1810 int (*on_extract)(
const char *filename,
void *arg),
1813 if (!stream || !dir) {
1821 if (!mz_zip_reader_init_mem(&zip_archive, stream, size, 0)) {
1826 return zip_archive_extract(&zip_archive, dir, on_extract, arg);
1836 int level,
char mode,
int *errnum) {
1837 struct zip_t *zip = (
struct zip_t *)calloc((
size_t)1,
sizeof(
struct zip_t));
1840 *errnum = ZIP_EOOMEM;
1845 level = MZ_DEFAULT_LEVEL;
1847 if ((level & 0xF) > MZ_UBER_COMPRESSION) {
1849 *errnum = ZIP_EINVLVL;
1852 zip->level = (mz_uint)level;
1854 if ((stream != NULL) && (size > 0) && (mode ==
'r')) {
1855 if (!mz_zip_reader_init_mem(&(zip->archive), stream, size, 0)) {
1856 *errnum = ZIP_ERINIT;
1859 }
else if ((stream == NULL) && (size == 0) && (mode ==
'w')) {
1861 if (!mz_zip_writer_init_heap(&(zip->archive), 0, 1024)) {
1863 *errnum = ZIP_EWINIT;
1867 *errnum = ZIP_EINVMODE;
1885 zip_archive_finalize(&(zip->archive));
1887 n = (size_t)zip->archive.m_archive_size;
1888 if (bufsize != NULL) {
1892 *buf = calloc(n,
sizeof(
unsigned char));
1893 memcpy(*buf, zip->archive.m_pState->m_pMem, n);
1900 mz_zip_writer_end(&(zip->archive));
1901 mz_zip_reader_end(&(zip->archive));
1913 struct zip_t *zip = NULL;
1917 *errnum = ZIP_ENOFILE;
1922 level = MZ_DEFAULT_LEVEL;
1923 if ((level & 0xF) > MZ_UBER_COMPRESSION) {
1925 *errnum = ZIP_EINVLVL;
1929 zip = (
struct zip_t *)calloc((
size_t)1,
sizeof(
struct zip_t));
1932 *errnum = ZIP_EOOMEM;
1936 zip->level = (mz_uint)level;
1940 if (!mz_zip_writer_init_cfile(&(zip->archive), stream,
1941 MZ_ZIP_FLAG_WRITE_ZIP64)) {
1943 *errnum = ZIP_EWINIT;
1949 if (!mz_zip_reader_init_cfile(
1950 &(zip->archive), stream, 0,
1951 zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) {
1954 *errnum = ZIP_ERINIT;
1961 if (!mz_zip_reader_init_cfile(
1962 &(zip->archive), stream, 0,
1963 zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) {
1966 *errnum = ZIP_ERINIT;
1969 if ((mode ==
'a' || mode ==
'd')) {
1970 if (!mz_zip_writer_init_from_reader_v2(&(zip->archive), NULL, 0)) {
1971 *errnum = ZIP_EWRINIT;
1972 mz_zip_reader_end(&(zip->archive));
1979 *errnum = ZIP_EINVMODE;
1992int zip_create(
const char *zipname,
const char *filenames[],
size_t len) {
1996 struct MZ_FILE_STAT_STRUCT file_stat;
1997 mz_uint32 ext_attributes = 0;
2000 if (!zipname || strlen(zipname) < 1) {
2002 return ZIP_EINVZIPNAME;
2006 if (!memset(&(zip_archive), 0,
sizeof(zip_archive))) {
2011 if (!mz_zip_writer_init_file(&zip_archive, zipname, 0)) {
2016 if (!memset((
void *)&file_stat, 0,
sizeof(
struct MZ_FILE_STAT_STRUCT))) {
2020 for (i = 0; i < len; ++i) {
2021 const char *name = filenames[i];
2023 err = ZIP_EINVENTNAME;
2027 if (MZ_FILE_STAT(name, &file_stat) != 0) {
2033#if defined(_WIN32) || defined(__WIN32__) || defined(DJGPP)
2038 modes = file_stat.st_mode &
2039 (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
2040 if (S_ISDIR(file_stat.st_mode))
2042 if (S_ISREG(file_stat.st_mode))
2044 if (S_ISLNK(file_stat.st_mode))
2046 if (S_ISBLK(file_stat.st_mode))
2048 if (S_ISCHR(file_stat.st_mode))
2050 if (S_ISFIFO(file_stat.st_mode))
2052 if (S_ISSOCK(file_stat.st_mode))
2053 modes |= UNX_IFSOCK;
2054 ext_attributes = (modes << 16) | !(file_stat.st_mode & S_IWUSR);
2055 if ((file_stat.st_mode & S_IFMT) == S_IFDIR) {
2056 ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
2060 if (!mz_zip_writer_add_file(&zip_archive, zip_basename(name), name,
"", 0,
2069 mz_zip_writer_finalize_archive(&zip_archive);
2070 mz_zip_writer_end(&zip_archive);
2075 int (*on_extract)(
const char *filename,
void *arg),
void *arg) {
2078 if (!zipname || !dir) {
2080 return ZIP_EINVZIPNAME;
2089 if (!mz_zip_reader_init_file(&zip_archive, zipname, 0)) {
2094 return zip_archive_extract(&zip_archive, dir, on_extract, arg);
int zip_is64(struct zip_t *zip)
struct zip_t * zip_openwitherror(const char *zipname, int level, char mode, int *errnum)
unsigned long long zip_entry_size(struct zip_t *zip)
int zip_entry_isdir(struct zip_t *zip)
ssize_t zip_entry_index(struct zip_t *zip)
const char * zip_entry_name(struct zip_t *zip)
struct zip_t * zip_open(const char *zipname, int level, char mode)
ssize_t zip_entries_deletebyindex(struct zip_t *zip, size_t entries[], size_t len)
void zip_stream_close(struct zip_t *zip)
int zip_entry_fread(struct zip_t *zip, const char *filename)
struct zip_t * zip_stream_open(const char *stream, size_t size, int level, char mode)
const char * zip_strerror(int errnum)
ssize_t zip_stream_copy(struct zip_t *zip, void **buf, size_t *bufsize)
ssize_t zip_entries_delete(struct zip_t *zip, char *const entries[], size_t len)
int zip_entry_fwrite(struct zip_t *zip, const char *filename)
void zip_cstream_close(struct zip_t *zip)
ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize)
int zip_offset(struct zip_t *zip, uint64_t *offset)
struct zip_t * zip_cstream_open(FILE *stream, int level, char mode)
unsigned int zip_entry_crc32(struct zip_t *zip)
unsigned long long zip_entry_uncomp_size(struct zip_t *zip)
struct zip_t * zip_stream_openwitherror(const char *stream, size_t size, int level, char mode, int *errnum)
#define ZIP_DEFAULT_COMPRESSION_LEVEL
int zip_create(const char *zipname, const char *filenames[], size_t len)
void zip_close(struct zip_t *zip)
int zip_entry_open(struct zip_t *zip, const char *entryname)
int zip_entry_opencasesensitive(struct zip_t *zip, const char *entryname)
int zip_extract(const char *zipname, const char *dir, int(*on_extract)(const char *filename, void *arg), void *arg)
struct zip_t * zip_cstream_openwitherror(FILE *stream, int level, char mode, int *errnum)
int zip_entry_close(struct zip_t *zip)
unsigned long long zip_entry_header_offset(struct zip_t *zip)
int zip_entry_openbyindex(struct zip_t *zip, size_t index)
int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize)
ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize)
unsigned long long zip_entry_dir_offset(struct zip_t *zip)
ssize_t zip_entries_total(struct zip_t *zip)
int zip_stream_extract(const char *stream, size_t size, const char *dir, int(*on_extract)(const char *filename, void *arg), void *arg)
unsigned long long zip_entry_comp_size(struct zip_t *zip)