Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/minizip/zip.c
21520 views
1
/* zip.c -- IO on .zip files using zlib
2
Version 1.1, February 14h, 2010
3
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4
5
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6
7
Modifications for Zip64 support
8
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
9
10
For more info read MiniZip_info.txt
11
12
Changes
13
Oct-2009 - Mathias Svensson - Remove old C style function prototypes
14
Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives
15
Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.
16
Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data
17
It is used when recreating zip archive with RAW when deleting items from a zip.
18
ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed.
19
Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)
20
Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
21
22
*/
23
24
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <time.h>
29
#ifndef ZLIB_CONST
30
# define ZLIB_CONST
31
#endif
32
#include "zlib.h"
33
#include "zip.h"
34
35
#ifdef STDC
36
# include <stddef.h>
37
#endif
38
#ifdef NO_ERRNO_H
39
extern int errno;
40
#else
41
# include <errno.h>
42
#endif
43
44
45
#ifndef local
46
# define local static
47
#endif
48
/* compile with -Dlocal if your debugger can't find static symbols */
49
50
#ifndef VERSIONMADEBY
51
# define VERSIONMADEBY (0x0) /* platform dependent */
52
#endif
53
54
#ifndef Z_BUFSIZE
55
#define Z_BUFSIZE (64*1024) /* (16384) */
56
#endif
57
58
#ifndef Z_MAXFILENAMEINZIP
59
#define Z_MAXFILENAMEINZIP (256)
60
#endif
61
62
#ifndef ALLOC
63
# define ALLOC(size) (malloc(size))
64
#endif
65
66
/*
67
#define SIZECENTRALDIRITEM (0x2e)
68
#define SIZEZIPLOCALHEADER (0x1e)
69
*/
70
71
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
72
73
74
/* NOT sure that this work on ALL platform */
75
#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))
76
77
#ifndef SEEK_CUR
78
#define SEEK_CUR 1
79
#endif
80
81
#ifndef SEEK_END
82
#define SEEK_END 2
83
#endif
84
85
#ifndef SEEK_SET
86
#define SEEK_SET 0
87
#endif
88
89
#ifndef DEF_MEM_LEVEL
90
#if MAX_MEM_LEVEL >= 8
91
# define DEF_MEM_LEVEL 8
92
#else
93
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
94
#endif
95
#endif
96
const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
97
98
99
#define SIZEDATA_INDATABLOCK (4096-(4*4))
100
101
#define LOCALHEADERMAGIC (0x04034b50)
102
#define CENTRALHEADERMAGIC (0x02014b50)
103
#define ENDHEADERMAGIC (0x06054b50)
104
#define ZIP64ENDHEADERMAGIC (0x6064b50)
105
#define ZIP64ENDLOCHEADERMAGIC (0x7064b50)
106
107
#define FLAG_LOCALHEADER_OFFSET (0x06)
108
#define CRC_LOCALHEADER_OFFSET (0x0e)
109
110
#define SIZECENTRALHEADER (0x2e) /* 46 */
111
112
typedef struct linkedlist_datablock_internal_s
113
{
114
struct linkedlist_datablock_internal_s* next_datablock;
115
uLong avail_in_this_block;
116
uLong filled_in_this_block;
117
uLong unused; /* for future use and alignment */
118
unsigned char data[SIZEDATA_INDATABLOCK];
119
} linkedlist_datablock_internal;
120
121
typedef struct linkedlist_data_s
122
{
123
linkedlist_datablock_internal* first_block;
124
linkedlist_datablock_internal* last_block;
125
} linkedlist_data;
126
127
128
/* zipAlreadyThere() set functions for a set of zero-terminated strings, and
129
// a block_t type for reading the central directory datablocks. */
130
typedef char *set_key_t;
131
#define set_cmp(a, b) strcmp(a, b)
132
#define set_drop(s, k) set_free(s, k)
133
#include "skipset.h"
134
typedef struct {
135
unsigned char *next; /* next byte in datablock data */
136
size_t left; /* number of bytes left in data (at least) */
137
linkedlist_datablock_internal *node; /* current datablock */
138
} block_t;
139
140
141
typedef struct
142
{
143
z_stream stream; /* zLib stream structure for inflate */
144
#ifdef HAVE_BZIP2
145
bz_stream bstream; /* bzLib stream structure for bziped */
146
#endif
147
148
int stream_initialised; /* 1 is stream is initialised */
149
uInt pos_in_buffered_data; /* last written byte in buffered_data */
150
151
ZPOS64_T pos_local_header; /* offset of the local header of the file
152
currently writing */
153
char* central_header; /* central header data for the current file */
154
uLong size_centralExtra;
155
uLong size_centralheader; /* size of the central header for cur file */
156
uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
157
uLong flag; /* flag of the file currently writing */
158
159
int method; /* compression method of file currently wr.*/
160
int raw; /* 1 for directly writing raw data */
161
Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
162
uLong dosDate;
163
uLong crc32;
164
int encrypt;
165
int zip64; /* Add ZIP64 extended information in the extra field */
166
ZPOS64_T pos_zip64extrainfo;
167
ZPOS64_T totalCompressedData;
168
ZPOS64_T totalUncompressedData;
169
#ifndef NOCRYPT
170
unsigned long keys[3]; /* keys defining the pseudo-random sequence */
171
const z_crc_t* pcrc_32_tab;
172
unsigned crypt_header_size;
173
#endif
174
} curfile64_info;
175
176
typedef struct
177
{
178
zlib_filefunc64_32_def z_filefunc;
179
voidpf filestream; /* io structure of the zipfile */
180
linkedlist_data central_dir;/* datablock with central dir in construction*/
181
int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
182
curfile64_info ci; /* info on the file currently writing */
183
184
ZPOS64_T begin_pos; /* position of the beginning of the zipfile */
185
ZPOS64_T add_position_when_writing_offset;
186
ZPOS64_T number_entry;
187
188
#ifndef NO_ADDFILEINEXISTINGZIP
189
char *globalcomment;
190
#endif
191
192
/* Support for zipAlreadyThere(). */
193
set_t set; /* set for detecting name collisions */
194
block_t block; /* block for reading the central directory */
195
196
} zip64_internal;
197
198
199
#ifndef NOCRYPT
200
#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
201
#include "crypt.h"
202
#endif
203
204
local linkedlist_datablock_internal* allocate_new_datablock(void) {
205
linkedlist_datablock_internal* ldi;
206
ldi = (linkedlist_datablock_internal*)
207
ALLOC(sizeof(linkedlist_datablock_internal));
208
if (ldi!=NULL)
209
{
210
ldi->next_datablock = NULL ;
211
ldi->filled_in_this_block = 0 ;
212
ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
213
}
214
return ldi;
215
}
216
217
local void free_datablock(linkedlist_datablock_internal* ldi) {
218
while (ldi!=NULL)
219
{
220
linkedlist_datablock_internal* ldinext = ldi->next_datablock;
221
free(ldi);
222
ldi = ldinext;
223
}
224
}
225
226
local void init_linkedlist(linkedlist_data* ll) {
227
ll->first_block = ll->last_block = NULL;
228
}
229
230
local void free_linkedlist(linkedlist_data* ll) {
231
free_datablock(ll->first_block);
232
ll->first_block = ll->last_block = NULL;
233
}
234
235
236
local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) {
237
linkedlist_datablock_internal* ldi;
238
const unsigned char* from_copy;
239
240
if (ll==NULL)
241
return ZIP_INTERNALERROR;
242
243
if (ll->last_block == NULL)
244
{
245
ll->first_block = ll->last_block = allocate_new_datablock();
246
if (ll->first_block == NULL)
247
return ZIP_INTERNALERROR;
248
}
249
250
ldi = ll->last_block;
251
from_copy = (const unsigned char*)buf;
252
253
while (len>0)
254
{
255
uInt copy_this;
256
uInt i;
257
unsigned char* to_copy;
258
259
if (ldi->avail_in_this_block==0)
260
{
261
ldi->next_datablock = allocate_new_datablock();
262
if (ldi->next_datablock == NULL)
263
return ZIP_INTERNALERROR;
264
ldi = ldi->next_datablock ;
265
ll->last_block = ldi;
266
}
267
268
if (ldi->avail_in_this_block < len)
269
copy_this = (uInt)ldi->avail_in_this_block;
270
else
271
copy_this = (uInt)len;
272
273
to_copy = &(ldi->data[ldi->filled_in_this_block]);
274
275
for (i=0;i<copy_this;i++)
276
*(to_copy+i)=*(from_copy+i);
277
278
ldi->filled_in_this_block += copy_this;
279
ldi->avail_in_this_block -= copy_this;
280
from_copy += copy_this ;
281
len -= copy_this;
282
}
283
return ZIP_OK;
284
}
285
286
/* zipAlreadyThere() operations. "set" in the zip internal structure keeps the
287
// set of names that are in the under-construction central directory so far. A
288
// skipset provides ~O(log n) time insertion and searching. Central directory
289
// records, stored in a linked list of allocated memory datablocks, is read
290
// through "block" in the zip internal structure.
291
292
// The block_*() functions support extracting the central directory file names
293
// from the datablocks. They are designed to support a growing directory by
294
// automatically continuing once more data has been appended to the linked
295
// datablocks.
296
297
// Initialize *block to the head of list. This should only be called once the
298
// list has at least some data in it, i.e. list->first_block is not NULL. */
299
local void block_init(block_t *block, linkedlist_data *list) {
300
block->node = list->first_block;
301
block->next = block->node->data;
302
block->left = block->node->filled_in_this_block;
303
}
304
305
/* Mark *block as bad, with all subsequent reads returning end, even if more
306
// data is added to the datablocks. This is invoked if the central directory is
307
// invalid, so there is no longer any point in attempting to interpret it. */
308
local void block_stop(block_t *block) {
309
block->left = 0;
310
block->next = NULL;
311
}
312
313
/* Return true if *block has reached the end of the data in the datablocks. */
314
local int block_end(block_t *block) {
315
linkedlist_datablock_internal *node = block->node;
316
if (node == NULL)
317
/* This block was previously terminated with extreme prejudice. */
318
return 1;
319
if (block->next < node->data + node->filled_in_this_block)
320
/* There are more bytes to read in the current datablock. */
321
return 0;
322
while (node->next_datablock != NULL) {
323
if (node->filled_in_this_block != 0)
324
/* There are some bytes in a later datablock. */
325
return 0;
326
node = node->next_datablock;
327
}
328
/* Reached the end of the list of datablocks. There's nothing. */
329
return 1;
330
}
331
332
/* Return one byte from *block, or -1 if the end is reached. */
333
local int block_get(block_t *block) {
334
while (block->left == 0) {
335
if (block->node == NULL)
336
/* We've been marked bad. Return end. */
337
return -1;
338
/* Update left in case more was filled in since we were last here. */
339
block->left = block->node->filled_in_this_block -
340
(block->next - block->node->data);
341
if (block->left != 0)
342
/* There was indeed more data appended in the current datablock. */
343
break;
344
if (block->node->next_datablock == NULL)
345
/* No more data here, and there is no next datablock. At the end. */
346
return -1;
347
/* Try the next datablock for more data. */
348
block->node = block->node->next_datablock;
349
block->next = block->node->data;
350
block->left = block->node->filled_in_this_block;
351
}
352
/* We have a byte to return. */
353
block->left--;
354
return *block->next++;
355
}
356
357
/* Return a 16-bit unsigned little-endian value from block, or a negative value
358
// if the end is reached. */
359
local long block_get2(block_t *block) {
360
long got = block_get(block);
361
return got | ((unsigned long)block_get(block) << 8);
362
}
363
364
/* Read up to len bytes from block into buf. Return the number of bytes read. */
365
local size_t block_read(block_t *block, unsigned char *buf, size_t len) {
366
size_t need = len;
367
while (need) {
368
if (block->left == 0) {
369
/* Get a byte to update and step through the linked list as needed. */
370
int got = block_get(block);
371
if (got == -1)
372
/* Reached the end. */
373
break;
374
*buf++ = (unsigned char)got;
375
need--;
376
continue;
377
}
378
size_t take = need > block->left ? block->left : need;
379
memcpy(buf, block->next, take);
380
block->next += take;
381
block->left -= take;
382
buf += take;
383
need -= take;
384
}
385
return len - need; /* return the number of bytes copied */
386
}
387
388
/* Skip n bytes in block. Return 0 on success or -1 if there are less than n
389
// bytes to the end. */
390
local int block_skip(block_t *block, size_t n) {
391
while (n > block->left) {
392
n -= block->left;
393
block->next += block->left;
394
block->left = 0;
395
if (block_get(block) == -1)
396
return -1;
397
n--;
398
}
399
block->next += n;
400
block->left -= n;
401
return 0;
402
}
403
404
/* Process the next central directory record at *block. Return the allocated,
405
// zero-terminated file name, or NULL for end of input or invalid data. If
406
// invalid, *block is marked bad. This uses *set for the allocation of memory. */
407
local char *block_central_name(block_t *block, set_t *set) {
408
char *name = NULL;
409
for (;;) {
410
if (block_end(block))
411
/* At the end of the central directory (so far). */
412
return NULL;
413
414
/* Check for a central directory record signature. */
415
if (block_get2(block) != (CENTRALHEADERMAGIC & 0xffff) ||
416
block_get2(block) != (CENTRALHEADERMAGIC >> 16))
417
/* Incorrect signature. */
418
break;
419
420
/* Go through the remaining fixed-length portion of the record,
421
// extracting the lengths of the three variable-length fields. */
422
block_skip(block, 24);
423
unsigned flen = block_get2(block); /* file name length */
424
unsigned xlen = block_get2(block); /* extra field length */
425
unsigned clen = block_get2(block); /* comment field length */
426
if (block_skip(block, 12) == -1)
427
/* Premature end of the record. */
428
break;
429
430
/* Extract the name and skip over the extra and comment fields. */
431
name = set_alloc(set, NULL, flen + 1);
432
if (block_read(block, (unsigned char *)name, flen) < flen ||
433
block_skip(block, xlen + clen) == -1)
434
/* Premature end of the record. */
435
break;
436
437
/* Check for embedded nuls in the name. */
438
if (memchr(name, 0, flen) != NULL) {
439
/* This name can never match the zero-terminated name provided to
440
// zipAlreadyThere(), so we discard it and go back to get another
441
// name. (Who the heck is putting nuls inside their zip file entry
442
// names anyway?) */
443
set_free(set, name);
444
continue;
445
}
446
447
/* All good. Return the zero-terminated file name. */
448
name[flen] = 0;
449
return name;
450
}
451
452
/* Invalid signature or premature end of the central directory record.
453
// Abandon trying to process the central directory. */
454
set_free(set, name);
455
block_stop(block);
456
return NULL;
457
}
458
459
/* Return 0 if name is not in the central directory so far, 1 if it is, -1 if
460
// the central directory is invalid, -2 if out of memory, or ZIP_PARAMERROR if
461
// file is NULL. */
462
extern int ZEXPORT zipAlreadyThere(zipFile file, char const *name) {
463
zip64_internal *zip = file;
464
if (zip == NULL)
465
return ZIP_PARAMERROR;
466
if (zip->central_dir.first_block == NULL)
467
/* No central directory yet, so no, name isn't there. */
468
return 0;
469
if (setjmp(zip->set.env)) {
470
/* Memory allocation failure. */
471
set_end(&zip->set);
472
return -2;
473
}
474
if (!set_ok(&zip->set)) {
475
/* This is the first time here with some central directory content. We
476
// construct this set of names only on demand. Prepare set and block. */
477
set_start(&zip->set);
478
block_init(&zip->block, &zip->central_dir);
479
}
480
481
/* Update the set of names from the current central directory contents.
482
// This reads any new central directory records since the last time we were
483
// here. */
484
for (;;) {
485
char *there = block_central_name(&zip->block, &zip->set);
486
if (there == NULL) {
487
if (zip->block.next == NULL)
488
/* The central directory is invalid. */
489
return -1;
490
break;
491
}
492
493
/* Add there to the set. */
494
if (set_insert(&zip->set, there))
495
/* There's already a duplicate in the central directory! We'll just
496
// let this be and carry on. */
497
set_free(&zip->set, there);
498
}
499
500
/* Return true if name is in the central directory. */
501
size_t len = strlen(name);
502
char *copy = set_alloc(&zip->set, NULL, len + 1);
503
strcpy(copy, name);
504
int found = set_found(&zip->set, copy);
505
set_free(&zip->set, copy);
506
return found;
507
}
508
509
510
/****************************************************************************/
511
512
#ifndef NO_ADDFILEINEXISTINGZIP
513
/* ===========================================================================
514
Inputs a long in LSB order to the given file
515
nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)
516
*/
517
518
local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) {
519
unsigned char buf[8];
520
int n;
521
for (n = 0; n < nbByte; n++)
522
{
523
buf[n] = (unsigned char)(x & 0xff);
524
x >>= 8;
525
}
526
if (x != 0)
527
{ /* data overflow - hack for ZIP64 (X Roche) */
528
for (n = 0; n < nbByte; n++)
529
{
530
buf[n] = 0xff;
531
}
532
}
533
534
if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte)
535
return ZIP_ERRNO;
536
else
537
return ZIP_OK;
538
}
539
540
local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) {
541
unsigned char* buf=(unsigned char*)dest;
542
int n;
543
for (n = 0; n < nbByte; n++) {
544
buf[n] = (unsigned char)(x & 0xff);
545
x >>= 8;
546
}
547
548
if (x != 0)
549
{ /* data overflow - hack for ZIP64 */
550
for (n = 0; n < nbByte; n++)
551
{
552
buf[n] = 0xff;
553
}
554
}
555
}
556
557
/****************************************************************************/
558
559
560
local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) {
561
uLong year = (uLong)ptm->tm_year;
562
if (year>=1980)
563
year-=1980;
564
else if (year>=80)
565
year-=80;
566
return
567
(uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) |
568
(((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
569
}
570
571
572
/****************************************************************************/
573
574
local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) {
575
unsigned char c;
576
int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
577
if (err==1)
578
{
579
*pi = (int)c;
580
return ZIP_OK;
581
}
582
else
583
{
584
if (ZERROR64(*pzlib_filefunc_def,filestream))
585
return ZIP_ERRNO;
586
else
587
return ZIP_EOF;
588
}
589
}
590
591
592
/* ===========================================================================
593
Reads a long in LSB order from the given gz_stream. Sets
594
*/
595
local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
596
uLong x ;
597
int i = 0;
598
int err;
599
600
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
601
x = (uLong)i;
602
603
if (err==ZIP_OK)
604
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
605
x += ((uLong)i)<<8;
606
607
if (err==ZIP_OK)
608
*pX = x;
609
else
610
*pX = 0;
611
return err;
612
}
613
614
local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
615
uLong x ;
616
int i = 0;
617
int err;
618
619
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
620
x = (uLong)i;
621
622
if (err==ZIP_OK)
623
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
624
x += ((uLong)i)<<8;
625
626
if (err==ZIP_OK)
627
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
628
x += ((uLong)i)<<16;
629
630
if (err==ZIP_OK)
631
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
632
x += ((uLong)i)<<24;
633
634
if (err==ZIP_OK)
635
*pX = x;
636
else
637
*pX = 0;
638
return err;
639
}
640
641
642
local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) {
643
ZPOS64_T x;
644
int i = 0;
645
int err;
646
647
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
648
x = (ZPOS64_T)i;
649
650
if (err==ZIP_OK)
651
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
652
x += ((ZPOS64_T)i)<<8;
653
654
if (err==ZIP_OK)
655
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
656
x += ((ZPOS64_T)i)<<16;
657
658
if (err==ZIP_OK)
659
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
660
x += ((ZPOS64_T)i)<<24;
661
662
if (err==ZIP_OK)
663
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
664
x += ((ZPOS64_T)i)<<32;
665
666
if (err==ZIP_OK)
667
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
668
x += ((ZPOS64_T)i)<<40;
669
670
if (err==ZIP_OK)
671
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
672
x += ((ZPOS64_T)i)<<48;
673
674
if (err==ZIP_OK)
675
err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
676
x += ((ZPOS64_T)i)<<56;
677
678
if (err==ZIP_OK)
679
*pX = x;
680
else
681
*pX = 0;
682
683
return err;
684
}
685
686
#ifndef BUFREADCOMMENT
687
#define BUFREADCOMMENT (0x400)
688
#endif
689
/*
690
Locate the Central directory of a zipfile (at the end, just before
691
the global comment)
692
*/
693
local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
694
unsigned char* buf;
695
ZPOS64_T uSizeFile;
696
ZPOS64_T uBackRead;
697
ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
698
ZPOS64_T uPosFound=0;
699
700
if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
701
return 0;
702
703
704
uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
705
706
if (uMaxBack>uSizeFile)
707
uMaxBack = uSizeFile;
708
709
buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
710
if (buf==NULL)
711
return 0;
712
713
uBackRead = 4;
714
while (uBackRead<uMaxBack)
715
{
716
uLong uReadSize;
717
ZPOS64_T uReadPos ;
718
int i;
719
if (uBackRead+BUFREADCOMMENT>uMaxBack)
720
uBackRead = uMaxBack;
721
else
722
uBackRead+=BUFREADCOMMENT;
723
uReadPos = uSizeFile-uBackRead ;
724
725
uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
726
(BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
727
if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
728
break;
729
730
if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
731
break;
732
733
for (i=(int)uReadSize-3; (i--)>0;)
734
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
735
((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
736
{
737
uPosFound = uReadPos+(unsigned)i;
738
break;
739
}
740
741
if (uPosFound!=0)
742
break;
743
}
744
free(buf);
745
return uPosFound;
746
}
747
748
/*
749
Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before
750
the global comment)
751
*/
752
local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
753
unsigned char* buf;
754
ZPOS64_T uSizeFile;
755
ZPOS64_T uBackRead;
756
ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
757
ZPOS64_T uPosFound=0;
758
uLong uL;
759
ZPOS64_T relativeOffset;
760
761
if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
762
return 0;
763
764
uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
765
766
if (uMaxBack>uSizeFile)
767
uMaxBack = uSizeFile;
768
769
buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
770
if (buf==NULL)
771
return 0;
772
773
uBackRead = 4;
774
while (uBackRead<uMaxBack)
775
{
776
uLong uReadSize;
777
ZPOS64_T uReadPos;
778
int i;
779
if (uBackRead+BUFREADCOMMENT>uMaxBack)
780
uBackRead = uMaxBack;
781
else
782
uBackRead+=BUFREADCOMMENT;
783
uReadPos = uSizeFile-uBackRead ;
784
785
uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
786
(BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
787
if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
788
break;
789
790
if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
791
break;
792
793
for (i=(int)uReadSize-3; (i--)>0;)
794
{
795
/* Signature "0x07064b50" Zip64 end of central directory locator */
796
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
797
{
798
uPosFound = uReadPos+(unsigned)i;
799
break;
800
}
801
}
802
803
if (uPosFound!=0)
804
break;
805
}
806
807
free(buf);
808
if (uPosFound == 0)
809
return 0;
810
811
/* Zip64 end of central directory locator */
812
if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
813
return 0;
814
815
/* the signature, already checked */
816
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
817
return 0;
818
819
/* number of the disk with the start of the zip64 end of central directory */
820
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
821
return 0;
822
if (uL != 0)
823
return 0;
824
825
/* relative offset of the zip64 end of central directory record */
826
if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK)
827
return 0;
828
829
/* total number of disks */
830
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
831
return 0;
832
if (uL != 1)
833
return 0;
834
835
/* Goto Zip64 end of central directory record */
836
if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
837
return 0;
838
839
/* the signature */
840
if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
841
return 0;
842
843
if (uL != 0x06064b50) /* signature of 'Zip64 end of central directory' */
844
return 0;
845
846
return relativeOffset;
847
}
848
849
local int LoadCentralDirectoryRecord(zip64_internal* pziinit) {
850
int err=ZIP_OK;
851
ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
852
853
ZPOS64_T size_central_dir; /* size of the central directory */
854
ZPOS64_T offset_central_dir; /* offset of start of central directory */
855
ZPOS64_T central_pos;
856
uLong uL;
857
858
uLong number_disk; /* number of the current disk, used for
859
spanning ZIP, unsupported, always 0*/
860
uLong number_disk_with_CD; /* number of the disk with central dir, used
861
for spanning ZIP, unsupported, always 0*/
862
ZPOS64_T number_entry;
863
ZPOS64_T number_entry_CD; /* total number of entries in
864
the central dir
865
(same than number_entry on nospan) */
866
uLong VersionMadeBy;
867
uLong VersionNeeded;
868
uLong size_comment;
869
870
int hasZIP64Record = 0;
871
872
/* check first if we find a ZIP64 record */
873
central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream);
874
if(central_pos > 0)
875
{
876
hasZIP64Record = 1;
877
}
878
else if(central_pos == 0)
879
{
880
central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream);
881
}
882
883
/* disable to allow appending to empty ZIP archive
884
if (central_pos==0)
885
err=ZIP_ERRNO;
886
*/
887
888
if(hasZIP64Record)
889
{
890
ZPOS64_T sizeEndOfCentralDirectory;
891
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
892
err=ZIP_ERRNO;
893
894
/* the signature, already checked */
895
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
896
err=ZIP_ERRNO;
897
898
/* size of zip64 end of central directory record */
899
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK)
900
err=ZIP_ERRNO;
901
902
/* version made by */
903
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK)
904
err=ZIP_ERRNO;
905
906
/* version needed to extract */
907
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK)
908
err=ZIP_ERRNO;
909
910
/* number of this disk */
911
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
912
err=ZIP_ERRNO;
913
914
/* number of the disk with the start of the central directory */
915
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
916
err=ZIP_ERRNO;
917
918
/* total number of entries in the central directory on this disk */
919
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK)
920
err=ZIP_ERRNO;
921
922
/* total number of entries in the central directory */
923
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK)
924
err=ZIP_ERRNO;
925
926
if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
927
err=ZIP_BADZIPFILE;
928
929
/* size of the central directory */
930
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK)
931
err=ZIP_ERRNO;
932
933
/* offset of start of central directory with respect to the
934
starting disk number */
935
if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK)
936
err=ZIP_ERRNO;
937
938
/* TODO..
939
// read the comment from the standard central header. */
940
size_comment = 0;
941
}
942
else
943
{
944
/* Read End of central Directory info */
945
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
946
err=ZIP_ERRNO;
947
948
/* the signature, already checked */
949
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
950
err=ZIP_ERRNO;
951
952
/* number of this disk */
953
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
954
err=ZIP_ERRNO;
955
956
/* number of the disk with the start of the central directory */
957
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
958
err=ZIP_ERRNO;
959
960
/* total number of entries in the central dir on this disk */
961
number_entry = 0;
962
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
963
err=ZIP_ERRNO;
964
else
965
number_entry = uL;
966
967
/* total number of entries in the central dir */
968
number_entry_CD = 0;
969
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
970
err=ZIP_ERRNO;
971
else
972
number_entry_CD = uL;
973
974
if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
975
err=ZIP_BADZIPFILE;
976
977
/* size of the central directory */
978
size_central_dir = 0;
979
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
980
err=ZIP_ERRNO;
981
else
982
size_central_dir = uL;
983
984
/* offset of start of central directory with respect to the starting disk number */
985
offset_central_dir = 0;
986
if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
987
err=ZIP_ERRNO;
988
else
989
offset_central_dir = uL;
990
991
992
/* zipfile global comment length */
993
if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK)
994
err=ZIP_ERRNO;
995
}
996
997
if ((central_pos<offset_central_dir+size_central_dir) &&
998
(err==ZIP_OK))
999
err=ZIP_BADZIPFILE;
1000
1001
if (err!=ZIP_OK)
1002
{
1003
ZCLOSE64(pziinit->z_filefunc, pziinit->filestream);
1004
return ZIP_ERRNO;
1005
}
1006
1007
if (size_comment>0)
1008
{
1009
pziinit->globalcomment = (char*)ALLOC(size_comment+1);
1010
if (pziinit->globalcomment)
1011
{
1012
size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment);
1013
pziinit->globalcomment[size_comment]=0;
1014
}
1015
}
1016
1017
byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);
1018
pziinit->add_position_when_writing_offset = byte_before_the_zipfile;
1019
1020
{
1021
ZPOS64_T size_central_dir_to_read = size_central_dir;
1022
size_t buf_size = SIZEDATA_INDATABLOCK;
1023
void* buf_read = (void*)ALLOC(buf_size);
1024
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
1025
err=ZIP_ERRNO;
1026
1027
while ((size_central_dir_to_read>0) && (err==ZIP_OK))
1028
{
1029
ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
1030
if (read_this > size_central_dir_to_read)
1031
read_this = size_central_dir_to_read;
1032
1033
if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this)
1034
err=ZIP_ERRNO;
1035
1036
if (err==ZIP_OK)
1037
err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this);
1038
1039
size_central_dir_to_read-=read_this;
1040
}
1041
free(buf_read);
1042
}
1043
pziinit->begin_pos = byte_before_the_zipfile;
1044
pziinit->number_entry = number_entry_CD;
1045
1046
if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)
1047
err=ZIP_ERRNO;
1048
1049
return err;
1050
}
1051
1052
1053
#endif /* !NO_ADDFILEINEXISTINGZIP*/
1054
1055
1056
/************************************************************/
1057
extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) {
1058
zip64_internal ziinit;
1059
zip64_internal* zi;
1060
int err=ZIP_OK;
1061
1062
ziinit.z_filefunc.zseek32_file = NULL;
1063
ziinit.z_filefunc.ztell32_file = NULL;
1064
if (pzlib_filefunc64_32_def==NULL) {
1065
//fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
1066
} else
1067
ziinit.z_filefunc = *pzlib_filefunc64_32_def;
1068
1069
ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
1070
pathname,
1071
(append == APPEND_STATUS_CREATE) ?
1072
(ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
1073
(ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
1074
1075
if (ziinit.filestream == NULL)
1076
return NULL;
1077
1078
if (append == APPEND_STATUS_CREATEAFTER)
1079
ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END);
1080
1081
ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream);
1082
ziinit.in_opened_file_inzip = 0;
1083
ziinit.ci.stream_initialised = 0;
1084
ziinit.number_entry = 0;
1085
ziinit.add_position_when_writing_offset = 0;
1086
init_linkedlist(&(ziinit.central_dir));
1087
memset(&ziinit.set, 0, sizeof(set_t)); /* make sure set appears dormant */
1088
1089
1090
1091
zi = (zip64_internal*)ALLOC(sizeof(zip64_internal));
1092
if (zi==NULL)
1093
{
1094
ZCLOSE64(ziinit.z_filefunc,ziinit.filestream);
1095
return NULL;
1096
}
1097
1098
/* now we add file in a zipfile */
1099
# ifndef NO_ADDFILEINEXISTINGZIP
1100
ziinit.globalcomment = NULL;
1101
if (append == APPEND_STATUS_ADDINZIP)
1102
{
1103
/* Read and Cache Central Directory Records */
1104
err = LoadCentralDirectoryRecord(&ziinit);
1105
}
1106
1107
if (globalcomment)
1108
{
1109
*globalcomment = ziinit.globalcomment;
1110
}
1111
# endif /* !NO_ADDFILEINEXISTINGZIP*/
1112
1113
if (err != ZIP_OK)
1114
{
1115
# ifndef NO_ADDFILEINEXISTINGZIP
1116
free(ziinit.globalcomment);
1117
# endif /* !NO_ADDFILEINEXISTINGZIP*/
1118
free(zi);
1119
return NULL;
1120
}
1121
else
1122
{
1123
*zi = ziinit;
1124
return (zipFile)zi;
1125
}
1126
}
1127
1128
extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) {
1129
if (pzlib_filefunc32_def != NULL)
1130
{
1131
zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
1132
fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
1133
return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
1134
}
1135
else
1136
return zipOpen3(pathname, append, globalcomment, NULL);
1137
}
1138
1139
extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) {
1140
if (pzlib_filefunc_def != NULL)
1141
{
1142
zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
1143
zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
1144
zlib_filefunc64_32_def_fill.ztell32_file = NULL;
1145
zlib_filefunc64_32_def_fill.zseek32_file = NULL;
1146
return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
1147
}
1148
else
1149
return zipOpen3(pathname, append, globalcomment, NULL);
1150
}
1151
1152
1153
1154
extern zipFile ZEXPORT zipOpen(const char* pathname, int append) {
1155
return zipOpen3((const void*)pathname,append,NULL,NULL);
1156
}
1157
1158
extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) {
1159
return zipOpen3(pathname,append,NULL,NULL);
1160
}
1161
1162
local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) {
1163
/* write the local header */
1164
int err;
1165
uInt size_filename = (uInt)strlen(filename);
1166
uInt size_extrafield = size_extrafield_local;
1167
1168
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4);
1169
1170
if (err==ZIP_OK)
1171
{
1172
if(zi->ci.zip64)
1173
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */
1174
else
1175
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
1176
}
1177
1178
if (err==ZIP_OK)
1179
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
1180
1181
if (err==ZIP_OK)
1182
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
1183
1184
if (err==ZIP_OK)
1185
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
1186
1187
/* CRC / Compressed size / Uncompressed size will be filled in later and rewritten later */
1188
if (err==ZIP_OK)
1189
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
1190
if (err==ZIP_OK)
1191
{
1192
if(zi->ci.zip64)
1193
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */
1194
else
1195
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
1196
}
1197
if (err==ZIP_OK)
1198
{
1199
if(zi->ci.zip64)
1200
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */
1201
else
1202
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
1203
}
1204
1205
if (err==ZIP_OK)
1206
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
1207
1208
if(zi->ci.zip64)
1209
{
1210
size_extrafield += 20;
1211
}
1212
1213
if (err==ZIP_OK)
1214
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2);
1215
1216
if ((err==ZIP_OK) && (size_filename > 0))
1217
{
1218
if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
1219
err = ZIP_ERRNO;
1220
}
1221
1222
if ((err==ZIP_OK) && (size_extrafield_local > 0))
1223
{
1224
if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
1225
err = ZIP_ERRNO;
1226
}
1227
1228
1229
if ((err==ZIP_OK) && (zi->ci.zip64))
1230
{
1231
/* write the Zip64 extended info */
1232
short HeaderID = 1;
1233
short DataSize = 16;
1234
ZPOS64_T CompressedSize = 0;
1235
ZPOS64_T UncompressedSize = 0;
1236
1237
/* Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) */
1238
zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);
1239
1240
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2);
1241
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2);
1242
1243
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);
1244
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);
1245
}
1246
1247
return err;
1248
}
1249
1250
/*
1251
NOTE.
1252
When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped
1253
before calling this function it can be done with zipRemoveExtraInfoBlock
1254
1255
It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize
1256
unnecessary allocations.
1257
*/
1258
extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1259
const void* extrafield_local, uInt size_extrafield_local,
1260
const void* extrafield_global, uInt size_extrafield_global,
1261
const char* comment, int method, int level, int raw,
1262
int windowBits,int memLevel, int strategy,
1263
const char* password, uLong crcForCrypting,
1264
uLong versionMadeBy, uLong flagBase, int zip64) {
1265
zip64_internal* zi;
1266
uInt size_filename;
1267
uInt size_comment;
1268
uInt i;
1269
int err = ZIP_OK;
1270
1271
# ifdef NOCRYPT
1272
if (password != NULL)
1273
return ZIP_PARAMERROR;
1274
# endif
1275
1276
if (file == NULL)
1277
return ZIP_PARAMERROR;
1278
1279
#ifdef HAVE_BZIP2
1280
if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED))
1281
return ZIP_PARAMERROR;
1282
#else
1283
if ((method!=0) && (method!=Z_DEFLATED))
1284
return ZIP_PARAMERROR;
1285
#endif
1286
1287
/* The filename and comment length must fit in 16 bits. */
1288
if ((filename!=NULL) && (strlen(filename)>0xffff))
1289
return ZIP_PARAMERROR;
1290
if ((comment!=NULL) && (strlen(comment)>0xffff))
1291
return ZIP_PARAMERROR;
1292
/* The extra field length must fit in 16 bits. If the member also requires
1293
// a Zip64 extra block, that will also need to fit within that 16-bit
1294
// length, but that will be checked for later. */
1295
if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
1296
return ZIP_PARAMERROR;
1297
1298
zi = (zip64_internal*)file;
1299
1300
if (zi->in_opened_file_inzip == 1)
1301
{
1302
err = zipCloseFileInZip (file);
1303
if (err != ZIP_OK)
1304
return err;
1305
}
1306
1307
if (filename==NULL)
1308
filename="-";
1309
1310
if (comment==NULL)
1311
size_comment = 0;
1312
else
1313
size_comment = (uInt)strlen(comment);
1314
1315
size_filename = (uInt)strlen(filename);
1316
1317
if (zipfi == NULL)
1318
zi->ci.dosDate = 0;
1319
else
1320
{
1321
if (zipfi->dosDate != 0)
1322
zi->ci.dosDate = zipfi->dosDate;
1323
else
1324
zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);
1325
}
1326
1327
zi->ci.flag = flagBase;
1328
if ((level==8) || (level==9))
1329
zi->ci.flag |= 2;
1330
if (level==2)
1331
zi->ci.flag |= 4;
1332
if (level==1)
1333
zi->ci.flag |= 6;
1334
if (password != NULL)
1335
zi->ci.flag |= 1;
1336
1337
zi->ci.crc32 = 0;
1338
zi->ci.method = method;
1339
zi->ci.encrypt = 0;
1340
zi->ci.stream_initialised = 0;
1341
zi->ci.pos_in_buffered_data = 0;
1342
zi->ci.raw = raw;
1343
zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream);
1344
1345
zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
1346
zi->ci.size_centralExtraFree = 32; /* Extra space we have reserved in case we need to add ZIP64 extra info data */
1347
1348
zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree);
1349
1350
zi->ci.size_centralExtra = size_extrafield_global;
1351
zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
1352
/* version info */
1353
zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2);
1354
zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
1355
zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
1356
zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
1357
zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
1358
zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
1359
zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
1360
zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
1361
zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
1362
zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
1363
zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
1364
zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
1365
1366
if (zipfi==NULL)
1367
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
1368
else
1369
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
1370
1371
if (zipfi==NULL)
1372
zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
1373
else
1374
zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
1375
1376
if(zi->ci.pos_local_header >= 0xffffffff)
1377
zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4);
1378
else
1379
zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4);
1380
1381
for (i=0;i<size_filename;i++)
1382
*(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
1383
1384
for (i=0;i<size_extrafield_global;i++)
1385
*(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
1386
*(((const char*)extrafield_global)+i);
1387
1388
for (i=0;i<size_comment;i++)
1389
*(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
1390
size_extrafield_global+i) = *(comment+i);
1391
if (zi->ci.central_header == NULL)
1392
return ZIP_INTERNALERROR;
1393
1394
zi->ci.zip64 = zip64;
1395
zi->ci.totalCompressedData = 0;
1396
zi->ci.totalUncompressedData = 0;
1397
zi->ci.pos_zip64extrainfo = 0;
1398
1399
err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local);
1400
1401
#ifdef HAVE_BZIP2
1402
zi->ci.bstream.avail_in = (uInt)0;
1403
zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1404
zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1405
zi->ci.bstream.total_in_hi32 = 0;
1406
zi->ci.bstream.total_in_lo32 = 0;
1407
zi->ci.bstream.total_out_hi32 = 0;
1408
zi->ci.bstream.total_out_lo32 = 0;
1409
#endif
1410
1411
zi->ci.stream.avail_in = (uInt)0;
1412
zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1413
zi->ci.stream.next_out = zi->ci.buffered_data;
1414
zi->ci.stream.total_in = 0;
1415
zi->ci.stream.total_out = 0;
1416
zi->ci.stream.data_type = Z_BINARY;
1417
1418
#ifdef HAVE_BZIP2
1419
if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1420
#else
1421
if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1422
#endif
1423
{
1424
if(zi->ci.method == Z_DEFLATED)
1425
{
1426
zi->ci.stream.zalloc = zi->z_filefunc.zfile_func64.alloc_mem;
1427
zi->ci.stream.zfree = zi->z_filefunc.zfile_func64.free_mem;
1428
zi->ci.stream.opaque = (voidpf)0;
1429
1430
if (windowBits>0)
1431
windowBits = -windowBits;
1432
1433
err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
1434
1435
if (err==Z_OK)
1436
zi->ci.stream_initialised = Z_DEFLATED;
1437
}
1438
else if(zi->ci.method == Z_BZIP2ED)
1439
{
1440
#ifdef HAVE_BZIP2
1441
/* Init BZip stuff here */
1442
zi->ci.bstream.bzalloc = 0;
1443
zi->ci.bstream.bzfree = 0;
1444
zi->ci.bstream.opaque = (voidpf)0;
1445
1446
err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35);
1447
if(err == BZ_OK)
1448
zi->ci.stream_initialised = Z_BZIP2ED;
1449
#endif
1450
}
1451
1452
}
1453
1454
# ifndef NOCRYPT
1455
zi->ci.crypt_header_size = 0;
1456
if ((err==Z_OK) && (password != NULL))
1457
{
1458
unsigned char bufHead[RAND_HEAD_LEN];
1459
unsigned int sizeHead;
1460
zi->ci.encrypt = 1;
1461
zi->ci.pcrc_32_tab = get_crc_table();
1462
/*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
1463
1464
sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
1465
zi->ci.crypt_header_size = sizeHead;
1466
1467
if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
1468
err = ZIP_ERRNO;
1469
}
1470
# endif
1471
1472
if (err==Z_OK)
1473
zi->in_opened_file_inzip = 1;
1474
return err;
1475
}
1476
1477
extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1478
const void* extrafield_local, uInt size_extrafield_local,
1479
const void* extrafield_global, uInt size_extrafield_global,
1480
const char* comment, int method, int level, int raw,
1481
int windowBits,int memLevel, int strategy,
1482
const char* password, uLong crcForCrypting,
1483
uLong versionMadeBy, uLong flagBase) {
1484
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1485
extrafield_local, size_extrafield_local,
1486
extrafield_global, size_extrafield_global,
1487
comment, method, level, raw,
1488
windowBits, memLevel, strategy,
1489
password, crcForCrypting, versionMadeBy, flagBase, 0);
1490
}
1491
1492
extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1493
const void* extrafield_local, uInt size_extrafield_local,
1494
const void* extrafield_global, uInt size_extrafield_global,
1495
const char* comment, int method, int level, int raw,
1496
int windowBits,int memLevel, int strategy,
1497
const char* password, uLong crcForCrypting) {
1498
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1499
extrafield_local, size_extrafield_local,
1500
extrafield_global, size_extrafield_global,
1501
comment, method, level, raw,
1502
windowBits, memLevel, strategy,
1503
password, crcForCrypting, VERSIONMADEBY, 0, 0);
1504
}
1505
1506
extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1507
const void* extrafield_local, uInt size_extrafield_local,
1508
const void* extrafield_global, uInt size_extrafield_global,
1509
const char* comment, int method, int level, int raw,
1510
int windowBits,int memLevel, int strategy,
1511
const char* password, uLong crcForCrypting, int zip64) {
1512
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1513
extrafield_local, size_extrafield_local,
1514
extrafield_global, size_extrafield_global,
1515
comment, method, level, raw,
1516
windowBits, memLevel, strategy,
1517
password, crcForCrypting, VERSIONMADEBY, 0, zip64);
1518
}
1519
1520
extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1521
const void* extrafield_local, uInt size_extrafield_local,
1522
const void* extrafield_global, uInt size_extrafield_global,
1523
const char* comment, int method, int level, int raw) {
1524
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1525
extrafield_local, size_extrafield_local,
1526
extrafield_global, size_extrafield_global,
1527
comment, method, level, raw,
1528
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1529
NULL, 0, VERSIONMADEBY, 0, 0);
1530
}
1531
1532
extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1533
const void* extrafield_local, uInt size_extrafield_local,
1534
const void* extrafield_global, uInt size_extrafield_global,
1535
const char* comment, int method, int level, int raw, int zip64) {
1536
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1537
extrafield_local, size_extrafield_local,
1538
extrafield_global, size_extrafield_global,
1539
comment, method, level, raw,
1540
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1541
NULL, 0, VERSIONMADEBY, 0, zip64);
1542
}
1543
1544
extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1545
const void* extrafield_local, uInt size_extrafield_local,
1546
const void*extrafield_global, uInt size_extrafield_global,
1547
const char* comment, int method, int level, int zip64) {
1548
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1549
extrafield_local, size_extrafield_local,
1550
extrafield_global, size_extrafield_global,
1551
comment, method, level, 0,
1552
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1553
NULL, 0, VERSIONMADEBY, 0, zip64);
1554
}
1555
1556
extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1557
const void* extrafield_local, uInt size_extrafield_local,
1558
const void*extrafield_global, uInt size_extrafield_global,
1559
const char* comment, int method, int level) {
1560
return zipOpenNewFileInZip4_64(file, filename, zipfi,
1561
extrafield_local, size_extrafield_local,
1562
extrafield_global, size_extrafield_global,
1563
comment, method, level, 0,
1564
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1565
NULL, 0, VERSIONMADEBY, 0, 0);
1566
}
1567
1568
local int zip64FlushWriteBuffer(zip64_internal* zi) {
1569
int err=ZIP_OK;
1570
1571
if (zi->ci.encrypt != 0)
1572
{
1573
#ifndef NOCRYPT
1574
uInt i;
1575
int t;
1576
for (i=0;i<zi->ci.pos_in_buffered_data;i++)
1577
zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t);
1578
#endif
1579
}
1580
1581
if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data)
1582
err = ZIP_ERRNO;
1583
1584
zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data;
1585
1586
#ifdef HAVE_BZIP2
1587
if(zi->ci.method == Z_BZIP2ED)
1588
{
1589
zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32;
1590
zi->ci.bstream.total_in_lo32 = 0;
1591
zi->ci.bstream.total_in_hi32 = 0;
1592
}
1593
else
1594
#endif
1595
{
1596
zi->ci.totalUncompressedData += zi->ci.stream.total_in;
1597
zi->ci.stream.total_in = 0;
1598
}
1599
1600
1601
zi->ci.pos_in_buffered_data = 0;
1602
1603
return err;
1604
}
1605
1606
extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) {
1607
zip64_internal* zi;
1608
int err=ZIP_OK;
1609
1610
if (file == NULL)
1611
return ZIP_PARAMERROR;
1612
zi = (zip64_internal*)file;
1613
1614
if (zi->in_opened_file_inzip == 0)
1615
return ZIP_PARAMERROR;
1616
1617
zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len);
1618
1619
#ifdef HAVE_BZIP2
1620
if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw))
1621
{
1622
zi->ci.bstream.next_in = (void*)buf;
1623
zi->ci.bstream.avail_in = len;
1624
err = BZ_RUN_OK;
1625
1626
while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0))
1627
{
1628
if (zi->ci.bstream.avail_out == 0)
1629
{
1630
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1631
err = ZIP_ERRNO;
1632
zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1633
zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1634
}
1635
1636
1637
if(err != BZ_RUN_OK)
1638
break;
1639
1640
if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1641
{
1642
uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;
1643
/* uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; */
1644
err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN);
1645
1646
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ;
1647
}
1648
}
1649
1650
if(err == BZ_RUN_OK)
1651
err = ZIP_OK;
1652
}
1653
else
1654
#endif
1655
{
1656
zi->ci.stream.next_in = buf;
1657
zi->ci.stream.avail_in = len;
1658
1659
while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
1660
{
1661
if (zi->ci.stream.avail_out == 0)
1662
{
1663
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1664
err = ZIP_ERRNO;
1665
zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1666
zi->ci.stream.next_out = zi->ci.buffered_data;
1667
}
1668
1669
1670
if(err != ZIP_OK)
1671
break;
1672
1673
if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1674
{
1675
uLong uTotalOutBefore = zi->ci.stream.total_out;
1676
err=deflate(&zi->ci.stream, Z_NO_FLUSH);
1677
1678
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1679
}
1680
else
1681
{
1682
uInt copy_this,i;
1683
if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
1684
copy_this = zi->ci.stream.avail_in;
1685
else
1686
copy_this = zi->ci.stream.avail_out;
1687
1688
for (i = 0; i < copy_this; i++)
1689
*(((char*)zi->ci.stream.next_out)+i) =
1690
*(((const char*)zi->ci.stream.next_in)+i);
1691
{
1692
zi->ci.stream.avail_in -= copy_this;
1693
zi->ci.stream.avail_out-= copy_this;
1694
zi->ci.stream.next_in+= copy_this;
1695
zi->ci.stream.next_out+= copy_this;
1696
zi->ci.stream.total_in+= copy_this;
1697
zi->ci.stream.total_out+= copy_this;
1698
zi->ci.pos_in_buffered_data += copy_this;
1699
}
1700
}
1701
}/* while(...) */
1702
}
1703
1704
return err;
1705
}
1706
1707
extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) {
1708
return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
1709
}
1710
1711
extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) {
1712
zip64_internal* zi;
1713
ZPOS64_T compressed_size;
1714
uLong invalidValue = 0xffffffff;
1715
unsigned datasize = 0;
1716
int err=ZIP_OK;
1717
1718
if (file == NULL)
1719
return ZIP_PARAMERROR;
1720
zi = (zip64_internal*)file;
1721
1722
if (zi->in_opened_file_inzip == 0)
1723
return ZIP_PARAMERROR;
1724
zi->ci.stream.avail_in = 0;
1725
1726
if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1727
{
1728
while (err==ZIP_OK)
1729
{
1730
uLong uTotalOutBefore;
1731
if (zi->ci.stream.avail_out == 0)
1732
{
1733
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1734
err = ZIP_ERRNO;
1735
zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1736
zi->ci.stream.next_out = zi->ci.buffered_data;
1737
}
1738
uTotalOutBefore = zi->ci.stream.total_out;
1739
err=deflate(&zi->ci.stream, Z_FINISH);
1740
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1741
}
1742
}
1743
else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1744
{
1745
#ifdef HAVE_BZIP2
1746
err = BZ_FINISH_OK;
1747
while (err==BZ_FINISH_OK)
1748
{
1749
uLong uTotalOutBefore;
1750
if (zi->ci.bstream.avail_out == 0)
1751
{
1752
if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1753
err = ZIP_ERRNO;
1754
zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1755
zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1756
}
1757
uTotalOutBefore = zi->ci.bstream.total_out_lo32;
1758
err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH);
1759
if(err == BZ_STREAM_END)
1760
err = Z_STREAM_END;
1761
1762
zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore);
1763
}
1764
1765
if(err == BZ_FINISH_OK)
1766
err = ZIP_OK;
1767
#endif
1768
}
1769
1770
if (err==Z_STREAM_END)
1771
err=ZIP_OK; /* this is normal */
1772
1773
if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
1774
{
1775
if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO)
1776
err = ZIP_ERRNO;
1777
}
1778
1779
if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1780
{
1781
int tmp_err = deflateEnd(&zi->ci.stream);
1782
if (err == ZIP_OK)
1783
err = tmp_err;
1784
zi->ci.stream_initialised = 0;
1785
}
1786
#ifdef HAVE_BZIP2
1787
else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1788
{
1789
int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream);
1790
if (err==ZIP_OK)
1791
err = tmperr;
1792
zi->ci.stream_initialised = 0;
1793
}
1794
#endif
1795
1796
if (!zi->ci.raw)
1797
{
1798
crc32 = (uLong)zi->ci.crc32;
1799
uncompressed_size = zi->ci.totalUncompressedData;
1800
}
1801
compressed_size = zi->ci.totalCompressedData;
1802
1803
# ifndef NOCRYPT
1804
compressed_size += zi->ci.crypt_header_size;
1805
# endif
1806
1807
/* update Current Item crc and sizes, */
1808
if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff)
1809
{
1810
/*version Made by*/
1811
zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2);
1812
/*version needed*/
1813
zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2);
1814
1815
}
1816
1817
zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
1818
1819
1820
if(compressed_size >= 0xffffffff)
1821
zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/
1822
else
1823
zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/
1824
1825
/* set internal file attributes field */
1826
if (zi->ci.stream.data_type == Z_ASCII)
1827
zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
1828
1829
if(uncompressed_size >= 0xffffffff)
1830
zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/
1831
else
1832
zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/
1833
1834
/* Add ZIP64 extra info field for uncompressed size */
1835
if(uncompressed_size >= 0xffffffff)
1836
datasize += 8;
1837
1838
/* Add ZIP64 extra info field for compressed size */
1839
if(compressed_size >= 0xffffffff)
1840
datasize += 8;
1841
1842
/* Add ZIP64 extra info field for relative offset to local file header of current file */
1843
if(zi->ci.pos_local_header >= 0xffffffff)
1844
datasize += 8;
1845
1846
if(datasize > 0)
1847
{
1848
char* p = NULL;
1849
1850
if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
1851
{
1852
/* we cannot write more data to the buffer that we have room for. */
1853
return ZIP_BADZIPFILE;
1854
}
1855
1856
p = zi->ci.central_header + zi->ci.size_centralheader;
1857
1858
/* Add Extra Information Header for 'ZIP64 information' */
1859
zip64local_putValue_inmemory(p, 0x0001, 2); /* HeaderID */
1860
p += 2;
1861
zip64local_putValue_inmemory(p, datasize, 2); /* DataSize */
1862
p += 2;
1863
1864
if(uncompressed_size >= 0xffffffff)
1865
{
1866
zip64local_putValue_inmemory(p, uncompressed_size, 8);
1867
p += 8;
1868
}
1869
1870
if(compressed_size >= 0xffffffff)
1871
{
1872
zip64local_putValue_inmemory(p, compressed_size, 8);
1873
p += 8;
1874
}
1875
1876
if(zi->ci.pos_local_header >= 0xffffffff)
1877
{
1878
zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8);
1879
p += 8;
1880
}
1881
1882
/* Update how much extra free space we got in the memory buffer
1883
// and increase the centralheader size so the new ZIP64 fields are included
1884
// ( 4 below is the size of HeaderID and DataSize field ) */
1885
zi->ci.size_centralExtraFree -= datasize + 4;
1886
zi->ci.size_centralheader += datasize + 4;
1887
1888
/* Update the extra info size field */
1889
zi->ci.size_centralExtra += datasize + 4;
1890
zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2);
1891
}
1892
1893
if (err==ZIP_OK)
1894
err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);
1895
1896
free(zi->ci.central_header);
1897
1898
if (err==ZIP_OK)
1899
{
1900
/* Update the LocalFileHeader with the new values. */
1901
1902
ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
1903
1904
if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
1905
err = ZIP_ERRNO;
1906
1907
if (err==ZIP_OK)
1908
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
1909
1910
if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
1911
{
1912
if(zi->ci.pos_zip64extrainfo > 0)
1913
{
1914
/* Update the size in the ZIP64 extended field. */
1915
if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0)
1916
err = ZIP_ERRNO;
1917
1918
if (err==ZIP_OK) /* compressed size, unknown */
1919
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8);
1920
1921
if (err==ZIP_OK) /* uncompressed size, unknown */
1922
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
1923
}
1924
else
1925
err = ZIP_BADZIPFILE; /* Caller passed zip64 = 0, so no room for zip64 info -> fatal */
1926
}
1927
else
1928
{
1929
if (err==ZIP_OK) /* compressed size, unknown */
1930
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
1931
1932
if (err==ZIP_OK) /* uncompressed size, unknown */
1933
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
1934
}
1935
1936
if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
1937
err = ZIP_ERRNO;
1938
}
1939
1940
zi->number_entry ++;
1941
zi->in_opened_file_inzip = 0;
1942
1943
return err;
1944
}
1945
1946
extern int ZEXPORT zipCloseFileInZip(zipFile file) {
1947
return zipCloseFileInZipRaw (file,0,0);
1948
}
1949
1950
local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) {
1951
int err = ZIP_OK;
1952
ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;
1953
1954
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);
1955
1956
/*num disks*/
1957
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
1958
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
1959
1960
/*relative offset*/
1961
if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
1962
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);
1963
1964
/*total disks*/ /* Do not support spawning of disk so always say 1 here*/
1965
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
1966
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);
1967
1968
return err;
1969
}
1970
1971
local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
1972
int err = ZIP_OK;
1973
1974
uLong Zip64DataSize = 44;
1975
1976
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4);
1977
1978
if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */
1979
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); /* why ZPOS64_T of this ? */
1980
1981
if (err==ZIP_OK) /* version made by */
1982
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
1983
1984
if (err==ZIP_OK) /* version needed */
1985
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
1986
1987
if (err==ZIP_OK) /* number of this disk */
1988
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
1989
1990
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
1991
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
1992
1993
if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
1994
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
1995
1996
if (err==ZIP_OK) /* total number of entries in the central dir */
1997
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
1998
1999
if (err==ZIP_OK) /* size of the central directory */
2000
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8);
2001
2002
if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
2003
{
2004
ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2005
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
2006
}
2007
return err;
2008
}
2009
2010
local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
2011
int err = ZIP_OK;
2012
2013
/*signature*/
2014
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
2015
2016
if (err==ZIP_OK) /* number of this disk */
2017
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
2018
2019
if (err==ZIP_OK) /* number of the disk with the start of the central directory */
2020
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
2021
2022
if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
2023
{
2024
{
2025
if(zi->number_entry >= 0xFFFF)
2026
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */
2027
else
2028
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
2029
}
2030
}
2031
2032
if (err==ZIP_OK) /* total number of entries in the central dir */
2033
{
2034
if(zi->number_entry >= 0xFFFF)
2035
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */
2036
else
2037
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
2038
}
2039
2040
if (err==ZIP_OK) /* size of the central directory */
2041
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
2042
2043
if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
2044
{
2045
ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2046
if(pos >= 0xffffffff)
2047
{
2048
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
2049
}
2050
else
2051
err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
2052
}
2053
2054
return err;
2055
}
2056
2057
local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) {
2058
int err = ZIP_OK;
2059
uInt size_global_comment = 0;
2060
2061
if(global_comment != NULL)
2062
size_global_comment = (uInt)strlen(global_comment);
2063
2064
err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
2065
2066
if (err == ZIP_OK && size_global_comment > 0)
2067
{
2068
if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment)
2069
err = ZIP_ERRNO;
2070
}
2071
return err;
2072
}
2073
2074
extern int ZEXPORT zipClose(zipFile file, const char* global_comment) {
2075
zip64_internal* zi;
2076
int err = 0;
2077
uLong size_centraldir = 0;
2078
ZPOS64_T centraldir_pos_inzip;
2079
ZPOS64_T pos;
2080
2081
if (file == NULL)
2082
return ZIP_PARAMERROR;
2083
2084
zi = (zip64_internal*)file;
2085
2086
if (zi->in_opened_file_inzip == 1)
2087
{
2088
err = zipCloseFileInZip (file);
2089
}
2090
2091
#ifndef NO_ADDFILEINEXISTINGZIP
2092
if (global_comment==NULL)
2093
global_comment = zi->globalcomment;
2094
#endif
2095
2096
centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
2097
2098
if (err==ZIP_OK)
2099
{
2100
linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
2101
while (ldi!=NULL)
2102
{
2103
if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
2104
{
2105
if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block)
2106
err = ZIP_ERRNO;
2107
}
2108
2109
size_centraldir += ldi->filled_in_this_block;
2110
ldi = ldi->next_datablock;
2111
}
2112
}
2113
free_linkedlist(&(zi->central_dir));
2114
2115
set_end(&zi->set); /* set was zeroed, so this is safe */
2116
2117
pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2118
if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
2119
{
2120
ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
2121
Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
2122
2123
Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
2124
}
2125
2126
if (err==ZIP_OK)
2127
err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
2128
2129
if(err == ZIP_OK)
2130
err = Write_GlobalComment(zi, global_comment);
2131
2132
if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0)
2133
if (err == ZIP_OK)
2134
err = ZIP_ERRNO;
2135
2136
#ifndef NO_ADDFILEINEXISTINGZIP
2137
free(zi->globalcomment);
2138
#endif
2139
free(zi);
2140
2141
return err;
2142
}
2143
2144
extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) {
2145
char* p = pData;
2146
int size = 0;
2147
char* pNewHeader;
2148
char* pTmp;
2149
short header;
2150
short dataSize;
2151
2152
int retVal = ZIP_OK;
2153
2154
if(pData == NULL || dataLen == NULL || *dataLen < 4)
2155
return ZIP_PARAMERROR;
2156
2157
pNewHeader = (char*)ALLOC((unsigned)*dataLen);
2158
pTmp = pNewHeader;
2159
2160
while(p < (pData + *dataLen))
2161
{
2162
header = *(short*)p;
2163
dataSize = *(((short*)p)+1);
2164
2165
if( header == sHeader ) /* Header found. */
2166
{
2167
p += dataSize + 4; /* skip it. do not copy to temp buffer */
2168
}
2169
else
2170
{
2171
/* Extra Info block should not be removed, So copy it to the temp buffer. */
2172
memcpy(pTmp, p, dataSize + 4);
2173
p += dataSize + 4;
2174
size += dataSize + 4;
2175
}
2176
2177
}
2178
2179
if(size < *dataLen)
2180
{
2181
/* clean old extra info block. */
2182
memset(pData,0, *dataLen);
2183
2184
/* copy the new extra info block over the old */
2185
if(size > 0)
2186
memcpy(pData, pNewHeader, size);
2187
2188
/* set the new extra info size */
2189
*dataLen = size;
2190
2191
retVal = ZIP_OK;
2192
}
2193
else
2194
retVal = ZIP_ERRNO;
2195
2196
free(pNewHeader);
2197
2198
return retVal;
2199
}
2200
2201