10#define __STDC_WANT_LIB_EXT1__ 1
16#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
17 defined(__MINGW32__) || defined(MSVC_CMAKE)
21#define MKDIR(DIRNAME) _mkdir(DIRNAME)
22#define STRCLONE(STR) ((STR) ? _strdup(STR) : NULL)
23#define HAS_DEVICE(P) \
24 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \
26#define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0)
32#define MKDIR(DIRNAME) mkdir(DIRNAME, 0755)
33#define STRCLONE(STR) ((STR) ? strdup(STR) : NULL)
48#define ftruncate(fd, sz) (-(_chsize_s((fd), (sz)) != 0))
53#define HAS_DEVICE(P) 0
56#ifndef FILESYSTEM_PREFIX_LEN
57#define FILESYSTEM_PREFIX_LEN(P) 0
61#define ISSLASH(C) ((C) == '/' || (C) == '\\')
75 mz_uint64 uncomp_size;
77 mz_uint32 uncomp_crc32;
79 mz_uint8 header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
80 mz_uint64 header_offset;
84 mz_uint32 external_attr;
102 enum zip_modify_t type;
103 mz_uint64 m_local_header_ofs;
107static const char *
const zip_errlist[30] = {
110 "invalid entry name\0",
112 "invalid zip mode\0",
113 "invalid compression level\0",
114 "no zip 64 support\0",
116 "cannot write data to entry\0",
117 "cannot initialize tdefl compressor\0",
119 "header not found\0",
120 "cannot flush tdefl buffer\0",
121 "cannot write entry header\0",
122 "cannot create entry header\0",
123 "cannot write to central dir\0",
124 "cannot open file\0",
125 "invalid entry type\0",
126 "extracting data using no memory allocation\0",
130 "invalid zip archive name\0",
133 "close archive error\0"
134 "capacity size too small\0",
142 if (errnum <= 0 || errnum >= 30) {
146 return zip_errlist[errnum];
149static const char *zip_basename(
const char *name) {
151 char const *base = name += FILESYSTEM_PREFIX_LEN(name);
154 for (p = name; *p; p++) {
162 if (*base ==
'\0' && ISSLASH(*name) && all_slashes)
168static int zip_mkpath(
char *path) {
170 char npath[MAX_PATH + 1];
172 int has_device = HAS_DEVICE(path);
174 memset(npath, 0, MAX_PATH + 1);
181 for (p = path + len; *p && len < MAX_PATH; p++) {
182 if (ISSLASH(*p) && ((!has_device && len > 0) || (has_device && len > 2))) {
183#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
191 if (MKDIR(npath) == -1) {
192 if (errno != EEXIST) {
203static char *zip_strrpl(
const char *str,
size_t n,
char oldchar,
char newchar) {
206 char *rpl = (
char *)calloc((1 + n),
sizeof(char));
212 for (i = 0; (i < n) && (c = *str++); ++i) {
222static char *zip_name_normalize(
char *name,
char *
const nname,
size_t len) {
224 size_t offnn = 0, ncpy = 0;
226 if (name == NULL || nname == NULL || len <= 0) {
230 while (ISSLASH(*name))
233 for (; offn < len; offn++) {
234 if (ISSLASH(name[offn])) {
235 if (ncpy > 0 && strcmp(&nname[offnn],
".\0") &&
236 strcmp(&nname[offnn],
"..\0")) {
238 nname[offnn++] = name[offn];
242 nname[offnn + ncpy] = name[offn];
248 if (ncpy == 0 || !strcmp(&nname[offnn],
".\0") ||
249 !strcmp(&nname[offnn],
"..\0")) {
255static mz_bool zip_name_match(
const char *name1,
const char *name2) {
256 int len2 = strlen(name2);
257 char *nname2 = zip_strrpl(name2, len2,
'\\',
'/');
262 mz_bool res = (strcmp(name1, nname2) == 0) ? MZ_TRUE : MZ_FALSE;
269 mz_uint64 file_size = pzip->m_archive_size;
270 if ((pzip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
273 if (pzip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED) {
274 if (pState->m_pFile) {
275 int fd = fileno(pState->m_pFile);
276 return ftruncate(fd, file_size);
282static int zip_archive_extract(
mz_zip_archive *zip_archive,
const char *dir,
283 int (*on_extract)(
const char *filename,
288 char path[MAX_PATH + 1];
289 char symlink_to[MAX_PATH + 1];
294 memset(path, 0,
sizeof(path));
295 memset(symlink_to, 0,
sizeof(symlink_to));
297 dirlen = strlen(dir);
298 if (dirlen + 1 > MAX_PATH) {
299 return ZIP_EINVENTNAME;
305 strcpy_s(path, MAX_PATH, dir);
310 if (!ISSLASH(path[dirlen - 1])) {
311#if defined(_WIN32) || defined(__WIN32__)
320 n = mz_zip_reader_get_num_files(zip_archive);
321 for (i = 0; i < n; ++i) {
322 if (!mz_zip_reader_file_stat(zip_archive, i, &info)) {
328 if (!zip_name_normalize(info.m_filename, info.m_filename,
329 strlen(info.m_filename))) {
331 err = ZIP_EINVENTNAME;
335 strncpy_s(&path[dirlen], MAX_PATH - dirlen, info.m_filename,
338 strncpy(&path[dirlen], info.m_filename, MAX_PATH - dirlen);
340 err = zip_mkpath(path);
346 if ((((info.m_version_made_by >> 8) == 3) ||
347 ((info.m_version_made_by >> 8) ==
350 && info.m_external_attr &
353#if defined(_WIN32) || defined(__WIN32__) || defined(_MSC_VER) || \
356 if (info.m_uncomp_size > MAX_PATH ||
357 !mz_zip_reader_extract_to_mem_no_alloc(zip_archive, i, symlink_to,
358 MAX_PATH, 0, NULL, 0)) {
359 err = ZIP_EMEMNOALLOC;
362 symlink_to[info.m_uncomp_size] =
'\0';
363 if (symlink(symlink_to, path) != 0) {
369 if (!mz_zip_reader_is_file_a_directory(zip_archive, i)) {
370 if (!mz_zip_reader_extract_to_file(zip_archive, i, path, 0)) {
380 xattr = (info.m_external_attr >> 16) & 0xFFFF;
382 if (chmod(path, (mode_t)xattr) < 0) {
391 if (on_extract(path, arg) < 0) {
399 if (!mz_zip_reader_end(zip_archive)) {
407 mz_zip_writer_finalize_archive(pzip);
408 zip_archive_truncate(pzip);
411static int zip_entry_mark(
struct zip_t *zip,
413 char *
const entries[],
const size_t len) {
415 if (!zip || !entry_mark || !entries) {
420 mz_uint64 d_pos = ~0;
421 for (
int i = 0; i < n; ++i) {
427 mz_bool name_matches = MZ_FALSE;
428 for (
int j = 0; j < (
const int)len; ++j) {
429 if (zip_name_match(zip->entry.name, entries[j])) {
430 name_matches = MZ_TRUE;
435 entry_mark[i].type = MZ_DELETE;
437 entry_mark[i].type = MZ_KEEP;
440 if (!mz_zip_reader_file_stat(&zip->archive, i, &file_stat)) {
446 entry_mark[i].m_local_header_ofs = file_stat.m_local_header_ofs;
447 entry_mark[i].file_index = -1;
448 entry_mark[i].lf_length = 0;
449 if ((entry_mark[i].type) == MZ_DELETE &&
450 (d_pos > entry_mark[i].m_local_header_ofs)) {
451 d_pos = entry_mark[i].m_local_header_ofs;
454 for (
int i = 0; i < n; ++i) {
455 if ((entry_mark[i].m_local_header_ofs > d_pos) &&
456 (entry_mark[i].type != MZ_DELETE)) {
457 entry_mark[i].type = MZ_MOVE;
463static int zip_index_next(mz_uint64 *local_header_ofs_array,
int cur_index) {
465 for (
int i = cur_index - 1; i >= 0; --i) {
466 if (local_header_ofs_array[cur_index] > local_header_ofs_array[i]) {
474static int zip_sort(mz_uint64 *local_header_ofs_array,
int cur_index) {
475 int nxt_index = zip_index_next(local_header_ofs_array, cur_index);
477 if (nxt_index != cur_index) {
478 mz_uint64 temp = local_header_ofs_array[cur_index];
479 for (
int i = cur_index; i > nxt_index; i--) {
480 local_header_ofs_array[i] = local_header_ofs_array[i - 1];
482 local_header_ofs_array[nxt_index] = temp;
487static int zip_index_update(
struct zip_entry_mark_t *entry_mark,
int last_index,
489 for (
int j = 0; j < last_index; j++) {
490 if (entry_mark[j].file_index >= nxt_index) {
491 entry_mark[j].file_index += 1;
494 entry_mark[nxt_index].file_index = last_index;
498static int zip_entry_finalize(
struct zip_t *zip,
502 mz_uint64 *local_header_ofs_array = (mz_uint64 *)calloc(n,
sizeof(mz_uint64));
503 if (!local_header_ofs_array) {
507 for (
int i = 0; i < n; ++i) {
508 local_header_ofs_array[i] = entry_mark[i].m_local_header_ofs;
509 int index = zip_sort(local_header_ofs_array, i);
512 zip_index_update(entry_mark, i, index);
514 entry_mark[i].file_index = index;
517 mz_uint64 *length = (mz_uint64 *)calloc(n,
sizeof(mz_uint64));
519 CLEANUP(local_header_ofs_array);
522 for (
int i = 0; i < n - 1; i++) {
523 length[i] = local_header_ofs_array[i + 1] - local_header_ofs_array[i];
525 length[n - 1] = zip->archive.m_archive_size - local_header_ofs_array[n - 1];
527 for (
int i = 0; i < n; i++) {
528 entry_mark[i].lf_length = length[entry_mark[i].file_index];
532 CLEANUP(local_header_ofs_array);
537 int n,
char *
const entries[],
const size_t len) {
540 if ((err = zip_entry_mark(zip, entry_mark, n, entries, len)) < 0) {
543 if ((err = zip_entry_finalize(zip, entry_mark, n)) < 0) {
549static mz_int64 zip_file_move(MZ_FILE *m_pFile,
const mz_uint64 to,
550 const mz_uint64 from,
const mz_uint64 length,
552 const mz_int64 capacity_size) {
553 if ((mz_int64)length > capacity_size) {
556 if (MZ_FSEEK64(m_pFile, from, SEEK_SET)) {
561 if (fread(move_buf, 1, length, m_pFile) != length) {
565 if (MZ_FSEEK64(m_pFile, to, SEEK_SET)) {
569 if (fwrite(move_buf, 1, length, m_pFile) != length) {
573 return (mz_int64)length;
576static mz_int64 zip_files_move(MZ_FILE *m_pFile, mz_uint64 writen_num,
577 mz_uint64 read_num, mz_uint64 length) {
579 const mz_int64 page_size = 1 << 12;
580 mz_uint8 *move_buf = (mz_uint8 *)calloc(1, page_size);
581 if (move_buf == NULL) {
585 mz_int64 moved_length = 0;
586 mz_int64 move_count = 0;
587 while ((mz_int64)length > 0) {
588 move_count = ((mz_int64)length >= page_size) ? page_size : (mz_int64)length;
589 n = zip_file_move(m_pFile, writen_num, read_num, move_count, move_buf,
596 if (n != move_count) {
600 writen_num += move_count;
601 read_num += move_count;
602 length -= move_count;
603 moved_length += move_count;
612 int end,
int entry_num) {
613 if (begin == entry_num) {
617 mz_uint64 l_size = 0;
618 mz_uint64 r_size = 0;
619 mz_uint64 d_size = 0;
620 mz_uint8 *next = NULL;
621 mz_uint8 *deleted = &MZ_ZIP_ARRAY_ELEMENT(
622 &pState->m_central_dir, mz_uint8,
623 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, begin));
624 l_size = (mz_uint32)(deleted - (mz_uint8 *)(pState->m_central_dir.m_p));
625 if (end == entry_num) {
628 next = &MZ_ZIP_ARRAY_ELEMENT(
629 &pState->m_central_dir, mz_uint8,
630 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, end));
631 r_size = pState->m_central_dir.m_size -
632 (mz_uint32)(next - (mz_uint8 *)(pState->m_central_dir.m_p));
633 d_size = next - deleted;
637 memmove(pState->m_central_dir.m_p, next, r_size);
638 pState->m_central_dir.m_p = MZ_REALLOC(pState->m_central_dir.m_p, r_size);
639 for (
int i = end; i < entry_num; i++) {
640 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i) -=
645 if (l_size * r_size != 0) {
646 memmove(deleted, next, r_size);
647 for (
int i = end; i < entry_num; i++) {
648 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i) -=
653 pState->m_central_dir.m_size = l_size + r_size;
658 int *deleted_entry_index_array,
664 while (i < entry_num) {
665 while ((!deleted_entry_index_array[i]) && (i < entry_num)) {
670 while ((deleted_entry_index_array[i]) && (i < entry_num)) {
674 zip_central_dir_move(pState, begin, end, entry_num);
678 while (i < entry_num) {
679 while ((!deleted_entry_index_array[i]) && (i < entry_num)) {
683 if (begin == entry_num) {
686 while ((deleted_entry_index_array[i]) && (i < entry_num)) {
691 for (
int j = end; j < entry_num; j++) {
692 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32,
694 (mz_uint32)MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets,
698 d_num += end - begin;
701 pState->m_central_dir_offsets.m_size =
702 sizeof(mz_uint32) * (entry_num - d_num);
706static int zip_entries_delete_mark(
struct zip_t *zip,
709 mz_uint64 writen_num = 0;
710 mz_uint64 read_num = 0;
711 mz_uint64 deleted_length = 0;
712 mz_uint64 move_length = 0;
714 int deleted_entry_num = 0;
717 mz_bool *deleted_entry_flag_array =
718 (mz_bool *)calloc(entry_num,
sizeof(mz_bool));
719 if (deleted_entry_flag_array == NULL) {
724 zip->archive.m_zip_mode = MZ_ZIP_MODE_WRITING;
726 if (MZ_FSEEK64(pState->m_pFile, 0, SEEK_SET)) {
727 CLEANUP(deleted_entry_flag_array);
731 while (i < entry_num) {
732 while ((entry_mark[i].type == MZ_KEEP) && (i < entry_num)) {
733 writen_num += entry_mark[i].lf_length;
734 read_num = writen_num;
738 while ((entry_mark[i].type == MZ_DELETE) && (i < entry_num)) {
739 deleted_entry_flag_array[i] = MZ_TRUE;
740 read_num += entry_mark[i].lf_length;
741 deleted_length += entry_mark[i].lf_length;
746 while ((entry_mark[i].type == MZ_MOVE) && (i < entry_num)) {
747 move_length += entry_mark[i].lf_length;
748 mz_uint8 *p = &MZ_ZIP_ARRAY_ELEMENT(
749 &pState->m_central_dir, mz_uint8,
750 MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i));
752 CLEANUP(deleted_entry_flag_array);
755 mz_uint32 offset = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
756 offset -= (mz_uint32)deleted_length;
757 MZ_WRITE_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS, offset);
761 n = zip_files_move(pState->m_pFile, writen_num, read_num, move_length);
762 if (n != (mz_int64)move_length) {
763 CLEANUP(deleted_entry_flag_array);
766 writen_num += move_length;
767 read_num += move_length;
770 zip->archive.m_archive_size -= deleted_length;
771 zip->archive.m_total_files = entry_num - deleted_entry_num;
773 zip_central_dir_delete(pState, deleted_entry_flag_array, entry_num);
774 CLEANUP(deleted_entry_flag_array);
776 return deleted_entry_num;
780 struct zip_t *zip = NULL;
782 if (!zipname || strlen(zipname) < 1) {
788 level = MZ_DEFAULT_LEVEL;
789 if ((level & 0xF) > MZ_UBER_COMPRESSION) {
794 zip = (
struct zip_t *)calloc((
size_t)1,
sizeof(
struct zip_t));
798 zip->level = (mz_uint)level;
802 if (!mz_zip_writer_init_file(&(zip->archive), zipname, 0)) {
811 if (!mz_zip_reader_init_file(
812 &(zip->archive), zipname,
813 zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) {
818 if ((mode ==
'a' || mode ==
'd') &&
819 !mz_zip_writer_init_from_reader(&(zip->archive), zipname)) {
820 mz_zip_reader_end(&(zip->archive));
840 mz_zip_writer_finalize_archive(&(zip->archive));
841 zip_archive_truncate(&(zip->archive));
842 mz_zip_writer_end(&(zip->archive));
843 mz_zip_reader_end(&(zip->archive));
850 if (!zip || !zip->archive.m_pState) {
855 return (
int)zip->archive.m_pState->m_zip64;
861 mz_uint num_alignment_padding_bytes, level;
870 return ZIP_EINVENTNAME;
873 entrylen = strlen(entryname);
875 return ZIP_EINVENTNAME;
889 if (zip->entry.name) {
890 CLEANUP(zip->entry.name);
892 zip->entry.name = zip_strrpl(entryname, entrylen,
'\\',
'/');
893 if (!zip->entry.name) {
895 return ZIP_EINVENTNAME;
898 pzip = &(zip->archive);
899 if (pzip->m_zip_mode == MZ_ZIP_MODE_READING) {
901 mz_zip_reader_locate_file(pzip, zip->entry.name, NULL, 0);
902 if (zip->entry.index < 0) {
907 if (!mz_zip_reader_file_stat(pzip, (mz_uint)zip->entry.index, &stats)) {
912 zip->entry.comp_size = stats.m_comp_size;
913 zip->entry.uncomp_size = stats.m_uncomp_size;
914 zip->entry.uncomp_crc32 = stats.m_crc32;
915 zip->entry.offset = stats.m_central_dir_ofs;
916 zip->entry.header_offset = stats.m_local_header_ofs;
917 zip->entry.method = stats.m_method;
918 zip->entry.external_attr = stats.m_external_attr;
920 zip->entry.m_time = stats.m_time;
926 zip->entry.index = (int)zip->archive.m_total_files;
927 zip->entry.comp_size = 0;
928 zip->entry.uncomp_size = 0;
929 zip->entry.uncomp_crc32 = MZ_CRC32_INIT;
930 zip->entry.offset = zip->archive.m_archive_size;
931 zip->entry.header_offset = zip->archive.m_archive_size;
932 memset(zip->entry.header, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE *
sizeof(mz_uint8));
933 zip->entry.method = 0;
936#if MZ_PLATFORM == 3 || MZ_PLATFORM == 19
938 zip->entry.external_attr = (mz_uint32)(0100644) << 16;
940 zip->entry.external_attr = 0;
943 num_alignment_padding_bytes =
944 mz_zip_writer_compute_padding_needed_for_file_alignment(pzip);
946 if (!pzip->m_pState || (pzip->m_zip_mode != MZ_ZIP_MODE_WRITING)) {
951 if (zip->level & MZ_ZIP_FLAG_COMPRESSED_DATA) {
957 if ((pzip->m_total_files == 0xFFFF) ||
958 ((pzip->m_archive_size + num_alignment_padding_bytes +
959 MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
960 entrylen) > 0xFFFFFFFF)) {
965 if (!mz_zip_writer_write_zeros(pzip, zip->entry.offset,
966 num_alignment_padding_bytes +
967 sizeof(zip->entry.header))) {
973 zip->entry.header_offset += num_alignment_padding_bytes;
974 if (pzip->m_file_offset_alignment) {
976 (zip->entry.header_offset & (pzip->m_file_offset_alignment - 1)) == 0);
978 zip->entry.offset += num_alignment_padding_bytes +
sizeof(zip->entry.header);
980 if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, zip->entry.name,
981 entrylen) != entrylen) {
987 zip->entry.offset += entrylen;
988 level = zip->level & 0xF;
990 zip->entry.state.m_pZip = pzip;
991 zip->entry.state.m_cur_archive_file_ofs = zip->entry.offset;
992 zip->entry.state.m_comp_size = 0;
994 if (tdefl_init(&(zip->entry.comp), mz_zip_writer_add_put_buf_callback,
996 (
int)tdefl_create_comp_flags_from_zip_params(
997 (
int)level, -15, MZ_DEFAULT_STRATEGY)) !=
1000 err = ZIP_ETDEFLINIT;
1005 zip->entry.m_time = time(NULL);
1010 CLEANUP(zip->entry.name);
1018 const mz_uint8 *pHeader;
1019 const char *pFilename;
1026 pZip = &(zip->archive);
1027 if (pZip->m_zip_mode != MZ_ZIP_MODE_READING) {
1029 return ZIP_EINVMODE;
1032 if (index < 0 || (mz_uint)index >= pZip->m_total_files) {
1037 if (!(pHeader = &MZ_ZIP_ARRAY_ELEMENT(
1038 &pZip->m_pState->m_central_dir, mz_uint8,
1039 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets,
1040 mz_uint32, index)))) {
1045 namelen = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1046 pFilename = (
const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1059 if (zip->entry.name) {
1060 CLEANUP(zip->entry.name);
1062 zip->entry.name = zip_strrpl(pFilename, namelen,
'\\',
'/');
1063 if (!zip->entry.name) {
1065 return ZIP_EINVENTNAME;
1068 if (!mz_zip_reader_file_stat(pZip, (mz_uint)index, &stats)) {
1072 zip->entry.index = index;
1073 zip->entry.comp_size = stats.m_comp_size;
1074 zip->entry.uncomp_size = stats.m_uncomp_size;
1075 zip->entry.uncomp_crc32 = stats.m_crc32;
1076 zip->entry.offset = stats.m_central_dir_ofs;
1077 zip->entry.header_offset = stats.m_local_header_ofs;
1078 zip->entry.method = stats.m_method;
1079 zip->entry.external_attr = stats.m_external_attr;
1080#ifndef MINIZ_NO_TIME
1081 zip->entry.m_time = stats.m_time;
1092 mz_uint16 dos_time = 0, dos_date = 0;
1101 pzip = &(zip->archive);
1102 if (pzip->m_zip_mode == MZ_ZIP_MODE_READING) {
1106 level = zip->level & 0xF;
1108 done = tdefl_compress_buffer(&(zip->entry.comp),
"", 0, TDEFL_FINISH);
1109 if (done != TDEFL_STATUS_DONE && done != TDEFL_STATUS_OKAY) {
1111 err = ZIP_ETDEFLBUF;
1114 zip->entry.comp_size = zip->entry.state.m_comp_size;
1115 zip->entry.offset = zip->entry.state.m_cur_archive_file_ofs;
1116 zip->entry.method = MZ_DEFLATED;
1119 entrylen = (mz_uint16)strlen(zip->entry.name);
1120 if ((zip->entry.comp_size > 0xFFFFFFFF) || (zip->entry.offset > 0xFFFFFFFF)) {
1126#ifndef MINIZ_NO_TIME
1127 mz_zip_time_t_to_dos_time(zip->entry.m_time, &dos_time, &dos_date);
1130 if (!mz_zip_writer_create_local_dir_header(
1131 pzip, zip->entry.header, entrylen, 0, zip->entry.uncomp_size,
1132 zip->entry.comp_size, zip->entry.uncomp_crc32, zip->entry.method, 0,
1133 dos_time, dos_date)) {
1139 if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.header_offset,
1141 sizeof(zip->entry.header)) !=
sizeof(zip->entry.header)) {
1147 if (!mz_zip_writer_add_to_central_dir(
1148 pzip, zip->entry.name, entrylen, NULL, 0,
"", 0,
1149 zip->entry.uncomp_size, zip->entry.comp_size, zip->entry.uncomp_crc32,
1150 zip->entry.method, 0, dos_time, dos_date, zip->entry.header_offset,
1151 zip->entry.external_attr)) {
1157 pzip->m_total_files++;
1158 pzip->m_archive_size = zip->entry.offset;
1162 zip->entry.m_time = 0;
1163 CLEANUP(zip->entry.name);
1174 return zip->entry.name;
1183 return zip->entry.index;
1192 if (zip->entry.index < 0) {
1197 return (
int)mz_zip_reader_is_file_a_directory(&zip->archive,
1198 (mz_uint)zip->entry.index);
1202 return zip ? zip->entry.uncomp_size : 0;
1206 return zip ? zip->entry.uncomp_crc32 : 0;
1212 tdefl_status status;
1219 pzip = &(zip->archive);
1220 if (buf && bufsize > 0) {
1221 zip->entry.uncomp_size += bufsize;
1222 zip->entry.uncomp_crc32 = (mz_uint32)mz_crc32(
1223 zip->entry.uncomp_crc32, (
const mz_uint8 *)buf, bufsize);
1225 level = zip->level & 0xF;
1227 if ((pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, buf,
1228 bufsize) != bufsize)) {
1232 zip->entry.offset += bufsize;
1233 zip->entry.comp_size += bufsize;
1235 status = tdefl_compress_buffer(&(zip->entry.comp), buf, bufsize,
1237 if (status != TDEFL_STATUS_DONE && status != TDEFL_STATUS_OKAY) {
1239 return ZIP_ETDEFLBUF;
1250 FILE *stream = NULL;
1251 mz_uint8 buf[MZ_ZIP_MAX_IO_BUF_SIZE];
1252 struct MZ_FILE_STAT_STRUCT file_stat;
1259 memset(buf, 0, MZ_ZIP_MAX_IO_BUF_SIZE);
1260 memset((
void *)&file_stat, 0,
sizeof(
struct MZ_FILE_STAT_STRUCT));
1261 if (MZ_FILE_STAT(filename, &file_stat) != 0) {
1266 if ((file_stat.st_mode & 0200) == 0) {
1268 zip->entry.external_attr |= 0x01;
1270 zip->entry.external_attr |= (mz_uint32)((file_stat.st_mode & 0xFFFF) << 16);
1271 zip->entry.m_time = file_stat.st_mtime;
1273#if defined(_MSC_VER)
1274 if (fopen_s(&stream, filename,
"rb"))
1276 if (!(stream = fopen(filename,
"rb")))
1280 return ZIP_EOPNFILE;
1283 while ((n = fread(buf,
sizeof(mz_uint8), MZ_ZIP_MAX_IO_BUF_SIZE, stream)) >
1305 pzip = &(zip->archive);
1306 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
1311 idx = (mz_uint)zip->entry.index;
1312 if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
1314 return ZIP_EINVENTTYPE;
1317 *buf = mz_zip_reader_extract_to_heap(pzip, idx, &size, 0);
1318 if (*buf && bufsize) {
1332 pzip = &(zip->archive);
1333 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
1338 if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index,
1339 buf, bufsize, 0, NULL, 0)) {
1340 return ZIP_EMEMNOALLOC;
1343 return (ssize_t)zip->entry.uncomp_size;
1349 mz_uint32 xattr = 0;
1358 pzip = &(zip->archive);
1359 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
1364 idx = (mz_uint)zip->entry.index;
1365 if (mz_zip_reader_is_file_a_directory(pzip, idx)) {
1367 return ZIP_EINVENTTYPE;
1370 if (!mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) {
1374#if defined(_MSC_VER)
1377 if (!mz_zip_reader_file_stat(pzip, idx, &info)) {
1382 xattr = (info.m_external_attr >> 16) & 0xFFFF;
1384 if (chmod(filename, (mode_t)xattr) < 0) {
1393int zip_entry_extract(
struct zip_t *zip,
1394 size_t (*on_extract)(
void *arg,
unsigned long long offset,
1395 const void *buf,
size_t bufsize),
1405 pzip = &(zip->archive);
1406 if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) {
1411 idx = (mz_uint)zip->entry.index;
1412 return (mz_zip_reader_extract_to_callback(pzip, idx, on_extract, arg, 0))
1423 return (
int)zip->archive.m_total_files;
1432 if (zip == NULL || (entries == NULL && len != 0)) {
1436 if (entries == NULL && len == 0) {
1448 zip->archive.m_zip_mode = MZ_ZIP_MODE_READING;
1450 err = zip_entry_set(zip, entry_mark, n, entries, len);
1452 CLEANUP(entry_mark);
1456 err = zip_entries_delete_mark(zip, entry_mark, n);
1457 CLEANUP(entry_mark);
1462 int (*on_extract)(
const char *filename,
void *arg),
1465 if (!stream || !dir) {
1473 if (!mz_zip_reader_init_mem(&zip_archive, stream, size, 0)) {
1478 return zip_archive_extract(&zip_archive, dir, on_extract, arg);
1483 struct zip_t *zip = (
struct zip_t *)calloc((
size_t)1,
sizeof(
struct zip_t));
1489 level = MZ_DEFAULT_LEVEL;
1491 if ((level & 0xF) > MZ_UBER_COMPRESSION) {
1495 zip->level = (mz_uint)level;
1497 if ((stream != NULL) && (size > 0) && (mode ==
'r')) {
1498 if (!mz_zip_reader_init_mem(&(zip->archive), stream, size, 0)) {
1501 }
else if ((stream == NULL) && (size == 0) && (mode ==
'w')) {
1503 if (!mz_zip_writer_init_heap(&(zip->archive), 0, 1024)) {
1522 zip_archive_finalize(&(zip->archive));
1524 if (bufsize != NULL) {
1525 *bufsize = zip->archive.m_archive_size;
1527 *buf = calloc(
sizeof(
unsigned char), zip->archive.m_archive_size);
1528 memcpy(*buf, zip->archive.m_pState->m_pMem, zip->archive.m_archive_size);
1530 return zip->archive.m_archive_size;
1535 mz_zip_writer_end(&(zip->archive));
1536 mz_zip_reader_end(&(zip->archive));
1541int zip_create(
const char *zipname,
const char *filenames[],
size_t len) {
1545 struct MZ_FILE_STAT_STRUCT file_stat;
1546 mz_uint32 ext_attributes = 0;
1548 if (!zipname || strlen(zipname) < 1) {
1550 return ZIP_EINVZIPNAME;
1554 if (!memset(&(zip_archive), 0,
sizeof(zip_archive))) {
1559 if (!mz_zip_writer_init_file(&zip_archive, zipname, 0)) {
1564 if (!memset((
void *)&file_stat, 0,
sizeof(
struct MZ_FILE_STAT_STRUCT))) {
1568 for (i = 0; i < len; ++i) {
1569 const char *name = filenames[i];
1571 err = ZIP_EINVENTNAME;
1575 if (MZ_FILE_STAT(name, &file_stat) != 0) {
1581 if ((file_stat.st_mode & 0200) == 0) {
1583 ext_attributes |= 0x01;
1585 ext_attributes |= (mz_uint32)((file_stat.st_mode & 0xFFFF) << 16);
1587 if (!mz_zip_writer_add_file(&zip_archive, zip_basename(name), name,
"", 0,
1596 mz_zip_writer_finalize_archive(&zip_archive);
1597 mz_zip_writer_end(&zip_archive);
1602 int (*on_extract)(
const char *filename,
void *arg),
void *arg) {
1605 if (!zipname || !dir) {
1607 return ZIP_EINVZIPNAME;
1616 if (!mz_zip_reader_init_file(&zip_archive, zipname, 0)) {
1621 return zip_archive_extract(&zip_archive, dir, on_extract, arg);
int zip_is64(struct zip_t *zip)
unsigned long long zip_entry_size(struct zip_t *zip)
ssize_t zip_stream_copy(struct zip_t *zip, void **buf, ssize_t *bufsize)
int zip_entry_isdir(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)
void zip_stream_close(struct zip_t *zip)
int zip_entry_fread(struct zip_t *zip, const char *filename)
int zip_entry_index(struct zip_t *zip)
struct zip_t * zip_stream_open(const char *stream, size_t size, int level, char mode)
const char * zip_strerror(int errnum)
int zip_entry_fwrite(struct zip_t *zip, const char *filename)
ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize)
unsigned int zip_entry_crc32(struct zip_t *zip)
#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_openbyindex(struct zip_t *zip, int index)
int zip_extract(const char *zipname, const char *dir, int(*on_extract)(const char *filename, void *arg), void *arg)
int zip_entries_total(struct zip_t *zip)
int zip_entry_close(struct zip_t *zip)
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)
int zip_entries_delete(struct zip_t *zip, char *const entries[], const size_t len)
int zip_stream_extract(const char *stream, size_t size, const char *dir, int(*on_extract)(const char *filename, void *arg), void *arg)