1 /* minizip.c
2    Version 2.8.1, December 1, 2018
3    part of the MiniZip project
4 
5    Copyright (C) 2010-2018 Nathan Moinvaziri
6      https://github.com/nmoinvaz/minizip
7    Copyright (C) 1998-2010 Gilles Vollant
8      https://www.winimage.com/zLibDll/minizip.html
9 
10    This program is distributed under the terms of the same license as zlib.
11    See the accompanying LICENSE file for the full text of the license.
12 */
13 
14 
15 #include "mz.h"
16 #include "mz_os.h"
17 #include "mz_strm.h"
18 #include "mz_strm_buf.h"
19 #include "mz_strm_split.h"
20 #include "mz_zip.h"
21 #include "mz_zip_rw.h"
22 
23 #include <stdio.h>  /* printf */
24 
25 /***************************************************************************/
26 
27 typedef struct minizip_opt_s {
28     uint8_t     include_path;
29     int16_t     compress_level;
30     uint8_t     compress_method;
31     uint8_t     overwrite;
32     uint8_t     append;
33     int64_t     disk_size;
34     uint8_t     zip_cd;
35     int32_t     encoding;
36     uint8_t     verbose;
37     uint8_t     aes;
38     const char *cert_path;
39     const char *cert_pwd;
40 } minizip_opt;
41 
42 /***************************************************************************/
43 
44 int32_t minizip_banner(void);
45 int32_t minizip_help(void);
46 
47 int32_t minizip_list(const char *path);
48 
49 int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info);
50 int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
51 int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path);
52 int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, const char **args);
53 
54 int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
55 int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
56 int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
57 int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, minizip_opt *options);
58 
59 int32_t minizip_erase(const char *src_path, const char *target_path, int32_t arg_count, const char **args);
60 
61 /***************************************************************************/
62 
minizip_banner(void)63 int32_t minizip_banner(void)
64 {
65     printf("Minizip %s - https://github.com/nmoinvaz/minizip\n", MZ_VERSION);
66     printf("---------------------------------------------------\n");
67     return MZ_OK;
68 }
69 
minizip_help(void)70 int32_t minizip_help(void)
71 {
72     printf("Usage : minizip [-x -d dir|-l|-e] [-o] [-c codepage] [-a] [-j] [-0 to -9] [-b|-m] [-k 512] [-p pwd] [-s] file.zip [files]\n\n" \
73            "  -x  Extract files\n" \
74            "  -l  List files\n" \
75            "  -d  Destination directory\n" \
76            "  -o  Overwrite existing files\n" \
77            "  -c  File names use cp437 encoding\n" \
78            "  -a  Append to existing zip file\n" \
79            "  -i  Include full path of files\n" \
80            "  -v  Verbose info\n" \
81            "  -0  Store only\n" \
82            "  -1  Compress faster\n" \
83            "  -9  Compress better\n" \
84            "  -k  Disk size in KB\n" \
85            "  -z  Zip central directory\n" \
86            "  -p  Encryption password\n" \
87            "  -s  AES encryption\n" \
88            "  -h  Pkcs12 certificate path\n" \
89            "  -w  Pkcs12 certificate password\n" \
90            "  -b  BZIP2 compression\n" \
91            "  -m  LZMA compression\n\n");
92     return MZ_OK;
93 }
94 
95 /***************************************************************************/
96 
minizip_list(const char * path)97 int32_t minizip_list(const char *path)
98 {
99     mz_zip_file *file_info = NULL;
100     uint32_t ratio = 0;
101     int16_t level = 0;
102     int32_t err = MZ_OK;
103     struct tm tmu_date;
104     const char *string_method = NULL;
105     char crypt = ' ';
106     void *reader = NULL;
107 
108 
109     mz_zip_reader_create(&reader);
110     err = mz_zip_reader_open_file(reader, path);
111     if (err != MZ_OK)
112     {
113         printf("Error %"PRId32" opening zip file %s\n", err, path);
114         mz_zip_reader_delete(&reader);
115         return err;
116     }
117 
118     err = mz_zip_reader_goto_first_entry(reader);
119 
120     if (err != MZ_OK && err != MZ_END_OF_LIST)
121     {
122         printf("Error %"PRId32" going to first entry in zip file\n", err);
123         mz_zip_reader_delete(&reader);
124         return err;
125     }
126 
127     printf("      Packed     Unpacked Ratio Method   Attribs Date     Time  CRC-32     Name\n");
128     printf("      ------     -------- ----- ------   ------- ----     ----  ------     ----\n");
129 
130     /* Enumerate all entries in the zip */
131     do
132     {
133         err = mz_zip_reader_entry_get_info(reader, &file_info);
134 
135         if (err != MZ_OK)
136         {
137             printf("Error %"PRId32" getting entry info in zip file\n", err);
138             break;
139         }
140 
141         ratio = 0;
142         if (file_info->uncompressed_size > 0)
143             ratio = (uint32_t)((file_info->compressed_size * 100) / file_info->uncompressed_size);
144 
145         /* Display a '*' if the file is encrypted */
146         if (file_info->flag & MZ_ZIP_FLAG_ENCRYPTED)
147             crypt = '*';
148 
149         switch (file_info->compression_method)
150         {
151         case MZ_COMPRESS_METHOD_STORE:
152             string_method = "Stored";
153             break;
154         case MZ_COMPRESS_METHOD_DEFLATE:
155             level = (int16_t)((file_info->flag & 0x6) / 2);
156             if (level == 0)
157                 string_method = "Defl:N";
158             else if (level == 1)
159                 string_method = "Defl:X";
160             else if ((level == 2) || (level == 3))
161                 string_method = "Defl:F"; /* 2: fast , 3: extra fast */
162             else
163                 string_method = "Defl:?";
164             break;
165         case MZ_COMPRESS_METHOD_BZIP2:
166             string_method = "BZip2";
167             break;
168         case MZ_COMPRESS_METHOD_LZMA:
169             string_method = "LZMA";
170             break;
171         default:
172             string_method = "?";
173         }
174 
175         mz_zip_time_t_to_tm(file_info->modified_date, &tmu_date);
176 
177         /* Print entry information */
178         printf("%12"PRId64" %12"PRId64"  %3"PRIu32"%% %6s%c %8"PRIx32" %2.2"PRIu32\
179                "-%2.2"PRIu32"-%2.2"PRIu32" %2.2"PRIu32":%2.2"PRIu32" %8.8"PRIx32"   %s\n",
180                 file_info->compressed_size, file_info->uncompressed_size, ratio,
181                 string_method, crypt, file_info->external_fa,
182                 (uint32_t)tmu_date.tm_mon + 1, (uint32_t)tmu_date.tm_mday,
183                 (uint32_t)tmu_date.tm_year % 100,
184                 (uint32_t)tmu_date.tm_hour, (uint32_t)tmu_date.tm_min,
185                 file_info->crc, file_info->filename);
186 
187         err = mz_zip_reader_goto_next_entry(reader);
188 
189         if (err != MZ_OK && err != MZ_END_OF_LIST)
190         {
191             printf("Error %"PRId32" going to next entry in zip file\n", err);
192             break;
193         }
194     }
195     while (err == MZ_OK);
196 
197     mz_zip_reader_delete(&reader);
198 
199     if (err == MZ_END_OF_LIST)
200         return MZ_OK;
201 
202     return err;
203 }
204 
205 /***************************************************************************/
206 
minizip_add_entry_cb(void * handle,void * userdata,mz_zip_file * file_info)207 int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info)
208 {
209     MZ_UNUSED(handle);
210     MZ_UNUSED(userdata);
211 
212     /* Print the current file we are trying to compress */
213     printf("Adding %s\n", file_info->filename);
214     return MZ_OK;
215 }
216 
minizip_add_progress_cb(void * handle,void * userdata,mz_zip_file * file_info,int64_t position)217 int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position)
218 {
219     minizip_opt *options = (minizip_opt *)userdata;
220     double progress = 0;
221     uint8_t raw = 0;
222 
223     MZ_UNUSED(userdata);
224 
225     mz_zip_writer_get_raw(handle, &raw);
226 
227     if (raw && file_info->compressed_size > 0)
228         progress = ((double)position / file_info->compressed_size) * 100;
229     else if (!raw && file_info->uncompressed_size > 0)
230         progress = ((double)position / file_info->uncompressed_size) * 100;
231 
232     /* Print the progress of the current compress operation */
233     if (options->verbose)
234         printf("%s - %"PRId64" / %"PRId64" (%.02f%%)\n", file_info->filename, position,
235             file_info->uncompressed_size, progress);
236     return MZ_OK;
237 }
238 
minizip_add_overwrite_cb(void * handle,void * userdata,const char * path)239 int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path)
240 {
241     minizip_opt *options = (minizip_opt *)userdata;
242 
243     MZ_UNUSED(handle);
244 
245     if (options->overwrite == 0)
246     {
247         /* If ask the user what to do because append and overwrite args not set */
248         char rep = 0;
249         do
250         {
251             char answer[128];
252             printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ", path);
253             if (scanf("%1s", answer) != 1)
254                 exit(EXIT_FAILURE);
255             rep = answer[0];
256 
257             if ((rep >= 'a') && (rep <= 'z'))
258                 rep -= 0x20;
259         }
260         while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
261 
262         if (rep == 'A')
263         {
264             return MZ_EXIST_ERROR;
265         }
266         else if (rep == 'N')
267         {
268             return MZ_INTERNAL_ERROR;
269         }
270     }
271 
272     return MZ_OK;
273 }
274 
minizip_add(const char * path,const char * password,minizip_opt * options,int32_t arg_count,const char ** args)275 int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, const char **args)
276 {
277     void *writer = NULL;
278     int32_t err = MZ_OK;
279     int32_t err_close = MZ_OK;
280     int32_t i = 0;
281     const char *filename_in_zip = NULL;
282 
283 
284     printf("Archive %s\n", path);
285 
286     /* Create zip writer */
287     mz_zip_writer_create(&writer);
288     mz_zip_writer_set_password(writer, password);
289     mz_zip_writer_set_compress_method(writer, options->compress_method);
290     mz_zip_writer_set_compress_level(writer, options->compress_level);
291     mz_zip_writer_set_overwrite_cb(writer, options, minizip_add_overwrite_cb);
292     mz_zip_writer_set_comment(writer, "xyz");
293     mz_zip_writer_set_progress_cb(writer, options, minizip_add_progress_cb);
294     mz_zip_writer_set_entry_cb(writer, options, minizip_add_entry_cb);
295     mz_zip_writer_set_zip_cd(writer, options->zip_cd);
296     if (options->cert_path != NULL)
297         mz_zip_writer_set_certificate(writer, options->cert_path, options->cert_pwd);
298 
299     err = mz_zip_writer_open_file(writer, path, options->disk_size, options->append);
300 
301     if (err == MZ_OK)
302     {
303         for (i = 0; i < arg_count; i += 1)
304         {
305             filename_in_zip = args[i];
306 
307             /* Add file system path to zip */
308             err = mz_zip_writer_add_path(writer, filename_in_zip, NULL, options->include_path, 1);
309             if (err != MZ_OK)
310                 printf("Error %"PRId32" adding path to zip %s\n", err, filename_in_zip);
311         }
312     }
313     else
314     {
315         printf("Error %"PRId32" opening zip for writing\n", err);
316     }
317 
318     err_close = mz_zip_writer_close(writer);
319     if (err_close != MZ_OK)
320     {
321         printf("Error %"PRId32" closing zip for writing %s\n", err_close, path);
322         err = err_close;
323     }
324 
325     mz_zip_writer_delete(&writer);
326     return err;
327 }
328 
329 /***************************************************************************/
330 
minizip_extract_entry_cb(void * handle,void * userdata,mz_zip_file * file_info,const char * path)331 int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path)
332 {
333     MZ_UNUSED(handle);
334     MZ_UNUSED(userdata);
335     MZ_UNUSED(path);
336 
337     /* Print the current entry extracting */
338     printf("Extracting %s\n", file_info->filename);
339     return MZ_OK;
340 }
341 
minizip_extract_progress_cb(void * handle,void * userdata,mz_zip_file * file_info,int64_t position)342 int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position)
343 {
344     minizip_opt *options = (minizip_opt *)userdata;
345     double progress = 0;
346     uint8_t raw = 0;
347 
348     MZ_UNUSED(userdata);
349 
350     mz_zip_reader_get_raw(handle, &raw);
351 
352     if (raw && file_info->compressed_size > 0)
353         progress = ((double)position / file_info->compressed_size) * 100;
354     else if (!raw && file_info->uncompressed_size > 0)
355         progress = ((double)position / file_info->uncompressed_size) * 100;
356 
357     /* Print the progress of the current extraction */
358     if (options->verbose)
359         printf("%s - %"PRId64" / %"PRId64" (%.02f%%)\n", file_info->filename, position,
360             file_info->uncompressed_size, progress);
361 
362     return MZ_OK;
363 }
364 
minizip_extract_overwrite_cb(void * handle,void * userdata,mz_zip_file * file_info,const char * path)365 int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path)
366 {
367     minizip_opt *options = (minizip_opt *)userdata;
368 
369     MZ_UNUSED(handle);
370     MZ_UNUSED(file_info);
371 
372     /* Verify if we want to overwrite current entry on disk */
373     if (options->overwrite == 0)
374     {
375         char rep = 0;
376         do
377         {
378             char answer[128];
379             printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ", path);
380             if (scanf("%1s", answer) != 1)
381                 exit(EXIT_FAILURE);
382             rep = answer[0];
383             if ((rep >= 'a') && (rep <= 'z'))
384                 rep -= 0x20;
385         } while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
386 
387         if (rep == 'N')
388             return MZ_EXIST_ERROR;
389         if (rep == 'A')
390             options->overwrite = 1;
391     }
392 
393     return MZ_OK;
394 }
395 
minizip_extract(const char * path,const char * pattern,const char * destination,const char * password,minizip_opt * options)396 int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, minizip_opt *options)
397 {
398     void *reader = NULL;
399     int32_t err = MZ_OK;
400     int32_t err_close = MZ_OK;
401 
402 
403     printf("Archive %s\n", path);
404 
405     /* Create zip reader */
406     mz_zip_reader_create(&reader);
407     mz_zip_reader_set_pattern(reader, pattern, 1);
408     mz_zip_reader_set_password(reader, password);
409     mz_zip_reader_set_encoding(reader, options->encoding);
410     mz_zip_reader_set_entry_cb(reader, options, minizip_extract_entry_cb);
411     mz_zip_reader_set_progress_cb(reader, options, minizip_extract_progress_cb);
412     mz_zip_reader_set_overwrite_cb(reader, options, minizip_extract_overwrite_cb);
413 
414     err = mz_zip_reader_open_file(reader, path);
415 
416     if (err != MZ_OK)
417     {
418         printf("Error %"PRId32" opening zip file %s\n", err, path);
419     }
420     else
421     {
422         /* Save all entries in zip file to destination directory */
423         err = mz_zip_reader_save_all(reader, destination);
424 
425         if (err == MZ_END_OF_LIST && pattern != NULL)
426             printf("Files matching %s not found in zip file\n", pattern);
427         if (err != MZ_OK)
428             printf("Error %"PRId32" saving zip entries to disk %s\n", err, path);
429     }
430 
431     err_close = mz_zip_reader_close(reader);
432     if (err_close != MZ_OK)
433     {
434         printf("Error %"PRId32" closing zip for reading\n", err_close);
435         err = err_close;
436     }
437 
438     mz_zip_reader_delete(&reader);
439     return err;
440 }
441 
442 /***************************************************************************/
443 
minizip_erase(const char * src_path,const char * target_path,int32_t arg_count,const char ** args)444 int32_t minizip_erase(const char *src_path, const char *target_path, int32_t arg_count, const char **args)
445 {
446     mz_zip_file *file_info = NULL;
447     const char *filename_in_zip = NULL;
448     const char *target_path_ptr = target_path;
449     void *reader = NULL;
450     void *writer = NULL;
451     int32_t skip = 0;
452     int32_t err = MZ_OK;
453     int32_t i = 0;
454     uint8_t zip_cd = 0;
455     char bak_path[256];
456     char tmp_path[256];
457 
458     if (target_path == NULL)
459     {
460         /* Construct temporary zip name */
461         strncpy(tmp_path, src_path, sizeof(tmp_path) - 1);
462         tmp_path[sizeof(tmp_path) - 1] = 0;
463         strncat(tmp_path, ".tmp.zip", sizeof(tmp_path) - strlen(tmp_path) - 1);
464         target_path_ptr = tmp_path;
465     }
466 
467     mz_zip_reader_create(&reader);
468     mz_zip_writer_create(&writer);
469 
470     /* Open original zip file we want to erase an entry in */
471     err = mz_zip_reader_open_file(reader, src_path);
472     if (err != MZ_OK)
473     {
474         printf("Error %"PRId32" opening zip for reading %s\n", err, src_path);
475         mz_zip_reader_delete(&reader);
476         return err;
477     }
478 
479     /* Open temporary zip file */
480     err = mz_zip_writer_open_file(writer, target_path_ptr, 0, 0);
481     if (err != MZ_OK)
482     {
483         printf("Error %"PRId32" opening zip for writing %s\n", err, target_path_ptr);
484         mz_zip_reader_delete(&reader);
485         mz_zip_writer_delete(&writer);
486         return err;
487     }
488 
489     err = mz_zip_reader_goto_first_entry(reader);
490 
491     if (err != MZ_OK && err != MZ_END_OF_LIST)
492         printf("Error %"PRId32" going to first entry in zip file\n", err);
493 
494     while (err == MZ_OK)
495     {
496         err = mz_zip_reader_entry_get_info(reader, &file_info);
497         if (err != MZ_OK)
498         {
499             printf("Error %"PRId32" getting info from zip\n", err);
500             break;
501         }
502 
503         /* Copy all entries from original zip file to temporary zip file
504            except the ones we don't want */
505         for (i = 0, skip = 0; i < arg_count; i += 1)
506         {
507             filename_in_zip = args[i];
508 
509             if (mz_path_compare_wc(file_info->filename, filename_in_zip, 1) == MZ_OK)
510                 skip = 1;
511         }
512 
513         if (skip)
514         {
515             printf("Skipping %s\n", file_info->filename);
516         }
517         else
518         {
519             printf("Copying %s\n", file_info->filename);
520             err = mz_zip_writer_copy_from_reader(writer, reader);
521         }
522 
523         if (err != MZ_OK)
524         {
525             printf("Error %"PRId32" copying entry into new zip\n", err);
526             break;
527         }
528 
529         err = mz_zip_reader_goto_next_entry(reader);
530 
531         if (err != MZ_OK && err != MZ_END_OF_LIST)
532             printf("Error %"PRId32" going to next entry in zip file\n", err);
533     }
534 
535     mz_zip_reader_get_zip_cd(reader, &zip_cd);
536     mz_zip_writer_set_zip_cd(writer, zip_cd);
537 
538     mz_zip_reader_close(reader);
539     mz_zip_reader_delete(&reader);
540 
541     mz_zip_writer_close(writer);
542     mz_zip_writer_delete(&writer);
543 
544     if (err == MZ_END_OF_LIST)
545     {
546         if (target_path == NULL)
547         {
548             /* Swap original zip with temporary zip, backup old zip if possible */
549             strncpy(bak_path, src_path, sizeof(bak_path) - 1);
550             bak_path[sizeof(bak_path) - 1] = 0;
551             strncat(bak_path, ".bak", sizeof(bak_path) - strlen(bak_path) - 1);
552 
553             if (mz_os_file_exists(bak_path) == MZ_OK)
554                 mz_os_delete(bak_path);
555 
556             if (mz_os_rename(src_path, bak_path) != MZ_OK)
557                 printf("Error backing up zip before replacing %s\n", bak_path);
558 
559             if (mz_os_rename(tmp_path, src_path) != MZ_OK)
560                 printf("Error replacing zip with temp %s\n", tmp_path);
561         }
562 
563         return MZ_OK;
564     }
565 
566     return err;
567 }
568 
569 /***************************************************************************/
570 
571 #if !defined(MZ_ZIP_NO_MAIN)
main(int argc,const char * argv[])572 int main(int argc, const char *argv[])
573 {
574     minizip_opt options;
575     int32_t path_arg = 0;
576     int32_t err = 0;
577     int32_t i = 0;
578     uint8_t do_list = 0;
579     uint8_t do_extract = 0;
580     uint8_t do_erase = 0;
581     const char *path = NULL;
582     const char *password = NULL;
583     const char *destination = NULL;
584     const char *filename_to_extract = NULL;
585 
586 
587     minizip_banner();
588     if (argc == 1)
589     {
590         minizip_help();
591         return 0;
592     }
593 
594     memset(&options, 0, sizeof(options));
595 
596     options.compress_method = MZ_COMPRESS_METHOD_DEFLATE;
597     options.compress_level = MZ_COMPRESS_LEVEL_DEFAULT;
598 
599     /* Parse command line options */
600     for (i = 1; i < argc; i += 1)
601     {
602         printf("%s ", argv[i]);
603         if (argv[i][0] == '-')
604         {
605             char c = argv[i][1];
606             if ((c == 'l') || (c == 'L'))
607                 do_list = 1;
608             else if ((c == 'x') || (c == 'X'))
609                 do_extract = 1;
610             else if ((c == 'e') || (c == 'E'))
611                 do_erase = 1;
612             else if ((c == 'a') || (c == 'A'))
613                 options.append = 1;
614             else if ((c == 'o') || (c == 'O'))
615                 options.overwrite = 1;
616             else if ((c == 'i') || (c == 'I'))
617                 options.include_path = 1;
618             else if ((c == 'z') || (c == 'Z'))
619                 options.zip_cd = 1;
620             else if ((c == 'v') || (c == 'V'))
621                 options.verbose = 1;
622             else if ((c >= '0') && (c <= '9'))
623             {
624                 options.compress_level = (c - '0');
625                 if (options.compress_level == 0)
626                     options.compress_method = MZ_COMPRESS_METHOD_STORE;
627             }
628             else if ((c == 'b') || (c == 'B'))
629 #ifdef HAVE_BZIP2
630                 options.compress_method = MZ_COMPRESS_METHOD_BZIP2;
631 #else
632                 err = MZ_SUPPORT_ERROR;
633 #endif
634             else if ((c == 'm') || (c == 'M'))
635 #ifdef HAVE_LZMA
636                 options.compress_method = MZ_COMPRESS_METHOD_LZMA;
637 #else
638                 err = MZ_SUPPORT_ERROR;
639 #endif
640             else if ((c == 's') || (c == 'S'))
641 #ifdef HAVE_WZAES
642                 options.aes = 1;
643 #else
644                 err = MZ_SUPPORT_ERROR;
645 #endif
646             else if (((c == 'h') || (c == 'H')) && (i + 1 < argc))
647             {
648 #ifndef MZ_ZIP_NO_SIGNING
649                 options.cert_path = argv[i + 1];
650                 printf("%s ", argv[i + 1]);
651 #else
652                 err = MZ_SUPPORT_ERROR;
653 #endif
654                 i += 1;
655             }
656             else if (((c == 'w') || (c == 'W')) && (i + 1 < argc))
657             {
658 #ifndef MZ_ZIP_NO_SIGNING
659                 options.cert_pwd = argv[i + 1];
660                 printf("%s ", argv[i + 1]);
661 #else
662                 err = MZ_SUPPORT_ERROR;
663 #endif
664                 i += 1;
665             }
666             else if (((c == 'c') || (c == 'C')) && (i + 1 < argc))
667             {
668                 options.encoding = (int32_t)atoi(argv[i + 1]);
669                 i += 1;
670             }
671             else if (((c == 'k') || (c == 'K')) && (i + 1 < argc))
672             {
673                 options.disk_size = (int64_t)atoi(argv[i + 1]) * 1024;
674                 printf("%s ", argv[i + 1]);
675                 i += 1;
676             }
677             else if (((c == 'd') || (c == 'D')) && (i + 1 < argc))
678             {
679                 destination = argv[i + 1];
680                 printf("%s ", argv[i + 1]);
681                 i += 1;
682             }
683             else if (((c == 'p') || (c == 'P')) && (i + 1 < argc))
684             {
685 #ifndef MZ_ZIP_NO_ENCRYPTION
686                 password = argv[i + 1];
687                 printf("*** ");
688 #else
689                 err = MZ_SUPPORT_ERROR;
690 #endif
691                 i += 1;
692             }
693         }
694         else if (path_arg == 0)
695             path_arg = i;
696     }
697     printf("\n");
698 
699     if (err == MZ_SUPPORT_ERROR)
700     {
701         printf("Feature not supported\n");
702         return err;
703     }
704 
705     if (path_arg == 0)
706     {
707         minizip_help();
708         return 0;
709     }
710 
711 
712     path = argv[path_arg];
713 
714     if (do_list)
715     {
716         /* List zip file contents */
717         err = minizip_list(path);
718     }
719     else if (do_extract)
720     {
721         if (argc > path_arg + 1)
722             filename_to_extract = argv[path_arg + 1];
723 
724         /* Extract zip file*/
725         err = minizip_extract(path, filename_to_extract, destination, password, &options);
726     }
727     else if (do_erase)
728     {
729         /* Erase file from zip */
730         err = minizip_erase(path, NULL, argc - (path_arg + 1), &argv[path_arg + 1]);
731     }
732     else
733     {
734         /* Add files to zip */
735         err = minizip_add(path, password, &options, argc - (path_arg + 1), &argv[path_arg + 1]);
736     }
737 
738 
739     return err;
740 }
741 #endif
742