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