Rev 6725 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 1 | /* |
2 | Copyright (c) 1990-2009 Info-ZIP. All rights reserved. |
||
3 | |||
4 | See the accompanying file LICENSE, version 2009-Jan-02 or later |
||
5 | (the contents of which are also included in unzip.h) for terms of use. |
||
6 | If, for some reason, all these files are missing, the Info-ZIP license |
||
7 | also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html |
||
8 | */ |
||
9 | /*--------------------------------------------------------------------------- |
||
10 | |||
11 | extract.c |
||
12 | |||
13 | This file contains the high-level routines ("driver routines") for extrac- |
||
14 | ting and testing zipfile members. It calls the low-level routines in files |
||
15 | explode.c, inflate.c, unreduce.c and unshrink.c. |
||
16 | |||
17 | Contains: extract_or_test_files() |
||
18 | store_info() |
||
19 | find_compr_idx() |
||
20 | extract_or_test_entrylist() |
||
21 | extract_or_test_member() |
||
22 | TestExtraField() |
||
23 | test_compr_eb() |
||
24 | memextract() |
||
25 | memflush() |
||
26 | extract_izvms_block() (VMS or VMS_TEXT_CONV) |
||
27 | set_deferred_symlink() (SYMLINKS only) |
||
28 | fnfilter() |
||
29 | dircomp() (SET_DIR_ATTRIB only) |
||
30 | UZbunzip2() (USE_BZIP2 only) |
||
31 | |||
32 | ---------------------------------------------------------------------------*/ |
||
33 | |||
34 | |||
35 | #define __EXTRACT_C /* identifies this source module */ |
||
36 | #define UNZIP_INTERNAL |
||
37 | #include "unzip.h" |
||
38 | #ifdef WINDLL |
||
39 | # ifdef POCKET_UNZIP |
||
40 | # include "wince/intrface.h" |
||
41 | # else |
||
42 | # include "windll/windll.h" |
||
43 | # endif |
||
44 | #endif |
||
45 | #include "crc32.h" |
||
46 | #include "crypt.h" |
||
47 | |||
48 | #define GRRDUMP(buf,len) { \ |
||
49 | int i, j; \ |
||
50 | \ |
||
51 | for (j = 0; j < (len)/16; ++j) { \ |
||
52 | printf(" "); \ |
||
53 | for (i = 0; i < 16; ++i) \ |
||
54 | printf("%02x ", (uch)(buf)[i+(j<<4)]); \ |
||
55 | printf("\n "); \ |
||
56 | for (i = 0; i < 16; ++i) { \ |
||
57 | char c = (char)(buf)[i+(j<<4)]; \ |
||
58 | \ |
||
59 | if (c == '\n') \ |
||
60 | printf("\\n "); \ |
||
61 | else if (c == '\r') \ |
||
62 | printf("\\r "); \ |
||
63 | else \ |
||
64 | printf(" %c ", c); \ |
||
65 | } \ |
||
66 | printf("\n"); \ |
||
67 | } \ |
||
68 | if ((len) % 16) { \ |
||
69 | printf(" "); \ |
||
70 | for (i = j<<4; i < (len); ++i) \ |
||
71 | printf("%02x ", (uch)(buf)[i]); \ |
||
72 | printf("\n "); \ |
||
73 | for (i = j<<4; i < (len); ++i) { \ |
||
74 | char c = (char)(buf)[i]; \ |
||
75 | \ |
||
76 | if (c == '\n') \ |
||
77 | printf("\\n "); \ |
||
78 | else if (c == '\r') \ |
||
79 | printf("\\r "); \ |
||
80 | else \ |
||
81 | printf(" %c ", c); \ |
||
82 | } \ |
||
83 | printf("\n"); \ |
||
84 | } \ |
||
85 | } |
||
86 | |||
87 | static int store_info OF((__GPRO)); |
||
88 | #ifdef SET_DIR_ATTRIB |
||
89 | static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, |
||
90 | ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, |
||
91 | unsigned *pnum_dirs, direntry **pdirlist, |
||
92 | int error_in_archive)); |
||
93 | #else |
||
94 | static int extract_or_test_entrylist OF((__GPRO__ unsigned numchunk, |
||
95 | ulg *pfilnum, ulg *pnum_bad_pwd, zoff_t *pold_extra_bytes, |
||
96 | int error_in_archive)); |
||
97 | #endif |
||
98 | static int extract_or_test_member OF((__GPRO)); |
||
99 | #ifndef SFX |
||
100 | static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len)); |
||
101 | static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size, |
||
102 | unsigned compr_offset, |
||
103 | int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, |
||
104 | uch *eb_ucptr, ulg eb_ucsize))); |
||
105 | #endif |
||
106 | #if (defined(VMS) || defined(VMS_TEXT_CONV)) |
||
107 | static void decompress_bits OF((uch *outptr, unsigned needlen, |
||
108 | ZCONST uch *bitptr)); |
||
109 | #endif |
||
110 | #ifdef SYMLINKS |
||
111 | static void set_deferred_symlink OF((__GPRO__ slinkentry *slnk_entry)); |
||
112 | #endif |
||
113 | #ifdef SET_DIR_ATTRIB |
||
114 | static int Cdecl dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b)); |
||
115 | #endif |
||
116 | |||
117 | |||
118 | |||
119 | /*******************************/ |
||
120 | /* Strings used in extract.c */ |
||
121 | /*******************************/ |
||
122 | |||
123 | static ZCONST char Far VersionMsg[] = |
||
124 | " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n"; |
||
125 | static ZCONST char Far ComprMsgNum[] = |
||
126 | " skipping: %-22s unsupported compression method %u\n"; |
||
127 | #ifndef SFX |
||
128 | static ZCONST char Far ComprMsgName[] = |
||
129 | " skipping: %-22s `%s' method not supported\n"; |
||
130 | static ZCONST char Far CmprNone[] = "store"; |
||
131 | static ZCONST char Far CmprShrink[] = "shrink"; |
||
132 | static ZCONST char Far CmprReduce[] = "reduce"; |
||
133 | static ZCONST char Far CmprImplode[] = "implode"; |
||
134 | static ZCONST char Far CmprTokenize[] = "tokenize"; |
||
135 | static ZCONST char Far CmprDeflate[] = "deflate"; |
||
136 | static ZCONST char Far CmprDeflat64[] = "deflate64"; |
||
137 | static ZCONST char Far CmprDCLImplode[] = "DCL implode"; |
||
138 | static ZCONST char Far CmprBzip[] = "bzip2"; |
||
139 | static ZCONST char Far CmprLZMA[] = "LZMA"; |
||
140 | static ZCONST char Far CmprIBMTerse[] = "IBM/Terse"; |
||
141 | static ZCONST char Far CmprIBMLZ77[] = "IBM LZ77"; |
||
142 | static ZCONST char Far CmprWavPack[] = "WavPack"; |
||
143 | static ZCONST char Far CmprPPMd[] = "PPMd"; |
||
144 | static ZCONST char Far *ComprNames[NUM_METHODS] = { |
||
145 | CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce, |
||
146 | CmprImplode, CmprTokenize, CmprDeflate, CmprDeflat64, CmprDCLImplode, |
||
147 | CmprBzip, CmprLZMA, CmprIBMTerse, CmprIBMLZ77, CmprWavPack, CmprPPMd |
||
148 | }; |
||
149 | static ZCONST unsigned ComprIDs[NUM_METHODS] = { |
||
150 | STORED, SHRUNK, REDUCED1, REDUCED2, REDUCED3, REDUCED4, |
||
151 | IMPLODED, TOKENIZED, DEFLATED, ENHDEFLATED, DCLIMPLODED, |
||
152 | BZIPPED, LZMAED, IBMTERSED, IBMLZ77ED, WAVPACKED, PPMDED |
||
153 | }; |
||
154 | #endif /* !SFX */ |
||
155 | static ZCONST char Far FilNamMsg[] = |
||
156 | "%s: bad filename length (%s)\n"; |
||
157 | #ifndef SFX |
||
158 | static ZCONST char Far WarnNoMemCFName[] = |
||
159 | "%s: warning, no memory for comparison with local header\n"; |
||
160 | static ZCONST char Far LvsCFNamMsg[] = |
||
161 | "%s: mismatching \"local\" filename (%s),\n\ |
||
162 | continuing with \"central\" filename version\n"; |
||
163 | #endif /* !SFX */ |
||
164 | #if (!defined(SFX) && defined(UNICODE_SUPPORT)) |
||
165 | static ZCONST char Far GP11FlagsDiffer[] = |
||
166 | "file #%lu (%s):\n\ |
||
167 | mismatch between local and central GPF bit 11 (\"UTF-8\"),\n\ |
||
168 | continuing with central flag (IsUTF8 = %d)\n"; |
||
169 | #endif /* !SFX && UNICODE_SUPPORT */ |
||
170 | static ZCONST char Far WrnStorUCSizCSizDiff[] = |
||
171 | "%s: ucsize %s <> csize %s for STORED entry\n\ |
||
172 | continuing with \"compressed\" size value\n"; |
||
173 | static ZCONST char Far ExtFieldMsg[] = |
||
174 | "%s: bad extra field length (%s)\n"; |
||
175 | static ZCONST char Far OffsetMsg[] = |
||
176 | "file #%lu: bad zipfile offset (%s): %ld\n"; |
||
177 | static ZCONST char Far ExtractMsg[] = |
||
178 | "%8sing: %-22s %s%s"; |
||
179 | #ifndef SFX |
||
180 | static ZCONST char Far LengthMsg[] = |
||
181 | "%s %s: %s bytes required to uncompress to %s bytes;\n %s\ |
||
182 | supposed to require %s bytes%s%s%s\n"; |
||
183 | #endif |
||
184 | |||
185 | static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n"; |
||
186 | static ZCONST char Far LocalHdrSig[] = "local header sig"; |
||
187 | static ZCONST char Far BadLocalHdr[] = "file #%lu: bad local header\n"; |
||
188 | static ZCONST char Far AttemptRecompensate[] = |
||
189 | " (attempting to re-compensate)\n"; |
||
190 | #ifndef SFX |
||
191 | static ZCONST char Far BackslashPathSep[] = |
||
192 | "warning: %s appears to use backslashes as path separators\n"; |
||
193 | #endif |
||
194 | static ZCONST char Far AbsolutePathWarning[] = |
||
195 | "warning: stripped absolute path spec from %s\n"; |
||
196 | static ZCONST char Far SkipVolumeLabel[] = |
||
197 | " skipping: %-22s %svolume label\n"; |
||
198 | |||
199 | #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */ |
||
200 | static ZCONST char Far DirlistEntryNoMem[] = |
||
201 | "warning: cannot alloc memory for dir times/permissions/UID/GID\n"; |
||
202 | static ZCONST char Far DirlistSortNoMem[] = |
||
203 | "warning: cannot alloc memory to sort dir times/perms/etc.\n"; |
||
204 | static ZCONST char Far DirlistSetAttrFailed[] = |
||
205 | "warning: set times/attribs failed for %s\n"; |
||
206 | static ZCONST char Far DirlistFailAttrSum[] = |
||
207 | " failed setting times/attribs for %lu dir entries"; |
||
208 | #endif |
||
209 | |||
210 | #ifdef SYMLINKS /* messages of the deferred symlinks handler */ |
||
211 | static ZCONST char Far SymLnkWarnNoMem[] = |
||
212 | "warning: deferred symlink (%s) failed:\n\ |
||
213 | out of memory\n"; |
||
214 | static ZCONST char Far SymLnkWarnInvalid[] = |
||
215 | "warning: deferred symlink (%s) failed:\n\ |
||
216 | invalid placeholder file\n"; |
||
217 | static ZCONST char Far SymLnkDeferred[] = |
||
218 | "finishing deferred symbolic links:\n"; |
||
219 | static ZCONST char Far SymLnkFinish[] = |
||
220 | " %-22s -> %s\n"; |
||
221 | #endif |
||
222 | |||
223 | #ifndef WINDLL |
||
224 | static ZCONST char Far ReplaceQuery[] = |
||
225 | # ifdef VMS |
||
226 | "new version of %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; |
||
227 | # else |
||
228 | "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: "; |
||
229 | # endif |
||
230 | static ZCONST char Far AssumeNone[] = |
||
231 | " NULL\n(EOF or read error, treating as \"[N]one\" ...)\n"; |
||
232 | static ZCONST char Far NewNameQuery[] = "new name: "; |
||
233 | static ZCONST char Far InvalidResponse[] = |
||
234 | "error: invalid response [%s]\n"; |
||
235 | #endif /* !WINDLL */ |
||
236 | |||
237 | static ZCONST char Far ErrorInArchive[] = |
||
238 | "At least one %serror was detected in %s.\n"; |
||
239 | static ZCONST char Far ZeroFilesTested[] = |
||
240 | "Caution: zero files tested in %s.\n"; |
||
241 | |||
242 | #ifndef VMS |
||
243 | static ZCONST char Far VMSFormatQuery[] = |
||
244 | "\n%s: stored in VMS format. Extract anyway? (y/n) "; |
||
245 | #endif |
||
246 | |||
247 | #if CRYPT |
||
248 | static ZCONST char Far SkipCannotGetPasswd[] = |
||
249 | " skipping: %-22s unable to get password\n"; |
||
250 | static ZCONST char Far SkipIncorrectPasswd[] = |
||
251 | " skipping: %-22s incorrect password\n"; |
||
252 | static ZCONST char Far FilesSkipBadPasswd[] = |
||
253 | "%lu file%s skipped because of incorrect password.\n"; |
||
254 | static ZCONST char Far MaybeBadPasswd[] = |
||
255 | " (may instead be incorrect password)\n"; |
||
256 | #else |
||
257 | static ZCONST char Far SkipEncrypted[] = |
||
258 | " skipping: %-22s encrypted (not supported)\n"; |
||
259 | #endif |
||
260 | |||
261 | static ZCONST char Far NoErrInCompData[] = |
||
262 | "No errors detected in compressed data of %s.\n"; |
||
263 | static ZCONST char Far NoErrInTestedFiles[] = |
||
264 | "No errors detected in %s for the %lu file%s tested.\n"; |
||
265 | static ZCONST char Far FilesSkipped[] = |
||
266 | "%lu file%s skipped because of unsupported compression or encoding.\n"; |
||
267 | |||
268 | static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n"; |
||
269 | static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n"; |
||
270 | static ZCONST char Far NotEnoughMem[] = "not enough memory to "; |
||
271 | static ZCONST char Far InvalidComprData[] = "invalid compressed data to "; |
||
272 | static ZCONST char Far Inflate[] = "inflate"; |
||
273 | #ifdef USE_BZIP2 |
||
274 | static ZCONST char Far BUnzip[] = "bunzip"; |
||
275 | #endif |
||
276 | |||
277 | #ifndef SFX |
||
278 | static ZCONST char Far Explode[] = "explode"; |
||
279 | #ifndef LZW_CLEAN |
||
280 | static ZCONST char Far Unshrink[] = "unshrink"; |
||
281 | #endif |
||
282 | #endif |
||
283 | |||
284 | #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK)) |
||
285 | static ZCONST char Far FileTruncated[] = |
||
286 | "warning: %s is probably truncated\n"; |
||
287 | #endif |
||
288 | |||
289 | static ZCONST char Far FileUnknownCompMethod[] = |
||
290 | "%s: unknown compression method\n"; |
||
291 | static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n"; |
||
292 | |||
293 | /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */ |
||
294 | char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s"; |
||
295 | char ZCONST Far TruncNTSD[] = |
||
296 | " compressed WinNT security data missing (%d bytes)%s"; |
||
297 | |||
298 | #ifndef SFX |
||
299 | static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \ |
||
300 | EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n"; |
||
301 | static ZCONST char Far InvalidComprDataEAs[] = |
||
302 | " invalid compressed data for EAs\n"; |
||
303 | # if (defined(WIN32) && defined(NTSD_EAS)) |
||
304 | static ZCONST char Far InvalidSecurityEAs[] = |
||
305 | " EAs fail security check\n"; |
||
306 | # endif |
||
307 | static ZCONST char Far UnsuppNTSDVersEAs[] = |
||
308 | " unsupported NTSD EAs version %d\n"; |
||
309 | static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n"; |
||
310 | static ZCONST char Far UnknComprMethodEAs[] = |
||
311 | " unknown compression method for EAs (%u)\n"; |
||
312 | static ZCONST char Far NotEnoughMemEAs[] = |
||
313 | " out of memory while inflating EAs\n"; |
||
314 | static ZCONST char Far UnknErrorEAs[] = |
||
315 | " unknown error on extended attributes\n"; |
||
316 | #endif /* !SFX */ |
||
317 | |||
318 | static ZCONST char Far UnsupportedExtraField[] = |
||
319 | "\nerror: unsupported extra-field compression type (%u)--skipping\n"; |
||
320 | static ZCONST char Far BadExtraFieldCRC[] = |
||
321 | "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n"; |
||
322 | |||
323 | |||
324 | |||
325 | |||
326 | |||
327 | /**************************************/ |
||
328 | /* Function extract_or_test_files() */ |
||
329 | /**************************************/ |
||
330 | |||
331 | int extract_or_test_files(__G) /* return PK-type error code */ |
||
332 | __GDEF |
||
333 | { |
||
334 | unsigned i, j; |
||
335 | zoff_t cd_bufstart; |
||
336 | uch *cd_inptr; |
||
337 | int cd_incnt; |
||
338 | ulg filnum=0L, blknum=0L; |
||
339 | int reached_end; |
||
340 | #ifndef SFX |
||
341 | int no_endsig_found; |
||
342 | #endif |
||
343 | int error, error_in_archive=PK_COOL; |
||
344 | int *fn_matched=NULL, *xn_matched=NULL; |
||
345 | zucn_t members_processed; |
||
346 | ulg num_skipped=0L, num_bad_pwd=0L; |
||
347 | zoff_t old_extra_bytes = 0L; |
||
348 | #ifdef SET_DIR_ATTRIB |
||
349 | unsigned num_dirs=0; |
||
350 | direntry *dirlist=(direntry *)NULL, **sorted_dirlist=(direntry **)NULL; |
||
351 | #endif |
||
352 | |||
353 | /* |
||
354 | * First, two general initializations are applied. These have been moved |
||
355 | * here from process_zipfiles() because they are only needed for accessing |
||
356 | * and/or extracting the data content of the zip archive. |
||
357 | */ |
||
358 | |||
359 | /* a) initialize the CRC table pointer (once) */ |
||
360 | if (CRC_32_TAB == NULL) { |
||
361 | if ((CRC_32_TAB = get_crc_table()) == NULL) { |
||
362 | return PK_MEM; |
||
363 | } |
||
364 | } |
||
365 | |||
366 | #if (!defined(SFX) || defined(SFX_EXDIR)) |
||
367 | /* b) check out if specified extraction root directory exists */ |
||
368 | if (uO.exdir != (char *)NULL && G.extract_flag) { |
||
369 | G.create_dirs = !uO.fflag; |
||
370 | if ((error = checkdir(__G__ uO.exdir, ROOT)) > MPN_INF_SKIP) { |
||
371 | /* out of memory, or file in way */ |
||
372 | return (error == MPN_NOMEM ? PK_MEM : PK_ERR); |
||
373 | } |
||
374 | } |
||
375 | #endif /* !SFX || SFX_EXDIR */ |
||
376 | |||
377 | /*--------------------------------------------------------------------------- |
||
378 | The basic idea of this function is as follows. Since the central di- |
||
379 | rectory lies at the end of the zipfile and the member files lie at the |
||
380 | beginning or middle or wherever, it is not very desirable to simply |
||
381 | read a central directory entry, jump to the member and extract it, and |
||
382 | then jump back to the central directory. In the case of a large zipfile |
||
383 | this would lead to a whole lot of disk-grinding, especially if each mem- |
||
384 | ber file is small. Instead, we read from the central directory the per- |
||
385 | tinent information for a block of files, then go extract/test the whole |
||
386 | block. Thus this routine contains two small(er) loops within a very |
||
387 | large outer loop: the first of the small ones reads a block of files |
||
388 | from the central directory; the second extracts or tests each file; and |
||
389 | the outer one loops over blocks. There's some file-pointer positioning |
||
390 | stuff in between, but that's about it. Btw, it's because of this jump- |
||
391 | ing around that we can afford to be lenient if an error occurs in one of |
||
392 | the member files: we should still be able to go find the other members, |
||
393 | since we know the offset of each from the beginning of the zipfile. |
||
394 | ---------------------------------------------------------------------------*/ |
||
395 | |||
396 | G.pInfo = G.info; |
||
397 | |||
398 | #if CRYPT |
||
399 | G.newzip = TRUE; |
||
400 | #endif |
||
401 | #ifndef SFX |
||
402 | G.reported_backslash = FALSE; |
||
403 | #endif |
||
404 | |||
405 | /* malloc space for check on unmatched filespecs (OK if one or both NULL) */ |
||
406 | if (G.filespecs > 0 && |
||
407 | (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL) |
||
408 | for (i = 0; i < G.filespecs; ++i) |
||
409 | fn_matched[i] = FALSE; |
||
410 | if (G.xfilespecs > 0 && |
||
411 | (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL) |
||
412 | for (i = 0; i < G.xfilespecs; ++i) |
||
413 | xn_matched[i] = FALSE; |
||
414 | |||
415 | /*--------------------------------------------------------------------------- |
||
416 | Begin main loop over blocks of member files. We know the entire central |
||
417 | directory is on this disk: we would not have any of this information un- |
||
418 | less the end-of-central-directory record was on this disk, and we would |
||
419 | not have gotten to this routine unless this is also the disk on which |
||
420 | the central directory starts. In practice, this had better be the ONLY |
||
421 | disk in the archive, but we'll add multi-disk support soon. |
||
422 | ---------------------------------------------------------------------------*/ |
||
423 | |||
424 | members_processed = 0; |
||
425 | #ifndef SFX |
||
426 | no_endsig_found = FALSE; |
||
427 | #endif |
||
428 | reached_end = FALSE; |
||
429 | while (!reached_end) { |
||
430 | j = 0; |
||
431 | #ifdef AMIGA |
||
432 | memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *)); |
||
433 | #endif |
||
434 | |||
435 | /* |
||
436 | * Loop through files in central directory, storing offsets, file |
||
437 | * attributes, case-conversion and text-conversion flags until block |
||
438 | * size is reached. |
||
439 | */ |
||
440 | |||
441 | while ((j < DIR_BLKSIZ)) { |
||
442 | G.pInfo = &G.info[j]; |
||
443 | |||
444 | if (readbuf(__G__ G.sig, 4) == 0) { |
||
445 | error_in_archive = PK_EOF; |
||
446 | reached_end = TRUE; /* ...so no more left to do */ |
||
447 | break; |
||
448 | } |
||
449 | if (memcmp(G.sig, central_hdr_sig, 4)) { /* is it a new entry? */ |
||
450 | /* no new central directory entry |
||
451 | * -> is the number of processed entries compatible with the |
||
452 | * number of entries as stored in the end_central record? |
||
453 | */ |
||
454 | if ((members_processed |
||
455 | & (G.ecrec.have_ecr64 ? MASK_ZUCN64 : MASK_ZUCN16)) |
||
456 | == G.ecrec.total_entries_central_dir) { |
||
457 | #ifndef SFX |
||
458 | /* yes, so look if we ARE back at the end_central record |
||
459 | */ |
||
460 | no_endsig_found = |
||
461 | ( (memcmp(G.sig, |
||
462 | (G.ecrec.have_ecr64 ? |
||
463 | end_central64_sig : end_central_sig), |
||
464 | 4) != 0) |
||
465 | && (!G.ecrec.is_zip64_archive) |
||
466 | && (memcmp(G.sig, end_central_sig, 4) != 0) |
||
467 | ); |
||
468 | #endif /* !SFX */ |
||
469 | } else { |
||
470 | /* no; we have found an error in the central directory |
||
471 | * -> report it and stop searching for more Zip entries |
||
472 | */ |
||
473 | Info(slide, 0x401, ((char *)slide, |
||
474 | LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1)); |
||
475 | Info(slide, 0x401, ((char *)slide, |
||
476 | LoadFarString(ReportMsg))); |
||
477 | error_in_archive = PK_BADERR; |
||
478 | } |
||
479 | reached_end = TRUE; /* ...so no more left to do */ |
||
480 | break; |
||
481 | } |
||
482 | /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */ |
||
483 | if ((error = process_cdir_file_hdr(__G)) != PK_COOL) { |
||
484 | error_in_archive = error; /* only PK_EOF defined */ |
||
485 | reached_end = TRUE; /* ...so no more left to do */ |
||
486 | break; |
||
487 | } |
||
488 | if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) != |
||
489 | PK_COOL) |
||
490 | { |
||
491 | if (error > error_in_archive) |
||
492 | error_in_archive = error; |
||
493 | if (error > PK_WARN) { /* fatal: no more left to do */ |
||
494 | Info(slide, 0x401, ((char *)slide, |
||
495 | LoadFarString(FilNamMsg), |
||
496 | FnFilter1(G.filename), "central")); |
||
497 | reached_end = TRUE; |
||
498 | break; |
||
499 | } |
||
500 | } |
||
501 | if ((error = do_string(__G__ G.crec.extra_field_length, |
||
502 | EXTRA_FIELD)) != 0) |
||
503 | { |
||
504 | if (error > error_in_archive) |
||
505 | error_in_archive = error; |
||
506 | if (error > PK_WARN) { /* fatal */ |
||
507 | Info(slide, 0x401, ((char *)slide, |
||
508 | LoadFarString(ExtFieldMsg), |
||
509 | FnFilter1(G.filename), "central")); |
||
510 | reached_end = TRUE; |
||
511 | break; |
||
512 | } |
||
513 | } |
||
514 | #ifdef AMIGA |
||
515 | G.filenote_slot = j; |
||
516 | if ((error = do_string(__G__ G.crec.file_comment_length, |
||
517 | uO.N_flag ? FILENOTE : SKIP)) != PK_COOL) |
||
518 | #else |
||
519 | if ((error = do_string(__G__ G.crec.file_comment_length, SKIP)) |
||
520 | != PK_COOL) |
||
521 | #endif |
||
522 | { |
||
523 | if (error > error_in_archive) |
||
524 | error_in_archive = error; |
||
525 | if (error > PK_WARN) { /* fatal */ |
||
526 | Info(slide, 0x421, ((char *)slide, |
||
527 | LoadFarString(BadFileCommLength), |
||
528 | FnFilter1(G.filename))); |
||
529 | reached_end = TRUE; |
||
530 | break; |
||
531 | } |
||
532 | } |
||
533 | if (G.process_all_files) { |
||
534 | if (store_info(__G)) |
||
535 | ++j; /* file is OK; info[] stored; continue with next */ |
||
536 | else |
||
537 | ++num_skipped; |
||
538 | } else { |
||
539 | int do_this_file; |
||
540 | |||
541 | if (G.filespecs == 0) |
||
542 | do_this_file = TRUE; |
||
543 | else { /* check if this entry matches an `include' argument */ |
||
544 | do_this_file = FALSE; |
||
545 | for (i = 0; i < G.filespecs; i++) |
||
546 | if (match(G.filename, G.pfnames[i], uO.C_flag WISEP)) { |
||
547 | do_this_file = TRUE; /* ^-- ignore case or not? */ |
||
548 | if (fn_matched) |
||
549 | fn_matched[i] = TRUE; |
||
550 | break; /* found match, so stop looping */ |
||
551 | } |
||
552 | } |
||
553 | if (do_this_file) { /* check if this is an excluded file */ |
||
554 | for (i = 0; i < G.xfilespecs; i++) |
||
555 | if (match(G.filename, G.pxnames[i], uO.C_flag WISEP)) { |
||
556 | do_this_file = FALSE; /* ^-- ignore case or not? */ |
||
557 | if (xn_matched) |
||
558 | xn_matched[i] = TRUE; |
||
559 | break; |
||
560 | } |
||
561 | } |
||
562 | if (do_this_file) { |
||
563 | if (store_info(__G)) |
||
564 | ++j; /* file is OK */ |
||
565 | else |
||
566 | ++num_skipped; /* unsupp. compression or encryption */ |
||
567 | } |
||
568 | } /* end if (process_all_files) */ |
||
569 | |||
570 | members_processed++; |
||
571 | |||
572 | } /* end while-loop (adding files to current block) */ |
||
573 | |||
574 | /* save position in central directory so can come back later */ |
||
575 | cd_bufstart = G.cur_zipfile_bufstart; |
||
576 | cd_inptr = G.inptr; |
||
577 | cd_incnt = G.incnt; |
||
578 | |||
579 | /*----------------------------------------------------------------------- |
||
580 | Second loop: process files in current block, extracting or testing |
||
581 | each one. |
||
582 | -----------------------------------------------------------------------*/ |
||
583 | |||
584 | error = extract_or_test_entrylist(__G__ j, |
||
585 | &filnum, &num_bad_pwd, &old_extra_bytes, |
||
586 | #ifdef SET_DIR_ATTRIB |
||
587 | &num_dirs, &dirlist, |
||
588 | #endif |
||
589 | error_in_archive); |
||
590 | if (error != PK_COOL) { |
||
591 | if (error > error_in_archive) |
||
592 | error_in_archive = error; |
||
593 | /* ...and keep going (unless disk full or user break) */ |
||
594 | if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { |
||
595 | /* clear reached_end to signal premature stop ... */ |
||
596 | reached_end = FALSE; |
||
597 | /* ... and cancel scanning the central directory */ |
||
598 | break; |
||
599 | } |
||
600 | } |
||
601 | |||
602 | |||
603 | /* |
||
604 | * Jump back to where we were in the central directory, then go and do |
||
605 | * the next batch of files. |
||
606 | */ |
||
607 | |||
608 | #ifdef USE_STRM_INPUT |
||
609 | zfseeko(G.zipfd, cd_bufstart, SEEK_SET); |
||
610 | G.cur_zipfile_bufstart = zftello(G.zipfd); |
||
611 | #else /* !USE_STRM_INPUT */ |
||
612 | G.cur_zipfile_bufstart = |
||
613 | zlseek(G.zipfd, cd_bufstart, SEEK_SET); |
||
614 | #endif /* ?USE_STRM_INPUT */ |
||
615 | read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */ |
||
616 | G.inptr = cd_inptr; |
||
617 | G.incnt = cd_incnt; |
||
618 | ++blknum; |
||
619 | |||
620 | #ifdef TEST |
||
621 | printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart); |
||
622 | printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart, |
||
623 | cur_zipfile_bufstart); |
||
624 | printf("inptr-inbuf = %d\n", G.inptr-G.inbuf); |
||
625 | printf("incnt = %d\n\n", G.incnt); |
||
626 | #endif |
||
627 | |||
628 | } /* end while-loop (blocks of files in central directory) */ |
||
629 | |||
630 | /*--------------------------------------------------------------------------- |
||
631 | Process the list of deferred symlink extractions and finish up |
||
632 | the symbolic links. |
||
633 | ---------------------------------------------------------------------------*/ |
||
634 | |||
635 | #ifdef SYMLINKS |
||
636 | if (G.slink_last != NULL) { |
||
637 | if (QCOND2) |
||
638 | Info(slide, 0, ((char *)slide, LoadFarString(SymLnkDeferred))); |
||
639 | while (G.slink_head != NULL) { |
||
640 | set_deferred_symlink(__G__ G.slink_head); |
||
641 | /* remove the processed entry from the chain and free its memory */ |
||
642 | G.slink_last = G.slink_head; |
||
643 | G.slink_head = G.slink_last->next; |
||
644 | free(G.slink_last); |
||
645 | } |
||
646 | G.slink_last = NULL; |
||
647 | } |
||
648 | #endif /* SYMLINKS */ |
||
649 | |||
650 | /*--------------------------------------------------------------------------- |
||
651 | Go back through saved list of directories, sort and set times/perms/UIDs |
||
652 | and GIDs from the deepest level on up. |
||
653 | ---------------------------------------------------------------------------*/ |
||
654 | |||
6775 | siemargl | 655 | #ifdef SET_DIR_ATTRIB |
656 | //Trace((stderr, "SET_DIR_ATTRIB[%d] \n", num_dirs)); hmm, too big number |
||
657 | |||
6725 | siemargl | 658 | if (num_dirs > 0) { |
659 | sorted_dirlist = (direntry **)malloc(num_dirs*sizeof(direntry *)); |
||
660 | if (sorted_dirlist == (direntry **)NULL) { |
||
661 | Info(slide, 0x401, ((char *)slide, |
||
662 | LoadFarString(DirlistSortNoMem))); |
||
663 | while (dirlist != (direntry *)NULL) { |
||
664 | direntry *d = dirlist; |
||
665 | |||
666 | dirlist = dirlist->next; |
||
667 | free(d); |
||
668 | } |
||
669 | } else { |
||
670 | ulg ndirs_fail = 0; |
||
671 | |||
672 | if (num_dirs == 1) |
||
673 | sorted_dirlist[0] = dirlist; |
||
674 | else { |
||
675 | for (i = 0; i < num_dirs; ++i) { |
||
676 | sorted_dirlist[i] = dirlist; |
||
677 | dirlist = dirlist->next; |
||
678 | } |
||
679 | qsort((char *)sorted_dirlist, num_dirs, sizeof(direntry *), |
||
680 | dircomp); |
||
681 | } |
||
682 | |||
683 | Trace((stderr, "setting directory times/perms/attributes\n")); |
||
684 | for (i = 0; i < num_dirs; ++i) { |
||
685 | direntry *d = sorted_dirlist[i]; |
||
686 | |||
687 | Trace((stderr, "dir = %s\n", d->fn)); |
||
688 | if ((error = set_direc_attribs(__G__ d)) != PK_OK) { |
||
689 | ndirs_fail++; |
||
690 | Info(slide, 0x201, ((char *)slide, |
||
691 | LoadFarString(DirlistSetAttrFailed), d->fn)); |
||
692 | if (!error_in_archive) |
||
693 | error_in_archive = error; |
||
694 | } |
||
695 | free(d); |
||
696 | } |
||
697 | free(sorted_dirlist); |
||
698 | if (!uO.tflag && QCOND2) { |
||
699 | if (ndirs_fail > 0) |
||
700 | Info(slide, 0, ((char *)slide, |
||
701 | LoadFarString(DirlistFailAttrSum), ndirs_fail)); |
||
702 | } |
||
703 | } |
||
704 | } |
||
705 | #endif /* SET_DIR_ATTRIB */ |
||
706 | |||
707 | /*--------------------------------------------------------------------------- |
||
708 | Check for unmatched filespecs on command line and print warning if any |
||
709 | found. Free allocated memory. (But suppress check when central dir |
||
710 | scan was interrupted prematurely.) |
||
711 | ---------------------------------------------------------------------------*/ |
||
712 | |||
713 | if (fn_matched) { |
||
714 | if (reached_end) for (i = 0; i < G.filespecs; ++i) |
||
715 | if (!fn_matched[i]) { |
||
716 | #ifdef DLL |
||
717 | if (!G.redirect_data && !G.redirect_text) |
||
718 | Info(slide, 0x401, ((char *)slide, |
||
719 | LoadFarString(FilenameNotMatched), G.pfnames[i])); |
||
720 | else |
||
721 | setFileNotFound(__G); |
||
722 | #else |
||
723 | Info(slide, 1, ((char *)slide, |
||
724 | LoadFarString(FilenameNotMatched), G.pfnames[i])); |
||
725 | #endif |
||
726 | if (error_in_archive <= PK_WARN) |
||
727 | error_in_archive = PK_FIND; /* some files not found */ |
||
728 | } |
||
729 | free((zvoid *)fn_matched); |
||
730 | } |
||
731 | if (xn_matched) { |
||
732 | if (reached_end) for (i = 0; i < G.xfilespecs; ++i) |
||
733 | if (!xn_matched[i]) |
||
734 | Info(slide, 0x401, ((char *)slide, |
||
735 | LoadFarString(ExclFilenameNotMatched), G.pxnames[i])); |
||
736 | free((zvoid *)xn_matched); |
||
737 | } |
||
738 | |||
739 | /*--------------------------------------------------------------------------- |
||
740 | Now, all locally allocated memory has been released. When the central |
||
741 | directory processing has been interrupted prematurely, it is safe to |
||
742 | return immediately. All completeness checks and summary messages are |
||
743 | skipped in this case. |
||
744 | ---------------------------------------------------------------------------*/ |
||
745 | if (!reached_end) |
||
746 | return error_in_archive; |
||
747 | |||
748 | /*--------------------------------------------------------------------------- |
||
749 | Double-check that we're back at the end-of-central-directory record, and |
||
750 | print quick summary of results, if we were just testing the archive. We |
||
751 | send the summary to stdout so that people doing the testing in the back- |
||
752 | ground and redirecting to a file can just do a "tail" on the output file. |
||
753 | ---------------------------------------------------------------------------*/ |
||
754 | |||
755 | #ifndef SFX |
||
756 | if (no_endsig_found) { /* just to make sure */ |
||
757 | Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg))); |
||
758 | Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg))); |
||
759 | if (!error_in_archive) /* don't overwrite stronger error */ |
||
760 | error_in_archive = PK_WARN; |
||
761 | } |
||
762 | #endif /* !SFX */ |
||
763 | if (uO.tflag) { |
||
764 | ulg num = filnum - num_bad_pwd; |
||
765 | |||
766 | if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */ |
||
767 | if (error_in_archive) |
||
768 | Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive), |
||
769 | (error_in_archive == PK_WARN)? "warning-" : "", G.zipfn)); |
||
770 | else if (num == 0L) |
||
771 | Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested), |
||
772 | G.zipfn)); |
||
773 | else if (G.process_all_files && (num_skipped+num_bad_pwd == 0L)) |
||
774 | Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData), |
||
775 | G.zipfn)); |
||
776 | else |
||
777 | Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles) |
||
778 | , G.zipfn, num, (num==1L)? "":"s")); |
||
779 | if (num_skipped > 0L) |
||
780 | Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped), |
||
781 | num_skipped, (num_skipped==1L)? "":"s")); |
||
782 | #if CRYPT |
||
783 | if (num_bad_pwd > 0L) |
||
784 | Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd) |
||
785 | , num_bad_pwd, (num_bad_pwd==1L)? "":"s")); |
||
786 | #endif /* CRYPT */ |
||
787 | } |
||
788 | } |
||
789 | |||
790 | /* give warning if files not tested or extracted (first condition can still |
||
791 | * happen if zipfile is empty and no files specified on command line) */ |
||
792 | |||
793 | if ((filnum == 0) && error_in_archive <= PK_WARN) { |
||
794 | if (num_skipped > 0L) |
||
795 | error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */ |
||
796 | else |
||
797 | error_in_archive = PK_FIND; /* no files found at all */ |
||
798 | } |
||
799 | #if CRYPT |
||
800 | else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN) |
||
801 | error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */ |
||
802 | #endif |
||
803 | else if ((num_skipped > 0L) && error_in_archive <= PK_WARN) |
||
804 | error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */ |
||
805 | #if CRYPT |
||
806 | else if ((num_bad_pwd > 0L) && !error_in_archive) |
||
807 | error_in_archive = PK_WARN; |
||
808 | #endif |
||
809 | |||
810 | return error_in_archive; |
||
811 | |||
812 | } /* end function extract_or_test_files() */ |
||
813 | |||
814 | |||
815 | |||
816 | |||
817 | |||
818 | /***************************/ |
||
819 | /* Function store_info() */ |
||
820 | /***************************/ |
||
821 | |||
822 | static int store_info(__G) /* return 0 if skipping, 1 if OK */ |
||
823 | __GDEF |
||
824 | { |
||
825 | #ifdef USE_BZIP2 |
||
826 | # define UNKN_BZ2 (G.crec.compression_method!=BZIPPED) |
||
827 | #else |
||
828 | # define UNKN_BZ2 TRUE /* bzip2 unknown */ |
||
829 | #endif |
||
830 | |||
831 | #ifdef USE_LZMA |
||
832 | # define UNKN_LZMA (G.crec.compression_method!=LZMAED) |
||
833 | #else |
||
834 | # define UNKN_LZMA TRUE /* LZMA unknown */ |
||
835 | #endif |
||
836 | |||
837 | #ifdef USE_WAVP |
||
838 | # define UNKN_WAVP (G.crec.compression_method!=WAVPACKED) |
||
839 | #else |
||
840 | # define UNKN_WAVP TRUE /* WavPack unknown */ |
||
841 | #endif |
||
842 | |||
843 | #ifdef USE_PPMD |
||
844 | # define UNKN_PPMD (G.crec.compression_method!=PPMDED) |
||
845 | #else |
||
846 | # define UNKN_PPMD TRUE /* PPMd unknown */ |
||
847 | #endif |
||
848 | |||
849 | #ifdef SFX |
||
850 | # ifdef USE_DEFLATE64 |
||
851 | # define UNKN_COMPR \ |
||
852 | (G.crec.compression_method!=STORED && G.crec.compression_method |
||
853 | && G.crec.compression_method>ENHDEFLATED \ |
||
854 | && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) |
||
855 | # else |
||
856 | # define UNKN_COMPR \ |
||
857 | (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED\ |
||
858 | && UNKN_BZ2 && UNKN_LZMA && UNKN_WAVP && UNKN_PPMD) |
||
859 | # endif |
||
860 | #else |
||
861 | # ifdef COPYRIGHT_CLEAN /* no reduced files */ |
||
862 | # define UNKN_RED (G.crec.compression_method >= REDUCED1 && \ |
||
863 | G.crec.compression_method <= REDUCED4) |
||
864 | # else |
||
865 | # define UNKN_RED FALSE /* reducing not unknown */ |
||
866 | # endif |
||
867 | # ifdef LZW_CLEAN /* no shrunk files */ |
||
868 | # define UNKN_SHR (G.crec.compression_method == SHRUNK) |
||
869 | # else |
||
870 | # define UNKN_SHR FALSE /* unshrinking not unknown */ |
||
871 | # endif |
||
872 | # ifdef USE_DEFLATE64 |
||
873 | # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ |
||
874 | G.crec.compression_method==TOKENIZED || \ |
||
875 | (G.crec.compression_method>ENHDEFLATED && UNKN_BZ2 && UNKN_LZMA \ |
||
876 | && UNKN_WAVP && UNKN_PPMD)) |
||
877 | # else |
||
878 | # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \ |
||
879 | G.crec.compression_method==TOKENIZED || \ |
||
880 | (G.crec.compression_method>DEFLATED && UNKN_BZ2 && UNKN_LZMA \ |
||
881 | && UNKN_WAVP && UNKN_PPMD)) |
||
882 | # endif |
||
883 | #endif |
||
884 | |||
885 | #if (defined(USE_BZIP2) && (UNZIP_VERSION < UNZIP_BZ2VERS)) |
||
886 | int unzvers_support = (UNKN_BZ2 ? UNZIP_VERSION : UNZIP_BZ2VERS); |
||
887 | # define UNZVERS_SUPPORT unzvers_support |
||
888 | #else |
||
889 | # define UNZVERS_SUPPORT UNZIP_VERSION |
||
890 | #endif |
||
891 | |||
892 | /*--------------------------------------------------------------------------- |
||
893 | Check central directory info for version/compatibility requirements. |
||
894 | ---------------------------------------------------------------------------*/ |
||
895 | |||
896 | G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */ |
||
897 | G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */ |
||
898 | G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */ |
||
899 | G.pInfo->crc = G.crec.crc32; |
||
900 | G.pInfo->compr_size = G.crec.csize; |
||
901 | G.pInfo->uncompr_size = G.crec.ucsize; |
||
902 | |||
903 | switch (uO.aflag) { |
||
904 | case 0: |
||
905 | G.pInfo->textmode = FALSE; /* bit field */ |
||
906 | break; |
||
907 | case 1: |
||
908 | G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */ |
||
909 | break; |
||
910 | default: /* case 2: */ |
||
911 | G.pInfo->textmode = TRUE; |
||
912 | break; |
||
913 | } |
||
914 | |||
915 | if (G.crec.version_needed_to_extract[1] == VMS_) { |
||
916 | if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) { |
||
917 | if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) |
||
918 | Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), |
||
919 | FnFilter1(G.filename), "VMS", |
||
920 | G.crec.version_needed_to_extract[0] / 10, |
||
921 | G.crec.version_needed_to_extract[0] % 10, |
||
922 | VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10)); |
||
923 | return 0; |
||
924 | } |
||
925 | #ifndef VMS /* won't be able to use extra field, but still have data */ |
||
926 | else if (!uO.tflag && !IS_OVERWRT_ALL) { /* if -o, extract anyway */ |
||
927 | Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery), |
||
928 | FnFilter1(G.filename))); |
||
929 | fgets(G.answerbuf, sizeof(G.answerbuf), stdin); |
||
930 | if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y')) |
||
931 | return 0; |
||
932 | } |
||
933 | #endif /* !VMS */ |
||
934 | /* usual file type: don't need VMS to extract */ |
||
935 | } else if (G.crec.version_needed_to_extract[0] > UNZVERS_SUPPORT) { |
||
936 | if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) |
||
937 | Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg), |
||
938 | FnFilter1(G.filename), "PK", |
||
939 | G.crec.version_needed_to_extract[0] / 10, |
||
940 | G.crec.version_needed_to_extract[0] % 10, |
||
941 | UNZVERS_SUPPORT / 10, UNZVERS_SUPPORT % 10)); |
||
942 | return 0; |
||
943 | } |
||
944 | |||
945 | if (UNKN_COMPR) { |
||
946 | if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) { |
||
947 | #ifndef SFX |
||
948 | unsigned cmpridx; |
||
949 | |||
950 | if ((cmpridx = find_compr_idx(G.crec.compression_method)) |
||
951 | < NUM_METHODS) |
||
952 | Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName), |
||
953 | FnFilter1(G.filename), |
||
954 | LoadFarStringSmall(ComprNames[cmpridx]))); |
||
955 | else |
||
956 | #endif |
||
957 | Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum), |
||
958 | FnFilter1(G.filename), |
||
959 | G.crec.compression_method)); |
||
960 | } |
||
961 | return 0; |
||
962 | } |
||
963 | #if (!CRYPT) |
||
964 | if (G.pInfo->encrypted) { |
||
965 | if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) |
||
966 | Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted), |
||
967 | FnFilter1(G.filename))); |
||
968 | return 0; |
||
969 | } |
||
970 | #endif /* !CRYPT */ |
||
971 | |||
972 | #ifndef SFX |
||
973 | /* store a copy of the central header filename for later comparison */ |
||
974 | if ((G.pInfo->cfilname = zfmalloc(strlen(G.filename) + 1)) == NULL) { |
||
975 | Info(slide, 0x401, ((char *)slide, LoadFarString(WarnNoMemCFName), |
||
976 | FnFilter1(G.filename))); |
||
977 | } else |
||
978 | zfstrcpy(G.pInfo->cfilname, G.filename); |
||
979 | #endif /* !SFX */ |
||
980 | |||
981 | /* map whatever file attributes we have into the local format */ |
||
982 | mapattr(__G); /* GRR: worry about return value later */ |
||
983 | |||
984 | G.pInfo->diskstart = G.crec.disk_number_start; |
||
985 | G.pInfo->offset = (zoff_t)G.crec.relative_offset_local_header; |
||
986 | return 1; |
||
987 | |||
988 | } /* end function store_info() */ |
||
989 | |||
990 | |||
991 | |||
992 | |||
993 | |||
994 | #ifndef SFX |
||
995 | /*******************************/ |
||
996 | /* Function find_compr_idx() */ |
||
997 | /*******************************/ |
||
998 | |||
999 | unsigned find_compr_idx(compr_methodnum) |
||
1000 | unsigned compr_methodnum; |
||
1001 | { |
||
1002 | unsigned i; |
||
1003 | |||
1004 | for (i = 0; i < NUM_METHODS; i++) { |
||
1005 | if (ComprIDs[i] == compr_methodnum) break; |
||
1006 | } |
||
1007 | return i; |
||
1008 | } |
||
1009 | #endif /* !SFX */ |
||
1010 | |||
1011 | |||
1012 | |||
1013 | |||
1014 | |||
1015 | /******************************************/ |
||
1016 | /* Function extract_or_test_entrylist() */ |
||
1017 | /******************************************/ |
||
1018 | |||
1019 | static int extract_or_test_entrylist(__G__ numchunk, |
||
1020 | pfilnum, pnum_bad_pwd, pold_extra_bytes, |
||
1021 | #ifdef SET_DIR_ATTRIB |
||
1022 | pnum_dirs, pdirlist, |
||
1023 | #endif |
||
1024 | error_in_archive) /* return PK-type error code */ |
||
1025 | __GDEF |
||
1026 | unsigned numchunk; |
||
1027 | ulg *pfilnum; |
||
1028 | ulg *pnum_bad_pwd; |
||
1029 | zoff_t *pold_extra_bytes; |
||
1030 | #ifdef SET_DIR_ATTRIB |
||
1031 | unsigned *pnum_dirs; |
||
1032 | direntry **pdirlist; |
||
1033 | #endif |
||
1034 | int error_in_archive; |
||
1035 | { |
||
1036 | unsigned i; |
||
1037 | int renamed, query; |
||
1038 | int skip_entry; |
||
1039 | zoff_t bufstart, inbuf_offset, request; |
||
1040 | int error, errcode; |
||
1041 | |||
1042 | /* possible values for local skip_entry flag: */ |
||
1043 | #define SKIP_NO 0 /* do not skip this entry */ |
||
1044 | #define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */ |
||
1045 | #define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */ |
||
1046 | |||
1047 | /*----------------------------------------------------------------------- |
||
1048 | Second loop: process files in current block, extracting or testing |
||
1049 | each one. |
||
1050 | -----------------------------------------------------------------------*/ |
||
1051 | |||
1052 | for (i = 0; i < numchunk; ++i) { |
||
1053 | (*pfilnum)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */ |
||
1054 | G.pInfo = &G.info[i]; |
||
1055 | #ifdef NOVELL_BUG_FAILSAFE |
||
1056 | G.dne = FALSE; /* assume file exists until stat() says otherwise */ |
||
1057 | #endif |
||
1058 | |||
1059 | /* if the target position is not within the current input buffer |
||
1060 | * (either haven't yet read far enough, or (maybe) skipping back- |
||
1061 | * ward), skip to the target position and reset readbuf(). */ |
||
1062 | |||
1063 | /* seek_zipf(__G__ pInfo->offset); */ |
||
1064 | request = G.pInfo->offset + G.extra_bytes; |
||
1065 | inbuf_offset = request % INBUFSIZ; |
||
1066 | bufstart = request - inbuf_offset; |
||
1067 | |||
1068 | Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n", |
||
1069 | (long)request, (long)inbuf_offset)); |
||
1070 | Trace((stderr, |
||
1071 | "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", |
||
1072 | (long)bufstart, (long)G.cur_zipfile_bufstart)); |
||
1073 | if (request < 0) { |
||
1074 | Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg), |
||
1075 | G.zipfn, LoadFarString(ReportMsg))); |
||
1076 | error_in_archive = PK_ERR; |
||
1077 | if (*pfilnum == 1 && G.extra_bytes != 0L) { |
||
1078 | Info(slide, 0x401, ((char *)slide, |
||
1079 | LoadFarString(AttemptRecompensate))); |
||
1080 | *pold_extra_bytes = G.extra_bytes; |
||
1081 | G.extra_bytes = 0L; |
||
1082 | request = G.pInfo->offset; /* could also check if != 0 */ |
||
1083 | inbuf_offset = request % INBUFSIZ; |
||
1084 | bufstart = request - inbuf_offset; |
||
1085 | Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n", |
||
1086 | (long)request, (long)inbuf_offset)); |
||
1087 | Trace((stderr, |
||
1088 | "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n", |
||
1089 | (long)bufstart, (long)G.cur_zipfile_bufstart)); |
||
1090 | /* try again */ |
||
1091 | if (request < 0) { |
||
1092 | Trace((stderr, |
||
1093 | "debug: recompensated request still < 0\n")); |
||
1094 | Info(slide, 0x401, ((char *)slide, |
||
1095 | LoadFarStringSmall(SeekMsg), |
||
1096 | G.zipfn, LoadFarString(ReportMsg))); |
||
1097 | error_in_archive = PK_BADERR; |
||
1098 | continue; |
||
1099 | } |
||
1100 | } else { |
||
1101 | error_in_archive = PK_BADERR; |
||
1102 | continue; /* this one hosed; try next */ |
||
1103 | } |
||
1104 | } |
||
1105 | |||
1106 | if (bufstart != G.cur_zipfile_bufstart) { |
||
1107 | Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n")); |
||
1108 | #ifdef USE_STRM_INPUT |
||
1109 | zfseeko(G.zipfd, bufstart, SEEK_SET); |
||
1110 | G.cur_zipfile_bufstart = zftello(G.zipfd); |
||
1111 | #else /* !USE_STRM_INPUT */ |
||
1112 | G.cur_zipfile_bufstart = |
||
1113 | zlseek(G.zipfd, bufstart, SEEK_SET); |
||
1114 | #endif /* ?USE_STRM_INPUT */ |
||
1115 | if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0) |
||
1116 | { |
||
1117 | Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), |
||
1118 | *pfilnum, "lseek", (long)bufstart)); |
||
1119 | error_in_archive = PK_BADERR; |
||
1120 | continue; /* can still do next file */ |
||
1121 | } |
||
1122 | G.inptr = G.inbuf + (int)inbuf_offset; |
||
1123 | G.incnt -= (int)inbuf_offset; |
||
1124 | } else { |
||
1125 | G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset; |
||
1126 | G.inptr = G.inbuf + (int)inbuf_offset; |
||
1127 | } |
||
1128 | |||
1129 | /* should be in proper position now, so check for sig */ |
||
1130 | if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */ |
||
1131 | Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), |
||
1132 | *pfilnum, "EOF", (long)request)); |
||
1133 | error_in_archive = PK_BADERR; |
||
1134 | continue; /* but can still try next one */ |
||
1135 | } |
||
1136 | if (memcmp(G.sig, local_hdr_sig, 4)) { |
||
1137 | Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg), |
||
1138 | *pfilnum, LoadFarStringSmall(LocalHdrSig), (long)request)); |
||
1139 | /* |
||
1140 | GRRDUMP(G.sig, 4) |
||
1141 | GRRDUMP(local_hdr_sig, 4) |
||
1142 | */ |
||
1143 | error_in_archive = PK_ERR; |
||
1144 | if ((*pfilnum == 1 && G.extra_bytes != 0L) || |
||
1145 | (G.extra_bytes == 0L && *pold_extra_bytes != 0L)) { |
||
1146 | Info(slide, 0x401, ((char *)slide, |
||
1147 | LoadFarString(AttemptRecompensate))); |
||
1148 | if (G.extra_bytes) { |
||
1149 | *pold_extra_bytes = G.extra_bytes; |
||
1150 | G.extra_bytes = 0L; |
||
1151 | } else |
||
1152 | G.extra_bytes = *pold_extra_bytes; /* third attempt */ |
||
1153 | if (((error = seek_zipf(__G__ G.pInfo->offset)) != PK_OK) || |
||
1154 | (readbuf(__G__ G.sig, 4) == 0)) { /* bad offset */ |
||
1155 | if (error != PK_BADERR) |
||
1156 | Info(slide, 0x401, ((char *)slide, |
||
1157 | LoadFarString(OffsetMsg), *pfilnum, "EOF", |
||
1158 | (long)request)); |
||
1159 | error_in_archive = PK_BADERR; |
||
1160 | continue; /* but can still try next one */ |
||
1161 | } |
||
1162 | if (memcmp(G.sig, local_hdr_sig, 4)) { |
||
1163 | Info(slide, 0x401, ((char *)slide, |
||
1164 | LoadFarString(OffsetMsg), *pfilnum, |
||
1165 | LoadFarStringSmall(LocalHdrSig), (long)request)); |
||
1166 | error_in_archive = PK_BADERR; |
||
1167 | continue; |
||
1168 | } |
||
1169 | } else |
||
1170 | continue; /* this one hosed; try next */ |
||
1171 | } |
||
1172 | if ((error = process_local_file_hdr(__G)) != PK_COOL) { |
||
1173 | Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr), |
||
1174 | *pfilnum)); |
||
1175 | error_in_archive = error; /* only PK_EOF defined */ |
||
1176 | continue; /* can still try next one */ |
||
1177 | } |
||
1178 | #if (!defined(SFX) && defined(UNICODE_SUPPORT)) |
||
1179 | if (((G.lrec.general_purpose_bit_flag & (1 << 11)) == (1 << 11)) |
||
1180 | != (G.pInfo->GPFIsUTF8 != 0)) { |
||
1181 | if (QCOND2) { |
||
1182 | # ifdef SMALL_MEM |
||
1183 | char *temp_cfilnam = slide + (7 * (WSIZE>>3)); |
||
1184 | |||
1185 | zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); |
||
1186 | # define cFile_PrintBuf temp_cfilnam |
||
1187 | # else |
||
1188 | # define cFile_PrintBuf G.pInfo->cfilname |
||
1189 | # endif |
||
1190 | Info(slide, 0x421, ((char *)slide, |
||
1191 | LoadFarStringSmall2(GP11FlagsDiffer), |
||
1192 | *pfilnum, FnFilter1(cFile_PrintBuf), G.pInfo->GPFIsUTF8)); |
||
1193 | # undef cFile_PrintBuf |
||
1194 | } |
||
1195 | if (error_in_archive < PK_WARN) |
||
1196 | error_in_archive = PK_WARN; |
||
1197 | } |
||
1198 | #endif /* !SFX && UNICODE_SUPPORT */ |
||
1199 | if ((error = do_string(__G__ G.lrec.filename_length, DS_FN_L)) != |
||
1200 | PK_COOL) |
||
1201 | { |
||
1202 | if (error > error_in_archive) |
||
1203 | error_in_archive = error; |
||
1204 | if (error > PK_WARN) { |
||
1205 | Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg), |
||
1206 | FnFilter1(G.filename), "local")); |
||
1207 | continue; /* go on to next one */ |
||
1208 | } |
||
1209 | } |
||
1210 | if (G.extra_field != (uch *)NULL) { |
||
1211 | free(G.extra_field); |
||
1212 | G.extra_field = (uch *)NULL; |
||
1213 | } |
||
1214 | if ((error = |
||
1215 | do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0) |
||
1216 | { |
||
1217 | if (error > error_in_archive) |
||
1218 | error_in_archive = error; |
||
1219 | if (error > PK_WARN) { |
||
1220 | Info(slide, 0x401, ((char *)slide, |
||
1221 | LoadFarString(ExtFieldMsg), |
||
1222 | FnFilter1(G.filename), "local")); |
||
1223 | continue; /* go on */ |
||
1224 | } |
||
1225 | } |
||
1226 | #ifndef SFX |
||
1227 | /* Filename consistency checks must come after reading in the local |
||
1228 | * extra field, so that a UTF-8 entry name e.f. block has already |
||
1229 | * been processed. |
||
1230 | */ |
||
1231 | if (G.pInfo->cfilname != (char Far *)NULL) { |
||
1232 | if (zfstrcmp(G.pInfo->cfilname, G.filename) != 0) { |
||
1233 | # ifdef SMALL_MEM |
||
1234 | char *temp_cfilnam = slide + (7 * (WSIZE>>3)); |
||
1235 | |||
1236 | zfstrcpy((char Far *)temp_cfilnam, G.pInfo->cfilname); |
||
1237 | # define cFile_PrintBuf temp_cfilnam |
||
1238 | # else |
||
1239 | # define cFile_PrintBuf G.pInfo->cfilname |
||
1240 | # endif |
||
1241 | Info(slide, 0x401, ((char *)slide, |
||
1242 | LoadFarStringSmall2(LvsCFNamMsg), |
||
1243 | FnFilter2(cFile_PrintBuf), FnFilter1(G.filename))); |
||
1244 | # undef cFile_PrintBuf |
||
1245 | zfstrcpy(G.filename, G.pInfo->cfilname); |
||
1246 | if (error_in_archive < PK_WARN) |
||
1247 | error_in_archive = PK_WARN; |
||
1248 | } |
||
1249 | zffree(G.pInfo->cfilname); |
||
1250 | G.pInfo->cfilname = (char Far *)NULL; |
||
1251 | } |
||
1252 | #endif /* !SFX */ |
||
1253 | /* Size consistency checks must come after reading in the local extra |
||
1254 | * field, so that any Zip64 extension local e.f. block has already |
||
1255 | * been processed. |
||
1256 | */ |
||
1257 | if (G.lrec.compression_method == STORED) { |
||
1258 | zusz_t csiz_decrypted = G.lrec.csize; |
||
1259 | |||
1260 | if (G.pInfo->encrypted) |
||
1261 | csiz_decrypted -= 12; |
||
1262 | if (G.lrec.ucsize != csiz_decrypted) { |
||
1263 | Info(slide, 0x401, ((char *)slide, |
||
1264 | LoadFarStringSmall2(WrnStorUCSizCSizDiff), |
||
1265 | FnFilter1(G.filename), |
||
1266 | FmZofft(G.lrec.ucsize, NULL, "u"), |
||
1267 | FmZofft(csiz_decrypted, NULL, "u"))); |
||
1268 | G.lrec.ucsize = csiz_decrypted; |
||
1269 | if (error_in_archive < PK_WARN) |
||
1270 | error_in_archive = PK_WARN; |
||
1271 | } |
||
1272 | } |
||
1273 | |||
1274 | #if CRYPT |
||
1275 | if (G.pInfo->encrypted && |
||
1276 | (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) { |
||
1277 | if (error == PK_WARN) { |
||
1278 | if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) |
||
1279 | Info(slide, 0x401, ((char *)slide, |
||
1280 | LoadFarString(SkipIncorrectPasswd), |
||
1281 | FnFilter1(G.filename))); |
||
1282 | ++(*pnum_bad_pwd); |
||
1283 | } else { /* (error > PK_WARN) */ |
||
1284 | if (error > error_in_archive) |
||
1285 | error_in_archive = error; |
||
1286 | Info(slide, 0x401, ((char *)slide, |
||
1287 | LoadFarString(SkipCannotGetPasswd), |
||
1288 | FnFilter1(G.filename))); |
||
1289 | } |
||
1290 | continue; /* go on to next file */ |
||
1291 | } |
||
1292 | #endif /* CRYPT */ |
||
1293 | |||
1294 | /* |
||
1295 | * just about to extract file: if extracting to disk, check if |
||
1296 | * already exists, and if so, take appropriate action according to |
||
1297 | * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper |
||
1298 | * loop because we don't store the possibly renamed filename[] in |
||
1299 | * info[]) |
||
1300 | */ |
||
1301 | #ifdef DLL |
||
1302 | if (!uO.tflag && !uO.cflag && !G.redirect_data) |
||
1303 | #else |
||
1304 | if (!uO.tflag && !uO.cflag) |
||
1305 | #endif |
||
1306 | { |
||
1307 | renamed = FALSE; /* user hasn't renamed output file yet */ |
||
1308 | |||
1309 | startover: |
||
1310 | query = FALSE; |
||
1311 | skip_entry = SKIP_NO; |
||
1312 | /* for files from DOS FAT, check for use of backslash instead |
||
1313 | * of slash as directory separator (bug in some zipper(s); so |
||
1314 | * far, not a problem in HPFS, NTFS or VFAT systems) |
||
1315 | */ |
||
1316 | #ifndef SFX |
||
1317 | if (G.pInfo->hostnum == FS_FAT_ && !MBSCHR(G.filename, '/')) { |
||
1318 | char *p=G.filename; |
||
1319 | |||
1320 | if (*p) do { |
||
1321 | if (*p == '\\') { |
||
1322 | if (!G.reported_backslash) { |
||
1323 | Info(slide, 0x21, ((char *)slide, |
||
1324 | LoadFarString(BackslashPathSep), G.zipfn)); |
||
1325 | G.reported_backslash = TRUE; |
||
1326 | if (!error_in_archive) |
||
1327 | error_in_archive = PK_WARN; |
||
1328 | } |
||
1329 | *p = '/'; |
||
1330 | } |
||
1331 | } while (*PREINCSTR(p)); |
||
1332 | } |
||
1333 | #endif /* !SFX */ |
||
1334 | |||
1335 | if (!renamed) { |
||
1336 | /* remove absolute path specs */ |
||
1337 | if (G.filename[0] == '/') { |
||
1338 | Info(slide, 0x401, ((char *)slide, |
||
1339 | LoadFarString(AbsolutePathWarning), |
||
1340 | FnFilter1(G.filename))); |
||
1341 | if (!error_in_archive) |
||
1342 | error_in_archive = PK_WARN; |
||
1343 | do { |
||
1344 | char *p = G.filename + 1; |
||
1345 | do { |
||
1346 | *(p-1) = *p; |
||
1347 | } while (*p++ != '\0'); |
||
1348 | } while (G.filename[0] == '/'); |
||
1349 | } |
||
1350 | } |
||
1351 | |||
1352 | /* mapname can create dirs if not freshening or if renamed */ |
||
1353 | error = mapname(__G__ renamed); |
||
1354 | if ((errcode = error & ~MPN_MASK) != PK_OK && |
||
1355 | error_in_archive < errcode) |
||
1356 | error_in_archive = errcode; |
||
1357 | if ((errcode = error & MPN_MASK) > MPN_INF_TRUNC) { |
||
1358 | if (errcode == MPN_CREATED_DIR) { |
||
1359 | #ifdef SET_DIR_ATTRIB |
||
1360 | direntry *d_entry; |
||
1361 | |||
1362 | error = defer_dir_attribs(__G__ &d_entry); |
||
1363 | if (d_entry == (direntry *)NULL) { |
||
1364 | /* There may be no dir_attribs info available, or |
||
1365 | * we have encountered a mem allocation error. |
||
1366 | * In case of an error, report it and set program |
||
1367 | * error state to warning level. |
||
1368 | */ |
||
1369 | if (error) { |
||
1370 | Info(slide, 0x401, ((char *)slide, |
||
1371 | LoadFarString(DirlistEntryNoMem))); |
||
1372 | if (!error_in_archive) |
||
1373 | error_in_archive = PK_WARN; |
||
1374 | } |
||
1375 | } else { |
||
1376 | d_entry->next = (*pdirlist); |
||
1377 | (*pdirlist) = d_entry; |
||
1378 | ++(*pnum_dirs); |
||
1379 | } |
||
1380 | #endif /* SET_DIR_ATTRIB */ |
||
1381 | } else if (errcode == MPN_VOL_LABEL) { |
||
1382 | #ifdef DOS_OS2_W32 |
||
1383 | Info(slide, 0x401, ((char *)slide, |
||
1384 | LoadFarString(SkipVolumeLabel), |
||
1385 | FnFilter1(G.filename), |
||
1386 | uO.volflag? "hard disk " : "")); |
||
1387 | #else |
||
1388 | Info(slide, 1, ((char *)slide, |
||
1389 | LoadFarString(SkipVolumeLabel), |
||
1390 | FnFilter1(G.filename), "")); |
||
1391 | #endif |
||
1392 | } else if (errcode > MPN_INF_SKIP && |
||
1393 | error_in_archive < PK_ERR) |
||
1394 | error_in_archive = PK_ERR; |
||
1395 | Trace((stderr, "mapname(%s) returns error code = %d\n", |
||
1396 | FnFilter1(G.filename), error)); |
||
1397 | continue; /* go on to next file */ |
||
1398 | } |
||
1399 | |||
1400 | #ifdef QDOS |
||
1401 | QFilename(__G__ G.filename); |
||
1402 | #endif |
||
1403 | switch (check_for_newer(__G__ G.filename)) { |
||
1404 | case DOES_NOT_EXIST: |
||
1405 | #ifdef NOVELL_BUG_FAILSAFE |
||
1406 | G.dne = TRUE; /* stat() says file DOES NOT EXIST */ |
||
1407 | #endif |
||
1408 | /* freshen (no new files): skip unless just renamed */ |
||
1409 | if (uO.fflag && !renamed) |
||
1410 | skip_entry = SKIP_Y_NONEXIST; |
||
1411 | break; |
||
1412 | case EXISTS_AND_OLDER: |
||
1413 | #ifdef UNIXBACKUP |
||
1414 | if (!uO.B_flag) |
||
1415 | #endif |
||
1416 | { |
||
1417 | if (IS_OVERWRT_NONE) |
||
1418 | /* never overwrite: skip file */ |
||
1419 | skip_entry = SKIP_Y_EXISTING; |
||
1420 | else if (!IS_OVERWRT_ALL) |
||
1421 | query = TRUE; |
||
1422 | } |
||
1423 | break; |
||
1424 | case EXISTS_AND_NEWER: /* (or equal) */ |
||
1425 | #ifdef UNIXBACKUP |
||
1426 | if ((!uO.B_flag && IS_OVERWRT_NONE) || |
||
1427 | #else |
||
1428 | if (IS_OVERWRT_NONE || |
||
1429 | #endif |
||
1430 | (uO.uflag && !renamed)) { |
||
1431 | /* skip if update/freshen & orig name */ |
||
1432 | skip_entry = SKIP_Y_EXISTING; |
||
1433 | } else { |
||
1434 | #ifdef UNIXBACKUP |
||
1435 | if (!IS_OVERWRT_ALL && !uO.B_flag) |
||
1436 | #else |
||
1437 | if (!IS_OVERWRT_ALL) |
||
1438 | #endif |
||
1439 | query = TRUE; |
||
1440 | } |
||
1441 | break; |
||
1442 | } |
||
1443 | #ifdef VMS |
||
1444 | /* 2008-07-24 SMS. |
||
1445 | * On VMS, if the file name includes a version number, |
||
1446 | * and "-V" ("retain VMS version numbers", V_flag) is in |
||
1447 | * effect, then the VMS-specific code will handle any |
||
1448 | * conflicts with an existing file, making this query |
||
1449 | * redundant. (Implicit "y" response here.) |
||
1450 | */ |
||
1451 | if (query && uO.V_flag) { |
||
1452 | /* Not discarding file versions. Look for one. */ |
||
1453 | int cndx = strlen(G.filename) - 1; |
||
1454 | |||
1455 | while ((cndx > 0) && (isdigit(G.filename[cndx]))) |
||
1456 | cndx--; |
||
1457 | if (G.filename[cndx] == ';') |
||
1458 | /* File version found; skip the generic query, |
||
1459 | * proceeding with its default response "y". |
||
1460 | */ |
||
1461 | query = FALSE; |
||
1462 | } |
||
1463 | #endif /* VMS */ |
||
1464 | if (query) { |
||
1465 | #ifdef WINDLL |
||
1466 | switch (G.lpUserFunctions->replace != NULL ? |
||
1467 | (*G.lpUserFunctions->replace)(G.filename, FILNAMSIZ) : |
||
1468 | IDM_REPLACE_NONE) { |
||
1469 | case IDM_REPLACE_RENAME: |
||
1470 | _ISO_INTERN(G.filename); |
||
1471 | renamed = TRUE; |
||
1472 | goto startover; |
||
1473 | case IDM_REPLACE_ALL: |
||
1474 | G.overwrite_mode = OVERWRT_ALWAYS; |
||
1475 | /* FALL THROUGH, extract */ |
||
1476 | case IDM_REPLACE_YES: |
||
1477 | break; |
||
1478 | case IDM_REPLACE_NONE: |
||
1479 | G.overwrite_mode = OVERWRT_NEVER; |
||
1480 | /* FALL THROUGH, skip */ |
||
1481 | case IDM_REPLACE_NO: |
||
1482 | skip_entry = SKIP_Y_EXISTING; |
||
1483 | break; |
||
1484 | } |
||
1485 | #else /* !WINDLL */ |
||
1486 | extent fnlen; |
||
1487 | reprompt: |
||
6775 | siemargl | 1488 | Info(slide, 0x81 & 0xFE, ((char *)slide, |
6725 | siemargl | 1489 | LoadFarString(ReplaceQuery), |
1490 | FnFilter1(G.filename))); |
||
1491 | if (fgets(G.answerbuf, sizeof(G.answerbuf), stdin) |
||
1492 | == (char *)NULL) { |
||
6775 | siemargl | 1493 | Info(slide, 1 & 0xFE, ((char *)slide, |
6725 | siemargl | 1494 | LoadFarString(AssumeNone))); |
1495 | *G.answerbuf = 'N'; |
||
1496 | if (!error_in_archive) |
||
1497 | error_in_archive = 1; /* not extracted: warning */ |
||
1498 | } |
||
1499 | switch (*G.answerbuf) { |
||
1500 | case 'r': |
||
1501 | case 'R': |
||
1502 | do { |
||
6775 | siemargl | 1503 | Info(slide, 0x81 & 0xFE, ((char *)slide, |
6725 | siemargl | 1504 | LoadFarString(NewNameQuery))); |
1505 | fgets(G.filename, FILNAMSIZ, stdin); |
||
1506 | /* usually get \n here: better check for it */ |
||
1507 | fnlen = strlen(G.filename); |
||
1508 | if (lastchar(G.filename, fnlen) == '\n') |
||
1509 | G.filename[--fnlen] = '\0'; |
||
1510 | } while (fnlen == 0); |
||
1511 | #ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */ |
||
1512 | _OEM_INTERN(G.filename); |
||
1513 | #endif |
||
1514 | renamed = TRUE; |
||
1515 | goto startover; /* sorry for a goto */ |
||
1516 | case 'A': /* dangerous option: force caps */ |
||
1517 | G.overwrite_mode = OVERWRT_ALWAYS; |
||
1518 | /* FALL THROUGH, extract */ |
||
1519 | case 'y': |
||
1520 | case 'Y': |
||
1521 | break; |
||
1522 | case 'N': |
||
1523 | G.overwrite_mode = OVERWRT_NEVER; |
||
1524 | /* FALL THROUGH, skip */ |
||
1525 | case 'n': |
||
1526 | /* skip file */ |
||
1527 | skip_entry = SKIP_Y_EXISTING; |
||
1528 | break; |
||
1529 | case '\n': |
||
1530 | case '\r': |
||
1531 | /* Improve echo of '\n' and/or '\r' |
||
1532 | (sizeof(G.answerbuf) == 10 (see globals.h), so |
||
1533 | there is enough space for the provided text...) */ |
||
1534 | strcpy(G.answerbuf, "{ENTER}"); |
||
1535 | /* fall through ... */ |
||
1536 | default: |
||
1537 | /* usually get \n here: remove it for nice display |
||
1538 | (fnlen can be re-used here, we are outside the |
||
1539 | "enter new filename" loop) */ |
||
1540 | fnlen = strlen(G.answerbuf); |
||
1541 | if (lastchar(G.answerbuf, fnlen) == '\n') |
||
1542 | G.answerbuf[--fnlen] = '\0'; |
||
6775 | siemargl | 1543 | Info(slide, 1 & 0xFE, ((char *)slide, |
6725 | siemargl | 1544 | LoadFarString(InvalidResponse), G.answerbuf)); |
1545 | goto reprompt; /* yet another goto? */ |
||
1546 | } /* end switch (*answerbuf) */ |
||
1547 | #endif /* ?WINDLL */ |
||
1548 | } /* end if (query) */ |
||
1549 | if (skip_entry != SKIP_NO) { |
||
1550 | #ifdef WINDLL |
||
1551 | if (skip_entry == SKIP_Y_EXISTING) { |
||
1552 | /* report skipping of an existing entry */ |
||
1553 | Info(slide, 0, ((char *)slide, |
||
1554 | ((IS_OVERWRT_NONE || !uO.uflag || renamed) ? |
||
1555 | "Target file exists. Skipping %s\n" : |
||
1556 | "Target file newer. Skipping %s\n"), |
||
1557 | FnFilter1(G.filename))); |
||
1558 | } |
||
1559 | #endif /* WINDLL */ |
||
1560 | continue; |
||
1561 | } |
||
1562 | } /* end if (extracting to disk) */ |
||
1563 | |||
1564 | #ifdef DLL |
||
1565 | if ((G.statreportcb != NULL) && |
||
1566 | (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn, |
||
1567 | G.filename, NULL)) { |
||
1568 | return IZ_CTRLC; /* cancel operation by user request */ |
||
1569 | } |
||
1570 | #endif |
||
1571 | #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ |
||
1572 | UserStop(); |
||
1573 | #endif |
||
1574 | #ifdef AMIGA |
||
1575 | G.filenote_slot = i; |
||
1576 | #endif |
||
1577 | G.disk_full = 0; |
||
1578 | if ((error = extract_or_test_member(__G)) != PK_COOL) { |
||
1579 | if (error > error_in_archive) |
||
1580 | error_in_archive = error; /* ...and keep going */ |
||
1581 | #ifdef DLL |
||
1582 | if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) { |
||
1583 | #else |
||
1584 | if (G.disk_full > 1) { |
||
1585 | #endif |
||
1586 | return error_in_archive; /* (unless disk full) */ |
||
1587 | } |
||
1588 | } |
||
1589 | #ifdef DLL |
||
1590 | if ((G.statreportcb != NULL) && |
||
1591 | (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn, |
||
1592 | G.filename, (zvoid *)&G.lrec.ucsize)) { |
||
1593 | return IZ_CTRLC; /* cancel operation by user request */ |
||
1594 | } |
||
1595 | #endif |
||
1596 | #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */ |
||
1597 | UserStop(); |
||
1598 | #endif |
||
1599 | } /* end for-loop (i: files in current block) */ |
||
1600 | |||
1601 | return error_in_archive; |
||
1602 | |||
1603 | } /* end function extract_or_test_entrylist() */ |
||
1604 | |||
1605 | |||
1606 | |||
1607 | |||
1608 | |||
1609 | /* wsize is used in extract_or_test_member() and UZbunzip2() */ |
||
1610 | #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) |
||
1611 | # define wsize G._wsize /* wsize is a variable */ |
||
1612 | #else |
||
1613 | # define wsize WSIZE /* wsize is a constant */ |
||
1614 | #endif |
||
1615 | |||
1616 | /***************************************/ |
||
1617 | /* Function extract_or_test_member() */ |
||
1618 | /***************************************/ |
||
1619 | |||
1620 | static int extract_or_test_member(__G) /* return PK-type error code */ |
||
1621 | __GDEF |
||
1622 | { |
||
1623 | char *nul="[empty] ", *txt="[text] ", *bin="[binary]"; |
||
1624 | #ifdef CMS_MVS |
||
1625 | char *ebc="[ebcdic]"; |
||
1626 | #endif |
||
1627 | register int b; |
||
1628 | int r, error=PK_COOL; |
||
1629 | |||
1630 | |||
1631 | /*--------------------------------------------------------------------------- |
||
1632 | Initialize variables, buffers, etc. |
||
1633 | ---------------------------------------------------------------------------*/ |
||
1634 | |||
1635 | G.bits_left = 0; |
||
1636 | G.bitbuf = 0L; /* unreduce and unshrink only */ |
||
1637 | G.zipeof = 0; |
||
1638 | G.newfile = TRUE; |
||
1639 | G.crc32val = CRCVAL_INITIAL; |
||
1640 | |||
1641 | #ifdef SYMLINKS |
||
1642 | /* If file is a (POSIX-compatible) symbolic link and we are extracting |
||
1643 | * to disk, prepare to restore the link. */ |
||
1644 | G.symlnk = (G.pInfo->symlink && |
||
1645 | !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0)); |
||
1646 | #endif /* SYMLINKS */ |
||
1647 | |||
1648 | if (uO.tflag) { |
||
1649 | if (!uO.qflag) |
||
1650 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test", |
||
1651 | FnFilter1(G.filename), "", "")); |
||
1652 | } else { |
||
1653 | #ifdef DLL |
||
1654 | if (uO.cflag && !G.redirect_data) |
||
1655 | #else |
||
1656 | if (uO.cflag) |
||
1657 | #endif |
||
1658 | { |
||
1659 | #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200)) |
||
1660 | G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */ |
||
1661 | #else |
||
1662 | G.outfile = stdout; |
||
1663 | #endif |
||
1664 | #ifdef DOS_FLX_NLM_OS2_W32 |
||
1665 | #if (defined(__HIGHC__) && !defined(FLEXOS)) |
||
1666 | setmode(G.outfile, _BINARY); |
||
1667 | #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */ |
||
1668 | setmode(fileno(G.outfile), O_BINARY); |
||
1669 | #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */ |
||
1670 | # define NEWLINE "\r\n" |
||
1671 | #else /* !DOS_FLX_NLM_OS2_W32 */ |
||
1672 | # define NEWLINE "\n" |
||
1673 | #endif /* ?DOS_FLX_NLM_OS2_W32 */ |
||
1674 | #ifdef VMS |
||
1675 | /* VMS: required even for stdout! */ |
||
1676 | if ((r = open_outfile(__G)) != 0) |
||
1677 | switch (r) { |
||
1678 | case OPENOUT_SKIPOK: |
||
1679 | return PK_OK; |
||
1680 | case OPENOUT_SKIPWARN: |
||
1681 | return PK_WARN; |
||
1682 | default: |
||
1683 | return PK_DISK; |
||
1684 | } |
||
1685 | } else if ((r = open_outfile(__G)) != 0) |
||
1686 | switch (r) { |
||
1687 | case OPENOUT_SKIPOK: |
||
1688 | return PK_OK; |
||
1689 | case OPENOUT_SKIPWARN: |
||
1690 | return PK_WARN; |
||
1691 | default: |
||
1692 | return PK_DISK; |
||
1693 | } |
||
1694 | #else /* !VMS */ |
||
1695 | } else if (open_outfile(__G)) |
||
1696 | return PK_DISK; |
||
1697 | #endif /* ?VMS */ |
||
1698 | } |
||
1699 | |||
1700 | /*--------------------------------------------------------------------------- |
||
1701 | Unpack the file. |
||
1702 | ---------------------------------------------------------------------------*/ |
||
1703 | |||
1704 | defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */ |
||
1705 | switch (G.lrec.compression_method) { |
||
1706 | case STORED: |
||
1707 | if (!uO.tflag && QCOND2) { |
||
1708 | #ifdef SYMLINKS |
||
1709 | if (G.symlnk) /* can also be deflated, but rarer... */ |
||
1710 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), |
||
1711 | "link", FnFilter1(G.filename), "", "")); |
||
1712 | else |
||
1713 | #endif /* SYMLINKS */ |
||
1714 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), |
||
1715 | "extract", FnFilter1(G.filename), |
||
1716 | (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? |
||
1717 | "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt : |
||
1718 | bin)), uO.cflag? NEWLINE : "")); |
||
1719 | } |
||
1720 | #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) |
||
1721 | if (G.redirect_slide) { |
||
1722 | wsize = G.redirect_size; redirSlide = G.redirect_buffer; |
||
1723 | } else { |
||
1724 | wsize = WSIZE; redirSlide = slide; |
||
1725 | } |
||
1726 | #endif |
||
1727 | G.outptr = redirSlide; |
||
1728 | G.outcnt = 0L; |
||
1729 | while ((b = NEXTBYTE) != EOF) { |
||
1730 | *G.outptr++ = (uch)b; |
||
1731 | if (++G.outcnt == wsize) { |
||
1732 | error = flush(__G__ redirSlide, G.outcnt, 0); |
||
1733 | G.outptr = redirSlide; |
||
1734 | G.outcnt = 0L; |
||
1735 | if (error != PK_COOL || G.disk_full) break; |
||
1736 | } |
||
1737 | } |
||
1738 | if (G.outcnt) { /* flush final (partial) buffer */ |
||
1739 | r = flush(__G__ redirSlide, G.outcnt, 0); |
||
1740 | if (error < r) error = r; |
||
1741 | } |
||
1742 | break; |
||
1743 | |||
1744 | #ifndef SFX |
||
1745 | #ifndef LZW_CLEAN |
||
1746 | case SHRUNK: |
||
1747 | if (!uO.tflag && QCOND2) { |
||
1748 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), |
||
1749 | LoadFarStringSmall(Unshrink), FnFilter1(G.filename), |
||
1750 | (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? |
||
1751 | "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); |
||
1752 | } |
||
1753 | if ((r = unshrink(__G)) != PK_COOL) { |
||
1754 | if (r < PK_DISK) { |
||
1755 | if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) |
||
1756 | Info(slide, 0x401, ((char *)slide, |
||
1757 | LoadFarStringSmall(ErrUnzipFile), r == PK_MEM3 ? |
||
1758 | LoadFarString(NotEnoughMem) : |
||
1759 | LoadFarString(InvalidComprData), |
||
1760 | LoadFarStringSmall2(Unshrink), |
||
1761 | FnFilter1(G.filename))); |
||
1762 | else |
||
1763 | Info(slide, 0x401, ((char *)slide, |
||
1764 | LoadFarStringSmall(ErrUnzipNoFile), r == PK_MEM3 ? |
||
1765 | LoadFarString(NotEnoughMem) : |
||
1766 | LoadFarString(InvalidComprData), |
||
1767 | LoadFarStringSmall2(Unshrink))); |
||
1768 | } |
||
1769 | error = r; |
||
1770 | } |
||
1771 | break; |
||
1772 | #endif /* !LZW_CLEAN */ |
||
1773 | |||
1774 | #ifndef COPYRIGHT_CLEAN |
||
1775 | case REDUCED1: |
||
1776 | case REDUCED2: |
||
1777 | case REDUCED3: |
||
1778 | case REDUCED4: |
||
1779 | if (!uO.tflag && QCOND2) { |
||
1780 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), |
||
1781 | "unreduc", FnFilter1(G.filename), |
||
1782 | (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? |
||
1783 | "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); |
||
1784 | } |
||
1785 | if ((r = unreduce(__G)) != PK_COOL) { |
||
1786 | /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */ |
||
1787 | error = r; |
||
1788 | } |
||
1789 | break; |
||
1790 | #endif /* !COPYRIGHT_CLEAN */ |
||
1791 | |||
1792 | case IMPLODED: |
||
1793 | if (!uO.tflag && QCOND2) { |
||
1794 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), |
||
1795 | "explod", FnFilter1(G.filename), |
||
1796 | (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? |
||
1797 | "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); |
||
1798 | } |
||
1799 | if ((r = explode(__G)) != 0) { |
||
1800 | if (r == 5) { /* treat 5 specially */ |
||
1801 | int warning = ((zusz_t)G.used_csize <= G.lrec.csize); |
||
1802 | |||
1803 | if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) |
||
1804 | Info(slide, 0x401, ((char *)slide, |
||
1805 | LoadFarString(LengthMsg), |
||
1806 | "", warning ? "warning" : "error", |
||
1807 | FmZofft(G.used_csize, NULL, NULL), |
||
1808 | FmZofft(G.lrec.ucsize, NULL, "u"), |
||
1809 | warning ? " " : "", |
||
1810 | FmZofft(G.lrec.csize, NULL, "u"), |
||
1811 | " [", FnFilter1(G.filename), "]")); |
||
1812 | else |
||
1813 | Info(slide, 0x401, ((char *)slide, |
||
1814 | LoadFarString(LengthMsg), |
||
1815 | "\n", warning ? "warning" : "error", |
||
1816 | FmZofft(G.used_csize, NULL, NULL), |
||
1817 | FmZofft(G.lrec.ucsize, NULL, "u"), |
||
1818 | warning ? " " : "", |
||
1819 | FmZofft(G.lrec.csize, NULL, "u"), |
||
1820 | "", "", ".")); |
||
1821 | error = warning ? PK_WARN : PK_ERR; |
||
1822 | } else if (r < PK_DISK) { |
||
1823 | if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) |
||
1824 | Info(slide, 0x401, ((char *)slide, |
||
1825 | LoadFarStringSmall(ErrUnzipFile), r == 3? |
||
1826 | LoadFarString(NotEnoughMem) : |
||
1827 | LoadFarString(InvalidComprData), |
||
1828 | LoadFarStringSmall2(Explode), |
||
1829 | FnFilter1(G.filename))); |
||
1830 | else |
||
1831 | Info(slide, 0x401, ((char *)slide, |
||
1832 | LoadFarStringSmall(ErrUnzipNoFile), r == 3? |
||
1833 | LoadFarString(NotEnoughMem) : |
||
1834 | LoadFarString(InvalidComprData), |
||
1835 | LoadFarStringSmall2(Explode))); |
||
1836 | error = ((r == 3) ? PK_MEM3 : PK_ERR); |
||
1837 | } else { |
||
1838 | error = r; |
||
1839 | } |
||
1840 | } |
||
1841 | break; |
||
1842 | #endif /* !SFX */ |
||
1843 | |||
1844 | case DEFLATED: |
||
1845 | #ifdef USE_DEFLATE64 |
||
1846 | case ENHDEFLATED: |
||
1847 | #endif |
||
1848 | if (!uO.tflag && QCOND2) { |
||
1849 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), |
||
1850 | "inflat", FnFilter1(G.filename), |
||
1851 | (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? |
||
1852 | "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); |
||
1853 | } |
||
1854 | #ifndef USE_ZLIB /* zlib's function is called inflate(), too */ |
||
1855 | # define UZinflate inflate |
||
1856 | #endif |
||
1857 | if ((r = UZinflate(__G__ |
||
1858 | (G.lrec.compression_method == ENHDEFLATED))) |
||
1859 | != 0) { |
||
1860 | if (r < PK_DISK) { |
||
1861 | if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) |
||
1862 | Info(slide, 0x401, ((char *)slide, |
||
1863 | LoadFarStringSmall(ErrUnzipFile), r == 3? |
||
1864 | LoadFarString(NotEnoughMem) : |
||
1865 | LoadFarString(InvalidComprData), |
||
1866 | LoadFarStringSmall2(Inflate), |
||
1867 | FnFilter1(G.filename))); |
||
1868 | else |
||
1869 | Info(slide, 0x401, ((char *)slide, |
||
1870 | LoadFarStringSmall(ErrUnzipNoFile), r == 3? |
||
1871 | LoadFarString(NotEnoughMem) : |
||
1872 | LoadFarString(InvalidComprData), |
||
1873 | LoadFarStringSmall2(Inflate))); |
||
1874 | error = ((r == 3) ? PK_MEM3 : PK_ERR); |
||
1875 | } else { |
||
1876 | error = r; |
||
1877 | } |
||
1878 | } |
||
1879 | break; |
||
1880 | |||
1881 | #ifdef USE_BZIP2 |
||
1882 | case BZIPPED: |
||
1883 | if (!uO.tflag && QCOND2) { |
||
1884 | Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), |
||
1885 | "bunzipp", FnFilter1(G.filename), |
||
1886 | (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)? |
||
1887 | "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : "")); |
||
1888 | } |
||
1889 | if ((r = UZbunzip2(__G)) != 0) { |
||
1890 | if (r < PK_DISK) { |
||
1891 | if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) |
||
1892 | Info(slide, 0x401, ((char *)slide, |
||
1893 | LoadFarStringSmall(ErrUnzipFile), r == 3? |
||
1894 | LoadFarString(NotEnoughMem) : |
||
1895 | LoadFarString(InvalidComprData), |
||
1896 | LoadFarStringSmall2(BUnzip), |
||
1897 | FnFilter1(G.filename))); |
||
1898 | else |
||
1899 | Info(slide, 0x401, ((char *)slide, |
||
1900 | LoadFarStringSmall(ErrUnzipNoFile), r == 3? |
||
1901 | LoadFarString(NotEnoughMem) : |
||
1902 | LoadFarString(InvalidComprData), |
||
1903 | LoadFarStringSmall2(BUnzip))); |
||
1904 | error = ((r == 3) ? PK_MEM3 : PK_ERR); |
||
1905 | } else { |
||
1906 | error = r; |
||
1907 | } |
||
1908 | } |
||
1909 | break; |
||
1910 | #endif /* USE_BZIP2 */ |
||
1911 | |||
1912 | default: /* should never get to this point */ |
||
1913 | Info(slide, 0x401, ((char *)slide, |
||
1914 | LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename))); |
||
1915 | /* close and delete file before return? */ |
||
1916 | undefer_input(__G); |
||
1917 | return PK_WARN; |
||
1918 | |||
1919 | } /* end switch (compression method) */ |
||
1920 | |||
1921 | /*--------------------------------------------------------------------------- |
||
1922 | Close the file and set its date and time (not necessarily in that order), |
||
1923 | and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit |
||
1924 | machines (redundant on 32-bit machines). |
||
1925 | ---------------------------------------------------------------------------*/ |
||
1926 | |||
1927 | #ifdef VMS /* VMS: required even for stdout! (final flush) */ |
||
1928 | if (!uO.tflag) /* don't close NULL file */ |
||
1929 | close_outfile(__G); |
||
1930 | #else |
||
1931 | #ifdef DLL |
||
1932 | if (!uO.tflag && (!uO.cflag || G.redirect_data)) { |
||
1933 | if (G.redirect_data) |
||
1934 | FINISH_REDIRECT(); |
||
1935 | else |
||
1936 | close_outfile(__G); |
||
1937 | } |
||
1938 | #else |
||
1939 | if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */ |
||
1940 | close_outfile(__G); |
||
1941 | #endif |
||
1942 | #endif /* VMS */ |
||
1943 | |||
1944 | /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */ |
||
1945 | |||
1946 | |||
1947 | if (G.disk_full) { /* set by flush() */ |
||
1948 | if (G.disk_full > 1) { |
||
1949 | #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK)) |
||
1950 | /* delete the incomplete file if we can */ |
||
1951 | if (unlink(G.filename) != 0) |
||
1952 | Trace((stderr, "extract.c: could not delete %s\n", |
||
1953 | FnFilter1(G.filename))); |
||
1954 | #else |
||
1955 | /* warn user about the incomplete file */ |
||
1956 | Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated), |
||
1957 | FnFilter1(G.filename))); |
||
1958 | #endif |
||
1959 | error = PK_DISK; |
||
1960 | } else { |
||
1961 | error = PK_WARN; |
||
1962 | } |
||
1963 | } |
||
1964 | |||
1965 | if (error > PK_WARN) {/* don't print redundant CRC error if error already */ |
||
1966 | undefer_input(__G); |
||
1967 | return error; |
||
1968 | } |
||
1969 | if (G.crc32val != G.lrec.crc32) { |
||
1970 | /* if quiet enough, we haven't output the filename yet: do it */ |
||
1971 | if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)) |
||
1972 | Info(slide, 0x401, ((char *)slide, "%-22s ", |
||
1973 | FnFilter1(G.filename))); |
||
1974 | Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val, |
||
1975 | G.lrec.crc32)); |
||
1976 | #if CRYPT |
||
1977 | if (G.pInfo->encrypted) |
||
1978 | Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd))); |
||
1979 | #endif |
||
1980 | error = PK_ERR; |
||
1981 | } else if (uO.tflag) { |
||
1982 | #ifndef SFX |
||
1983 | if (G.extra_field) { |
||
1984 | if ((r = TestExtraField(__G__ G.extra_field, |
||
1985 | G.lrec.extra_field_length)) > error) |
||
1986 | error = r; |
||
1987 | } else |
||
1988 | #endif /* !SFX */ |
||
1989 | if (!uO.qflag) |
||
1990 | Info(slide, 0, ((char *)slide, " OK\n")); |
||
1991 | } else { |
||
1992 | if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */ |
||
1993 | Info(slide, 0, ((char *)slide, "\n")); |
||
1994 | } |
||
1995 | |||
1996 | undefer_input(__G); |
||
1997 | return error; |
||
1998 | |||
1999 | } /* end function extract_or_test_member() */ |
||
2000 | |||
2001 | |||
2002 | |||
2003 | |||
2004 | |||
2005 | #ifndef SFX |
||
2006 | |||
2007 | /*******************************/ |
||
2008 | /* Function TestExtraField() */ |
||
2009 | /*******************************/ |
||
2010 | |||
2011 | static int TestExtraField(__G__ ef, ef_len) |
||
2012 | __GDEF |
||
2013 | uch *ef; |
||
2014 | unsigned ef_len; |
||
2015 | { |
||
2016 | ush ebID; |
||
2017 | unsigned ebLen; |
||
2018 | unsigned eb_cmpr_offs = 0; |
||
2019 | int r; |
||
2020 | |||
2021 | /* we know the regular compressed file data tested out OK, or else we |
||
2022 | * wouldn't be here ==> print filename if any extra-field errors found |
||
2023 | */ |
||
2024 | while (ef_len >= EB_HEADSIZE) { |
||
2025 | ebID = makeword(ef); |
||
2026 | ebLen = (unsigned)makeword(ef+EB_LEN); |
||
2027 | |||
2028 | if (ebLen > (ef_len - EB_HEADSIZE)) { |
||
2029 | /* Discovered some extra field inconsistency! */ |
||
2030 | if (uO.qflag) |
||
2031 | Info(slide, 1, ((char *)slide, "%-22s ", |
||
2032 | FnFilter1(G.filename))); |
||
2033 | Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength), |
||
2034 | ebLen, (ef_len - EB_HEADSIZE))); |
||
2035 | return PK_ERR; |
||
2036 | } |
||
2037 | |||
2038 | switch (ebID) { |
||
2039 | case EF_OS2: |
||
2040 | case EF_ACL: |
||
2041 | case EF_MAC3: |
||
2042 | case EF_BEOS: |
||
2043 | case EF_ATHEOS: |
||
2044 | switch (ebID) { |
||
2045 | case EF_OS2: |
||
2046 | case EF_ACL: |
||
2047 | eb_cmpr_offs = EB_OS2_HLEN; |
||
2048 | break; |
||
2049 | case EF_MAC3: |
||
2050 | if (ebLen >= EB_MAC3_HLEN && |
||
2051 | (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) |
||
2052 | & EB_M3_FL_UNCMPR) && |
||
2053 | (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN)) |
||
2054 | eb_cmpr_offs = 0; |
||
2055 | else |
||
2056 | eb_cmpr_offs = EB_MAC3_HLEN; |
||
2057 | break; |
||
2058 | case EF_BEOS: |
||
2059 | case EF_ATHEOS: |
||
2060 | if (ebLen >= EB_BEOS_HLEN && |
||
2061 | (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) && |
||
2062 | (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN)) |
||
2063 | eb_cmpr_offs = 0; |
||
2064 | else |
||
2065 | eb_cmpr_offs = EB_BEOS_HLEN; |
||
2066 | break; |
||
2067 | } |
||
2068 | if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL)) |
||
2069 | != PK_OK) { |
||
2070 | if (uO.qflag) |
||
2071 | Info(slide, 1, ((char *)slide, "%-22s ", |
||
2072 | FnFilter1(G.filename))); |
||
2073 | switch (r) { |
||
2074 | case IZ_EF_TRUNC: |
||
2075 | Info(slide, 1, ((char *)slide, |
||
2076 | LoadFarString(TruncEAs), |
||
2077 | ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n")); |
||
2078 | break; |
||
2079 | case PK_ERR: |
||
2080 | Info(slide, 1, ((char *)slide, |
||
2081 | LoadFarString(InvalidComprDataEAs))); |
||
2082 | break; |
||
2083 | case PK_MEM3: |
||
2084 | case PK_MEM4: |
||
2085 | Info(slide, 1, ((char *)slide, |
||
2086 | LoadFarString(NotEnoughMemEAs))); |
||
2087 | break; |
||
2088 | default: |
||
2089 | if ((r & 0xff) != PK_ERR) |
||
2090 | Info(slide, 1, ((char *)slide, |
||
2091 | LoadFarString(UnknErrorEAs))); |
||
2092 | else { |
||
2093 | ush m = (ush)(r >> 8); |
||
2094 | if (m == DEFLATED) /* GRR KLUDGE! */ |
||
2095 | Info(slide, 1, ((char *)slide, |
||
2096 | LoadFarString(BadCRC_EAs))); |
||
2097 | else |
||
2098 | Info(slide, 1, ((char *)slide, |
||
2099 | LoadFarString(UnknComprMethodEAs), m)); |
||
2100 | } |
||
2101 | break; |
||
2102 | } |
||
2103 | return r; |
||
2104 | } |
||
2105 | break; |
||
2106 | |||
2107 | case EF_NTSD: |
||
2108 | Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen)); |
||
2109 | r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC : |
||
2110 | ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ? |
||
2111 | (PK_WARN | 0x4000) : |
||
2112 | test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD)); |
||
2113 | if (r != PK_OK) { |
||
2114 | if (uO.qflag) |
||
2115 | Info(slide, 1, ((char *)slide, "%-22s ", |
||
2116 | FnFilter1(G.filename))); |
||
2117 | switch (r) { |
||
2118 | case IZ_EF_TRUNC: |
||
2119 | Info(slide, 1, ((char *)slide, |
||
2120 | LoadFarString(TruncNTSD), |
||
2121 | ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n")); |
||
2122 | break; |
||
2123 | #if (defined(WIN32) && defined(NTSD_EAS)) |
||
2124 | case PK_WARN: |
||
2125 | Info(slide, 1, ((char *)slide, |
||
2126 | LoadFarString(InvalidSecurityEAs))); |
||
2127 | break; |
||
2128 | #endif |
||
2129 | case PK_ERR: |
||
2130 | Info(slide, 1, ((char *)slide, |
||
2131 | LoadFarString(InvalidComprDataEAs))); |
||
2132 | break; |
||
2133 | case PK_MEM3: |
||
2134 | case PK_MEM4: |
||
2135 | Info(slide, 1, ((char *)slide, |
||
2136 | LoadFarString(NotEnoughMemEAs))); |
||
2137 | break; |
||
2138 | case (PK_WARN | 0x4000): |
||
2139 | Info(slide, 1, ((char *)slide, |
||
2140 | LoadFarString(UnsuppNTSDVersEAs), |
||
2141 | (int)ef[EB_HEADSIZE+EB_NTSD_VERSION])); |
||
2142 | r = PK_WARN; |
||
2143 | break; |
||
2144 | default: |
||
2145 | if ((r & 0xff) != PK_ERR) |
||
2146 | Info(slide, 1, ((char *)slide, |
||
2147 | LoadFarString(UnknErrorEAs))); |
||
2148 | else { |
||
2149 | ush m = (ush)(r >> 8); |
||
2150 | if (m == DEFLATED) /* GRR KLUDGE! */ |
||
2151 | Info(slide, 1, ((char *)slide, |
||
2152 | LoadFarString(BadCRC_EAs))); |
||
2153 | else |
||
2154 | Info(slide, 1, ((char *)slide, |
||
2155 | LoadFarString(UnknComprMethodEAs), m)); |
||
2156 | } |
||
2157 | break; |
||
2158 | } |
||
2159 | return r; |
||
2160 | } |
||
2161 | break; |
||
2162 | case EF_PKVMS: |
||
2163 | if (makelong(ef+EB_HEADSIZE) != |
||
2164 | crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4), |
||
2165 | (extent)(ebLen-4))) |
||
2166 | Info(slide, 1, ((char *)slide, |
||
2167 | LoadFarString(BadCRC_EAs))); |
||
2168 | break; |
||
2169 | case EF_PKW32: |
||
2170 | case EF_PKUNIX: |
||
2171 | case EF_ASIUNIX: |
||
2172 | case EF_IZVMS: |
||
2173 | case EF_IZUNIX: |
||
2174 | case EF_VMCMS: |
||
2175 | case EF_MVS: |
||
2176 | case EF_SPARK: |
||
2177 | case EF_TANDEM: |
||
2178 | case EF_THEOS: |
||
2179 | case EF_AV: |
||
2180 | default: |
||
2181 | break; |
||
2182 | } |
||
2183 | ef_len -= (ebLen + EB_HEADSIZE); |
||
2184 | ef += (ebLen + EB_HEADSIZE); |
||
2185 | } |
||
2186 | |||
2187 | if (!uO.qflag) |
||
2188 | Info(slide, 0, ((char *)slide, " OK\n")); |
||
2189 | |||
2190 | return PK_COOL; |
||
2191 | |||
2192 | } /* end function TestExtraField() */ |
||
2193 | |||
2194 | |||
2195 | |||
2196 | |||
2197 | |||
2198 | /******************************/ |
||
2199 | /* Function test_compr_eb() */ |
||
2200 | /******************************/ |
||
2201 | |||
2202 | #ifdef PROTO |
||
2203 | static int test_compr_eb( |
||
2204 | __GPRO__ |
||
2205 | uch *eb, |
||
2206 | unsigned eb_size, |
||
2207 | unsigned compr_offset, |
||
2208 | int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size, |
||
2209 | uch *eb_ucptr, ulg eb_ucsize)) |
||
2210 | #else /* !PROTO */ |
||
2211 | static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata) |
||
2212 | __GDEF |
||
2213 | uch *eb; |
||
2214 | unsigned eb_size; |
||
2215 | unsigned compr_offset; |
||
2216 | int (*test_uc_ebdata)(); |
||
2217 | #endif /* ?PROTO */ |
||
2218 | { |
||
2219 | ulg eb_ucsize; |
||
2220 | uch *eb_ucptr; |
||
2221 | int r; |
||
2222 | |||
2223 | if (compr_offset < 4) /* field is not compressed: */ |
||
2224 | return PK_OK; /* do nothing and signal OK */ |
||
2225 | |||
2226 | if ((eb_size < (EB_UCSIZE_P + 4)) || |
||
2227 | ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L && |
||
2228 | eb_size <= (compr_offset + EB_CMPRHEADLEN))) |
||
2229 | return IZ_EF_TRUNC; /* no compressed data! */ |
||
2230 | |||
2231 | if ( |
||
2232 | #ifdef INT_16BIT |
||
2233 | (((ulg)(extent)eb_ucsize) != eb_ucsize) || |
||
2234 | #endif |
||
2235 | (eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL) |
||
2236 | return PK_MEM4; |
||
2237 | |||
2238 | r = memextract(__G__ eb_ucptr, eb_ucsize, |
||
2239 | eb + (EB_HEADSIZE + compr_offset), |
||
2240 | (ulg)(eb_size - compr_offset)); |
||
2241 | |||
2242 | if (r == PK_OK && test_uc_ebdata != NULL) |
||
2243 | r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize); |
||
2244 | |||
2245 | free(eb_ucptr); |
||
2246 | return r; |
||
2247 | |||
2248 | } /* end function test_compr_eb() */ |
||
2249 | |||
2250 | #endif /* !SFX */ |
||
2251 | |||
2252 | |||
2253 | |||
2254 | |||
2255 | |||
2256 | /***************************/ |
||
2257 | /* Function memextract() */ |
||
2258 | /***************************/ |
||
2259 | |||
2260 | int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */ |
||
2261 | __GDEF /* extra field block; */ |
||
2262 | uch *tgt; /* return PK-type error */ |
||
2263 | ulg tgtsize; /* level */ |
||
2264 | ZCONST uch *src; |
||
2265 | ulg srcsize; |
||
2266 | { |
||
2267 | zoff_t old_csize=G.csize; |
||
2268 | uch *old_inptr=G.inptr; |
||
2269 | int old_incnt=G.incnt; |
||
2270 | int r, error=PK_OK; |
||
2271 | ush method; |
||
2272 | ulg extra_field_crc; |
||
2273 | |||
2274 | |||
2275 | method = makeword(src); |
||
2276 | extra_field_crc = makelong(src+2); |
||
2277 | |||
2278 | /* compressed extra field exists completely in memory at this location: */ |
||
2279 | G.inptr = (uch *)src + (2 + 4); /* method and extra_field_crc */ |
||
2280 | G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4))); |
||
2281 | G.mem_mode = TRUE; |
||
2282 | G.outbufptr = tgt; |
||
2283 | G.outsize = tgtsize; |
||
2284 | |||
2285 | switch (method) { |
||
2286 | case STORED: |
||
2287 | memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt); |
||
2288 | G.outcnt = (ulg)G.csize; /* for CRC calculation */ |
||
2289 | break; |
||
2290 | case DEFLATED: |
||
2291 | #ifdef USE_DEFLATE64 |
||
2292 | case ENHDEFLATED: |
||
2293 | #endif |
||
2294 | G.outcnt = 0L; |
||
2295 | if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) { |
||
2296 | if (!uO.tflag) |
||
2297 | Info(slide, 0x401, ((char *)slide, |
||
2298 | LoadFarStringSmall(ErrUnzipNoFile), r == 3? |
||
2299 | LoadFarString(NotEnoughMem) : |
||
2300 | LoadFarString(InvalidComprData), |
||
2301 | LoadFarStringSmall2(Inflate))); |
||
2302 | error = (r == 3)? PK_MEM3 : PK_ERR; |
||
2303 | } |
||
2304 | if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */ |
||
2305 | break; |
||
2306 | break; |
||
2307 | default: |
||
2308 | if (uO.tflag) |
||
2309 | error = PK_ERR | ((int)method << 8); |
||
2310 | else { |
||
2311 | Info(slide, 0x401, ((char *)slide, |
||
2312 | LoadFarString(UnsupportedExtraField), method)); |
||
2313 | error = PK_ERR; /* GRR: should be passed on up via SetEAs() */ |
||
2314 | } |
||
2315 | break; |
||
2316 | } |
||
2317 | |||
2318 | G.inptr = old_inptr; |
||
2319 | G.incnt = old_incnt; |
||
2320 | G.csize = old_csize; |
||
2321 | G.mem_mode = FALSE; |
||
2322 | |||
2323 | if (!error) { |
||
2324 | register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt); |
||
2325 | |||
2326 | if (crcval != extra_field_crc) { |
||
2327 | if (uO.tflag) |
||
2328 | error = PK_ERR | (DEFLATED << 8); /* kludge for now */ |
||
2329 | else { |
||
2330 | Info(slide, 0x401, ((char *)slide, |
||
2331 | LoadFarString(BadExtraFieldCRC), G.zipfn, crcval, |
||
2332 | extra_field_crc)); |
||
2333 | error = PK_ERR; |
||
2334 | } |
||
2335 | } |
||
2336 | } |
||
2337 | return error; |
||
2338 | |||
2339 | } /* end function memextract() */ |
||
2340 | |||
2341 | |||
2342 | |||
2343 | |||
2344 | |||
2345 | /*************************/ |
||
2346 | /* Function memflush() */ |
||
2347 | /*************************/ |
||
2348 | |||
2349 | int memflush(__G__ rawbuf, size) |
||
2350 | __GDEF |
||
2351 | ZCONST uch *rawbuf; |
||
2352 | ulg size; |
||
2353 | { |
||
2354 | if (size > G.outsize) |
||
2355 | /* Here, PK_DISK is a bit off-topic, but in the sense of marking |
||
2356 | "overflow of output space", its use may be tolerated. */ |
||
2357 | return PK_DISK; /* more data than output buffer can hold */ |
||
2358 | |||
2359 | |||
2360 | |||
2361 | memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size); |
||
2362 | G.outbufptr += (unsigned int)size; |
||
2363 | G.outsize -= size; |
||
2364 | G.outcnt += size; |
||
2365 | |||
2366 | return 0; |
||
2367 | |||
2368 | } /* end function memflush() */ |
||
2369 | |||
2370 | |||
2371 | |||
2372 | |||
2373 | |||
2374 | #if (defined(VMS) || defined(VMS_TEXT_CONV)) |
||
2375 | |||
2376 | /************************************/ |
||
2377 | /* Function extract_izvms_block() */ |
||
2378 | /************************************/ |
||
2379 | |||
2380 | /* |
||
2381 | * Extracts block from p. If resulting length is less than needed, fill |
||
2382 | * extra space with corresponding bytes from 'init'. |
||
2383 | * Currently understands 3 formats of block compression: |
||
2384 | * - Simple storing |
||
2385 | * - Compression of zero bytes to zero bits |
||
2386 | * - Deflation (see memextract()) |
||
2387 | * The IZVMS block data is returned in malloc'd space. |
||
2388 | */ |
||
2389 | uch *extract_izvms_block(__G__ ebdata, size, retlen, init, needlen) |
||
2390 | __GDEF |
||
2391 | ZCONST uch *ebdata; |
||
2392 | unsigned size; |
||
2393 | unsigned *retlen; |
||
2394 | ZCONST uch *init; |
||
2395 | unsigned needlen; |
||
2396 | { |
||
2397 | uch *ucdata; /* Pointer to block allocated */ |
||
2398 | int cmptype; |
||
2399 | unsigned usiz, csiz; |
||
2400 | |||
2401 | cmptype = (makeword(ebdata+EB_IZVMS_FLGS) & EB_IZVMS_BCMASK); |
||
2402 | csiz = size - EB_IZVMS_HLEN; |
||
2403 | usiz = (cmptype == EB_IZVMS_BCSTOR ? |
||
2404 | csiz : makeword(ebdata+EB_IZVMS_UCSIZ)); |
||
2405 | |||
2406 | if (retlen) |
||
2407 | *retlen = usiz; |
||
2408 | |||
2409 | if ((ucdata = (uch *)malloc(MAX(needlen, usiz))) == NULL) |
||
2410 | return NULL; |
||
2411 | |||
2412 | if (init && (usiz < needlen)) |
||
2413 | memcpy((char *)ucdata, (ZCONST char *)init, needlen); |
||
2414 | |||
2415 | switch (cmptype) |
||
2416 | { |
||
2417 | case EB_IZVMS_BCSTOR: /* The simplest case */ |
||
2418 | memcpy(ucdata, ebdata+EB_IZVMS_HLEN, usiz); |
||
2419 | break; |
||
2420 | case EB_IZVMS_BC00: |
||
2421 | decompress_bits(ucdata, usiz, ebdata+EB_IZVMS_HLEN); |
||
2422 | break; |
||
2423 | case EB_IZVMS_BCDEFL: |
||
2424 | memextract(__G__ ucdata, (ulg)usiz, |
||
2425 | ebdata+EB_IZVMS_HLEN, (ulg)csiz); |
||
2426 | break; |
||
2427 | default: |
||
2428 | free(ucdata); |
||
2429 | ucdata = NULL; |
||
2430 | } |
||
2431 | return ucdata; |
||
2432 | |||
2433 | } /* end of extract_izvms_block */ |
||
2434 | |||
2435 | |||
2436 | |||
2437 | |||
2438 | |||
2439 | /********************************/ |
||
2440 | /* Function decompress_bits() */ |
||
2441 | /********************************/ |
||
2442 | /* |
||
2443 | * Simple uncompression routine. The compression uses bit stream. |
||
2444 | * Compression scheme: |
||
2445 | * |
||
2446 | * if (byte!=0) |
||
2447 | * putbit(1),putbyte(byte) |
||
2448 | * else |
||
2449 | * putbit(0) |
||
2450 | */ |
||
2451 | static void decompress_bits(outptr, needlen, bitptr) |
||
2452 | uch *outptr; /* Pointer into output block */ |
||
2453 | unsigned needlen; /* Size of uncompressed block */ |
||
2454 | ZCONST uch *bitptr; /* Pointer into compressed data */ |
||
2455 | { |
||
2456 | ulg bitbuf = 0; |
||
2457 | int bitcnt = 0; |
||
2458 | |||
2459 | #define _FILL { bitbuf |= (*bitptr++) << bitcnt;\ |
||
2460 | bitcnt += 8; \ |
||
2461 | } |
||
2462 | |||
2463 | while (needlen--) |
||
2464 | { |
||
2465 | if (bitcnt <= 0) |
||
2466 | _FILL; |
||
2467 | |||
2468 | if (bitbuf & 1) |
||
2469 | { |
||
2470 | bitbuf >>= 1; |
||
2471 | if ((bitcnt -= 1) < 8) |
||
2472 | _FILL; |
||
2473 | *outptr++ = (uch)bitbuf; |
||
2474 | bitcnt -= 8; |
||
2475 | bitbuf >>= 8; |
||
2476 | } |
||
2477 | else |
||
2478 | { |
||
2479 | *outptr++ = '\0'; |
||
2480 | bitcnt -= 1; |
||
2481 | bitbuf >>= 1; |
||
2482 | } |
||
2483 | } |
||
2484 | } /* end function decompress_bits() */ |
||
2485 | |||
2486 | #endif /* VMS || VMS_TEXT_CONV */ |
||
2487 | |||
2488 | |||
2489 | |||
2490 | |||
2491 | |||
2492 | #ifdef SYMLINKS |
||
2493 | /***********************************/ |
||
2494 | /* Function set_deferred_symlink() */ |
||
2495 | /***********************************/ |
||
2496 | |||
2497 | static void set_deferred_symlink(__G__ slnk_entry) |
||
2498 | __GDEF |
||
2499 | slinkentry *slnk_entry; |
||
2500 | { |
||
2501 | extent ucsize = slnk_entry->targetlen; |
||
2502 | char *linkfname = slnk_entry->fname; |
||
2503 | char *linktarget = (char *)malloc(ucsize+1); |
||
2504 | |||
2505 | if (!linktarget) { |
||
2506 | Info(slide, 0x201, ((char *)slide, |
||
2507 | LoadFarString(SymLnkWarnNoMem), FnFilter1(linkfname))); |
||
2508 | return; |
||
2509 | } |
||
2510 | linktarget[ucsize] = '\0'; |
||
2511 | G.outfile = zfopen(linkfname, FOPR); /* open link placeholder for reading */ |
||
2512 | /* Check that the following conditions are all fulfilled: |
||
2513 | * a) the placeholder file exists, |
||
2514 | * b) the placeholder file contains exactly "ucsize" bytes |
||
2515 | * (read the expected placeholder content length + 1 extra byte, this |
||
2516 | * should return the expected content length), |
||
2517 | * c) the placeholder content matches the link target specification as |
||
2518 | * stored in the symlink control structure. |
||
2519 | */ |
||
2520 | if (!G.outfile || |
||
2521 | fread(linktarget, 1, ucsize+1, G.outfile) != ucsize || |
||
2522 | strcmp(slnk_entry->target, linktarget)) |
||
2523 | { |
||
2524 | Info(slide, 0x201, ((char *)slide, |
||
2525 | LoadFarString(SymLnkWarnInvalid), FnFilter1(linkfname))); |
||
2526 | free(linktarget); |
||
2527 | if (G.outfile) |
||
2528 | fclose(G.outfile); |
||
2529 | return; |
||
2530 | } |
||
2531 | fclose(G.outfile); /* close "data" file for good... */ |
||
2532 | unlink(linkfname); /* ...and delete it */ |
||
2533 | if (QCOND2) |
||
2534 | Info(slide, 0, ((char *)slide, LoadFarString(SymLnkFinish), |
||
2535 | FnFilter1(linkfname), FnFilter2(linktarget))); |
||
2536 | if (symlink(linktarget, linkfname)) /* create the real link */ |
||
2537 | perror("symlink error"); |
||
2538 | free(linktarget); |
||
2539 | #ifdef SET_SYMLINK_ATTRIBS |
||
2540 | set_symlnk_attribs(__G__ slnk_entry); |
||
2541 | #endif |
||
2542 | return; /* can't set time on symlinks */ |
||
2543 | |||
2544 | } /* end function set_deferred_symlink() */ |
||
2545 | #endif /* SYMLINKS */ |
||
2546 | |||
2547 | |||
2548 | |||
2549 | |||
2550 | /*************************/ |
||
2551 | /* Function fnfilter() */ /* here instead of in list.c for SFX */ |
||
2552 | /*************************/ |
||
2553 | |||
2554 | char *fnfilter(raw, space, size) /* convert name to safely printable form */ |
||
2555 | ZCONST char *raw; |
||
2556 | uch *space; |
||
2557 | extent size; |
||
2558 | { |
||
2559 | #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */ |
||
2560 | ZCONST uch *r=(ZCONST uch *)raw; |
||
2561 | uch *s=space; |
||
2562 | uch *slim=NULL; |
||
2563 | uch *se=NULL; |
||
2564 | int have_overflow = FALSE; |
||
2565 | |||
2566 | if (size > 0) { |
||
2567 | slim = space + size |
||
2568 | #ifdef _MBCS |
||
2569 | - (MB_CUR_MAX - 1) |
||
2570 | #endif |
||
2571 | - 4; |
||
2572 | } |
||
2573 | while (*r) { |
||
2574 | if (size > 0 && s >= slim && se == NULL) { |
||
2575 | se = s; |
||
2576 | } |
||
2577 | #ifdef QDOS |
||
2578 | if (qlflag & 2) { |
||
2579 | if (*r == '/' || *r == '.') { |
||
2580 | if (se != NULL && (s > (space + (size-3)))) { |
||
2581 | have_overflow = TRUE; |
||
2582 | break; |
||
2583 | } |
||
2584 | ++r; |
||
2585 | *s++ = '_'; |
||
2586 | continue; |
||
2587 | } |
||
2588 | } else |
||
2589 | #endif |
||
2590 | #ifdef HAVE_WORKING_ISPRINT |
||
2591 | # ifndef UZ_FNFILTER_REPLACECHAR |
||
2592 | /* A convenient choice for the replacement of unprintable char codes is |
||
2593 | * the "single char wildcard", as this character is quite unlikely to |
||
2594 | * appear in filenames by itself. The following default definition |
||
2595 | * sets the replacement char to a question mark as the most common |
||
2596 | * "single char wildcard"; this setting should be overridden in the |
||
2597 | * appropiate system-specific configuration header when needed. |
||
2598 | */ |
||
2599 | # define UZ_FNFILTER_REPLACECHAR '?' |
||
2600 | # endif |
||
2601 | if (!isprint(*r)) { |
||
2602 | if (*r < 32) { |
||
2603 | /* ASCII control codes are escaped as "^{letter}". */ |
||
2604 | if (se != NULL && (s > (space + (size-4)))) { |
||
2605 | have_overflow = TRUE; |
||
2606 | break; |
||
2607 | } |
||
2608 | *s++ = '^', *s++ = (uch)(64 + *r++); |
||
2609 | } else { |
||
2610 | /* Other unprintable codes are replaced by the |
||
2611 | * placeholder character. */ |
||
2612 | if (se != NULL && (s > (space + (size-3)))) { |
||
2613 | have_overflow = TRUE; |
||
2614 | break; |
||
2615 | } |
||
2616 | *s++ = UZ_FNFILTER_REPLACECHAR; |
||
2617 | INCSTR(r); |
||
2618 | } |
||
2619 | #else /* !HAVE_WORKING_ISPRINT */ |
||
2620 | if (*r < 32) { |
||
2621 | /* ASCII control codes are escaped as "^{letter}". */ |
||
2622 | if (se != NULL && (s > (space + (size-4)))) { |
||
2623 | have_overflow = TRUE; |
||
2624 | break; |
||
2625 | } |
||
2626 | *s++ = '^', *s++ = (uch)(64 + *r++); |
||
2627 | #endif /* ?HAVE_WORKING_ISPRINT */ |
||
2628 | } else { |
||
2629 | #ifdef _MBCS |
||
2630 | unsigned i = CLEN(r); |
||
2631 | if (se != NULL && (s > (space + (size-i-2)))) { |
||
2632 | have_overflow = TRUE; |
||
2633 | break; |
||
2634 | } |
||
2635 | for (; i > 0; i--) |
||
2636 | *s++ = *r++; |
||
2637 | #else |
||
2638 | if (se != NULL && (s > (space + (size-3)))) { |
||
2639 | have_overflow = TRUE; |
||
2640 | break; |
||
2641 | } |
||
2642 | *s++ = *r++; |
||
2643 | #endif |
||
2644 | } |
||
2645 | } |
||
2646 | if (have_overflow) { |
||
2647 | strcpy((char *)se, "..."); |
||
2648 | } else { |
||
2649 | *s = '\0'; |
||
2650 | } |
||
2651 | |||
2652 | #ifdef WINDLL |
||
2653 | INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */ |
||
2654 | #else |
||
2655 | #if (defined(WIN32) && !defined(_WIN32_WCE)) |
||
2656 | /* Win9x console always uses OEM character coding, and |
||
2657 | WinNT console is set to OEM charset by default, too */ |
||
2658 | INTERN_TO_OEM((char *)space, (char *)space); |
||
2659 | #endif /* (WIN32 && !_WIN32_WCE) */ |
||
2660 | #endif /* ?WINDLL */ |
||
2661 | |||
2662 | return (char *)space; |
||
2663 | |||
2664 | #else /* NATIVE: EBCDIC or whatever */ |
||
2665 | return (char *)raw; |
||
2666 | #endif |
||
2667 | |||
2668 | } /* end function fnfilter() */ |
||
2669 | |||
2670 | |||
2671 | |||
2672 | |||
2673 | #ifdef SET_DIR_ATTRIB |
||
2674 | /* must sort saved directories so can set perms from bottom up */ |
||
2675 | |||
2676 | /************************/ |
||
2677 | /* Function dircomp() */ |
||
2678 | /************************/ |
||
2679 | |||
2680 | static int Cdecl dircomp(a, b) /* used by qsort(); swiped from Zip */ |
||
2681 | ZCONST zvoid *a, *b; |
||
2682 | { |
||
2683 | /* order is significant: this sorts in reverse order (deepest first) */ |
||
2684 | return strcmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); |
||
2685 | /* return namecmp((*(direntry **)b)->fn, (*(direntry **)a)->fn); */ |
||
2686 | } |
||
2687 | |||
2688 | #endif /* SET_DIR_ATTRIB */ |
||
2689 | |||
2690 | |||
2691 | #ifdef USE_BZIP2 |
||
2692 | |||
2693 | /**************************/ |
||
2694 | /* Function UZbunzip2() */ |
||
2695 | /**************************/ |
||
2696 | |||
2697 | int UZbunzip2(__G) |
||
2698 | __GDEF |
||
2699 | /* decompress a bzipped entry using the libbz2 routines */ |
||
2700 | { |
||
2701 | int retval = 0; /* return code: 0 = "no error" */ |
||
2702 | int err=BZ_OK; |
||
2703 | int repeated_buf_err; |
||
2704 | bz_stream bstrm; |
||
2705 | |||
2706 | #if (defined(DLL) && !defined(NO_SLIDE_REDIR)) |
||
2707 | if (G.redirect_slide) |
||
2708 | wsize = G.redirect_size, redirSlide = G.redirect_buffer; |
||
2709 | else |
||
2710 | wsize = WSIZE, redirSlide = slide; |
||
2711 | #endif |
||
2712 | |||
2713 | bstrm.next_out = (char *)redirSlide; |
||
2714 | bstrm.avail_out = wsize; |
||
2715 | |||
2716 | bstrm.next_in = (char *)G.inptr; |
||
2717 | bstrm.avail_in = G.incnt; |
||
2718 | |||
2719 | { |
||
2720 | /* local buffer for efficiency */ |
||
2721 | /* $TODO Check for BZIP LIB version? */ |
||
2722 | |||
2723 | bstrm.bzalloc = NULL; |
||
2724 | bstrm.bzfree = NULL; |
||
2725 | bstrm.opaque = NULL; |
||
2726 | |||
2727 | Trace((stderr, "initializing bzlib()\n")); |
||
2728 | err = BZ2_bzDecompressInit(&bstrm, 0, 0); |
||
2729 | |||
2730 | if (err == BZ_MEM_ERROR) |
||
2731 | return 3; |
||
2732 | else if (err != BZ_OK) |
||
2733 | Trace((stderr, "oops! (BZ2_bzDecompressInit() err = %d)\n", err)); |
||
2734 | } |
||
2735 | |||
2736 | #ifdef FUNZIP |
||
2737 | while (err != BZ_STREAM_END) { |
||
2738 | #else /* !FUNZIP */ |
||
2739 | while (G.csize > 0) { |
||
2740 | Trace((stderr, "first loop: G.csize = %ld\n", G.csize)); |
||
2741 | #endif /* ?FUNZIP */ |
||
2742 | while (bstrm.avail_out > 0) { |
||
2743 | err = BZ2_bzDecompress(&bstrm); |
||
2744 | |||
2745 | if (err == BZ_DATA_ERROR) { |
||
2746 | retval = 2; goto uzbunzip_cleanup_exit; |
||
2747 | } else if (err == BZ_MEM_ERROR) { |
||
2748 | retval = 3; goto uzbunzip_cleanup_exit; |
||
2749 | } else if (err != BZ_OK && err != BZ_STREAM_END) |
||
2750 | Trace((stderr, "oops! (bzip(first loop) err = %d)\n", err)); |
||
2751 | |||
2752 | #ifdef FUNZIP |
||
2753 | if (err == BZ_STREAM_END) /* "END-of-entry-condition" ? */ |
||
2754 | #else /* !FUNZIP */ |
||
2755 | if (G.csize <= 0L) /* "END-of-entry-condition" ? */ |
||
2756 | #endif /* ?FUNZIP */ |
||
2757 | break; |
||
2758 | |||
2759 | if (bstrm.avail_in == 0) { |
||
2760 | if (fillinbuf(__G) == 0) { |
||
2761 | /* no "END-condition" yet, but no more data */ |
||
2762 | retval = 2; goto uzbunzip_cleanup_exit; |
||
2763 | } |
||
2764 | |||
2765 | bstrm.next_in = (char *)G.inptr; |
||
2766 | bstrm.avail_in = G.incnt; |
||
2767 | } |
||
2768 | Trace((stderr, " avail_in = %u\n", bstrm.avail_in)); |
||
2769 | } |
||
2770 | /* flush slide[] */ |
||
2771 | if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) |
||
2772 | goto uzbunzip_cleanup_exit; |
||
2773 | Trace((stderr, "inside loop: flushing %ld bytes (ptr diff = %ld)\n", |
||
2774 | (long)(wsize - bstrm.avail_out), |
||
2775 | (long)(bstrm.next_out-(char *)redirSlide))); |
||
2776 | bstrm.next_out = (char *)redirSlide; |
||
2777 | bstrm.avail_out = wsize; |
||
2778 | } |
||
2779 | |||
2780 | /* no more input, so loop until we have all output */ |
||
2781 | Trace((stderr, "beginning final loop: err = %d\n", err)); |
||
2782 | repeated_buf_err = FALSE; |
||
2783 | while (err != BZ_STREAM_END) { |
||
2784 | err = BZ2_bzDecompress(&bstrm); |
||
2785 | if (err == BZ_DATA_ERROR) { |
||
2786 | retval = 2; goto uzbunzip_cleanup_exit; |
||
2787 | } else if (err == BZ_MEM_ERROR) { |
||
2788 | retval = 3; goto uzbunzip_cleanup_exit; |
||
2789 | } else if (err != BZ_OK && err != BZ_STREAM_END) { |
||
2790 | Trace((stderr, "oops! (bzip(final loop) err = %d)\n", err)); |
||
2791 | DESTROYGLOBALS(); |
||
2792 | EXIT(PK_MEM3); |
||
2793 | } |
||
2794 | /* final flush of slide[] */ |
||
2795 | if ((retval = FLUSH(wsize - bstrm.avail_out)) != 0) |
||
2796 | goto uzbunzip_cleanup_exit; |
||
2797 | Trace((stderr, "final loop: flushing %ld bytes (ptr diff = %ld)\n", |
||
2798 | (long)(wsize - bstrm.avail_out), |
||
2799 | (long)(bstrm.next_out-(char *)redirSlide))); |
||
2800 | bstrm.next_out = (char *)redirSlide; |
||
2801 | bstrm.avail_out = wsize; |
||
2802 | } |
||
2803 | #ifdef LARGE_FILE_SUPPORT |
||
2804 | Trace((stderr, "total in = %llu, total out = %llu\n", |
||
2805 | (zusz_t)(bstrm.total_in_lo32) + ((zusz_t)(bstrm.total_in_hi32))<<32, |
||
2806 | (zusz_t)(bstrm.total_out_lo32) + ((zusz_t)(bstrm.total_out_hi32))<<32)); |
||
2807 | #else |
||
2808 | Trace((stderr, "total in = %lu, total out = %lu\n", bstrm.total_in_lo32, |
||
2809 | bstrm.total_out_lo32)); |
||
2810 | #endif |
||
2811 | |||
2812 | G.inptr = (uch *)bstrm.next_in; |
||
2813 | G.incnt = (G.inbuf + INBUFSIZ) - G.inptr; /* reset for other routines */ |
||
2814 | |||
2815 | uzbunzip_cleanup_exit: |
||
2816 | err = BZ2_bzDecompressEnd(&bstrm); |
||
2817 | if (err != BZ_OK) |
||
2818 | Trace((stderr, "oops! (BZ2_bzDecompressEnd() err = %d)\n", err)); |
||
2819 | |||
2820 | return retval; |
||
2821 | } /* end function UZbunzip2() */ |
||
2822 | #endif /* USE_BZIP2 */32)); |