blob: 01bb559eb8cb6b6270f2b7930e0ec0f2c1af8109 [file] [log] [blame]
Nathan Moinvaziric680ad32014-01-12 14:04:54 -07001/* minizip.c
Nathan Moinvaziridb958942021-01-23 16:18:11 -08002 part of the minizip-ng project
Nathan Moinvaziri35c61022012-01-21 14:53:44 -07003
Nathan Moinvaziridb958942021-01-23 16:18:11 -08004 Copyright (C) 2010-2021 Nathan Moinvaziri
5 https://github.com/zlib-ng/minizip-ng
Nathan Moinvaziric680ad32014-01-12 14:04:54 -07006 Copyright (C) 1998-2010 Gilles Vollant
Viktor Szakats9dea6f22018-10-17 22:39:01 +00007 https://www.winimage.com/zLibDll/minizip.html
Nathan Moinvaziri35c61022012-01-21 14:53:44 -07008
Nathan Moinvaziric680ad32014-01-12 14:04:54 -07009 This program is distributed under the terms of the same license as zlib.
10 See the accompanying LICENSE file for the full text of the license.
Nathan Moinvaziri35c61022012-01-21 14:53:44 -070011*/
12
Nathan Moinvaziri35c61022012-01-21 14:53:44 -070013
Nathan Moinvaziri00cca9f2017-10-16 07:37:11 -070014#include "mz.h"
Nathan Moinvaziriaa323f52017-10-05 23:32:57 -070015#include "mz_os.h"
Nathan Moinvaziri41cfdcb2017-10-04 22:10:11 -070016#include "mz_strm.h"
Nathan Moinvaziri02123b82018-01-02 09:22:38 -080017#include "mz_strm_buf.h"
Nathan Moinvaziri00cca9f2017-10-16 07:37:11 -070018#include "mz_strm_split.h"
Nathan Moinvaziriaa323f52017-10-05 23:32:57 -070019#include "mz_zip.h"
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -070020#include "mz_zip_rw.h"
Nathan Moinvaziri900129b2017-10-04 20:06:25 -070021
Nathan Moinvazirie8496272018-11-21 15:05:58 -080022#include <stdio.h> /* printf */
23
Nathan Moinvaziri900129b2017-10-04 20:06:25 -070024/***************************************************************************/
Nathan Moinvaziri35c61022012-01-21 14:53:44 -070025
Nathan Moinvaziri98047622018-10-08 22:41:16 -070026typedef struct minizip_opt_s {
Nathan Moinvaziri8721aaf2018-11-03 22:58:04 -070027 uint8_t include_path;
28 int16_t compress_level;
29 uint8_t compress_method;
30 uint8_t overwrite;
31 uint8_t append;
32 int64_t disk_size;
Nathan Moinvaziri9cb3cb12019-05-05 12:24:08 -070033 uint8_t follow_links;
Nathan Moinvaziria5a1d5d2019-05-05 20:13:58 -070034 uint8_t store_links;
Nathan Moinvaziri8721aaf2018-11-03 22:58:04 -070035 uint8_t zip_cd;
36 int32_t encoding;
37 uint8_t verbose;
38 uint8_t aes;
Nathan Moinvazirie1f68fc2018-10-23 09:04:04 -070039 const char *cert_path;
40 const char *cert_pwd;
Nathan Moinvaziri98047622018-10-08 22:41:16 -070041} minizip_opt;
42
43/***************************************************************************/
44
45int32_t minizip_banner(void);
46int32_t minizip_help(void);
47
48int32_t minizip_list(const char *path);
49
50int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info);
Nathan Moinvaziri904c4082018-10-08 23:31:21 -070051int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
Nathan Moinvaziri98047622018-10-08 22:41:16 -070052int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path);
53int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, const char **args);
54
55int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
Nathan Moinvaziri904c4082018-10-08 23:31:21 -070056int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
Nathan Moinvaziri98047622018-10-08 22:41:16 -070057int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
58int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, minizip_opt *options);
59
60int32_t minizip_erase(const char *src_path, const char *target_path, int32_t arg_count, const char **args);
61
62/***************************************************************************/
63
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -070064int32_t minizip_banner(void) {
Nathan Moinvaziridb958942021-01-23 16:18:11 -080065 printf("minizip-ng %s - https://github.com/zlib-ng/minizip-ng\n", MZ_VERSION);
Nathan Moinvaziri973457d2017-10-05 18:45:23 -070066 printf("---------------------------------------------------\n");
Nathan Moinvaziri98047622018-10-08 22:41:16 -070067 return MZ_OK;
Nathan Moinvaziri35c61022012-01-21 14:53:44 -070068}
69
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -070070int32_t minizip_help(void) {
Nathan Moinvaziri1f4758b2020-06-14 21:52:55 -070071 printf("Usage: minizip [-x][-d dir|-l|-e][-o][-f][-y][-c cp][-a][-0 to -9][-b|-m|-t][-k 512][-p pwd][-s] file.zip [files]\n\n" \
Nathan Moinvaziria66cc312017-10-18 16:51:10 -070072 " -x Extract files\n" \
73 " -l List files\n" \
74 " -d Destination directory\n" \
Nathan Moinvaziri3f1d2a42020-06-14 14:56:37 -070075 " -e Erase files\n" \
Nathan Moinvaziria66cc312017-10-18 16:51:10 -070076 " -o Overwrite existing files\n" \
Nathan Moinvaziria5a1d5d2019-05-05 20:13:58 -070077 " -c File names use cp437 encoding (or specified codepage)\n" \
Nathan Moinvaziria66cc312017-10-18 16:51:10 -070078 " -a Append to existing zip file\n" \
Nathan Moinvazirie33916b2018-05-01 13:45:08 -070079 " -i Include full path of files\n" \
Nathan Moinvaziri9cb3cb12019-05-05 12:24:08 -070080 " -f Follow symbolic links\n" \
Nathan Moinvaziria5a1d5d2019-05-05 20:13:58 -070081 " -y Store symbolic links\n" \
Nathan Moinvaziricce11ba2018-10-27 08:31:01 -070082 " -v Verbose info\n" \
Nathan Moinvaziria66cc312017-10-18 16:51:10 -070083 " -0 Store only\n" \
84 " -1 Compress faster\n" \
85 " -9 Compress better\n" \
86 " -k Disk size in KB\n" \
Nathan Moinvaziriea5e45d2018-10-30 13:59:17 -070087 " -z Zip central directory\n" \
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -080088 " -p Encryption password\n" \
89 " -s AES encryption\n" \
Nathan Moinvazirid484eca2019-02-13 09:08:59 -080090 " -h PKCS12 certificate path\n" \
91 " -w PKCS12 certificate password\n" \
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -080092 " -b BZIP2 compression\n" \
Nathan Moinvaziri1f4758b2020-06-14 21:52:55 -070093 " -m LZMA compression\n" \
Nathan Moinvaziric4668ed2020-10-25 11:56:19 -070094 " -n XZ compression\n" \
Nathan Moinvaziri1f4758b2020-06-14 21:52:55 -070095 " -t ZSTD compression\n\n");
Nathan Moinvaziri98047622018-10-08 22:41:16 -070096 return MZ_OK;
Nathan Moinvaziri35c61022012-01-21 14:53:44 -070097}
98
Nathan Moinvaziri900129b2017-10-04 20:06:25 -070099/***************************************************************************/
100
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700101int32_t minizip_list(const char *path) {
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700102 mz_zip_file *file_info = NULL;
103 uint32_t ratio = 0;
Nathan Moinvaziri5f9e5d32017-10-20 07:59:39 -0700104 int32_t err = MZ_OK;
Nathan Moinvazirie33916b2018-05-01 13:45:08 -0700105 struct tm tmu_date;
Nathan Moinvaziric4668ed2020-10-25 11:56:19 -0700106 const char *method = NULL;
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700107 char crypt = ' ';
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700108 void *reader = NULL;
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700109
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700110
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700111 mz_zip_reader_create(&reader);
112 err = mz_zip_reader_open_file(reader, path);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700113 if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700114 printf("Error %" PRId32 " opening archive %s\n", err, path);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700115 mz_zip_reader_delete(&reader);
116 return err;
117 }
118
Nathan Moinvaziri9f863b32018-08-14 09:20:17 -0700119 err = mz_zip_reader_goto_first_entry(reader);
Viktor Szakatse7215072018-09-04 15:06:53 +0000120
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700121 if (err != MZ_OK && err != MZ_END_OF_LIST) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700122 printf("Error %" PRId32 " going to first entry in archive\n", err);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700123 mz_zip_reader_delete(&reader);
Nathan Moinvaziria9002ab2017-10-26 08:07:16 -0700124 return err;
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700125 }
Nathan Moinvaziria9002ab2017-10-26 08:07:16 -0700126
Nathan Moinvaziri2ff079d2018-11-07 20:07:13 -0800127 printf(" Packed Unpacked Ratio Method Attribs Date Time CRC-32 Name\n");
128 printf(" ------ -------- ----- ------ ------- ---- ---- ------ ----\n");
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700129
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800130 /* Enumerate all entries in the archive */
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700131 do {
Nathan Moinvaziri829ffb52018-08-14 14:00:16 -0700132 err = mz_zip_reader_entry_get_info(reader, &file_info);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700133
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700134 if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700135 printf("Error %" PRId32 " getting entry info in archive\n", err);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700136 break;
137 }
138
Nathan Moinvaziri9a3ae752018-05-02 09:54:44 -0700139 ratio = 0;
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700140 if (file_info->uncompressed_size > 0)
141 ratio = (uint32_t)((file_info->compressed_size * 100) / file_info->uncompressed_size);
Viktor Szakats915b82e2018-04-24 10:02:39 +0000142
Nathan Moinvazirib16ab562018-11-20 16:56:21 -0800143 /* Display a '*' if the file is encrypted */
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700144 if (file_info->flag & MZ_ZIP_FLAG_ENCRYPTED)
145 crypt = '*';
Nathan Moinvazirie7ede972019-01-16 11:15:00 -0800146 else
147 crypt = ' ';
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700148
Nathan Moinvaziric4668ed2020-10-25 11:56:19 -0700149 method = mz_zip_get_compression_method_string(file_info->compression_method);
Nathan Moinvaziri9eab88e2017-10-22 14:32:37 -0700150 mz_zip_time_t_to_tm(file_info->modified_date, &tmu_date);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700151
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800152 /* Print entry information */
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700153 printf("%12" PRId64 " %12" PRId64 " %3" PRIu32 "%% %6s%c %8" PRIx32 " %2.2" PRIu32 \
154 "-%2.2" PRIu32 "-%2.2" PRIu32 " %2.2" PRIu32 ":%2.2" PRIu32 " %8.8" PRIx32 " %s\n",
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700155 file_info->compressed_size, file_info->uncompressed_size, ratio,
Nathan Moinvaziric4668ed2020-10-25 11:56:19 -0700156 method, crypt, file_info->external_fa,
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700157 (uint32_t)tmu_date.tm_mon + 1, (uint32_t)tmu_date.tm_mday,
158 (uint32_t)tmu_date.tm_year % 100,
159 (uint32_t)tmu_date.tm_hour, (uint32_t)tmu_date.tm_min,
160 file_info->crc, file_info->filename);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700161
Nathan Moinvaziri9f863b32018-08-14 09:20:17 -0700162 err = mz_zip_reader_goto_next_entry(reader);
Nathan Moinvaziric7855492017-10-23 18:58:56 -0700163
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700164 if (err != MZ_OK && err != MZ_END_OF_LIST) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700165 printf("Error %" PRId32 " going to next entry in archive\n", err);
Nathan Moinvaziricfa2e602018-08-13 23:29:11 -0700166 break;
Nathan Moinvaziria9002ab2017-10-26 08:07:16 -0700167 }
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700168 } while (err == MZ_OK);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700169
170 mz_zip_reader_delete(&reader);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700171
172 if (err == MZ_END_OF_LIST)
173 return MZ_OK;
174
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700175 return err;
176}
177
178/***************************************************************************/
179
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700180int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info) {
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700181 MZ_UNUSED(handle);
182 MZ_UNUSED(userdata);
Nathan Moinvaziri32fd8052019-07-04 10:32:02 -0700183
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800184 /* Print the current file we are trying to compress */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700185 printf("Adding %s\n", file_info->filename);
186 return MZ_OK;
187}
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700188
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700189int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position) {
Nathan Moinvaziri13d9e762018-10-26 23:01:24 -0700190 minizip_opt *options = (minizip_opt *)userdata;
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700191 double progress = 0;
192 uint8_t raw = 0;
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700193
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700194 MZ_UNUSED(userdata);
Nathan Moinvaziri32fd8052019-07-04 10:32:02 -0700195
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700196 mz_zip_writer_get_raw(handle, &raw);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700197
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700198 if (raw && file_info->compressed_size > 0)
199 progress = ((double)position / file_info->compressed_size) * 100;
200 else if (!raw && file_info->uncompressed_size > 0)
201 progress = ((double)position / file_info->uncompressed_size) * 100;
202
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800203 /* Print the progress of the current compress operation */
Nathan Moinvaziricce11ba2018-10-27 08:31:01 -0700204 if (options->verbose)
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700205 printf("%s - %" PRId64 " / %" PRId64 " (%.02f%%)\n", file_info->filename, position,
Nathan Moinvaziri13d9e762018-10-26 23:01:24 -0700206 file_info->uncompressed_size, progress);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700207 return MZ_OK;
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700208}
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700209
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700210int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path) {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700211 minizip_opt *options = (minizip_opt *)userdata;
212
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700213 MZ_UNUSED(handle);
Nathan Moinvaziri32fd8052019-07-04 10:32:02 -0700214
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700215 if (options->overwrite == 0) {
Nathan Moinvazirib16ab562018-11-20 16:56:21 -0800216 /* If ask the user what to do because append and overwrite args not set */
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700217 char rep = 0;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700218 do {
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700219 char answer[128];
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700220 printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ", path);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700221 if (scanf("%1s", answer) != 1)
222 exit(EXIT_FAILURE);
223 rep = answer[0];
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700224
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700225 if ((rep >= 'a') && (rep <= 'z'))
226 rep -= 0x20;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700227 } while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700228
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700229 if (rep == 'A') {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700230 return MZ_EXIST_ERROR;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700231 } else if (rep == 'N') {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700232 return MZ_INTERNAL_ERROR;
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700233 }
234 }
235
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700236 return MZ_OK;
237}
238
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700239int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, const char **args) {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700240 void *writer = NULL;
241 int32_t err = MZ_OK;
242 int32_t err_close = MZ_OK;
243 int32_t i = 0;
244 const char *filename_in_zip = NULL;
245
246
247 printf("Archive %s\n", path);
248
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800249 /* Create zip writer */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700250 mz_zip_writer_create(&writer);
251 mz_zip_writer_set_password(writer, password);
Nathan Moinvaziri808ba3b2020-10-13 11:18:46 -0700252 mz_zip_writer_set_aes(writer, options->aes);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700253 mz_zip_writer_set_compress_method(writer, options->compress_method);
254 mz_zip_writer_set_compress_level(writer, options->compress_level);
Nathan Moinvaziri9cb3cb12019-05-05 12:24:08 -0700255 mz_zip_writer_set_follow_links(writer, options->follow_links);
Nathan Moinvaziria5a1d5d2019-05-05 20:13:58 -0700256 mz_zip_writer_set_store_links(writer, options->store_links);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700257 mz_zip_writer_set_overwrite_cb(writer, options, minizip_add_overwrite_cb);
258 mz_zip_writer_set_progress_cb(writer, options, minizip_add_progress_cb);
Nathan Moinvaziricb9c40c2018-10-27 15:32:28 -0700259 mz_zip_writer_set_entry_cb(writer, options, minizip_add_entry_cb);
Nathan Moinvaziri37b4da02018-10-27 18:19:18 -0700260 mz_zip_writer_set_zip_cd(writer, options->zip_cd);
Nathan Moinvazirie1f68fc2018-10-23 09:04:04 -0700261 if (options->cert_path != NULL)
Nathan Moinvaziri648f5962018-10-25 19:35:50 -0700262 mz_zip_writer_set_certificate(writer, options->cert_path, options->cert_pwd);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700263
264 err = mz_zip_writer_open_file(writer, path, options->disk_size, options->append);
265
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700266 if (err == MZ_OK) {
267 for (i = 0; i < arg_count; i += 1) {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700268 filename_in_zip = args[i];
269
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800270 /* Add file system path to archive */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700271 err = mz_zip_writer_add_path(writer, filename_in_zip, NULL, options->include_path, 1);
272 if (err != MZ_OK)
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700273 printf("Error %" PRId32 " adding path to archive %s\n", err, filename_in_zip);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700274 }
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700275 } else {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700276 printf("Error %" PRId32 " opening archive for writing\n", err);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700277 }
Viktor Szakatse7215072018-09-04 15:06:53 +0000278
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700279 err_close = mz_zip_writer_close(writer);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700280 if (err_close != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700281 printf("Error %" PRId32 " closing archive for writing %s\n", err_close, path);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700282 err = err_close;
283 }
284
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700285 mz_zip_writer_delete(&writer);
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700286 return err;
287}
288
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700289/***************************************************************************/
290
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700291int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path) {
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700292 MZ_UNUSED(handle);
293 MZ_UNUSED(userdata);
294 MZ_UNUSED(path);
Nathan Moinvaziri32fd8052019-07-04 10:32:02 -0700295
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800296 /* Print the current entry extracting */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700297 printf("Extracting %s\n", file_info->filename);
298 return MZ_OK;
299}
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700300
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700301int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position) {
Nathan Moinvaziri13d9e762018-10-26 23:01:24 -0700302 minizip_opt *options = (minizip_opt *)userdata;
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700303 double progress = 0;
304 uint8_t raw = 0;
Viktor Szakatse7215072018-09-04 15:06:53 +0000305
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700306 MZ_UNUSED(userdata);
Nathan Moinvaziri32fd8052019-07-04 10:32:02 -0700307
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700308 mz_zip_reader_get_raw(handle, &raw);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700309
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700310 if (raw && file_info->compressed_size > 0)
311 progress = ((double)position / file_info->compressed_size) * 100;
312 else if (!raw && file_info->uncompressed_size > 0)
313 progress = ((double)position / file_info->uncompressed_size) * 100;
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700314
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800315 /* Print the progress of the current extraction */
Nathan Moinvaziricce11ba2018-10-27 08:31:01 -0700316 if (options->verbose)
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700317 printf("%s - %" PRId64 " / %" PRId64 " (%.02f%%)\n", file_info->filename, position,
Nathan Moinvaziri13d9e762018-10-26 23:01:24 -0700318 file_info->uncompressed_size, progress);
319
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700320 return MZ_OK;
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700321}
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700322
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700323int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path) {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700324 minizip_opt *options = (minizip_opt *)userdata;
325
Nathan Moinvaziri98047622018-10-08 22:41:16 -0700326 MZ_UNUSED(handle);
327 MZ_UNUSED(file_info);
Nathan Moinvaziri32fd8052019-07-04 10:32:02 -0700328
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800329 /* Verify if we want to overwrite current entry on disk */
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700330 if (options->overwrite == 0) {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700331 char rep = 0;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700332 do {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700333 char answer[128];
334 printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ", path);
335 if (scanf("%1s", answer) != 1)
336 exit(EXIT_FAILURE);
337 rep = answer[0];
338 if ((rep >= 'a') && (rep <= 'z'))
339 rep -= 0x20;
340 } while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700341
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700342 if (rep == 'N')
343 return MZ_EXIST_ERROR;
344 if (rep == 'A')
345 options->overwrite = 1;
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700346 }
347
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700348 return MZ_OK;
349}
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700350
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700351int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, minizip_opt *options) {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700352 void *reader = NULL;
353 int32_t err = MZ_OK;
354 int32_t err_close = MZ_OK;
355
356
357 printf("Archive %s\n", path);
358
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800359 /* Create zip reader */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700360 mz_zip_reader_create(&reader);
361 mz_zip_reader_set_pattern(reader, pattern, 1);
362 mz_zip_reader_set_password(reader, password);
Nathan Moinvaziriea5e45d2018-10-30 13:59:17 -0700363 mz_zip_reader_set_encoding(reader, options->encoding);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700364 mz_zip_reader_set_entry_cb(reader, options, minizip_extract_entry_cb);
365 mz_zip_reader_set_progress_cb(reader, options, minizip_extract_progress_cb);
366 mz_zip_reader_set_overwrite_cb(reader, options, minizip_extract_overwrite_cb);
367
368 err = mz_zip_reader_open_file(reader, path);
369
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700370 if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700371 printf("Error %" PRId32 " opening archive %s\n", err, path);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700372 } else {
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800373 /* Save all entries in archive to destination directory */
Nathan Moinvaziri37b4da02018-10-27 18:19:18 -0700374 err = mz_zip_reader_save_all(reader, destination);
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800375
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700376 if (err == MZ_END_OF_LIST) {
377 if (pattern != NULL) {
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800378 printf("Files matching %s not found in archive\n", pattern);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700379 } else {
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800380 printf("No files in archive\n");
381 err = MZ_OK;
382 }
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700383 } else if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700384 printf("Error %" PRId32 " saving entries to disk %s\n", err, path);
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800385 }
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700386 }
Nathan Moinvazirifa620e42018-10-20 10:37:10 -0700387
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700388 err_close = mz_zip_reader_close(reader);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700389 if (err_close != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700390 printf("Error %" PRId32 " closing archive for reading\n", err_close);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700391 err = err_close;
392 }
393
394 mz_zip_reader_delete(&reader);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700395 return err;
396}
397
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700398/***************************************************************************/
399
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700400int32_t minizip_erase(const char *src_path, const char *target_path, int32_t arg_count, const char **args) {
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700401 mz_zip_file *file_info = NULL;
402 const char *filename_in_zip = NULL;
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800403 const char *target_path_ptr = target_path;
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700404 void *reader = NULL;
405 void *writer = NULL;
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800406 int32_t skip = 0;
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700407 int32_t err = MZ_OK;
408 int32_t i = 0;
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800409 uint8_t zip_cd = 0;
410 char bak_path[256];
411 char tmp_path[256];
412
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700413 if (target_path == NULL) {
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800414 /* Construct temporary zip name */
415 strncpy(tmp_path, src_path, sizeof(tmp_path) - 1);
416 tmp_path[sizeof(tmp_path) - 1] = 0;
417 strncat(tmp_path, ".tmp.zip", sizeof(tmp_path) - strlen(tmp_path) - 1);
418 target_path_ptr = tmp_path;
419 }
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700420
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700421 mz_zip_reader_create(&reader);
422 mz_zip_writer_create(&writer);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700423
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800424 /* Open original archive we want to erase an entry in */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700425 err = mz_zip_reader_open_file(reader, src_path);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700426 if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700427 printf("Error %" PRId32 " opening archive for reading %s\n", err, src_path);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700428 mz_zip_reader_delete(&reader);
429 return err;
430 }
431
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800432 /* Open temporary archive */
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800433 err = mz_zip_writer_open_file(writer, target_path_ptr, 0, 0);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700434 if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700435 printf("Error %" PRId32 " opening archive for writing %s\n", err, target_path_ptr);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700436 mz_zip_reader_delete(&reader);
437 mz_zip_writer_delete(&writer);
438 return err;
439 }
440
Nathan Moinvaziri9f863b32018-08-14 09:20:17 -0700441 err = mz_zip_reader_goto_first_entry(reader);
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700442
443 if (err != MZ_OK && err != MZ_END_OF_LIST)
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700444 printf("Error %" PRId32 " going to first entry in archive\n", err);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700445
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700446 while (err == MZ_OK) {
Nathan Moinvaziri829ffb52018-08-14 14:00:16 -0700447 err = mz_zip_reader_entry_get_info(reader, &file_info);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700448 if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700449 printf("Error %" PRId32 " getting info from archive\n", err);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700450 break;
451 }
452
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800453 /* Copy all entries from original archive to temporary archive
Nathan Moinvaziri13a51b92018-11-22 09:15:23 -0800454 except the ones we don't want */
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700455 for (i = 0, skip = 0; i < arg_count; i += 1) {
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700456 filename_in_zip = args[i];
457
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800458 if (mz_path_compare_wc(file_info->filename, filename_in_zip, 1) == MZ_OK)
459 skip = 1;
460 }
461
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700462 if (skip) {
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800463 printf("Skipping %s\n", file_info->filename);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700464 } else {
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800465 printf("Copying %s\n", file_info->filename);
466 err = mz_zip_writer_copy_from_reader(writer, reader);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700467 }
468
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700469 if (err != MZ_OK) {
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700470 printf("Error %" PRId32 " copying entry into new zip\n", err);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700471 break;
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700472 }
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700473
Nathan Moinvaziri9f863b32018-08-14 09:20:17 -0700474 err = mz_zip_reader_goto_next_entry(reader);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700475
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700476 if (err != MZ_OK && err != MZ_END_OF_LIST)
Nathan Moinvazirife33c3d2019-09-16 11:07:43 -0700477 printf("Error %" PRId32 " going to next entry in archive\n", err);
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700478 }
479
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800480 mz_zip_reader_get_zip_cd(reader, &zip_cd);
481 mz_zip_writer_set_zip_cd(writer, zip_cd);
482
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700483 mz_zip_reader_close(reader);
484 mz_zip_reader_delete(&reader);
485
486 mz_zip_writer_close(writer);
487 mz_zip_writer_delete(&writer);
488
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700489 if (err == MZ_END_OF_LIST) {
490 if (target_path == NULL) {
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800491 /* Swap original archive with temporary archive, backup old archive if possible */
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800492 strncpy(bak_path, src_path, sizeof(bak_path) - 1);
493 bak_path[sizeof(bak_path) - 1] = 0;
494 strncat(bak_path, ".bak", sizeof(bak_path) - strlen(bak_path) - 1);
495
496 if (mz_os_file_exists(bak_path) == MZ_OK)
Nathan Moinvaziri3249eac2019-05-02 21:07:39 -0700497 mz_os_unlink(bak_path);
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800498
499 if (mz_os_rename(src_path, bak_path) != MZ_OK)
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800500 printf("Error backing up archive before replacing %s\n", bak_path);
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800501
502 if (mz_os_rename(tmp_path, src_path) != MZ_OK)
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800503 printf("Error replacing archive with temp %s\n", tmp_path);
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800504 }
505
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700506 return MZ_OK;
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800507 }
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700508
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700509 return err;
510}
511
512/***************************************************************************/
513
Nathan Moinvazirie63d2312018-11-03 19:45:41 -0700514#if !defined(MZ_ZIP_NO_MAIN)
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700515int main(int argc, const char *argv[]) {
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700516 minizip_opt options;
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700517 int32_t path_arg = 0;
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700518 int32_t err = 0;
519 int32_t i = 0;
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700520 uint8_t do_list = 0;
521 uint8_t do_extract = 0;
522 uint8_t do_erase = 0;
Nathan Moinvaziric599dd62018-07-31 11:55:32 -0700523 const char *path = NULL;
524 const char *password = NULL;
525 const char *destination = NULL;
526 const char *filename_to_extract = NULL;
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700527
Nathan Moinvaziri900129b2017-10-04 20:06:25 -0700528
Nathan Moinvazirie24ed8d2017-03-18 16:16:06 -0700529 minizip_banner();
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700530 if (argc == 1) {
Nathan Moinvazirie24ed8d2017-03-18 16:16:06 -0700531 minizip_help();
Nathan Moinvaziri35c61022012-01-21 14:53:44 -0700532 return 0;
533 }
Nathan Moinvaziriea5e45d2018-10-30 13:59:17 -0700534
Nathan Moinvaziri77008c62017-10-16 14:50:31 -0700535 memset(&options, 0, sizeof(options));
Nathan Moinvaziri973457d2017-10-05 18:45:23 -0700536
Nathan Moinvaziria66cc312017-10-18 16:51:10 -0700537 options.compress_method = MZ_COMPRESS_METHOD_DEFLATE;
538 options.compress_level = MZ_COMPRESS_LEVEL_DEFAULT;
Nathan Moinvaziri973457d2017-10-05 18:45:23 -0700539
Nathan Moinvazirib16ab562018-11-20 16:56:21 -0800540 /* Parse command line options */
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700541 for (i = 1; i < argc; i += 1) {
Nathan Moinvazirid4f27372018-11-20 09:18:30 -0800542 printf("%s ", argv[i]);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700543 if (argv[i][0] == '-') {
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700544 char c = argv[i][1];
545 if ((c == 'l') || (c == 'L'))
546 do_list = 1;
Nathan Moinvazirib8300ce2018-08-27 08:30:57 -0700547 else if ((c == 'x') || (c == 'X'))
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700548 do_extract = 1;
Nathan Moinvazirib8300ce2018-08-27 08:30:57 -0700549 else if ((c == 'e') || (c == 'E'))
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700550 do_erase = 1;
Nathan Moinvazirib8300ce2018-08-27 08:30:57 -0700551 else if ((c == 'a') || (c == 'A'))
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700552 options.append = 1;
Nathan Moinvazirib8300ce2018-08-27 08:30:57 -0700553 else if ((c == 'o') || (c == 'O'))
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700554 options.overwrite = 1;
Nathan Moinvaziri9cb3cb12019-05-05 12:24:08 -0700555 else if ((c == 'f') || (c == 'F'))
556 options.follow_links = 1;
Nathan Moinvaziria5a1d5d2019-05-05 20:13:58 -0700557 else if ((c == 'y') || (c == 'Y'))
558 options.store_links = 1;
Nathan Moinvazirib8300ce2018-08-27 08:30:57 -0700559 else if ((c == 'i') || (c == 'I'))
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700560 options.include_path = 1;
Nathan Moinvazirifa620e42018-10-20 10:37:10 -0700561 else if ((c == 'z') || (c == 'Z'))
562 options.zip_cd = 1;
Nathan Moinvaziricce11ba2018-10-27 08:31:01 -0700563 else if ((c == 'v') || (c == 'V'))
564 options.verbose = 1;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700565 else if ((c >= '0') && (c <= '9')) {
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700566 options.compress_level = (c - '0');
567 if (options.compress_level == 0)
Nathan Moinvazirid08e1562018-08-08 09:43:14 -0700568 options.compress_method = MZ_COMPRESS_METHOD_STORE;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700569 } else if ((c == 'b') || (c == 'B'))
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800570#ifdef HAVE_BZIP2
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700571 options.compress_method = MZ_COMPRESS_METHOD_BZIP2;
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800572#else
573 err = MZ_SUPPORT_ERROR;
574#endif
Nathan Moinvazirib8300ce2018-08-27 08:30:57 -0700575 else if ((c == 'm') || (c == 'M'))
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800576#ifdef HAVE_LZMA
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700577 options.compress_method = MZ_COMPRESS_METHOD_LZMA;
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800578#else
579 err = MZ_SUPPORT_ERROR;
580#endif
Nathan Moinvazirib7296532020-10-25 12:31:43 -0700581 else if ((c == 'n') || (c == 'N'))
Nathan Moinvaziri1a7e7e42020-10-25 14:50:53 -0700582#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP)
Nathan Moinvaziric4668ed2020-10-25 11:56:19 -0700583 options.compress_method = MZ_COMPRESS_METHOD_XZ;
584#else
585 err = MZ_SUPPORT_ERROR;
586#endif
Nathan Moinvaziri1f4758b2020-06-14 21:52:55 -0700587 else if ((c == 't') || (c == 'T'))
588#ifdef HAVE_ZSTD
589 options.compress_method = MZ_COMPRESS_METHOD_ZSTD;
590#else
591 err = MZ_SUPPORT_ERROR;
592#endif
Nathan Moinvazirib8300ce2018-08-27 08:30:57 -0700593 else if ((c == 's') || (c == 'S'))
Nathan Moinvaziri76fb8902018-11-21 15:14:09 -0800594#ifdef HAVE_WZAES
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700595 options.aes = 1;
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800596#else
597 err = MZ_SUPPORT_ERROR;
598#endif
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700599 else if (((c == 'h') || (c == 'H')) && (i + 1 < argc)) {
Nathan Moinvaziri84a39802019-08-14 20:31:04 -0700600#ifdef MZ_ZIP_SIGNING
Nathan Moinvazirie1f68fc2018-10-23 09:04:04 -0700601 options.cert_path = argv[i + 1];
Nathan Moinvazirid4f27372018-11-20 09:18:30 -0800602 printf("%s ", argv[i + 1]);
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800603#else
604 err = MZ_SUPPORT_ERROR;
605#endif
Nathan Moinvazirie1f68fc2018-10-23 09:04:04 -0700606 i += 1;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700607 } else if (((c == 'w') || (c == 'W')) && (i + 1 < argc)) {
Nathan Moinvaziri84a39802019-08-14 20:31:04 -0700608#ifdef MZ_ZIP_SIGNING
Nathan Moinvazirie1f68fc2018-10-23 09:04:04 -0700609 options.cert_pwd = argv[i + 1];
Nathan Moinvazirid4f27372018-11-20 09:18:30 -0800610 printf("%s ", argv[i + 1]);
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800611#else
612 err = MZ_SUPPORT_ERROR;
613#endif
Nathan Moinvazirie1f68fc2018-10-23 09:04:04 -0700614 i += 1;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700615 } else if (((c == 'c') || (c == 'C')) && (i + 1 < argc)) {
Nathan Moinvaziriea5e45d2018-10-30 13:59:17 -0700616 options.encoding = (int32_t)atoi(argv[i + 1]);
617 i += 1;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700618 } else if (((c == 'k') || (c == 'K')) && (i + 1 < argc)) {
Nathan Moinvaziri85d36c52018-08-31 16:43:41 -0700619 options.disk_size = (int64_t)atoi(argv[i + 1]) * 1024;
Nathan Moinvazirid4f27372018-11-20 09:18:30 -0800620 printf("%s ", argv[i + 1]);
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700621 i += 1;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700622 } else if (((c == 'd') || (c == 'D')) && (i + 1 < argc)) {
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700623 destination = argv[i + 1];
Nathan Moinvazirid4f27372018-11-20 09:18:30 -0800624 printf("%s ", argv[i + 1]);
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700625 i += 1;
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700626 } else if (((c == 'p') || (c == 'P')) && (i + 1 < argc)) {
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800627#ifndef MZ_ZIP_NO_ENCRYPTION
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700628 password = argv[i + 1];
Nathan Moinvaziri783d2582018-11-20 16:57:25 -0800629 printf("*** ");
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800630#else
631 err = MZ_SUPPORT_ERROR;
632#endif
Nathan Moinvaziricb5798a2018-11-04 10:23:50 -0800633 i += 1;
Nathan Moinvaziri9eecff32018-07-08 18:52:41 -0700634 }
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700635 } else if (path_arg == 0)
Nathan Moinvaziri900129b2017-10-04 20:06:25 -0700636 path_arg = i;
Nathan Moinvaziri35c61022012-01-21 14:53:44 -0700637 }
Nathan Moinvazirid4f27372018-11-20 09:18:30 -0800638 printf("\n");
Nathan Moinvaziri32fd8052019-07-04 10:32:02 -0700639
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700640 if (err == MZ_SUPPORT_ERROR) {
Nathan Moinvaziricdef32b2018-11-04 10:21:27 -0800641 printf("Feature not supported\n");
642 return err;
643 }
644
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700645 if (path_arg == 0) {
Nathan Moinvazirie24ed8d2017-03-18 16:16:06 -0700646 minizip_help();
Nathan Moinvaziri0deccb82012-10-25 00:21:50 -0700647 return 0;
648 }
Nathan Moinvaziri900129b2017-10-04 20:06:25 -0700649
650 path = argv[path_arg];
Nathan Moinvaziri0deccb82012-10-25 00:21:50 -0700651
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700652 if (do_list) {
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800653 /* List archive contents */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700654 err = minizip_list(path);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700655 } else if (do_extract) {
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700656 if (argc > path_arg + 1)
657 filename_to_extract = argv[path_arg + 1];
658
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800659 /* Extract archive */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700660 err = minizip_extract(path, filename_to_extract, destination, password, &options);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700661 } else if (do_erase) {
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800662 /* Erase file in archive */
Nathan Moinvaziriba1db162018-11-23 10:07:35 -0800663 err = minizip_erase(path, NULL, argc - (path_arg + 1), &argv[path_arg + 1]);
Nathan Moinvaziridc6962b2020-06-14 15:19:14 -0700664 } else {
Nathan Moinvazirid484eca2019-02-13 09:08:59 -0800665 /* Add files to archive */
Nathan Moinvaziri9a170d42018-08-13 23:07:42 -0700666 err = minizip_add(path, password, &options, argc - (path_arg + 1), &argv[path_arg + 1]);
Nathan Moinvaziri02123b82018-01-02 09:22:38 -0800667 }
Viktor Szakats915b82e2018-04-24 10:02:39 +0000668
Nathan Moinvaziri7679d212018-07-31 10:20:21 -0700669 return err;
Nathan Moinvaziric65c7a92018-07-31 14:43:30 -0700670}
Nathan Moinvaziri1b3ce712018-09-10 08:51:33 -0700671#endif