-
Notifications
You must be signed in to change notification settings - Fork 0
/
zipfile.c
6820 lines (6078 loc) · 217 KB
/
zipfile.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
/*
zipfile.c - Zip 3
Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
See the accompanying file LICENSE, version 2007-Mar-4 or later
(the contents of which are also included in zip.h) for terms of use.
If, for some reason, all these files are missing, the Info-ZIP license
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
*/
/*
* zipfile.c by Mark Adler.
*/
#define __ZIPFILE_C
#include "zip.h"
#include "revision.h"
#ifdef UNICODE_SUPPORT
# include "crc32.h"
#endif
/* for realloc 2/6/2005 EG */
#include <stdlib.h>
#include <errno.h>
/* for toupper() */
#include <ctype.h>
#ifdef VMS
# include "vms/vms.h"
# include "vms/vmsmunch.h"
# include "vms/vmsdefs.h"
#endif
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif
/*
* XXX start of zipfile.h
*/
#ifdef THEOS
/* Macros cause stack overflow in compiler */
ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); }
ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); }
#else /* !THEOS */
/* Macros for converting integers in little-endian to machine format */
# define SH(a) ((ush)(((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8)))
# define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16))
# ifdef ZIP64_SUPPORT /* zip64 support 08/31/2003 R.Nausedat */
# define LLG(a) ((zoff_t)LG(a) | ((zoff_t)LG((a)+4) << 32))
# endif
#endif /* ?THEOS */
/* Macros for writing machine integers to little-endian format */
#define PUTSH(a,f) {putc((char)((a) & 0xff),(f)); putc((char)((a) >> 8),(f));}
#define PUTLG(a,f) {PUTSH((a) & 0xffff,(f)) PUTSH((a) >> 16,(f))}
#ifdef ZIP64_SUPPORT /* zip64 support 08/31/2003 R.Nausedat */
# define PUTLLG(a,f) {PUTLG((a) & 0xffffffff,(f)) PUTLG((a) >> 32,(f))}
#endif
/* -- Structure of a ZIP file -- */
/* Signatures for zip file information headers */
#define LOCSIG 0x04034b50L
#define CENSIG 0x02014b50L
#define ENDSIG 0x06054b50L
#define EXTLOCSIG 0x08074b50L
/* Offsets of values in headers */
/* local header */
#define LOCVER 0 /* version needed to extract */
#define LOCFLG 2 /* encrypt, deflate flags */
#define LOCHOW 4 /* compression method */
#define LOCTIM 6 /* last modified file time, DOS format */
#define LOCDAT 8 /* last modified file date, DOS format */
#define LOCCRC 10 /* uncompressed crc-32 for file */
#define LOCSIZ 14 /* compressed size in zip file */
#define LOCLEN 18 /* uncompressed size */
#define LOCNAM 22 /* length of filename */
#define LOCEXT 24 /* length of extra field */
/* extended local header (data descriptor) following file data (if bit 3 set) */
/* if Zip64 then all are 8 byte and not below - 11/1/03 EG */
#define EXTCRC 0 /* uncompressed crc-32 for file */
#define EXTSIZ 4 /* compressed size in zip file */
#define EXTLEN 8 /* uncompressed size */
/* central directory header */
#define CENVEM 0 /* version made by */
#define CENVER 2 /* version needed to extract */
#define CENFLG 4 /* encrypt, deflate flags */
#define CENHOW 6 /* compression method */
#define CENTIM 8 /* last modified file time, DOS format */
#define CENDAT 10 /* last modified file date, DOS format */
#define CENCRC 12 /* uncompressed crc-32 for file */
#define CENSIZ 16 /* compressed size in zip file */
#define CENLEN 20 /* uncompressed size */
#define CENNAM 24 /* length of filename */
#define CENEXT 26 /* length of extra field */
#define CENCOM 28 /* file comment length */
#define CENDSK 30 /* disk number start */
#define CENATT 32 /* internal file attributes */
#define CENATX 34 /* external file attributes */
#define CENOFF 38 /* relative offset of local header */
/* end of central directory record */
#define ENDDSK 0 /* number of this disk */
#define ENDBEG 2 /* number of the starting disk */
#define ENDSUB 4 /* entries on this disk */
#define ENDTOT 6 /* total number of entries */
#define ENDSIZ 8 /* size of entire central directory */
#define ENDOFF 12 /* offset of central on starting disk */
#define ENDCOM 16 /* length of zip file comment */
/* zip64 support 08/31/2003 R.Nausedat */
/* EOCDL_SIG used to detect Zip64 archive */
#define ZIP64_EOCDL_SIG 0x07064b50
/* EOCDL size is used in the empty archive check */
#define ZIP64_EOCDL_OFS_SIZE 20
#define ZIP_UWORD16_MAX 0xFFFF /* border value */
#define ZIP_UWORD32_MAX 0xFFFFFFFF /* border value */
#define ZIP_EF_HEADER_SIZE 4 /* size of pre-header of extra fields */
#ifdef ZIP64_SUPPORT
# define ZIP64_EXTCRC 0 /* uncompressed crc-32 for file */
# define ZIP64_EXTSIZ 4 /* compressed size in zip file */
# define ZIP64_EXTLEN 12 /* uncompressed size */
# define ZIP64_EOCD_SIG 0x06064b50
# define ZIP64_EOCD_OFS_SIZE 40
# define ZIP64_EOCD_OFS_CD_START 48
# define ZIP64_EOCDL_OFS_SIZE 20
# define ZIP64_EOCDL_OFS_EOCD_START 8
# define ZIP64_EOCDL_OFS_TOTALDISKS 16
# define ZIP64_MIN_VER 45 /* min version to set in the CD extra records */
# define ZIP64_CENTRAL_DIR_TAIL_SIZE (56 - 8 - 4) /* size of zip64 central dir tail, minus sig and size field bytes */
# define ZIP64_CENTRAL_DIR_TAIL_SIG 0x06064B50L /* zip64 central dir tail signature */
# define ZIP64_CENTRAL_DIR_TAIL_END_SIG 0x07064B50L /* zip64 end of cen dir locator signature */
# define ZIP64_LARGE_FILE_HEAD_SIZE 32 /* total size of zip64 extra field */
# define ZIP64_EF_TAG 0x0001 /* ID for zip64 extra field */
# define ZIP64_EFIELD_OFS_OSIZE ZIP_EF_HEADER_SIZE /* zip64 extra field: offset to original file size */
# define ZIP64_EFIELD_OFS_CSIZE (ZIP64_EFIELD_OFS_OSIZE + 8) /* zip64 extra field: offset to compressed file size */
# define ZIP64_EFIELD_OFS_OFS (ZIP64_EFIELD_OFS_CSIZE + 8) /* zip64 extra field: offset to offset in archive */
# define ZIP64_EFIELD_OFS_DISK (ZIP64_EFIELD_OFS_OFS + 8) /* zip64 extra field: offset to start disk # */
/* -------------------------------------------------------------------------------------------------------------------------- */
local int adjust_zip_local_entry OF((struct zlist far *));
local void adjust_zip_central_entry OF((struct zlist far *));
#if 0
local int remove_local_extra_field OF((struct zlist far *, ulg));
local int remove_central_extra_field OF((struct zlist far *, ulg));
#endif
local int add_central_zip64_extra_field OF((struct zlist far *));
local int add_local_zip64_extra_field OF((struct zlist far *));
#endif /* ZIP64_SUPPORT */
#ifdef UNICODE_SUPPORT
# define UTF8_PATH_EF_TAG 0x7075 /* ID for Unicode path (up) extra field */
local int add_Unicode_Path_local_extra_field OF((struct zlist far *));
local int add_Unicode_Path_cen_extra_field OF((struct zlist far *));
#endif
/* New General Purpose Bit Flag bit 11 flags when entry path and
comment are in UTF-8 */
#define UTF8_BIT (1 << 11)
/* moved out of ZIP64_SUPPORT - 2/6/2005 EG */
local void write_ushort_to_mem OF((ush, char *)); /* little endian conversions */
local void write_ulong_to_mem OF((ulg, char *));
#ifdef ZIP64_SUPPORT
local void write_int64_to_mem OF((uzoff_t, char *));
#endif /* def ZIP64_SUPPORT */
#ifdef UNICODE_SUPPORT
local void write_string_to_mem OF((char *, char *));
#endif
#if 0
local char *get_extra_field OF((ush, char *, unsigned)); /* zip64 */
#endif
#ifdef UNICODE_SUPPORT
local void read_Unicode_Path_entry OF((struct zlist far *));
local void read_Unicode_Path_local_entry OF((struct zlist far *));
#endif
/* added these self allocators - 2/6/2005 EG */
local void append_ushort_to_mem OF((ush, char **, extent *, extent *));
local void append_ulong_to_mem OF((ulg, char **, extent *, extent *));
#ifdef ZIP64_SUPPORT
local void append_int64_to_mem OF((uzoff_t, char **, extent *, extent *));
#endif /* def ZIP64_SUPPORT */
local void append_string_to_mem OF((char *, int, char**, extent *, extent *));
/* Local functions */
local int find_next_signature OF((FILE *f));
local int find_signature OF((FILE *, ZCONST char *));
local int is_signature OF((ZCONST char *, ZCONST char *));
local int at_signature OF((FILE *, ZCONST char *));
local int zqcmp OF((ZCONST zvoid *, ZCONST zvoid *));
#ifdef UNICODE_SUPPORT
local int zuqcmp OF((ZCONST zvoid *, ZCONST zvoid *));
#endif
#if 0
local int scanzipf_reg OF((FILE *f));
#endif
local int scanzipf_regnew OF((void));
#ifndef UTIL
local int rqcmp OF((ZCONST zvoid *, ZCONST zvoid *));
local int zbcmp OF((ZCONST zvoid *, ZCONST zvoid far *));
# ifdef UNICODE_SUPPORT
local int zubcmp OF((ZCONST zvoid *, ZCONST zvoid far *));
# if 0
local int zuebcmp OF((ZCONST zvoid *, ZCONST zvoid far *));
# endif
# endif /* UNICODE_SUPPORT */
local void zipoddities OF((struct zlist far *));
# if 0
local int scanzipf_fix OF((FILE *f));
# endif
local int scanzipf_fixnew OF((void));
# ifdef USE_EF_UT_TIME
local int ef_scan_ut_time OF((char *ef_buf, extent ef_len, int ef_is_cent,
iztimes *z_utim));
# endif /* USE_EF_UT_TIME */
local void cutpath OF((char *p, int delim));
#endif /* !UTIL */
/*
* XXX end of zipfile.h
*/
/* Local data */
#ifdef HANDLE_AMIGA_SFX
ulg amiga_sfx_offset; /* place where size field needs updating */
#endif
local int zqcmp(a, b)
ZCONST zvoid *a, *b; /* pointers to pointers to zip entries */
/* Used by qsort() to compare entries in the zfile list.
* Compares the internal names z->iname */
{
char *aname = (*(struct zlist far **)a)->iname;
char *bname = (*(struct zlist far **)b)->iname;
return namecmp(aname, bname);
}
#ifdef UNICODE_SUPPORT
local int zuqcmp(a, b)
ZCONST zvoid *a, *b; /* pointers to pointers to zip entries */
/* Used by qsort() to compare entries in the zfile list.
* Compares the internal names z->zuname */
{
char *aname = (*(struct zlist far **)a)->iname;
char *bname = (*(struct zlist far **)b)->iname;
/* zuname could be NULL */
if ((*(struct zlist far **)a)->zuname)
aname = (*(struct zlist far **)a)->zuname;
if ((*(struct zlist far **)b)->zuname)
bname = (*(struct zlist far **)b)->zuname;
return namecmp(aname, bname);
}
#endif
#ifndef UTIL
local int rqcmp(a, b)
ZCONST zvoid *a, *b; /* pointers to pointers to zip entries */
/* Used by qsort() to compare entries in the zfile list.
* Compare the internal names z->iname, but in reverse order. */
{
return namecmp((*(struct zlist far **)b)->iname,
(*(struct zlist far **)a)->iname);
}
local int zbcmp(n, z)
ZCONST zvoid *n; /* string to search for */
ZCONST zvoid far *z; /* pointer to a pointer to a zip entry */
/* Used by search() to compare a target to an entry in the zfile list. */
{
return namecmp((char *)n, ((struct zlist far *)z)->zname);
}
#ifdef UNICODE_SUPPORT
/* search unicode paths */
local int zubcmp(n, z)
ZCONST zvoid *n; /* string to search for */
ZCONST zvoid far *z; /* pointer to a pointer to a zip entry */
/* Used by search() to compare a target to an entry in the zfile list. */
{
char *zuname = ((struct zlist far *)z)->zuname;
/* zuname is NULL if no UTF-8 name */
if (zuname == NULL)
zuname = ((struct zlist far *)z)->zname;
return namecmp((char *)n, zuname);
}
#if 0
/* search escaped unicode paths */
local int zuebcmp(n, z)
ZCONST zvoid *n; /* string to search for */
ZCONST zvoid far *z; /* pointer to a pointer to a zip entry */
/* Used by search() to compare a target to an entry in the zfile list. */
{
char *zuname = ((struct zlist far *)z)->zuname;
char *zuename;
int k;
/* zuname is NULL if no UTF-8 name */
if (zuname == NULL)
zuname = ((struct zlist far *)z)->zname;
zuename = local_to_escape_string(zuname);
k = namecmp((char *)n, zuename);
free(zuename);
return k;
}
#endif
#endif
struct zlist far *zsearch(n)
ZCONST char *n; /* name to find */
/* Return a pointer to the entry in zfile with the name n, or NULL if
not found. */
{
zvoid far **p; /* result of search() */
if (zcount) {
if ((p = search(n, (ZCONST zvoid far **)zsort, zcount, zbcmp)) != NULL)
return *(struct zlist far **)p;
#ifdef UNICODE_SUPPORT
else if (unicode_mismatch != 3 && fix != 2 &&
(p = search(n, (ZCONST zvoid far **)zusort, zcount, zubcmp)) != NULL)
return *(struct zlist far **)p;
#endif
else
return NULL;
}
return NULL;
}
#endif /* !UTIL */
#ifndef VMS /* See [.VMS]VMS.C for VMS-specific ziptyp(). */
# ifndef PATHCUT
# define PATHCUT '/'
# endif
char *ziptyp(s)
char *s; /* file name to force to zip */
/* If the file name *s has a dot (other than the first char), or if
the -A option is used (adjust self-extracting file) then return
the name, otherwise append .zip to the name. Allocate the space for
the name in either case. Return a pointer to the new name, or NULL
if malloc() fails. */
{
char *q; /* temporary pointer */
char *t; /* pointer to malloc'ed string */
# ifdef THEOS
char *r; /* temporary pointer */
char *disk;
# endif
if ((t = malloc(strlen(s) + 5)) == NULL)
return NULL;
strcpy(t, s);
# ifdef __human68k__
_toslash(t);
# endif
# ifdef MSDOS
for (q = t; *q; INCSTR(q))
if (*q == '\\')
*q = '/';
# endif /* MSDOS */
# if defined(__RSXNT__) || defined(WIN32_CRT_OEM)
/* RSXNT/EMX C rtl uses OEM charset */
AnsiToOem(t, t);
# endif
if (adjust) return t;
# ifndef RISCOS
# ifndef QDOS
# ifdef AMIGA
if ((q = MBSRCHR(t, '/')) == NULL)
q = MBSRCHR(t, ':');
if (MBSRCHR((q ? q + 1 : t), '.') == NULL)
# else /* !AMIGA */
# ifdef THEOS
/* the argument expansion add a dot to the end of file names when
* there is no extension and at least one of a argument has wild cards.
* So check for at least one character in the extension if there is a dot
* in file name */
if ((q = MBSRCHR((q = MBSRCHR(t, PATHCUT)) == NULL ? t : q + 1, '.')) == NULL
|| q[1] == '\0') {
# else /* !THEOS */
# ifdef TANDEM
if (MBSRCHR((q = MBSRCHR(t, '.')) == NULL ? t : q + 1, ' ') == NULL)
# else /* !TANDEM */
if (MBSRCHR((q = MBSRCHR(t, PATHCUT)) == NULL ? t : q + 1, '.') == NULL)
# endif /* ?TANDEM */
# endif /* ?THEOS */
# endif /* ?AMIGA */
# ifdef CMS_MVS
if (strncmp(t,"dd:",3) != 0 && strncmp(t,"DD:",3) != 0)
# endif /* CMS_MVS */
# ifdef THEOS
/* insert .zip extension before disk name */
if ((r = MBSRCHR(t, ':')) != NULL) {
/* save disk name */
if ((disk = strdup(r)) == NULL)
return NULL;
strcpy(r[-1] == '.' ? r - 1 : r, ".zip");
strcat(t, disk);
free(disk);
} else {
if (q != NULL && *q == '.')
strcpy(q, ".zip");
else
strcat(t, ".zip");
}
}
# else /* !THEOS */
# ifdef TANDEM /* Tandem can't cope with extensions */
strcat(t, " ZIP");
# else /* !TANDEM */
strcat(t, ".zip");
# endif /* ?TANDEM */
# endif /* ?THEOS */
# else /* QDOS */
q = LastDir(t);
if(MBSRCHR(q, '_') == NULL && MBSRCHR(q, '.') == NULL)
{
strcat(t, "_zip");
}
# endif /* QDOS */
# endif /* !RISCOS */
return t;
}
#endif /* ndef VMS */
/* ---------------------------------------------------- */
/* moved out of ZIP64_SUPPORT - 2/6/2005 EG */
/* 08/31/2003 R.Nausedat */
local void write_ushort_to_mem( OFT( ush) usValue,
OFT( char *)pPtr)
#ifdef NO_PROTO
ush usValue;
char *pPtr;
#endif /* def NO_PROTO */
{
*pPtr++ = ((char)(usValue) & 0xff);
*pPtr = ((char)(usValue >> 8) & 0xff);
}
local void write_ulong_to_mem(uValue, pPtr)
ulg uValue;
char *pPtr;
{
write_ushort_to_mem((ush)(uValue & 0xffff), pPtr);
write_ushort_to_mem((ush)((uValue >> 16) & 0xffff), pPtr + 2);
}
#ifdef ZIP64_SUPPORT
local void write_int64_to_mem(l64Value,pPtr)
uzoff_t l64Value;
char *pPtr;
{
write_ulong_to_mem((ulg)(l64Value & 0xffffffff),pPtr);
write_ulong_to_mem((ulg)((l64Value >> 32) & 0xffffffff),pPtr + 4);
}
#endif /* def ZIP64_SUPPORT */
#ifdef UNICODE_SUPPORT
/* Write a string to memory */
local void write_string_to_mem(strValue, pPtr)
char *strValue;
char *pPtr;
{
if (strValue != NULL) {
int ssize = strlen(strValue);
int i;
for (i = 0; i < ssize; i++) {
*(pPtr + i) = *(strValue + i);
}
}
}
#endif /* def UNICODE_SUPPORT */
/* same as above but allocate memory as needed and keep track of current end
using offset - 2/6/05 EG */
#if 0 /* ubyte version not used */
local void append_ubyte_to_mem( OFT( unsigned char) ubValue,
OFT( char **) pPtr,
OFT( extent *) offset,
OFT( extent *) blocksize)
#ifdef NO_PROTO
unsigned char ubValue; /* byte to append */
char **pPtr; /* start of block */
extent *offset; /* next byte to write */
extent *blocksize; /* current size of block */
#endif /* def NO_PROTO */
{
if (*pPtr == NULL) {
/* malloc a 1K block */
(*blocksize) = 1024;
*pPtr = (char *) malloc(*blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_ubyte_to_mem");
}
}
/* if (*offset) + 1 > (*blocksize) - 1 */
else if ((*offset) > (*blocksize) - (1 + 1)) {
/* realloc a bigger block in 1 K increments */
(*blocksize) += 1024;
*pPtr = realloc(*pPtr, *blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_ubyte_to_mem");
}
}
*(*pPtr + *offset) = ubValue;
(*offset)++;
}
#endif
local void append_ushort_to_mem( OFT( ush) usValue,
OFT( char **) pPtr,
OFT( extent *) offset,
OFT( extent *) blocksize)
#ifdef NO_PROTO
ush usValue;
char **pPtr;
extent *offset;
extent *blocksize;
#endif /* def NO_PROTO */
{
if (*pPtr == NULL) {
/* malloc a 1K block */
(*blocksize) = 1024;
*pPtr = (char *) malloc(*blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_ushort_to_mem");
}
}
/* if (*offset) + 2 > (*blocksize) - 1 */
else if ((*offset) > (*blocksize) - (1 + 2)) {
/* realloc a bigger block in 1 K increments */
(*blocksize) += 1024;
*pPtr = realloc(*pPtr, (extent)*blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_ushort_to_mem");
}
}
write_ushort_to_mem(usValue, (*pPtr) + (*offset));
(*offset) += 2;
}
local void append_ulong_to_mem(uValue, pPtr, offset, blocksize)
ulg uValue;
char **pPtr;
extent *offset;
extent *blocksize;
{
if (*pPtr == NULL) {
/* malloc a 1K block */
(*blocksize) = 1024;
*pPtr = (char *) malloc(*blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_ulong_to_mem");
}
}
else if ((*offset) > (*blocksize) - (1 + 4)) {
/* realloc a bigger block in 1 K increments */
(*blocksize) += 1024;
*pPtr = realloc(*pPtr, *blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_ulong_to_mem");
}
}
write_ulong_to_mem(uValue, (*pPtr) + (*offset));
(*offset) += 4;
}
#ifdef ZIP64_SUPPORT
local void append_int64_to_mem(l64Value, pPtr, offset, blocksize)
uzoff_t l64Value;
char **pPtr;
extent *offset;
extent *blocksize;
{
if (*pPtr == NULL) {
/* malloc a 1K block */
(*blocksize) = 1024;
*pPtr = (char *) malloc(*blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_int64_to_mem");
}
}
else if ((*offset) > (*blocksize) - (1 + 8)) {
/* realloc a bigger block in 1 K increments */
(*blocksize) += 1024;
*pPtr = realloc(*pPtr, *blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_int64_to_mem");
}
}
write_int64_to_mem(l64Value, (*pPtr) + (*offset));
(*offset) += 8;
}
#endif /* def ZIP64_SUPPORT */
/* Append a string to the memory block. */
local void append_string_to_mem(strValue, strLength, pPtr, offset, blocksize)
char *strValue;
int strLength;
char **pPtr;
extent *offset;
extent *blocksize;
{
if (strValue != NULL) {
unsigned bsize = 1024;
unsigned ssize = strLength;
unsigned i;
if (ssize > bsize) {
bsize = ssize;
}
if (*pPtr == NULL) {
/* malloc a 1K block */
(*blocksize) = bsize;
*pPtr = (char *) malloc(*blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_string_to_mem");
}
}
else if ((*offset) + ssize > (*blocksize) - 1) {
/* realloc a bigger block in 1 K increments */
(*blocksize) += bsize;
*pPtr = realloc(*pPtr, *blocksize);
if (*pPtr == NULL) {
ziperr(ZE_MEM, "append_string_to_mem");
}
}
for (i = 0; i < ssize; i++) {
*(*pPtr + *offset + i) = *(strValue + i);
}
(*offset) += ssize;
}
}
/* ---------------------------------------------------- */
/* zip64 support 08/31/2003 R.Nausedat */
/* moved out of zip64 support 10/22/05 */
/* Searches pExtra for extra field with specified tag.
* If it finds one it returns a pointer to it, else NULL.
* Renamed and made generic. 10/3/03
*/
char *get_extra_field( OFT( ush) tag,
OFT( char *) pExtra,
OFT( unsigned) iExtraLen)
#ifdef NO_PROTO
ush tag; /* tag to look for */
char *pExtra; /* pointer to extra field in memory */
unsigned iExtraLen; /* length of extra field */
#endif /* def NO_PROTO */
{
char *pTemp;
ush usBlockTag;
ush usBlockSize;
if( pExtra == NULL )
return NULL;
for (pTemp = pExtra; pTemp < pExtra + iExtraLen - ZIP_EF_HEADER_SIZE;)
{
usBlockTag = SH(pTemp); /* get tag */
usBlockSize = SH(pTemp + 2); /* get field data size */
if (usBlockTag == tag)
return pTemp;
pTemp += (usBlockSize + ZIP_EF_HEADER_SIZE);
}
return NULL;
}
/* copy_nondup_extra_fields
*
* Copy any extra fields in old that are not in new to new.
* Returns the new extra fields block and newLen is new length.
*/
char *copy_nondup_extra_fields(oldExtra, oldExtraLen, newExtra, newExtraLen, newLen)
char *oldExtra; /* pointer to old extra fields */
unsigned oldExtraLen; /* length of old extra fields */
char *newExtra; /* pointer to new extra fields */
unsigned newExtraLen; /* length of new extra fields */
unsigned *newLen; /* length of new extra fields after copy */
{
char *returnExtra = NULL;
ush returnExtraLen = 0;
char *tempExtra;
char *pTemp;
ush tag;
ush blocksize;
if( oldExtra == NULL ) {
/* no old extra fields so return copy of newExtra */
if (newExtra == NULL || newExtraLen == 0) {
*newLen = 0;
return NULL;
} else {
if ((returnExtra = malloc(newExtraLen)) == NULL)
ZIPERR(ZE_MEM, "extra field copy");
memcpy(returnExtra, newExtra, newExtraLen);
returnExtraLen = newExtraLen;
*newLen = returnExtraLen;
return returnExtra;
}
}
/* allocate block large enough for all extra fields */
if ((tempExtra = malloc(0xFFFF)) == NULL)
ZIPERR(ZE_MEM, "extra field copy");
/* look for each old extra field in new block */
for (pTemp = oldExtra; pTemp < oldExtra + oldExtraLen;)
{
tag = SH(pTemp); /* get tag */
blocksize = SH(pTemp + 2); /* get field data size */
if (get_extra_field(tag, newExtra, newExtraLen) == NULL) {
/* tag not in new block so add it */
memcpy(tempExtra + returnExtraLen, pTemp, blocksize + 4);
returnExtraLen += blocksize + 4;
}
pTemp += blocksize + 4;
}
/* copy all extra fields from new block */
memcpy(tempExtra + returnExtraLen, newExtra, newExtraLen);
returnExtraLen += newExtraLen;
/* copy tempExtra to returnExtra */
if ((returnExtra = malloc(returnExtraLen)) == NULL)
ZIPERR(ZE_MEM, "extra field copy");
memcpy(returnExtra, tempExtra, returnExtraLen);
free(tempExtra);
*newLen = returnExtraLen;
return returnExtra;
}
#ifdef UNICODE_SUPPORT
/* The latest format is
1 byte Version of Unicode Path Extra Field
4 bytes Name Field CRC32 Checksum
variable UTF-8 Version Of Name
*/
local void read_Unicode_Path_entry(pZipListEntry)
struct zlist far *pZipListEntry;
{
char *pTemp;
char *UPath;
char *iname;
ush ELen;
uch Version;
ush ULen;
ulg chksum = CRCVAL_INITIAL;
ulg iname_chksum;
/* check if we have a Unicode Path extra field ... */
pTemp = get_extra_field( UTF8_PATH_EF_TAG, pZipListEntry->cextra, pZipListEntry->cext );
pZipListEntry->uname = NULL;
if( pTemp == NULL ) {
return;
}
/* ... if so, update corresponding entries in struct zlist */
pTemp += 2;
/* length of this extra field */
ELen = SH(pTemp);
pTemp += 2;
/* version */
Version = (uch) *pTemp;
pTemp += 1;
if (Version > 1) {
zipwarn("Unicode Path Extra Field version > 1 - skipping", pZipListEntry->oname);
return;
}
/* iname CRC */
iname_chksum = LG(pTemp);
pTemp += 4;
/*
* Compute the CRC-32 checksum of iname
*/
/*
crc_16 = crc16f((uch *)(pZipListEntry->iname), strlen(pZipListEntry->iname));
*/
if ((iname = malloc(strlen(pZipListEntry->iname) + 1)) == NULL) {
ZIPERR(ZE_MEM, "write Unicode");
}
strcpy(iname, pZipListEntry->iname);
chksum = crc32(chksum, (uch *)(iname), strlen(iname));
free(iname);
/* chksum = adler16(ADLERVAL_INITIAL,
(uch *)(pZipListEntry->iname), strlen(pZipListEntry->iname));
*/
/* If the checksums's don't match then likely iname has been modified and
* the Unicode Path is no longer valid
*/
if (chksum != iname_chksum) {
printf("unicode_mismatch = %d\n", unicode_mismatch);
if (unicode_mismatch == 1) {
/* warn and continue */
zipwarn("Unicode does not match path - ignoring Unicode: ", pZipListEntry->oname);
} else if (unicode_mismatch == 2) {
/* ignore and continue */
} else if (unicode_mismatch == 0) {
/* error */
sprintf(errbuf, "Unicode does not match path: %s\n", pZipListEntry->oname);
strcat(errbuf,
" Likely entry name changed but Unicode not updated\n");
strcat(errbuf,
" Use -UN=i to ignore errors or n for no Unicode paths");
zipwarn(errbuf, "");
ZIPERR(ZE_FORM, "Unicode path error");
}
return;
}
ULen = ELen - 5;
/* UTF-8 Path */
if (ULen == 0) {
/* standard path is UTF-8 so use that */
ULen = pZipListEntry->nam;
if ((UPath = malloc(ULen + 1)) == NULL) {
return;
}
strcpy(UPath, pZipListEntry->name);
} else {
/* use Unicode path */
if ((UPath = malloc(ULen + 1)) == NULL) {
return;
}
strncpy(UPath, pTemp, ULen);
UPath[ULen] = '\0';
}
pZipListEntry->uname = UPath;
return;
}
local void read_Unicode_Path_local_entry(pZipListEntry)
struct zlist far *pZipListEntry;
{
char *pTemp;
char *UPath;
char *iname;
ush ELen;
uch Version;
ush ULen;
ulg chksum = CRCVAL_INITIAL;
ulg iname_chksum;
/* check if we have a Unicode Path extra field ... */
pTemp = get_extra_field( UTF8_PATH_EF_TAG, pZipListEntry->extra, pZipListEntry->ext );
pZipListEntry->uname = NULL;
if( pTemp == NULL ) {
return;
}
/* ... if so, update corresponding entries in struct zlist */
pTemp += 2;
/* length of this extra field */
ELen = SH(pTemp);
pTemp += 2;
/* version */
Version = (uch) *pTemp;
pTemp += 1;
if (Version > 1) {
zipwarn("Unicode Path Extra Field version > 1 - skipping", pZipListEntry->oname);
return;
}
/* iname CRC */
iname_chksum = LG(pTemp);
pTemp += 4;
/*
* Compute 32-bit crc of iname and AND halves to make 16-bit version
*/
/*
chksum = adler16(ADLERVAL_INITIAL,
(uch *)(pZipListEntry->iname), strlen(pZipListEntry->iname));
*/
if ((iname = malloc(strlen(pZipListEntry->iname) + 1)) == NULL) {
ZIPERR(ZE_MEM, "write Unicode");
}
strcpy(iname, pZipListEntry->iname);
chksum = crc32(chksum, (uch *)(iname), strlen(iname));
free(iname);
/* If the checksums's don't match then likely iname has been modified and
* the Unicode Path is no longer valid
*/
if (chksum != iname_chksum) {
if (unicode_mismatch == 1) {
/* warn and continue */
zipwarn("Unicode does not match path - ignoring Unicode: ", pZipListEntry->oname);
} else if (unicode_mismatch == 2) {
/* ignore and continue */
} else if (unicode_mismatch == 0) {
/* error */
sprintf(errbuf, "Unicode does not match path: %s\n", pZipListEntry->oname);
strcat(errbuf,
" Likely entry name changed but Unicode not updated\n");
strcat(errbuf,
" Use -UN=i to ignore errors or n for no Unicode paths");
zipwarn(errbuf, "");
ZIPERR(ZE_FORM, "Unicode path error");
}
return;
}
ULen = ELen - 5;
/* UTF-8 Path */
if (ULen == 0) {
/* standard path is UTF-8 so use that */
ULen = pZipListEntry->nam;
if ((UPath = malloc(ULen + 1)) == NULL) {
return;
}
strcpy(UPath, pZipListEntry->name);
} else {
/* use Unicode path */
if ((UPath = malloc(ULen + 1)) == NULL) {
return;
}
strncpy(UPath, pTemp, ULen);
UPath[ULen] = '\0';
}
pZipListEntry->uname = UPath;
return;
}
#endif /* def UNICODE_SUPPORT */
#ifdef ZIP64_SUPPORT /* zip64 support 08/31/2003 R.Nausedat */
/* searches the cextra member of zlist for a zip64 extra field. if it finds one it */
/* updates the len, siz and off members of zlist with the corresponding values of */
/* the zip64 extra field, that is if either the len, siz or off member of zlist is */
/* set to its max value we have to use the corresponding value from the zip64 extra */
/* field. as of now the dsk member of zlist is not much of interest since we should */
/* not modify multi volume archives at all. */
local void adjust_zip_central_entry(pZipListEntry)
struct zlist far *pZipListEntry;
{
char *pTemp;