forked from cysin/info-zip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
zip.c
6007 lines (5609 loc) · 188 KB
/
zip.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
zip.c - Zip 3
Copyright 2023, dSPACE GmbH. All rights reserved
Based on info-zip (Copyright (c) 1990-2008 Info-ZIP)
Mofifications:
- Removed option -T (test zip archive)
- Removed option -TT (provide command to use for -T)
This fixes the following vulnurability:
https://nvd.nist.gov/vuln/detail/CVE-2018-13410
*/
/*
* zip.c by Mark Adler.
*/
#define __ZIP_C
#include "zip.h"
#include <time.h> /* for tzset() declaration */
#if defined(WIN32) || defined(WINDLL)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
#ifdef WINDLL
# include <setjmp.h>
# include "windll/windll.h"
#endif
#define DEFCPYRT /* main module: enable copyright string defines! */
#include "revision.h"
#include "crc32.h"
#include "crypt.h"
#include "ttyio.h"
#include <ctype.h>
#include <errno.h>
#ifdef VMS
# include <stsdef.h>
# include "vms/vmsmunch.h"
# include "vms/vms.h"
#endif
#ifdef MACOS
# include "macglob.h"
extern MacZipGlobals MacZip;
extern int error_level;
#endif
#if (defined(MSDOS) && !defined(__GO32__)) || defined(__human68k__)
# include <process.h>
# if (!defined(P_WAIT) && defined(_P_WAIT))
# define P_WAIT _P_WAIT
# endif
#endif
#include <signal.h>
#include <stdio.h>
#ifdef UNICODE_TEST
# ifdef WIN32
# include <direct.h>
# endif
#endif
#ifdef BZIP2_SUPPORT
/* If IZ_BZIP2 is defined as the location of the bzip2 files then
assume the location has been added to include path. For Unix
this is done by the configure script. */
/* Also do not need path for bzip2 include if OS includes support
for bzip2 library. */
# include "bzlib.h"
#endif
#define MAXCOM 256 /* Maximum one-line comment size */
/* Local option flags */
#ifndef DELETE
#define DELETE 0
#endif
#define ADD 1
#define UPDATE 2
#define FRESHEN 3
#define ARCHIVE 4
local int action = ADD; /* one of ADD, UPDATE, FRESHEN, DELETE, or ARCHIVE */
local int comadd = 0; /* 1=add comments for new files */
local int zipedit = 0; /* 1=edit zip comment and all file comments */
local int latest = 0; /* 1=set zip file time to time of latest file */
local int test = 0; /* 1=test zip file with unzip -t */
local char *unzip_path = NULL; /* where to find unzip */
local int tempdir = 0; /* 1=use temp directory (-b) */
local int junk_sfx = 0; /* 1=junk the sfx prefix */
#if defined(AMIGA) || defined(MACOS)
local int filenotes = 0; /* 1=take comments from AmigaDOS/MACOS filenotes */
#endif
#ifdef EBCDIC
int aflag = __EBCDIC; /* Convert EBCDIC to ASCII or stay EBCDIC ? */
#endif
#ifdef CMS_MVS
int bflag = 0; /* Use text mode as default */
#endif
#ifdef QDOS
char _version[] = VERSION;
#endif
#ifdef WINDLL
jmp_buf zipdll_error_return;
#ifdef ZIP64_SUPPORT
unsigned long low, high; /* returning 64 bit values for systems without an _int64 */
uzoff_t filesize64;
#endif
#endif
#if CRYPT
/* Pointer to crc_table, needed in crypt.c */
# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
ZCONST ulg near *crc_32_tab;
# else
ZCONST uLongf *crc_32_tab;
# endif
#endif /* CRYPT */
/* Local functions */
local void freeup OF((void));
local int finish OF((int));
#if (!defined(MACOS) && !defined(WINDLL))
local void handler OF((int));
local void license OF((void));
#ifndef VMSCLI
local void help OF((void));
local void help_extended OF((void));
#endif /* !VMSCLI */
#endif /* !MACOS && !WINDLL */
/* prereading of arguments is not supported in new command
line interpreter get_option() so read filters as arguments
are processed and convert to expected array later */
local int add_filter OF((int flag, char *pattern));
local int filterlist_to_patterns OF((void));
/* not used
local int get_filters OF((int argc, char **argv));
*/
/* list to store file arguments */
local long add_name OF((char *filearg));
local int DisplayRunningStats OF((void));
local int BlankRunningStats OF((void));
#if !defined(WINDLL)
local void version_info OF((void));
# if !defined(MACOS)
local void zipstdout OF((void));
# endif /* !MACOS */
local int check_unzip_version OF((char *unzippath));
local void check_zipfile OF((char *zipname, char *zippath));
#endif /* !WINDLL */
/* structure used by add_filter to store filters */
struct filterlist_struct {
char flag;
char *pattern;
struct filterlist_struct *next;
};
struct filterlist_struct *filterlist = NULL; /* start of list */
struct filterlist_struct *lastfilter = NULL; /* last filter in list */
/* structure used by add_filearg to store file arguments */
struct filelist_struct {
char *name;
struct filelist_struct *next;
};
long filearg_count = 0;
struct filelist_struct *filelist = NULL; /* start of list */
struct filelist_struct *lastfile = NULL; /* last file in list */
local void freeup()
/* Free all allocations in the 'found' list, the 'zfiles' list and
the 'patterns' list. */
{
struct flist far *f; /* steps through found list */
struct zlist far *z; /* pointer to next entry in zfiles list */
for (f = found; f != NULL; f = fexpel(f))
;
while (zfiles != NULL)
{
z = zfiles->nxt;
if (zfiles->zname && zfiles->zname != zfiles->name)
free((zvoid *)(zfiles->zname));
if (zfiles->name)
free((zvoid *)(zfiles->name));
if (zfiles->iname)
free((zvoid *)(zfiles->iname));
if (zfiles->cext && zfiles->cextra && zfiles->cextra != zfiles->extra)
free((zvoid *)(zfiles->cextra));
if (zfiles->ext && zfiles->extra)
free((zvoid *)(zfiles->extra));
if (zfiles->com && zfiles->comment)
free((zvoid *)(zfiles->comment));
if (zfiles->oname)
free((zvoid *)(zfiles->oname));
#ifdef UNICODE_SUPPORT
if (zfiles->uname)
free((zvoid *)(zfiles->uname));
if (zfiles->zuname)
free((zvoid *)(zfiles->zuname));
if (zfiles->ouname)
free((zvoid *)(zfiles->ouname));
# ifdef WIN32
if (zfiles->namew)
free((zvoid *)(zfiles->namew));
if (zfiles->inamew)
free((zvoid *)(zfiles->inamew));
if (zfiles->znamew)
free((zvoid *)(zfiles->znamew));
# endif
#endif
farfree((zvoid far *)zfiles);
zfiles = z;
zcount--;
}
if (patterns != NULL) {
while (pcount-- > 0) {
if (patterns[pcount].zname != NULL)
free((zvoid *)(patterns[pcount].zname));
}
free((zvoid *)patterns);
patterns = NULL;
}
/* close logfile */
if (logfile) {
fclose(logfile);
}
}
local int finish(e)
int e; /* exit code */
/* Process -o and -m options (if specified), free up malloc'ed stuff, and
exit with the code e. */
{
int r; /* return value from trash() */
ulg t; /* latest time in zip file */
struct zlist far *z; /* pointer into zfile list */
/* If latest, set time to zip file to latest file in zip file */
if (latest && zipfile && strcmp(zipfile, "-"))
{
diag("changing time of zip file to time of latest file in it");
/* find latest time in zip file */
if (zfiles == NULL)
zipwarn("zip file is empty, can't make it as old as latest entry", "");
else {
t = 0;
for (z = zfiles; z != NULL; z = z->nxt)
/* Ignore directories in time comparisons */
#ifdef USE_EF_UT_TIME
if (z->iname[z->nam-1] != (char)0x2f) /* ascii '/' */
{
iztimes z_utim;
ulg z_tim;
z_tim = ((get_ef_ut_ztime(z, &z_utim) & EB_UT_FL_MTIME) ?
unix2dostime(&z_utim.mtime) : z->tim);
if (t < z_tim)
t = z_tim;
}
#else /* !USE_EF_UT_TIME */
if (z->iname[z->nam-1] != (char)0x2f /* ascii '/' */
&& t < z->tim)
t = z->tim;
#endif /* ?USE_EF_UT_TIME */
/* set modified time of zip file to that time */
if (t != 0)
stamp(zipfile, t);
else
zipwarn(
"zip file has only directories, can't make it as old as latest entry",
"");
}
}
if (tempath != NULL)
{
free((zvoid *)tempath);
tempath = NULL;
}
if (zipfile != NULL)
{
free((zvoid *)zipfile);
zipfile = NULL;
}
if (in_file != NULL)
{
fclose(in_file);
in_file = NULL;
}
if (in_path != NULL)
{
free((zvoid *)in_path);
in_path = NULL;
}
if (out_path != NULL)
{
free((zvoid *)out_path);
out_path = NULL;
}
if (zcomment != NULL)
{
free((zvoid *)zcomment);
zcomment = NULL;
}
/* If dispose, delete all files in the zfiles list that are marked */
if (dispose)
{
diag("deleting files that were added to zip file");
if ((r = trash()) != ZE_OK)
ZIPERR(r, "was deleting moved files and directories");
}
/* Done! */
freeup();
return e;
}
void ziperr(c, h)
int c; /* error code from the ZE_ class */
ZCONST char *h; /* message about how it happened */
/* Issue a message for the error, clean up files and memory, and exit. */
{
#ifndef WINDLL
#ifndef MACOS
static int error_level = 0;
#endif
if (error_level++ > 0)
/* avoid recursive ziperr() printouts (his should never happen) */
EXIT(ZE_LOGIC); /* ziperr recursion is an internal logic error! */
#endif /* !WINDLL */
if (mesg_line_started) {
fprintf(mesg, "\n");
mesg_line_started = 0;
}
if (logfile && logfile_line_started) {
fprintf(logfile, "\n");
logfile_line_started = 0;
}
if (h != NULL) {
if (PERR(c))
fprintf(mesg, "zip I/O error: %s", strerror(errno));
/* perror("zip I/O error"); */
fflush(mesg);
fprintf(mesg, "\nzip error: %s (%s)\n", ZIPERRORS(c), h);
#ifdef DOS
check_for_windows("Zip");
#endif
if (logfile) {
if (PERR(c))
fprintf(logfile, "zip I/O error: %s\n", strerror(errno));
fprintf(logfile, "\nzip error: %s (%s)\n", ZIPERRORS(c), h);
logfile_line_started = 0;
}
}
if (tempzip != NULL)
{
if (tempzip != zipfile) {
if (current_local_file)
fclose(current_local_file);
if (y != current_local_file && y != NULL)
fclose(y);
#ifndef DEBUG
destroy(tempzip);
#endif
free((zvoid *)tempzip);
} else {
/* -g option, attempt to restore the old file */
/* zip64 support 09/05/2003 R.Nausedat */
uzoff_t k = 0; /* keep count for end header */
uzoff_t cb = cenbeg; /* get start of central */
struct zlist far *z; /* steps through zfiles linked list */
fprintf(mesg, "attempting to restore %s to its previous state\n",
zipfile);
if (logfile)
fprintf(logfile, "attempting to restore %s to its previous state\n",
zipfile);
zfseeko(y, cenbeg, SEEK_SET);
tempzn = cenbeg;
for (z = zfiles; z != NULL; z = z->nxt)
{
putcentral(z);
tempzn += 4 + CENHEAD + z->nam + z->cext + z->com;
k++;
}
putend(k, tempzn - cb, cb, zcomlen, zcomment);
fclose(y);
y = NULL;
}
}
if (key != NULL) {
free((zvoid *)key);
key = NULL;
}
if (tempath != NULL) {
free((zvoid *)tempath);
tempath = NULL;
}
if (zipfile != NULL) {
free((zvoid *)zipfile);
zipfile = NULL;
}
if (out_path != NULL) {
free((zvoid *)out_path);
out_path = NULL;
}
if (zcomment != NULL) {
free((zvoid *)zcomment);
zcomment = NULL;
}
freeup();
#ifndef WINDLL
EXIT(c);
#else
longjmp(zipdll_error_return, c);
#endif
}
void error(h)
ZCONST char *h;
/* Internal error, should never happen */
{
ziperr(ZE_LOGIC, h);
}
#if (!defined(MACOS) && !defined(WINDLL))
local void handler(s)
int s; /* signal number (ignored) */
/* Upon getting a user interrupt, turn echo back on for tty and abort
cleanly using ziperr(). */
{
#if defined(AMIGA) && defined(__SASC)
_abort();
#else
#if !defined(MSDOS) && !defined(__human68k__) && !defined(RISCOS)
echon();
putc('\n', mesg);
#endif /* !MSDOS */
#endif /* AMIGA && __SASC */
ziperr(ZE_ABORT, "aborting");
s++; /* keep some compilers happy */
}
#endif /* !MACOS && !WINDLL */
void zipmessage_nl(a, nl)
ZCONST char *a; /* message string to output */
int nl; /* 1 = add nl to end */
/* If nl false, print a message to mesg without new line.
If nl true, print and add new line. If logfile is
open then also write message to log file. */
{
if (noisy) {
if (a && strlen(a)) {
fprintf(mesg, "%s", a);
mesg_line_started = 1;
}
if (nl) {
if (mesg_line_started) {
fprintf(mesg, "\n");
mesg_line_started = 0;
}
} else if (a && strlen(a)) {
mesg_line_started = 1;
}
fflush(mesg);
}
if (logfile) {
if (a && strlen(a)) {
fprintf(logfile, "%s", a);
logfile_line_started = 1;
}
if (nl) {
if (logfile_line_started) {
fprintf(logfile, "\n");
logfile_line_started = 0;
}
} else if (a && strlen(a)) {
logfile_line_started = 1;
}
fflush(logfile);
}
}
void zipmessage(a, b)
ZCONST char *a, *b; /* message strings juxtaposed in output */
/* Print a message to mesg and flush. Also write to log file if
open. Write new line first if current line has output already. */
{
if (noisy) {
if (mesg_line_started)
fprintf(mesg, "\n");
fprintf(mesg, "%s%s\n", a, b);
mesg_line_started = 0;
fflush(mesg);
}
if (logfile) {
if (logfile_line_started)
fprintf(logfile, "\n");
fprintf(logfile, "%s%s\n", a, b);
logfile_line_started = 0;
fflush(logfile);
}
}
void zipwarn(a, b)
ZCONST char *a, *b; /* message strings juxtaposed in output */
/* Print a warning message to mesg (usually stderr) and return. */
{
if (noisy) {
if (mesg_line_started)
fprintf(mesg, "\n");
fprintf(mesg, "\tzip warning: %s%s\n", a, b);
mesg_line_started = 0;
fflush(mesg);
}
if (logfile) {
if (logfile_line_started)
fprintf(logfile, "\n");
fprintf(logfile, "\tzip warning: %s%s\n", a, b);
logfile_line_started = 0;
fflush(logfile);
}
}
#ifndef WINDLL
local void license()
/* Print license information to stdout. */
{
extent i; /* counter for copyright array */
for (i = 0; i < sizeof(swlicense)/sizeof(char *); i++)
puts(swlicense[i]);
}
#ifdef VMSCLI
void help()
#else
local void help()
#endif
/* Print help (along with license info) to stdout. */
{
extent i; /* counter for help array */
/* help array */
static ZCONST char *text[] = {
#ifdef VMS
"ds-zip %s (%s). Usage: zip == \"$ disk:[dir]zip.exe\"",
#else
"ds-zip %s (%s). Usage:",
#endif
#ifdef MACOS
"zip [-options] [-b fm] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]",
" The default action is to add or replace zipfile entries from list.",
" ",
" -f freshen: only changed files -u update: only changed or new files",
" -d delete entries in zipfile -m move into zipfile (delete OS files)",
" -r recurse into directories -j junk (don't record) directory names",
" -0 store only -l convert LF to CR LF (-ll CR LF to LF)",
" -1 compress faster -9 compress better",
" -q quiet operation -v verbose operation/print version info",
" -c add one-line comments -z add zipfile comment",
" -o make zipfile as old as latest entry",
" -F fix zipfile (-FF try harder) -D do not add directory entries",
" -X eXclude eXtra file attributes",
# if CRYPT
" -e encrypt -n don't compress these suffixes"
# else
" -h show this help -n don't compress these suffixes"
# endif
," -h2 show more help",
" Macintosh specific:",
" -jj record Fullpath (+ Volname) -N store finder-comments as comments",
" -df zip only datafork of a file -S include finder invisible/system files"
#else /* !MACOS */
#ifdef VM_CMS
"zip [-options] [-b fm] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]",
#else /* !VM_CMS */
"zip [-options] [-b path] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]",
#endif /* ?VM_CMS */
" The default action is to add or replace zipfile entries from list, which",
" can include the special name - to compress standard input.",
" If zipfile and list are omitted, zip compresses stdin to stdout.",
" -f freshen: only changed files -u update: only changed or new files",
" -d delete entries in zipfile -m move into zipfile (delete OS files)",
" -r recurse into directories -j junk (don't record) directory names",
#ifdef THEOS
" -0 store only -l convert CR to CR LF (-ll CR LF to CR)",
#else
" -0 store only -l convert LF to CR LF (-ll CR LF to LF)",
#endif
" -1 compress faster -9 compress better",
" -q quiet operation -v verbose operation/print version info",
" -c add one-line comments -z add zipfile comment",
" -@ read names from stdin -o make zipfile as old as latest entry",
" -x exclude the following names -i include only the following names",
#ifdef EBCDIC
#ifdef CMS_MVS
" -a translate to ASCII -B force binary read (text is default)",
#else /* !CMS_MVS */
" -a translate to ASCII",
#endif /* ?CMS_MVS */
#endif /* EBCDIC */
#ifdef TANDEM
" -Bn set Enscribe formatting options",
#endif
" -F fix zipfile (-FF try harder) -D do not add directory entries",
" -A adjust self-extracting exe -J junk zipfile prefix (unzipsfx)",
" -X eXclude eXtra file attributes",
#ifdef VMS
" -C preserve case of file names -C- down-case all file names",
" -C2 preserve case of ODS2 names -C2- down-case ODS2 file names* (*=default)",
" -C5 preserve case of ODS5 names* -C5- down-case ODS5 file names",
" -V save VMS file attributes (-VV also save allocated blocks past EOF)",
" -w store file version numbers\
-ww store file version numbers as \".nnn\"",
#endif /* def VMS */
#ifdef NTSD_EAS
" -! use privileges (if granted) to obtain all aspects of WinNT security",
#endif /* NTSD_EAS */
#ifdef OS2
" -E use the .LONGNAME Extended attribute (if found) as filename",
#endif /* OS2 */
#ifdef S_IFLNK
" -y store symbolic links as the link instead of the referenced file",
#endif /* !S_IFLNK */
/*
" -R PKZIP recursion (see manual)",
*/
#if defined(MSDOS) || defined(OS2)
" -$ include volume label -S include system and hidden files",
#endif
#ifdef AMIGA
# if CRYPT
" -N store filenotes as comments -e encrypt",
" -h show this help -n don't compress these suffixes"
# else
" -N store filenotes as comments -n don't compress these suffixes"
# endif
#else /* !AMIGA */
# if CRYPT
" -e encrypt -n don't compress these suffixes"
# else
" -h show this help -n don't compress these suffixes"
# endif
#endif /* ?AMIGA */
#ifdef RISCOS
," -h2 show more help -I don't scan thru Image files"
#else
," -h2 show more help"
#endif
#endif /* ?MACOS */
#ifdef VMS
," (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND)"
#endif /* def VMS */
," "
};
for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
{
printf(copyright[i], "zip");
putchar('\n');
}
for (i = 0; i < sizeof(text)/sizeof(char *); i++)
{
printf(text[i], VERSION, REVDATE);
putchar('\n');
}
}
#ifdef VMSCLI
void help_extended()
#else
local void help_extended()
#endif
/* Print extended help to stdout. */
{
extent i; /* counter for help array */
/* help array */
static ZCONST char *text[] = {
"",
"Extended Help for Zip",
"",
"See the Zip Manual for more detailed help",
"",
"",
"Zip stores files in zip archives. The default action is to add or replace",
"zipfile entries.",
"",
"Basic command line:",
" zip options archive_name file file ...",
"",
"Some examples:",
" Add file.txt to z.zip (create z if needed): zip z file.txt",
" Zip all files in current dir: zip z *",
" Zip files in current dir and subdirs also: zip -r z .",
"",
"Basic modes:",
" External modes (selects files from file system):",
" add - add new files/update existing files in archive (default)",
" -u update - add new files/update existing files only if later date",
" -f freshen - update existing files only (no files added)",
" -FS filesync - update if date or size changed, delete if no OS match",
" Internal modes (selects entries in archive):",
" -d delete - delete files from archive (see below)",
" -U copy - select files in archive to copy (use with --out)",
"",
"Basic options:",
" -r recurse into directories (see Recursion below)",
" -m after archive created, delete original files (move into archive)",
" -j junk directory names (store just file names)",
" -q quiet operation",
" -v verbose operation (just \"zip -v\" shows version information)",
" -c prompt for one-line comment for each entry",
" -z prompt for comment for archive (end with just \".\" line or EOF)",
" -@ read names to zip from stdin (one path per line)",
" -o make zipfile as old as latest entry",
"",
"",
"Syntax:",
" The full command line syntax is:",
"",
" zip [-shortopts ...] [--longopt ...] [zipfile [path path ...]] [-xi list]",
"",
" Any number of short option and long option arguments are allowed",
" (within limits) as well as any number of path arguments for files",
" to zip up. If zipfile exists, the archive is read in. If zipfile",
" is \"-\", stream to stdout. If any path is \"-\", zip stdin.",
"",
"Options and Values:",
" For short options that take values, use -ovalue or -o value or -o=value",
" For long option values, use either --longoption=value or --longoption value",
" For example:",
" zip -ds 10 --temp-dir=path zipfile path1 path2 --exclude pattern pattern",
" Avoid -ovalue (no space between) to avoid confusion",
" In particular, be aware of 2-character options. For example:",
" -d -s is (delete, split size) while -ds is (dot size)",
" Usually better to break short options across multiple arguments by function",
" zip -r -dbdcds 10m -lilalf logfile archive input_directory -ll",
"",
" All args after just \"--\" arg are read verbatim as paths and not options.",
" zip zipfile path path ... -- verbatimpath verbatimpath ...",
" Use -nw to also disable wildcards, so paths are read literally:",
" zip zipfile -nw -- \"-leadingdashpath\" \"a[path].c\" \"path*withwildcard\"",
" You may still have to escape or quote arguments to avoid shell expansion",
"",
"Wildcards:",
" Internally zip supports the following wildcards:",
" ? (or %% or #, depending on OS) matches any single character",
" * matches any number of characters, including zero",
" [list] matches char in list (regex), can do range [ac-f], all but [!bf]",
" If port supports [], must escape [ as [[] or use -nw to turn off wildcards",
" For shells that expand wildcards, escape (\\* or \"*\") so zip can recurse",
" zip zipfile -r . -i \"*.h\"",
"",
" Normally * crosses dir bounds in path, e.g. 'a*b' can match 'ac/db'. If",
" -ws option used, * does not cross dir bounds but ** does",
"",
" For DOS and Windows, [list] is now disabled unless the new option",
" -RE enable [list] (regular expression) matching",
" is used to avoid problems with file paths containing \"[\" and \"]\":",
" zip files_ending_with_number -RE foo[0-9].c",
"",
"Include and Exclude:",
" -i pattern pattern ... include files that match a pattern",
" -x pattern pattern ... exclude files that match a pattern",
" Patterns are paths with optional wildcards and match paths as stored in",
" archive. Exclude and include lists end at next option, @, or end of line.",
" zip -x pattern pattern @ zipfile path path ...",
"",
"Case matching:",
" On most OS the case of patterns must match the case in the archive, unless",
" the -ic option is used.",
" -ic ignore case of archive entries",
" This option not available on case-sensitive file systems. On others, case",
" ignored when matching files on file system but matching against archive",
" entries remains case sensitive for modes -f (freshen), -U (archive copy),",
" and -d (delete) because archive paths are always case sensitive. With",
" -ic, all matching ignores case, but it's then possible multiple archive",
" entries that differ only in case will match.",
"",
"End Of Line Translation (text files only):",
" -l change CR or LF (depending on OS) line end to CR LF (Unix->Win)",
" -ll change CR LF to CR or LF (depending on OS) line end (Win->Unix)",
" If first buffer read from file contains binary the translation is skipped",
"",
"Recursion:",
" -r recurse paths, include files in subdirs: zip -r a path path ...",
" -R recurse current dir and match patterns: zip -R a ptn ptn ...",
" Use -i and -x with either to include or exclude paths",
" Path root in archive starts at current dir, so if /a/b/c/file and",
" current dir is /a/b, 'zip -r archive .' puts c/file in archive",
"",
"Date filtering:",
" -t date exclude before (include files modified on this date and later)",
" -tt date include before (include files modified before date)",
" Can use both at same time to set a date range",
" Dates are mmddyyyy or yyyy-mm-dd",
"",
"Deletion, File Sync:",
" -d delete files",
" Delete archive entries matching internal archive paths in list",
" zip archive -d pattern pattern ...",
" Can use -t and -tt to select files in archive, but NOT -x or -i, so",
" zip archive -d \"*\" -t 2005-12-27",
" deletes all files from archive.zip with date of 27 Dec 2005 and later",
" Note the * (escape as \"*\" on Unix) to select all files in archive",
"",
" -FS file sync",
" Similar to update, but files updated if date or size of entry does not",
" match file on OS. Also deletes entry from archive if no matching file",
" on OS.",
" zip archive_to_update -FS -r dir_used_before",
" Result generally same as creating new archive, but unchanged entries",
" are copied instead of being read and compressed so can be faster.",
" WARNING: -FS deletes entries so make backup copy of archive first",
"",
"Compression:",
" -0 store files (no compression)",
" -1 to -9 compress fastest to compress best (default is 6)",
" -Z cm set compression method to cm:",
" store - store without compression, same as option -0",
" deflate - original zip deflate, same as -1 to -9 (default)",
" if bzip2 is enabled:",
" bzip2 - use bzip2 compression (need modern unzip)",
"",
"Encryption:",
" -e use standard (weak) PKZip 2.0 encryption, prompt for password",
" -P pswd use standard encryption, password is pswd",
"",
"Splits (archives created as a set of split files):",
" -s ssize create split archive with splits of size ssize, where ssize nm",
" n number and m multiplier (kmgt, default m), 100k -> 100 kB",
" -sp pause after each split closed to allow changing disks",
" WARNING: Archives created with -sp use data descriptors and should",
" work with most unzips but may not work with some",
" -sb ring bell when pause",
" -sv be verbose about creating splits",
" Split archives CANNOT be updated, but see --out and Copy Mode below",
"",
"Using --out (output to new archive):",
" --out oa output to new archive oa",
" Instead of updating input archive, create new output archive oa.",
" Result is same as without --out but in new archive. Input archive",
" unchanged.",
" WARNING: --out ALWAYS overwrites any existing output file",
" For example, to create new_archive like old_archive but add newfile1",
" and newfile2:",
" zip old_archive newfile1 newfile2 --out new_archive",
" Cannot update split archive, so use --out to out new archive:",
" zip in_split_archive newfile1 newfile2 --out out_split_archive",
" If input is split, output will default to same split size",
" Use -s=0 or -s- to turn off splitting to convert split to single file:",
" zip in_split_archive -s 0 --out out_single_file_archive",
" WARNING: If overwriting old split archive but need less splits,",
" old splits not overwritten are not needed but remain",
"",
"Copy Mode (copying from archive to archive):",
" -U (also --copy) select entries in archive to copy (reverse delete)",
" Copy Mode copies entries from old to new archive with --out and is used by",
" zip when either no input files on command line or -U (--copy) used.",
" zip inarchive --copy pattern pattern ... --out outarchive",
" To copy only files matching *.c into new archive, excluding foo.c:",
" zip old_archive --copy \"*.c\" --out new_archive -x foo.c",
" If no input files and --out, copy all entries in old archive:",
" zip old_archive --out new_archive",
"",
"Streaming and FIFOs:",
" prog1 | zip -ll z - zip output of prog1 to zipfile z, converting CR LF",
" zip - -R \"*.c\" | prog2 zip *.c files in current dir and stream to prog2 ",
" prog1 | zip | prog2 zip in pipe with no in or out acts like zip - -",
" If Zip is Zip64 enabled, streaming stdin creates Zip64 archives by default",
" that need PKZip 4.5 unzipper like UnZip 6.0",
" WARNING: Some archives created with streaming use data descriptors and",
" should work with most unzips but may not work with some",
" Can use -fz- to turn off Zip64 if input not large (< 4 GB):",
" prog_with_small_output | zip archive -fz-",
"",
" Zip now can read Unix FIFO (named pipes). Off by default to prevent zip",
" from stopping unexpectedly on unfed pipe, use -FI to enable:",
" zip -FI archive fifo",
"",
"Dots, counts:",
" -db display running count of bytes processed and bytes to go",
" (uncompressed size, except delete and copy show stored size)",
" -dc display running count of entries done and entries to go",
" -dd display dots every 10 MB (or dot size) while processing files",
" -dg display dots globally for archive instead of for each file",
" zip -qdgds 10m will turn off most output except dots every 10 MB",
" -ds siz each dot is siz processed where siz is nm as splits (0 no dots)",
" -du display original uncompressed size for each entry as added",
" -dv display volume (disk) number in format in_disk>out_disk",
" Dot size is approximate, especially for dot sizes less than 1 MB",
" Dot options don't apply to Scanning files dots (dot/2sec) (-q turns off)",
"",
"Logging:",
" -lf path open file at path as logfile (overwrite existing file)",
" -la append to existing logfile",
" -li include info messages (default just warnings and errors)",
"",
"Testing archives:",
" Options -T and -TT have been removed to avoid vulnerabilty:",
" https://nvd.nist.gov/vuln/detail/CVE-2018-13410",
"",
"Fixing archives:",
" -F attempt to fix a mostly intact archive (try this first)",
" -FF try to salvage what can (may get more but less reliable)",
" Fix options copy entries from potentially bad archive to new archive.",
" -F tries to read archive normally and copy only intact entries, while",
" -FF tries to salvage what can and may result in incomplete entries.",
" Must use --out option to specify output archive:",
" zip -F bad.zip --out fixed.zip",
" Use -v (verbose) with -FF to see details:",
" zip reallybad.zip -FF -v --out fixed.zip",
" Currently neither option fixes bad entries, as from text mode ftp get.",
"",
"Difference mode:",
" -DF (also --dif) only include files that have changed or are",
" new as compared to the input archive",
" Difference mode can be used to create incremental backups. For example:",
" zip --dif full_backup.zip -r somedir --out diff.zip",
" will store all new files, as well as any files in full_backup.zip where",
" either file time or size have changed from that in full_backup.zip,",
" in new diff.zip. Output archive not excluded automatically if exists,",
" so either use -x to exclude it or put outside what is being zipped.",
"",
"DOS Archive bit (Windows only):",
" -AS include only files with the DOS Archive bit set",
" -AC after archive created, clear archive bit of included files",
" WARNING: Once the archive bits are cleared they are cleared",
" Can also use -sf to save file list before zipping files",
"",
"Show files:",
" -sf show files to operate on and exit (-sf- logfile only)",
" -su as -sf but show escaped UTF-8 Unicode names also if exist",
" -sU as -sf but show escaped UTF-8 Unicode names instead",
" Any character not in the current locale is escaped as #Uxxxx, where x",
" is hex digit, if 16-bit code is sufficient, or #Lxxxxxx if 24-bits",
" are needed. If add -UN=e, Zip escapes all non-ASCII characters.",
"",
"Unicode:",
" If compiled with Unicode support, Zip stores UTF-8 path of entries.",
" This is backward compatible. Unicode paths allow better conversion",
" of entry names between different character sets.",
"",
" New Unicode extra field includes checksum to verify Unicode path",
" goes with standard path for that entry (as utilities like ZipNote",
" can rename entries). If these do not match, use below options to",
" set what Zip does:",
" -UN=Quit - if mismatch, exit with error",
" -UN=Warn - if mismatch, warn, ignore UTF-8 (default)",
" -UN=Ignore - if mismatch, quietly ignore UTF-8",
" -UN=No - ignore any UTF-8 paths, use standard paths for all",
" An exception to -UN=N are entries with new UTF-8 bit set (instead",
" of using extra fields). These are always handled as Unicode.",
"",
" Normally Zip escapes all chars outside current char set, but leaves",
" as is supported chars, which may not be OK in path names. -UN=Escape",
" escapes any character not ASCII:",
" zip -sU -UN=e archive",
" Can use either normal path or escaped Unicode path on command line",
" to match files in archive.",
"",
" Zip now stores UTF-8 in entry path and comment fields on systems",
" where UTF-8 char set is default, such as most modern Unix, and",
" and on other systems in new extra fields with escaped versions in",
" entry path and comment fields for backward compatibility.",
" Option -UN=UTF8 will force storing UTF-8 in entry path and comment",
" fields:",
" -UN=UTF8 - store UTF-8 in entry path and comment fields",
" This option can be useful for multi-byte char sets on Windows where",
" escaped paths and comments can be too long to be valid as the UTF-8",
" versions tend to be shorter.",
"",
" Only UTF-8 comments on UTF-8 native systems supported. UTF-8 comments",
" for other systems planned in next release.",