]> git.saurik.com Git - wxWidgets.git/blob - utils/Install/packzip/extract.c
A little less flicker when selecting text.
[wxWidgets.git] / utils / Install / packzip / extract.c
1 /*---------------------------------------------------------------------------
2
3 extract.c
4
5 This file contains the high-level routines ("driver routines") for extrac-
6 ting and testing zipfile members. It calls the low-level routines in files
7 explode.c, inflate.c, unreduce.c and unshrink.c.
8
9 Contains: extract_or_test_files()
10 store_info()
11 extract_or_test_member()
12 TestExtraField()
13 test_compr_eb()
14 memextract()
15 memflush()
16 fnfilter()
17
18 ---------------------------------------------------------------------------*/
19
20
21 #define EXTRACT_C
22 #define UNZIP_INTERNAL
23 #include "unzip.h"
24 #include "crypt.h"
25 #ifdef WINDLL
26 # ifdef POCKET_UNZIP
27 # include "wince/intrface.h"
28 # else
29 # include "windll/windll.h"
30 # endif
31 #endif
32
33 #define GRRDUMP(buf,len) { \
34 int i, j; \
35 \
36 for (j = 0; j < (len)/16; ++j) { \
37 pipeit(" "); \
38 for (i = 0; i < 16; ++i) \
39 pipeit("%02x ", (uch)(buf)[i+(j<<4)]); \
40 pipeit("\n "); \
41 for (i = 0; i < 16; ++i) { \
42 char c = (char)(buf)[i+(j<<4)]; \
43 \
44 if (c == '\n') \
45 pipeit("\\n "); \
46 else if (c == '\r') \
47 pipeit("\\r "); \
48 else \
49 pipeit(" %c ", c); \
50 } \
51 pipeit("\n"); \
52 } \
53 if ((len) % 16) { \
54 pipeit(" "); \
55 for (i = j<<4; i < (len); ++i) \
56 pipeit("%02x ", (uch)(buf)[i]); \
57 pipeit("\n "); \
58 for (i = j<<4; i < (len); ++i) { \
59 char c = (char)(buf)[i]; \
60 \
61 if (c == '\n') \
62 pipeit("\\n "); \
63 else if (c == '\r') \
64 pipeit("\\r "); \
65 else \
66 pipeit(" %c ", c); \
67 } \
68 pipeit("\n"); \
69 } \
70 }
71
72 static int store_info OF((__GPRO));
73 static int extract_or_test_member OF((__GPRO));
74 #ifndef SFX
75 static int TestExtraField OF((__GPRO__ uch *ef, unsigned ef_len));
76 static int test_compr_eb OF((__GPRO__ uch *eb, unsigned eb_size,
77 unsigned compr_offset,
78 int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
79 uch *eb_ucptr, ulg eb_ucsize)));
80 #endif
81 #ifdef SET_DIR_ATTRIB
82 static int dircomp OF((ZCONST zvoid *a, ZCONST zvoid *b));
83 #endif
84
85
86
87 /*******************************/
88 /* Strings used in extract.c */
89 /*******************************/
90
91 static ZCONST char Far VersionMsg[] =
92 " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n";
93 static ZCONST char Far ComprMsgNum[] =
94 " skipping: %-22s unsupported compression method %u\n";
95 #ifndef SFX
96 static ZCONST char Far ComprMsgName[] =
97 " skipping: %-22s `%s' method not supported\n";
98 static ZCONST char Far CmprNone[] = "store";
99 static ZCONST char Far CmprShrink[] = "shrink";
100 static ZCONST char Far CmprReduce[] = "reduce";
101 static ZCONST char Far CmprImplode[] = "implode";
102 static ZCONST char Far CmprTokenize[] = "tokenize";
103 static ZCONST char Far CmprDeflate[] = "deflate";
104 static ZCONST char Far CmprEnDeflate[] = "enhanced deflate";
105 static ZCONST char Far CmprDCLImplode[] = "DCL implode";
106 static ZCONST char Far *ComprNames[NUM_METHODS] = {
107 CmprNone, CmprShrink, CmprReduce, CmprReduce, CmprReduce, CmprReduce,
108 CmprImplode, CmprTokenize, CmprDeflate, CmprEnDeflate, CmprDCLImplode
109 };
110 #endif /* !SFX */
111 static ZCONST char Far FilNamMsg[] =
112 "%s: bad filename length (%s)\n";
113 static ZCONST char Far ExtFieldMsg[] =
114 "%s: bad extra field length (%s)\n";
115 static ZCONST char Far OffsetMsg[] =
116 "file #%u: bad zipfile offset (%s): %ld\n";
117 static ZCONST char Far ExtractMsg[] =
118 "%8sing: %-22s %s%s";
119 #ifndef SFX
120 static ZCONST char Far LengthMsg[] =
121 "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\
122 supposed to require %lu bytes%s%s%s\n";
123 #endif
124
125 static ZCONST char Far BadFileCommLength[] = "%s: bad file comment length\n";
126 static ZCONST char Far LocalHdrSig[] = "local header sig";
127 static ZCONST char Far BadLocalHdr[] = "file #%u: bad local header\n";
128 static ZCONST char Far AttemptRecompensate[] =
129 " (attempting to re-compensate)\n";
130 #ifndef SFX
131 static ZCONST char Far BackslashPathSep[] =
132 "warning: %s appears to use backslashes as path separators\n";
133 #endif
134 static ZCONST char Far SkipVolumeLabel[] =
135 " skipping: %-22s %svolume label\n";
136
137 #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */
138 static ZCONST char Far DirlistEntryNoMem[] =
139 "warning: cannot alloc memory for dir times/permissions/UID/GID\n";
140 static ZCONST char Far DirlistSortNoMem[] =
141 "warning: cannot alloc memory to sort dir times/perms/etc.\n";
142 static ZCONST char Far DirlistSetAttrFailed[] =
143 "warning: set times/attribs failed for %s\n";
144 #endif
145
146 #ifndef WINDLL
147 static ZCONST char Far ReplaceQuery[] =
148 "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
149 static ZCONST char Far AssumeNone[] = " NULL\n(assuming [N]one)\n";
150 static ZCONST char Far NewNameQuery[] = "new name: ";
151 static ZCONST char Far InvalidResponse[] = "error: invalid response [%c]\n";
152 #endif /* !WINDLL */
153
154 static ZCONST char Far ErrorInArchive[] =
155 "At least one %serror was detected in %s.\n";
156 static ZCONST char Far ZeroFilesTested[] =
157 "Caution: zero files tested in %s.\n";
158
159 #ifndef VMS
160 static ZCONST char Far VMSFormatQuery[] =
161 "\n%s: stored in VMS format. Extract anyway? (y/n) ";
162 #endif
163
164 #if CRYPT
165 static ZCONST char Far SkipCannotGetPasswd[] =
166 " skipping: %-22s unable to get password\n";
167 static ZCONST char Far SkipIncorrectPasswd[] =
168 " skipping: %-22s incorrect password\n";
169 static ZCONST char Far FilesSkipBadPasswd[] =
170 "%u file%s skipped because of incorrect password.\n";
171 static ZCONST char Far MaybeBadPasswd[] =
172 " (may instead be incorrect password)\n";
173 #else
174 static ZCONST char Far SkipEncrypted[] =
175 " skipping: %-22s encrypted (not supported)\n";
176 #endif
177
178 static ZCONST char Far NoErrInCompData[] =
179 "No errors detected in compressed data of %s.\n";
180 static ZCONST char Far NoErrInTestedFiles[] =
181 "No errors detected in %s for the %u file%s tested.\n";
182 static ZCONST char Far FilesSkipped[] =
183 "%u file%s skipped because of unsupported compression or encoding.\n";
184
185 static ZCONST char Far ErrUnzipFile[] = " error: %s%s %s\n";
186 static ZCONST char Far ErrUnzipNoFile[] = "\n error: %s%s\n";
187 static ZCONST char Far NotEnoughMem[] = "not enough memory to ";
188 static ZCONST char Far InvalidComprData[] = "invalid compressed data to ";
189 static ZCONST char Far Inflate[] = "inflate";
190
191 #ifndef SFX
192 static ZCONST char Far Explode[] = "explode";
193 #ifndef LZW_CLEAN
194 static ZCONST char Far Unshrink[] = "unshrink";
195 #endif
196 #endif
197
198 #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
199 static ZCONST char Far FileTruncated[] =
200 "warning: %s is probably truncated\n";
201 #endif
202
203 static ZCONST char Far FileUnknownCompMethod[] =
204 "%s: unknown compression method\n";
205 static ZCONST char Far BadCRC[] = " bad CRC %08lx (should be %08lx)\n";
206
207 /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
208 char ZCONST Far TruncEAs[] = " compressed EA data missing (%d bytes)%s";
209 char ZCONST Far TruncNTSD[] =
210 " compressed WinNT security data missing (%d bytes)%s";
211
212 #ifndef SFX
213 static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
214 EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
215 static ZCONST char Far InvalidComprDataEAs[] =
216 " invalid compressed data for EAs\n";
217 # if (defined(WIN32) && defined(NTSD_EAS))
218 static ZCONST char Far InvalidSecurityEAs[] =
219 " EAs fail security check\n";
220 # endif
221 static ZCONST char Far UnsuppNTSDVersEAs[] =
222 " unsupported NTSD EAs version %d\n";
223 static ZCONST char Far BadCRC_EAs[] = " bad CRC for extended attributes\n";
224 static ZCONST char Far UnknComprMethodEAs[] =
225 " unknown compression method for EAs (%u)\n";
226 static ZCONST char Far NotEnoughMemEAs[] =
227 " out of memory while inflating EAs\n";
228 static ZCONST char Far UnknErrorEAs[] =
229 " unknown error on extended attributes\n";
230 #endif /* !SFX */
231
232 static ZCONST char Far UnsupportedExtraField[] =
233 "\nerror: unsupported extra-field compression type (%u)--skipping\n";
234 static ZCONST char Far BadExtraFieldCRC[] =
235 "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n";
236
237
238
239
240
241 /**************************************/
242 /* Function extract_or_test_files() */
243 /**************************************/
244
245 int extract_or_test_files(__G) /* return PK-type error code */
246 __GDEF
247 {
248 uch *cd_inptr;
249 unsigned i, j, filnum=0, blknum=0;
250 int cd_incnt, renamed, query;
251 int error, error_in_archive=PK_COOL, *fn_matched=NULL, *xn_matched=NULL;
252 #ifdef WINDLL
253 int done_once = 0;
254 #else
255 extent len;
256 #endif
257 unsigned members_remaining, num_skipped=0, num_bad_pwd=0;
258 long cd_bufstart, bufstart, inbuf_offset, request;
259 LONGINT old_extra_bytes = 0L;
260 #ifdef SET_DIR_ATTRIB
261 unsigned num_dirs=0;
262 dirtime *dirlist=(dirtime *)NULL, **sorted_dirlist=(dirtime **)NULL;
263 #endif
264
265
266 /*---------------------------------------------------------------------------
267 The basic idea of this function is as follows. Since the central di-
268 rectory lies at the end of the zipfile and the member files lie at the
269 beginning or middle or wherever, it is not very desirable to simply
270 read a central directory entry, jump to the member and extract it, and
271 then jump back to the central directory. In the case of a large zipfile
272 this would lead to a whole lot of disk-grinding, especially if each mem-
273 ber file is small. Instead, we read from the central directory the per-
274 tinent information for a block of files, then go extract/test the whole
275 block. Thus this routine contains two small(er) loops within a very
276 large outer loop: the first of the small ones reads a block of files
277 from the central directory; the second extracts or tests each file; and
278 the outer one loops over blocks. There's some file-pointer positioning
279 stuff in between, but that's about it. Btw, it's because of this jump-
280 ing around that we can afford to be lenient if an error occurs in one of
281 the member files: we should still be able to go find the other members,
282 since we know the offset of each from the beginning of the zipfile.
283 ---------------------------------------------------------------------------*/
284
285 G.pInfo = G.info;
286 members_remaining = (unsigned)G.ecrec.total_entries_central_dir;
287
288 #if CRYPT
289 G.newzip = TRUE;
290 #endif
291 #ifndef SFX
292 G.reported_backslash = FALSE;
293 #endif
294
295 /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
296 if (G.filespecs > 0 &&
297 (fn_matched=(int *)malloc(G.filespecs*sizeof(int))) != (int *)NULL)
298 for (i = 0; i < G.filespecs; ++i)
299 fn_matched[i] = FALSE;
300 if (G.xfilespecs > 0 &&
301 (xn_matched=(int *)malloc(G.xfilespecs*sizeof(int))) != (int *)NULL)
302 for (i = 0; i < G.xfilespecs; ++i)
303 xn_matched[i] = FALSE;
304
305 /*---------------------------------------------------------------------------
306 Begin main loop over blocks of member files. We know the entire central
307 directory is on this disk: we would not have any of this information un-
308 less the end-of-central-directory record was on this disk, and we would
309 not have gotten to this routine unless this is also the disk on which
310 the central directory starts. In practice, this had better be the ONLY
311 disk in the archive, but we'll add multi-disk support soon.
312 ---------------------------------------------------------------------------*/
313
314 while (members_remaining) {
315 j = 0;
316 #ifdef AMIGA
317 memzero(G.filenotes, DIR_BLKSIZ * sizeof(char *));
318 #endif
319
320 /*
321 * Loop through files in central directory, storing offsets, file
322 * attributes, case-conversion and text-conversion flags until block
323 * size is reached.
324 */
325
326 while (members_remaining && (j < DIR_BLKSIZ)) {
327 --members_remaining;
328 G.pInfo = &G.info[j];
329
330 if (readbuf(__G__ G.sig, 4) == 0) {
331 error_in_archive = PK_EOF;
332 members_remaining = 0; /* ...so no more left to do */
333 break;
334 }
335 if (strncmp(G.sig, central_hdr_sig, 4)) { /* just to make sure */
336 Info(slide, 0x401, ((char *)slide, LoadFarString(CentSigMsg),
337 j + blknum*DIR_BLKSIZ + 1));
338 Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
339 error_in_archive = PK_BADERR;
340 members_remaining = 0; /* ...so no more left to do */
341 break;
342 }
343 /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
344 if ((error = process_cdir_file_hdr(__G)) != PK_COOL) {
345 error_in_archive = error; /* only PK_EOF defined */
346 members_remaining = 0; /* ...so no more left to do */
347 break;
348 }
349 if ((error = do_string(__G__ G.crec.filename_length, DS_FN)) !=
350 PK_COOL)
351 {
352 if (error > error_in_archive)
353 error_in_archive = error;
354 if (error > PK_WARN) { /* fatal: no more left to do */
355 Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
356 FnFilter1(G.filename), "central"));
357 members_remaining = 0;
358 break;
359 }
360 }
361 if ((error = do_string(__G__ G.crec.extra_field_length,
362 EXTRA_FIELD)) != 0)
363 {
364 if (error > error_in_archive)
365 error_in_archive = error;
366 if (error > PK_WARN) { /* fatal */
367 Info(slide, 0x401, ((char *)slide,
368 LoadFarString(ExtFieldMsg),
369 FnFilter1(G.filename), "central"));
370 members_remaining = 0;
371 break;
372 }
373 }
374 #ifdef AMIGA
375 G.filenote_slot = j;
376 if ((error = do_string(__G__ G.crec.file_comment_length,
377 uO.N_flag ? FILENOTE : SKIP)) != PK_COOL)
378 #else
379 if ((error = do_string(__G__ G.crec.file_comment_length, SKIP))
380 != PK_COOL)
381 #endif
382 {
383 if (error > error_in_archive)
384 error_in_archive = error;
385 if (error > PK_WARN) { /* fatal */
386 Info(slide, 0x421, ((char *)slide,
387 LoadFarString(BadFileCommLength),
388 FnFilter1(G.filename)));
389 members_remaining = 0;
390 break;
391 }
392 }
393 if (G.process_all_files) {
394 if (store_info(__G))
395 ++j; /* file is OK; info[] stored; continue with next */
396 else
397 ++num_skipped;
398 } else {
399 int do_this_file;
400
401 if (G.filespecs == 0)
402 do_this_file = TRUE;
403 else { /* check if this entry matches an `include' argument */
404 do_this_file = FALSE;
405 for (i = 0; i < G.filespecs; i++)
406 if (match(G.filename, G.pfnames[i], uO.C_flag)) {
407 do_this_file = TRUE; /* ^-- ignore case or not? */
408 if (fn_matched)
409 fn_matched[i] = TRUE;
410 break; /* found match, so stop looping */
411 }
412 }
413 if (do_this_file) { /* check if this is an excluded file */
414 for (i = 0; i < G.xfilespecs; i++)
415 if (match(G.filename, G.pxnames[i], uO.C_flag)) {
416 do_this_file = FALSE; /* ^-- ignore case or not? */
417 if (xn_matched)
418 xn_matched[i] = TRUE;
419 break;
420 }
421 }
422 if (do_this_file) {
423 if (store_info(__G))
424 ++j; /* file is OK */
425 else
426 ++num_skipped; /* unsupp. compression or encryption */
427 }
428 } /* end if (process_all_files) */
429
430
431 } /* end while-loop (adding files to current block) */
432
433 /* save position in central directory so can come back later */
434 cd_bufstart = G.cur_zipfile_bufstart;
435 cd_inptr = G.inptr;
436 cd_incnt = G.incnt;
437
438 /*-----------------------------------------------------------------------
439 Second loop: process files in current block, extracting or testing
440 each one.
441 -----------------------------------------------------------------------*/
442
443 for (i = 0; i < j; ++i) {
444 filnum++; /* filnum = i + blknum*DIR_BLKSIZ + 1; */
445 G.pInfo = &G.info[i];
446 #ifdef NOVELL_BUG_FAILSAFE
447 G.dne = FALSE; /* assume file exists until stat() says otherwise */
448 #endif
449
450 /* if the target position is not within the current input buffer
451 * (either haven't yet read far enough, or (maybe) skipping back-
452 * ward), skip to the target position and reset readbuf(). */
453
454 /* ZLSEEK(pInfo->offset): */
455 request = G.pInfo->offset + G.extra_bytes;
456 inbuf_offset = request % INBUFSIZ;
457 bufstart = request - inbuf_offset;
458
459 Trace((stderr, "\ndebug: request = %ld, inbuf_offset = %ld\n",
460 request, inbuf_offset));
461 Trace((stderr,
462 "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
463 bufstart, G.cur_zipfile_bufstart));
464 if (request < 0) {
465 Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
466 G.zipfn, LoadFarString(ReportMsg)));
467 error_in_archive = PK_ERR;
468 if (filnum == 1 && G.extra_bytes != 0L) {
469 Info(slide, 0x401, ((char *)slide,
470 LoadFarString(AttemptRecompensate)));
471 old_extra_bytes = G.extra_bytes;
472 G.extra_bytes = 0L;
473 request = G.pInfo->offset; /* could also check if != 0 */
474 inbuf_offset = request % INBUFSIZ;
475 bufstart = request - inbuf_offset;
476 Trace((stderr, "debug: request = %ld, inbuf_offset = %ld\n",
477 request, inbuf_offset));
478 Trace((stderr,
479 "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
480 bufstart, G.cur_zipfile_bufstart));
481 } else {
482 error_in_archive = PK_BADERR;
483 continue; /* this one hosed; try next */
484 }
485 }
486 /* try again */
487 if (request < 0) {
488 Trace((stderr, "debug: recompensated request still < 0\n"));
489 Info(slide, 0x401, ((char *)slide, LoadFarStringSmall(SeekMsg),
490 G.zipfn, LoadFarString(ReportMsg)));
491 error_in_archive = PK_BADERR;
492 continue;
493 } else if (bufstart != G.cur_zipfile_bufstart) {
494 Trace((stderr, "debug: bufstart != cur_zipfile_bufstart\n"));
495 #ifdef USE_STRM_INPUT
496 fseek((FILE *)G.zipfd,(LONGINT)bufstart,SEEK_SET);
497 G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
498 #else /* !USE_STRM_INPUT */
499 G.cur_zipfile_bufstart =
500 lseek(G.zipfd,(LONGINT)bufstart,SEEK_SET);
501 #endif /* ?USE_STRM_INPUT */
502 if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) <= 0)
503 {
504 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
505 filnum, "lseek", bufstart));
506 error_in_archive = PK_BADERR;
507 continue; /* can still do next file */
508 }
509 G.inptr = G.inbuf + (int)inbuf_offset;
510 G.incnt -= (int)inbuf_offset;
511 } else {
512 G.incnt += (int)(G.inptr-G.inbuf) - (int)inbuf_offset;
513 G.inptr = G.inbuf + (int)inbuf_offset;
514 }
515
516 /* should be in proper position now, so check for sig */
517 if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */
518 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
519 filnum, "EOF", request));
520 error_in_archive = PK_BADERR;
521 continue; /* but can still try next one */
522 }
523 if (strncmp(G.sig, local_hdr_sig, 4)) {
524 Info(slide, 0x401, ((char *)slide, LoadFarString(OffsetMsg),
525 filnum, LoadFarStringSmall(LocalHdrSig), request));
526 /*
527 GRRDUMP(G.sig, 4)
528 GRRDUMP(local_hdr_sig, 4)
529 */
530 error_in_archive = PK_ERR;
531 if ((filnum == 1 && G.extra_bytes != 0L) ||
532 (G.extra_bytes == 0L && old_extra_bytes != 0L)) {
533 Info(slide, 0x401, ((char *)slide,
534 LoadFarString(AttemptRecompensate)));
535 if (G.extra_bytes) {
536 old_extra_bytes = G.extra_bytes;
537 G.extra_bytes = 0L;
538 } else
539 G.extra_bytes = old_extra_bytes; /* third attempt */
540 ZLSEEK(G.pInfo->offset)
541 if (readbuf(__G__ G.sig, 4) == 0) { /* bad offset */
542 Info(slide, 0x401, ((char *)slide,
543 LoadFarString(OffsetMsg), filnum, "EOF", request));
544 error_in_archive = PK_BADERR;
545 continue; /* but can still try next one */
546 }
547 if (strncmp(G.sig, local_hdr_sig, 4)) {
548 Info(slide, 0x401, ((char *)slide,
549 LoadFarString(OffsetMsg), filnum,
550 LoadFarStringSmall(LocalHdrSig), request));
551 error_in_archive = PK_BADERR;
552 continue;
553 }
554 } else
555 continue; /* this one hosed; try next */
556 }
557 if ((error = process_local_file_hdr(__G)) != PK_COOL) {
558 Info(slide, 0x421, ((char *)slide, LoadFarString(BadLocalHdr),
559 filnum));
560 error_in_archive = error; /* only PK_EOF defined */
561 continue; /* can still try next one */
562 }
563 if ((error = do_string(__G__ G.lrec.filename_length, DS_FN)) !=
564 PK_COOL)
565 {
566 if (error > error_in_archive)
567 error_in_archive = error;
568 if (error > PK_WARN) {
569 Info(slide, 0x401, ((char *)slide, LoadFarString(FilNamMsg),
570 FnFilter1(G.filename), "local"));
571 continue; /* go on to next one */
572 }
573 }
574 if (G.extra_field != (uch *)NULL) {
575 free(G.extra_field);
576 G.extra_field = (uch *)NULL;
577 }
578 if ((error =
579 do_string(__G__ G.lrec.extra_field_length, EXTRA_FIELD)) != 0)
580 {
581 if (error > error_in_archive)
582 error_in_archive = error;
583 if (error > PK_WARN) {
584 Info(slide, 0x401, ((char *)slide,
585 LoadFarString(ExtFieldMsg),
586 FnFilter1(G.filename), "local"));
587 continue; /* go on */
588 }
589 }
590
591 #if CRYPT
592 if (G.pInfo->encrypted &&
593 (error = decrypt(__G__ uO.pwdarg)) != PK_COOL) {
594 if (error == PK_WARN) {
595 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
596 Info(slide, 0x401, ((char *)slide,
597 LoadFarString(SkipIncorrectPasswd),
598 FnFilter1(G.filename)));
599 ++num_bad_pwd;
600 } else { /* (error > PK_WARN) */
601 if (error > error_in_archive)
602 error_in_archive = error;
603 Info(slide, 0x401, ((char *)slide,
604 LoadFarString(SkipCannotGetPasswd),
605 FnFilter1(G.filename)));
606 }
607 continue; /* go on to next file */
608 }
609 #endif /* CRYPT */
610
611 /*
612 * just about to extract file: if extracting to disk, check if
613 * already exists, and if so, take appropriate action according to
614 * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
615 * loop because we don't store the possibly renamed filename[] in
616 * info[])
617 */
618 #ifdef DLL
619 if (!uO.tflag && !uO.cflag && !G.redirect_data)
620 #else
621 if (!uO.tflag && !uO.cflag)
622 #endif
623 {
624 renamed = FALSE; /* user hasn't renamed output file yet */
625
626 startover:
627 query = FALSE;
628 /* for files from DOS FAT, check for use of backslash instead
629 * of slash as directory separator (bug in some zipper(s); so
630 * far, not a problem in HPFS, NTFS or VFAT systems)
631 */
632 #ifndef SFX
633 if (G.pInfo->hostnum == FS_FAT_ && !strchr(G.filename, '/')) {
634 char *p=G.filename-1;
635
636 while (*++p) {
637 if (*p == '\\') {
638 if (!G.reported_backslash) {
639 Info(slide, 0x21, ((char *)slide,
640 LoadFarString(BackslashPathSep), G.zipfn));
641 G.reported_backslash = TRUE;
642 if (!error_in_archive)
643 error_in_archive = PK_WARN;
644 }
645 *p = '/';
646 }
647 }
648 }
649 #endif /* !SFX */
650
651 /* mapname can create dirs if not freshening or if renamed */
652 if ((error = mapname(__G__ renamed)) > PK_WARN) {
653 if (error == IZ_CREATED_DIR) {
654 #ifdef SET_DIR_ATTRIB
655 dirtime *d_entry;
656
657 d_entry = (dirtime *)malloc(sizeof(dirtime));
658 if (d_entry == (dirtime *)NULL) {
659 Info(slide, 0x401, ((char *)slide,
660 LoadFarString(DirlistEntryNoMem)));
661 } else {
662 unsigned eb_izux_flg;
663
664 d_entry->next = dirlist;
665 dirlist = d_entry;
666 dirlist->fn =
667 (char *)malloc(strlen(G.filename) + 1);
668 if (dirlist->fn == (char *)NULL) {
669 Info(slide, 0x401, ((char *)slide,
670 LoadFarString(DirlistEntryNoMem)));
671 dirlist = d_entry->next;
672 free(d_entry);
673 if (!error_in_archive)
674 error_in_archive = PK_WARN;
675 continue;
676 }
677 strcpy(dirlist->fn, G.filename);
678 dirlist->perms = G.pInfo->file_attr;
679 #ifdef USE_EF_UT_TIME
680 eb_izux_flg = G.extra_field? ef_scan_for_izux(
681 G.extra_field, G.lrec.extra_field_length, 0,
682 G.lrec.last_mod_dos_datetime,
683 #ifdef IZ_CHECK_TZ
684 (G.tz_is_valid ? &(dirlist->u.t3) : NULL),
685 #else
686 &(dirlist->u.t3),
687 #endif
688 dirlist->uidgid)
689 : 0;
690 #else /* !USE_EF_UT_TIME */
691 eb_izux_flg = 0;
692 #endif /* ?USE_EF_UT_TIME */
693 if (eb_izux_flg & EB_UT_FL_MTIME) {
694 TTrace((stderr,
695 "\nextract: Unix dir e.f. modtime = %ld\n",
696 dirlist->u.t3.mtime));
697 } else {
698 dirlist->u.t3.mtime = dos_to_unix_time(
699 G.lrec.last_mod_dos_datetime);
700 }
701 if (eb_izux_flg & EB_UT_FL_ATIME) {
702 TTrace((stderr,
703 "\nextract: Unix dir e.f. actime = %ld\n",
704 dirlist->u.t3.atime));
705 } else {
706 dirlist->u.t3.atime =
707 dirlist->u.t3.mtime;
708 }
709 dirlist->have_uidgid =
710 (uO.X_flag && (eb_izux_flg & EB_UX2_VALID));
711 ++num_dirs;
712 }
713 #endif /* SET_DIR_ATTRIB */
714 } else if (error == IZ_VOL_LABEL) {
715 #ifdef DOS_OS2_W32
716 Info(slide, 0x401, ((char *)slide,
717 LoadFarString(SkipVolumeLabel),
718 FnFilter1(G.filename),
719 uO.volflag? "hard disk " : ""));
720 #else
721 Info(slide, 1, ((char *)slide,
722 LoadFarString(SkipVolumeLabel),
723 FnFilter1(G.filename), ""));
724 #endif
725 /* if (!error_in_archive)
726 error_in_archive = PK_WARN; */
727 } else if (error > PK_ERR && error_in_archive < PK_ERR)
728 error_in_archive = PK_ERR;
729 Trace((stderr, "mapname(%s) returns error = %d\n",
730 FnFilter1(G.filename), error));
731 continue; /* go on to next file */
732 }
733
734 #ifdef QDOS
735 QFilename(__G__ G.filename);
736 #endif
737 switch (check_for_newer(__G__ G.filename)) {
738 case DOES_NOT_EXIST:
739 #ifdef NOVELL_BUG_FAILSAFE
740 G.dne = TRUE; /* stat() says file DOES NOT EXIST */
741 #endif
742 /* if freshening, don't skip if just renamed */
743 if (uO.fflag && !renamed)
744 continue; /* freshen (no new files): skip */
745 break;
746 case EXISTS_AND_OLDER:
747 if (uO.overwrite_none) {
748 #ifdef WINDLL
749 char szStr[FILNAMSIZ+40]; /* add. space for text */
750
751 if ((!G.prompt_always) || (done_once)) {
752 sprintf(szStr,
753 "Target file exists.\nSkipping %s\n",
754 FnFilter1(G.filename));
755 win_fprintf((zvoid *)&G, stdout,
756 strlen(szStr), szStr);
757 } else {
758 query = TRUE;
759 break;
760 }
761 #endif /* WINDLL */
762 continue; /* never overwrite: skip file */
763 }
764 #ifdef UNIXBACKUP
765 if (!uO.overwrite_all && !uO.B_flag)
766 #else
767 if (!uO.overwrite_all)
768 #endif
769 query = TRUE;
770 break;
771 case EXISTS_AND_NEWER: /* (or equal) */
772 if (uO.overwrite_none || (uO.uflag && !renamed)) {
773 #ifdef WINDLL
774 char szStr[FILNAMSIZ+40]; /* add. space for text */
775
776 if ((!G.prompt_always) || (done_once)) {
777 sprintf(szStr,
778 "Target file newer.\nSkipping %s\n",
779 FnFilter1(G.filename));
780 win_fprintf((zvoid *)&G, stdout,
781 strlen(szStr), szStr);
782 } else {
783 query = TRUE;
784 break;
785 }
786 #endif /* WINDLL */
787 continue; /* skip if update/freshen & orig name */
788 }
789 #ifdef UNIXBACKUP
790 if (!uO.overwrite_all && !uO.B_flag)
791 #else
792 if (!uO.overwrite_all)
793 #endif
794 query = TRUE;
795 break;
796 }
797 if (query) {
798 #ifdef WINDLL
799 switch (G.lpUserFunctions->replace != NULL ?
800 (*G.lpUserFunctions->replace)(G.filename) :
801 IDM_REPLACE_NONE) {
802 case IDM_REPLACE_RENAME:
803 _ISO_INTERN(G.filename);
804 renamed = TRUE;
805 goto startover;
806 case IDM_REPLACE_YES:
807 break;
808 case IDM_REPLACE_ALL:
809 uO.overwrite_all = TRUE;
810 uO.overwrite_none = FALSE; /* just to make sure */
811 break;
812 case IDM_REPLACE_NONE:
813 uO.overwrite_none = TRUE;
814 uO.overwrite_all = FALSE; /* make sure */
815 done_once = TRUE;
816 /* FALL THROUGH, skip */
817 case IDM_REPLACE_NO:
818 {
819 char szStr[FILNAMSIZ+40];
820
821 sprintf(szStr,
822 "Target file newer.\nSkipping %s\n",
823 FnFilter1(G.filename));
824 win_fprintf((zvoid *)&G, stdout,
825 strlen(szStr), szStr);
826 }
827 continue;
828 }
829 #else /* !WINDLL */
830 reprompt:
831 Info(slide, 0x81, ((char *)slide,
832 LoadFarString(ReplaceQuery),
833 FnFilter1(G.filename)));
834 if (fgets(G.answerbuf, 9, stdin) == (char *)NULL) {
835 Info(slide, 1, ((char *)slide,
836 LoadFarString(AssumeNone)));
837 *G.answerbuf = 'N';
838 if (!error_in_archive)
839 error_in_archive = 1; /* not extracted: warning */
840 }
841 switch (*G.answerbuf) {
842 case 'A': /* dangerous option: force caps */
843 uO.overwrite_all = TRUE;
844 uO.overwrite_none = FALSE; /* just to make sure */
845 break;
846 case 'r':
847 case 'R':
848 do {
849 Info(slide, 0x81, ((char *)slide,
850 LoadFarString(NewNameQuery)));
851 fgets(G.filename, FILNAMSIZ, stdin);
852 /* usually get \n here: better check for it */
853 len = strlen(G.filename);
854 if (G.filename[len-1] == '\n')
855 G.filename[--len] = '\0';
856 } while (len == 0);
857 #ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */
858 _OEM_INTERN(G.filename);
859 #endif
860 renamed = TRUE;
861 goto startover; /* sorry for a goto */
862 case 'y':
863 case 'Y':
864 break;
865 case 'N':
866 uO.overwrite_none = TRUE;
867 uO.overwrite_all = FALSE; /* make sure */
868 /* FALL THROUGH, skip */
869 case 'n':
870 continue; /* skip file */
871 default:
872 Info(slide, 1, ((char *)slide,
873 LoadFarString(InvalidResponse), *G.answerbuf));
874 goto reprompt; /* yet another goto? */
875 } /* end switch (*answerbuf) */
876 #endif /* ?WINDLL */
877 } /* end if (query) */
878 } /* end if (extracting to disk) */
879
880 #ifdef DLL
881 if ((G.statreportcb != NULL) &&
882 (*G.statreportcb)(__G__ UZ_ST_START_EXTRACT, G.zipfn,
883 G.filename, NULL)) {
884 if (fn_matched)
885 free((zvoid *)fn_matched);
886 if (xn_matched)
887 free((zvoid *)xn_matched);
888 return IZ_CTRLC; /* cancel operation by user request */
889 }
890 #endif
891 #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
892 UserStop();
893 #endif
894 #ifdef AMIGA
895 G.filenote_slot = i;
896 #endif
897 G.disk_full = 0;
898 if ((error = extract_or_test_member(__G)) != PK_COOL) {
899 if (error > error_in_archive)
900 error_in_archive = error; /* ...and keep going */
901 #ifdef DLL
902 if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
903 #else
904 if (G.disk_full > 1) {
905 #endif
906 if (fn_matched)
907 free((zvoid *)fn_matched);
908 if (xn_matched)
909 free((zvoid *)xn_matched);
910 return error_in_archive; /* (unless disk full) */
911 }
912 }
913 #ifdef DLL
914 if ((G.statreportcb != NULL) &&
915 (*G.statreportcb)(__G__ UZ_ST_FINISH_MEMBER, G.zipfn,
916 G.filename, (zvoid *)&G.lrec.ucsize)) {
917 if (fn_matched)
918 free((zvoid *)fn_matched);
919 if (xn_matched)
920 free((zvoid *)xn_matched);
921 return IZ_CTRLC; /* cancel operation by user request */
922 }
923 #endif
924 #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
925 UserStop();
926 #endif
927 } /* end for-loop (i: files in current block) */
928
929
930 /*
931 * Jump back to where we were in the central directory, then go and do
932 * the next batch of files.
933 */
934
935 #ifdef USE_STRM_INPUT
936 fseek((FILE *)G.zipfd, (LONGINT)cd_bufstart, SEEK_SET);
937 G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);
938 #else /* !USE_STRM_INPUT */
939 G.cur_zipfile_bufstart = lseek(G.zipfd,(LONGINT)cd_bufstart,SEEK_SET);
940 #endif /* ?USE_STRM_INPUT */
941 read(G.zipfd, (char *)G.inbuf, INBUFSIZ); /* been here before... */
942 G.inptr = cd_inptr;
943 G.incnt = cd_incnt;
944 ++blknum;
945
946 #ifdef TEST
947 pipeit("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
948 pipeit("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
949 cur_zipfile_bufstart);
950 pipeit("inptr-inbuf = %d\n", G.inptr-G.inbuf);
951 pipeit("incnt = %d\n\n", G.incnt);
952 #endif
953
954 } /* end while-loop (blocks of files in central directory) */
955
956 /*---------------------------------------------------------------------------
957 Go back through saved list of directories, sort and set times/perms/UIDs
958 and GIDs from the deepest level on up.
959 ---------------------------------------------------------------------------*/
960
961 #ifdef SET_DIR_ATTRIB
962 if (num_dirs > 0) {
963 sorted_dirlist = (dirtime **)malloc(num_dirs*sizeof(dirtime *));
964 if (sorted_dirlist == (dirtime **)NULL) {
965 Info(slide, 0x401, ((char *)slide,
966 LoadFarString(DirlistSortNoMem)));
967 while (dirlist != (dirtime *)NULL) {
968 dirtime *d = dirlist;
969
970 dirlist = dirlist->next;
971 free(d);
972 }
973 } else {
974 if (num_dirs == 1)
975 sorted_dirlist[0] = dirlist;
976 else {
977 for (i = 0; i < num_dirs; ++i) {
978 sorted_dirlist[i] = dirlist;
979 dirlist = dirlist->next;
980 }
981 qsort((char *)sorted_dirlist, num_dirs, sizeof(dirtime *),
982 dircomp);
983 }
984
985 Trace((stderr, "setting directory times/perms/attributes\n"));
986 for (i = 0; i < num_dirs; ++i) {
987 dirtime *d = sorted_dirlist[i];
988
989 Trace((stderr, "dir = %s\n", d->fn));
990 if ((error = set_direc_attribs(__G__ d)) != PK_OK) {
991 Info(slide, 0x201, ((char *)slide,
992 LoadFarString(DirlistSetAttrFailed), d->fn));
993 if (!error_in_archive)
994 error_in_archive = error;
995 }
996 free(d->fn);
997 free(d);
998 }
999 free(sorted_dirlist);
1000 }
1001 }
1002 #endif /* SET_DIR_ATTRIB */
1003
1004 #if (defined(WIN32) && defined(NTSD_EAS))
1005 process_defer_NT(__G); /* process any deferred items for this .zip file */
1006 #endif
1007
1008 /*---------------------------------------------------------------------------
1009 Check for unmatched filespecs on command line and print warning if any
1010 found. Free allocated memory.
1011 ---------------------------------------------------------------------------*/
1012
1013 if (fn_matched) {
1014 for (i = 0; i < G.filespecs; ++i)
1015 if (!fn_matched[i]) {
1016 #ifdef DLL
1017 if (!G.redirect_data && !G.redirect_text)
1018 Info(slide, 0x401, ((char *)slide,
1019 LoadFarString(FilenameNotMatched), G.pfnames[i]));
1020 else
1021 setFileNotFound(__G);
1022 #else
1023 Info(slide, 1, ((char *)slide,
1024 LoadFarString(FilenameNotMatched), G.pfnames[i]));
1025 #endif
1026 if (error_in_archive <= PK_WARN)
1027 error_in_archive = PK_FIND; /* some files not found */
1028 }
1029 free((zvoid *)fn_matched);
1030 }
1031 if (xn_matched) {
1032 for (i = 0; i < G.xfilespecs; ++i)
1033 if (!xn_matched[i])
1034 Info(slide, 0x401, ((char *)slide,
1035 LoadFarString(ExclFilenameNotMatched), G.pxnames[i]));
1036 free((zvoid *)xn_matched);
1037 }
1038
1039 /*---------------------------------------------------------------------------
1040 Double-check that we're back at the end-of-central-directory record, and
1041 print quick summary of results, if we were just testing the archive. We
1042 send the summary to stdout so that people doing the testing in the back-
1043 ground and redirecting to a file can just do a "tail" on the output file.
1044 ---------------------------------------------------------------------------*/
1045
1046 #ifndef SFX
1047 if (readbuf(__G__ G.sig, 4) == 0)
1048 error_in_archive = PK_EOF;
1049 if (strncmp(G.sig, end_central_sig, 4)) { /* just to make sure */
1050 Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
1051 Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
1052 if (!error_in_archive) /* don't overwrite stronger error */
1053 error_in_archive = PK_WARN;
1054 }
1055 #endif /* !SFX */
1056 if (uO.tflag) {
1057 unsigned num = filnum - num_bad_pwd;
1058
1059 if (uO.qflag < 2) { /* GRR 930710: was (uO.qflag == 1) */
1060 if (error_in_archive)
1061 Info(slide, 0, ((char *)slide, LoadFarString(ErrorInArchive),
1062 (error_in_archive == 1)? "warning-" : "", G.zipfn));
1063 else if (num == 0)
1064 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
1065 G.zipfn));
1066 else if (G.process_all_files && (num_skipped+num_bad_pwd == 0))
1067 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInCompData),
1068 G.zipfn));
1069 else
1070 Info(slide, 0, ((char *)slide, LoadFarString(NoErrInTestedFiles)
1071 , G.zipfn, num, (num==1)? "":"s"));
1072 if (num_skipped > 0)
1073 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipped),
1074 num_skipped, (num_skipped==1)? "":"s"));
1075 #if CRYPT
1076 if (num_bad_pwd > 0)
1077 Info(slide, 0, ((char *)slide, LoadFarString(FilesSkipBadPasswd)
1078 , num_bad_pwd, (num_bad_pwd==1)? "":"s"));
1079 #endif /* CRYPT */
1080 } else if ((uO.qflag == 0) && !error_in_archive && (num == 0))
1081 Info(slide, 0, ((char *)slide, LoadFarString(ZeroFilesTested),
1082 G.zipfn));
1083 }
1084
1085 /* give warning if files not tested or extracted (first condition can still
1086 * happen if zipfile is empty and no files specified on command line) */
1087
1088 if ((filnum == 0) && error_in_archive <= PK_WARN) {
1089 if (num_skipped > 0)
1090 error_in_archive = IZ_UNSUP; /* unsupport. compression/encryption */
1091 else
1092 error_in_archive = PK_FIND; /* no files found at all */
1093 }
1094 #if CRYPT
1095 else if ((filnum == num_bad_pwd) && error_in_archive <= PK_WARN)
1096 error_in_archive = IZ_BADPWD; /* bad passwd => all files skipped */
1097 #endif
1098 else if ((num_skipped > 0) && error_in_archive <= PK_WARN)
1099 error_in_archive = IZ_UNSUP; /* was PK_WARN; Jean-loup complained */
1100 #if CRYPT
1101 else if ((num_bad_pwd > 0) && !error_in_archive)
1102 error_in_archive = PK_WARN;
1103 #endif
1104
1105 return error_in_archive;
1106
1107 } /* end function extract_or_test_files() */
1108
1109
1110
1111
1112
1113 /***************************/
1114 /* Function store_info() */
1115 /***************************/
1116
1117 static int store_info(__G) /* return 0 if skipping, 1 if OK */
1118 __GDEF
1119 {
1120 #ifdef SFX
1121 # define UNKN_COMPR \
1122 (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED)
1123 #else
1124 # ifdef COPYRIGHT_CLEAN /* no reduced files */
1125 # define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
1126 G.crec.compression_method <= REDUCED4)
1127 # else
1128 # define UNKN_RED FALSE /* reducing not unknown */
1129 # endif
1130 # ifdef LZW_CLEAN /* no shrunk files */
1131 # define UNKN_SHR (G.crec.compression_method == SHRUNK)
1132 # else
1133 # define UNKN_SHR FALSE /* unshrinking not unknown */
1134 # endif
1135 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
1136 G.crec.compression_method==TOKENIZED || G.crec.compression_method>DEFLATED)
1137 #endif
1138
1139 /*---------------------------------------------------------------------------
1140 Check central directory info for version/compatibility requirements.
1141 ---------------------------------------------------------------------------*/
1142
1143 G.pInfo->encrypted = G.crec.general_purpose_bit_flag & 1; /* bit field */
1144 G.pInfo->ExtLocHdr = (G.crec.general_purpose_bit_flag & 8) == 8; /* bit */
1145 G.pInfo->textfile = G.crec.internal_file_attributes & 1; /* bit field */
1146 G.pInfo->crc = G.crec.crc32;
1147 G.pInfo->compr_size = G.crec.csize;
1148 G.pInfo->uncompr_size = G.crec.ucsize;
1149
1150 switch (uO.aflag) {
1151 case 0:
1152 G.pInfo->textmode = FALSE; /* bit field */
1153 break;
1154 case 1:
1155 G.pInfo->textmode = G.pInfo->textfile; /* auto-convert mode */
1156 break;
1157 default: /* case 2: */
1158 G.pInfo->textmode = TRUE;
1159 break;
1160 }
1161
1162 if (G.crec.version_needed_to_extract[1] == VMS_) {
1163 if (G.crec.version_needed_to_extract[0] > VMS_UNZIP_VERSION) {
1164 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
1165 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
1166 FnFilter1(G.filename), "VMS",
1167 G.crec.version_needed_to_extract[0] / 10,
1168 G.crec.version_needed_to_extract[0] % 10,
1169 VMS_UNZIP_VERSION / 10, VMS_UNZIP_VERSION % 10));
1170 return 0;
1171 }
1172 #ifndef VMS /* won't be able to use extra field, but still have data */
1173 else if (!uO.tflag && !uO.overwrite_all) { /* if -o, extract anyway */
1174 Info(slide, 0x481, ((char *)slide, LoadFarString(VMSFormatQuery),
1175 FnFilter1(G.filename)));
1176 fgets(G.answerbuf, 9, stdin);
1177 if ((*G.answerbuf != 'y') && (*G.answerbuf != 'Y'))
1178 return 0;
1179 }
1180 #endif /* !VMS */
1181 /* usual file type: don't need VMS to extract */
1182 } else if (G.crec.version_needed_to_extract[0] > UNZIP_VERSION) {
1183 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
1184 Info(slide, 0x401, ((char *)slide, LoadFarString(VersionMsg),
1185 FnFilter1(G.filename), "PK",
1186 G.crec.version_needed_to_extract[0] / 10,
1187 G.crec.version_needed_to_extract[0] % 10,
1188 UNZIP_VERSION / 10, UNZIP_VERSION % 10));
1189 return 0;
1190 }
1191
1192 if UNKN_COMPR {
1193 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))) {
1194 #ifndef SFX
1195 if (G.crec.compression_method < NUM_METHODS)
1196 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgName),
1197 FnFilter1(G.filename),
1198 LoadFarStringSmall(ComprNames[G.crec.compression_method])));
1199 else
1200 #endif
1201 Info(slide, 0x401, ((char *)slide, LoadFarString(ComprMsgNum),
1202 FnFilter1(G.filename),
1203 G.crec.compression_method));
1204 }
1205 return 0;
1206 }
1207 #if (!CRYPT)
1208 if (G.pInfo->encrypted) {
1209 if (!((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2)))
1210 Info(slide, 0x401, ((char *)slide, LoadFarString(SkipEncrypted),
1211 FnFilter1(G.filename)));
1212 return 0;
1213 }
1214 #endif /* !CRYPT */
1215
1216 /* map whatever file attributes we have into the local format */
1217 mapattr(__G); /* GRR: worry about return value later */
1218
1219 G.pInfo->offset = (long)G.crec.relative_offset_local_header;
1220 return 1;
1221
1222 } /* end function store_info() */
1223
1224
1225
1226
1227
1228 /***************************************/
1229 /* Function extract_or_test_member() */
1230 /***************************************/
1231
1232 static int extract_or_test_member(__G) /* return PK-type error code */
1233 __GDEF
1234 {
1235 char *nul="[empty] ", *txt="[text] ", *bin="[binary]";
1236 #ifdef CMS_MVS
1237 char *ebc="[ebcdic]";
1238 #endif
1239 register int b;
1240 int r, error=PK_COOL;
1241 #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
1242 ulg wsize;
1243 #else
1244 # define wsize WSIZE
1245 #endif
1246
1247
1248 /*---------------------------------------------------------------------------
1249 Initialize variables, buffers, etc.
1250 ---------------------------------------------------------------------------*/
1251
1252 G.bits_left = 0;
1253 G.bitbuf = 0L; /* unreduce and unshrink only */
1254 G.zipeof = 0;
1255 G.newfile = TRUE;
1256 G.crc32val = CRCVAL_INITIAL;
1257
1258 #ifdef SYMLINKS
1259 /* if file came from Unix and is a symbolic link and we are extracting
1260 * to disk, prepare to restore the link */
1261 if (S_ISLNK(G.pInfo->file_attr) &&
1262 (G.pInfo->hostnum == UNIX_ || G.pInfo->hostnum == ATARI_ ||
1263 G.pInfo->hostnum == BEOS_) &&
1264 !uO.tflag && !uO.cflag && (G.lrec.ucsize > 0))
1265 G.symlnk = TRUE;
1266 else
1267 G.symlnk = FALSE;
1268 #endif /* SYMLINKS */
1269
1270 if (uO.tflag) {
1271 if (!uO.qflag)
1272 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg), "test",
1273 FnFilter1(G.filename), "", ""));
1274 } else {
1275 #ifdef DLL
1276 if (uO.cflag && !G.redirect_data)
1277 #else
1278 if (uO.cflag)
1279 #endif
1280 {
1281 #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
1282 G.outfile = freopen("", "wb", stdout); /* VAC++ ignores setmode */
1283 #else
1284 G.outfile = stdout;
1285 #endif
1286 #ifdef DOS_FLX_H68_OS2_W32
1287 #if (defined(__HIGHC__) && !defined(FLEXOS))
1288 setmode(G.outfile, _BINARY);
1289 #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
1290 setmode(fileno(G.outfile), O_BINARY);
1291 #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
1292 # define NEWLINE "\r\n"
1293 #else /* !DOS_FLX_H68_OS2_W32 */
1294 # define NEWLINE "\n"
1295 #endif /* ?DOS_FLX_H68_OS2_W32 */
1296 #ifdef VMS
1297 if (open_outfile(__G)) /* VMS: required even for stdout! */
1298 return PK_DISK;
1299 #endif
1300 } else if (open_outfile(__G))
1301 return PK_DISK;
1302 }
1303
1304 /*---------------------------------------------------------------------------
1305 Unpack the file.
1306 ---------------------------------------------------------------------------*/
1307
1308 defer_leftover_input(__G); /* so NEXTBYTE bounds check will work */
1309 switch (G.lrec.compression_method) {
1310 case STORED:
1311 if (!uO.tflag && QCOND2) {
1312 #ifdef SYMLINKS
1313 if (G.symlnk) /* can also be deflated, but rarer... */
1314 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1315 "link", FnFilter1(G.filename), "", ""));
1316 else
1317 #endif /* SYMLINKS */
1318 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1319 "extract", FnFilter1(G.filename),
1320 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1321 "" : (G.lrec.ucsize == 0L? nul : (G.pInfo->textfile? txt :
1322 bin)), uO.cflag? NEWLINE : ""));
1323 }
1324 #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
1325 if (G.redirect_slide) {
1326 wsize = G.redirect_size; redirSlide = G.redirect_buffer;
1327 } else {
1328 wsize = WSIZE; redirSlide = slide;
1329 }
1330 #endif
1331 G.outptr = redirSlide;
1332 G.outcnt = 0L;
1333 while ((b = NEXTBYTE) != EOF && !G.disk_full) {
1334 *G.outptr++ = (uch)b;
1335 if (++G.outcnt == wsize) {
1336 flush(__G__ redirSlide, G.outcnt, 0);
1337 G.outptr = redirSlide;
1338 G.outcnt = 0L;
1339 }
1340 }
1341 if (G.outcnt) /* flush final (partial) buffer */
1342 flush(__G__ redirSlide, G.outcnt, 0);
1343 break;
1344
1345 #ifndef SFX
1346 #ifndef LZW_CLEAN
1347 case SHRUNK:
1348 if (!uO.tflag && QCOND2) {
1349 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1350 LoadFarStringSmall(Unshrink), FnFilter1(G.filename),
1351 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1352 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1353 }
1354 if ((r = unshrink(__G)) != PK_COOL) {
1355 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1356 Info(slide, 0x401, ((char *)slide,
1357 LoadFarStringSmall(ErrUnzipFile),
1358 LoadFarString(NotEnoughMem),
1359 LoadFarStringSmall2(Unshrink),
1360 FnFilter1(G.filename)));
1361 else
1362 Info(slide, 0x401, ((char *)slide,
1363 LoadFarStringSmall(ErrUnzipNoFile),
1364 LoadFarString(NotEnoughMem),
1365 LoadFarStringSmall2(Unshrink)));
1366 error = r;
1367 }
1368 break;
1369 #endif /* !LZW_CLEAN */
1370
1371 #ifndef COPYRIGHT_CLEAN
1372 case REDUCED1:
1373 case REDUCED2:
1374 case REDUCED3:
1375 case REDUCED4:
1376 if (!uO.tflag && QCOND2) {
1377 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1378 "unreduc", FnFilter1(G.filename),
1379 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1380 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1381 }
1382 unreduce(__G);
1383 break;
1384 #endif /* !COPYRIGHT_CLEAN */
1385
1386 case IMPLODED:
1387 if (!uO.tflag && QCOND2) {
1388 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1389 "explod", FnFilter1(G.filename),
1390 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1391 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1392 }
1393 if (((r = explode(__G)) != 0) && (r != 5)) { /* treat 5 specially */
1394 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1395 Info(slide, 0x401, ((char *)slide,
1396 LoadFarStringSmall(ErrUnzipFile), r == 3?
1397 LoadFarString(NotEnoughMem) :
1398 LoadFarString(InvalidComprData),
1399 LoadFarStringSmall2(Explode),
1400 FnFilter1(G.filename)));
1401 else
1402 Info(slide, 0x401, ((char *)slide,
1403 LoadFarStringSmall(ErrUnzipNoFile), r == 3?
1404 LoadFarString(NotEnoughMem) :
1405 LoadFarString(InvalidComprData),
1406 LoadFarStringSmall2(Explode)));
1407 error = (r == 3)? PK_MEM3 : PK_ERR;
1408 }
1409 if (r == 5) {
1410 int warning = ((ulg)G.used_csize <= G.lrec.csize);
1411
1412 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1413 Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
1414 "", warning? "warning" : "error", G.used_csize,
1415 G.lrec.ucsize, warning? " " : "", G.lrec.csize,
1416 " [", FnFilter1(G.filename), "]"));
1417 else
1418 Info(slide, 0x401, ((char *)slide, LoadFarString(LengthMsg),
1419 "\n", warning? "warning" : "error", G.used_csize,
1420 G.lrec.ucsize, warning? " ":"", G.lrec.csize,
1421 "", "", "."));
1422 error = warning? PK_WARN : PK_ERR;
1423 }
1424 break;
1425 #endif /* !SFX */
1426
1427 case DEFLATED:
1428 if (!uO.tflag && QCOND2) {
1429 Info(slide, 0, ((char *)slide, LoadFarString(ExtractMsg),
1430 "inflat", FnFilter1(G.filename),
1431 (uO.aflag != 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1432 "" : (G.pInfo->textfile? txt : bin), uO.cflag? NEWLINE : ""));
1433 }
1434 #ifndef USE_ZLIB /* zlib's function is called inflate(), too */
1435 # define UZinflate inflate
1436 #endif
1437 if ((r = UZinflate(__G)) != 0) {
1438 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1439 Info(slide, 0x401, ((char *)slide,
1440 LoadFarStringSmall(ErrUnzipFile), r == 3?
1441 LoadFarString(NotEnoughMem) :
1442 LoadFarString(InvalidComprData),
1443 LoadFarStringSmall2(Inflate),
1444 FnFilter1(G.filename)));
1445 else
1446 Info(slide, 0x401, ((char *)slide,
1447 LoadFarStringSmall(ErrUnzipNoFile), r == 3?
1448 LoadFarString(NotEnoughMem) :
1449 LoadFarString(InvalidComprData),
1450 LoadFarStringSmall2(Inflate)));
1451 error = (r == 3)? PK_MEM3 : PK_ERR;
1452 }
1453 break;
1454
1455 default: /* should never get to this point */
1456 Info(slide, 0x401, ((char *)slide,
1457 LoadFarString(FileUnknownCompMethod), FnFilter1(G.filename)));
1458 /* close and delete file before return? */
1459 undefer_input(__G);
1460 return PK_WARN;
1461
1462 } /* end switch (compression method) */
1463
1464 /*---------------------------------------------------------------------------
1465 Close the file and set its date and time (not necessarily in that order),
1466 and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit
1467 machines (redundant on 32-bit machines).
1468 ---------------------------------------------------------------------------*/
1469
1470 #ifdef VMS /* VMS: required even for stdout! (final flush) */
1471 if (!uO.tflag) /* don't close NULL file */
1472 close_outfile(__G);
1473 #else
1474 #ifdef DLL
1475 if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
1476 if (G.redirect_data)
1477 FINISH_REDIRECT();
1478 else
1479 close_outfile(__G);
1480 }
1481 #else
1482 if (!uO.tflag && !uO.cflag) /* don't close NULL file or stdout */
1483 close_outfile(__G);
1484 #endif
1485 #endif /* VMS */
1486
1487 /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */
1488
1489
1490 if (G.disk_full) { /* set by flush() */
1491 if (G.disk_full > 1) {
1492 #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
1493 /* delete the incomplete file if we can */
1494 if (unlink(G.filename) != 0)
1495 Trace((stderr, "extract.c: could not delete %s\n",
1496 FnFilter1(G.filename)));
1497 #else
1498 /* warn user about the incomplete file */
1499 Info(slide, 0x421, ((char *)slide, LoadFarString(FileTruncated),
1500 FnFilter1(G.filename)));
1501 #endif
1502 error = PK_DISK;
1503 } else {
1504 error = PK_WARN;
1505 }
1506 }
1507
1508 if (error > PK_WARN) {/* don't print redundant CRC error if error already */
1509 undefer_input(__G);
1510 return error;
1511 }
1512 if (G.crc32val != G.lrec.crc32) {
1513 /* if quiet enough, we haven't output the filename yet: do it */
1514 if ((uO.tflag && uO.qflag) || (!uO.tflag && !QCOND2))
1515 Info(slide, 0x401, ((char *)slide, "%-22s ",
1516 FnFilter1(G.filename)));
1517 Info(slide, 0x401, ((char *)slide, LoadFarString(BadCRC), G.crc32val,
1518 G.lrec.crc32));
1519 #if CRYPT
1520 if (G.pInfo->encrypted)
1521 Info(slide, 0x401, ((char *)slide, LoadFarString(MaybeBadPasswd)));
1522 #endif
1523 error = PK_ERR;
1524 } else if (uO.tflag) {
1525 #ifndef SFX
1526 if (G.extra_field) {
1527 if ((r = TestExtraField(__G__ G.extra_field,
1528 G.lrec.extra_field_length)) > error)
1529 error = r;
1530 } else
1531 #endif /* !SFX */
1532 if (!uO.qflag)
1533 Info(slide, 0, ((char *)slide, " OK\n"));
1534 } else {
1535 if (QCOND2 && !error) /* GRR: is stdout reset to text mode yet? */
1536 Info(slide, 0, ((char *)slide, "\n"));
1537 }
1538
1539 undefer_input(__G);
1540 return error;
1541
1542 } /* end function extract_or_test_member() */
1543
1544
1545
1546
1547
1548 #ifndef SFX
1549
1550 /*******************************/
1551 /* Function TestExtraField() */
1552 /*******************************/
1553
1554 static int TestExtraField(__G__ ef, ef_len)
1555 __GDEF
1556 uch *ef;
1557 unsigned ef_len;
1558 {
1559 ush ebID;
1560 unsigned ebLen;
1561 unsigned eb_cmpr_offs = 0;
1562 int r;
1563
1564 /* we know the regular compressed file data tested out OK, or else we
1565 * wouldn't be here ==> print filename if any extra-field errors found
1566 */
1567 while (ef_len >= EB_HEADSIZE) {
1568 ebID = makeword(ef);
1569 ebLen = (unsigned)makeword(ef+EB_LEN);
1570
1571 if (ebLen > (ef_len - EB_HEADSIZE)) {
1572 /* Discovered some extra field inconsistency! */
1573 if (uO.qflag)
1574 Info(slide, 1, ((char *)slide, "%-22s ",
1575 FnFilter1(G.filename)));
1576 Info(slide, 1, ((char *)slide, LoadFarString(InconsistEFlength),
1577 ebLen, (ef_len - EB_HEADSIZE)));
1578 return PK_ERR;
1579 }
1580
1581 switch (ebID) {
1582 case EF_OS2:
1583 case EF_ACL:
1584 case EF_MAC3:
1585 case EF_BEOS:
1586 switch (ebID) {
1587 case EF_OS2:
1588 case EF_ACL:
1589 eb_cmpr_offs = EB_OS2_HLEN;
1590 break;
1591 case EF_MAC3:
1592 if (ebLen >= EB_MAC3_HLEN &&
1593 (makeword(ef+(EB_HEADSIZE+EB_FLGS_OFFS))
1594 & EB_M3_FL_UNCMPR) &&
1595 (makelong(ef+EB_HEADSIZE) == ebLen - EB_MAC3_HLEN))
1596 eb_cmpr_offs = 0;
1597 else
1598 eb_cmpr_offs = EB_MAC3_HLEN;
1599 break;
1600 case EF_BEOS:
1601 if (ebLen >= EB_BEOS_HLEN &&
1602 (*(ef+(EB_HEADSIZE+EB_FLGS_OFFS)) & EB_BE_FL_UNCMPR) &&
1603 (makelong(ef+EB_HEADSIZE) == ebLen - EB_BEOS_HLEN))
1604 eb_cmpr_offs = 0;
1605 else
1606 eb_cmpr_offs = EB_BEOS_HLEN;
1607 break;
1608 }
1609 if ((r = test_compr_eb(__G__ ef, ebLen, eb_cmpr_offs, NULL))
1610 != PK_OK) {
1611 if (uO.qflag)
1612 Info(slide, 1, ((char *)slide, "%-22s ",
1613 FnFilter1(G.filename)));
1614 switch (r) {
1615 case IZ_EF_TRUNC:
1616 Info(slide, 1, ((char *)slide,
1617 LoadFarString(TruncEAs),
1618 ebLen-(eb_cmpr_offs+EB_CMPRHEADLEN), "\n"));
1619 break;
1620 case PK_ERR:
1621 Info(slide, 1, ((char *)slide,
1622 LoadFarString(InvalidComprDataEAs)));
1623 break;
1624 case PK_MEM3:
1625 case PK_MEM4:
1626 Info(slide, 1, ((char *)slide,
1627 LoadFarString(NotEnoughMemEAs)));
1628 break;
1629 default:
1630 if ((r & 0xff) != PK_ERR)
1631 Info(slide, 1, ((char *)slide,
1632 LoadFarString(UnknErrorEAs)));
1633 else {
1634 ush m = (ush)(r >> 8);
1635 if (m == DEFLATED) /* GRR KLUDGE! */
1636 Info(slide, 1, ((char *)slide,
1637 LoadFarString(BadCRC_EAs)));
1638 else
1639 Info(slide, 1, ((char *)slide,
1640 LoadFarString(UnknComprMethodEAs), m));
1641 }
1642 break;
1643 }
1644 return r;
1645 }
1646 break;
1647
1648 case EF_NTSD:
1649 Trace((stderr, "ebID: %i / ebLen: %u\n", ebID, ebLen));
1650 r = ebLen < EB_NTSD_L_LEN ? IZ_EF_TRUNC :
1651 ((ef[EB_HEADSIZE+EB_NTSD_VERSION] > EB_NTSD_MAX_VER) ?
1652 (PK_WARN | 0x4000) :
1653 test_compr_eb(__G__ ef, ebLen, EB_NTSD_L_LEN, TEST_NTSD));
1654 if (r != PK_OK) {
1655 if (uO.qflag)
1656 Info(slide, 1, ((char *)slide, "%-22s ",
1657 FnFilter1(G.filename)));
1658 switch (r) {
1659 case IZ_EF_TRUNC:
1660 Info(slide, 1, ((char *)slide,
1661 LoadFarString(TruncNTSD),
1662 ebLen-(EB_NTSD_L_LEN+EB_CMPRHEADLEN), "\n"));
1663 break;
1664 #if (defined(WIN32) && defined(NTSD_EAS))
1665 case PK_WARN:
1666 Info(slide, 1, ((char *)slide,
1667 LoadFarString(InvalidSecurityEAs)));
1668 break;
1669 #endif
1670 case PK_ERR:
1671 Info(slide, 1, ((char *)slide,
1672 LoadFarString(InvalidComprDataEAs)));
1673 break;
1674 case PK_MEM3:
1675 case PK_MEM4:
1676 Info(slide, 1, ((char *)slide,
1677 LoadFarString(NotEnoughMemEAs)));
1678 break;
1679 case (PK_WARN | 0x4000):
1680 Info(slide, 1, ((char *)slide,
1681 LoadFarString(UnsuppNTSDVersEAs),
1682 (int)ef[EB_HEADSIZE+EB_NTSD_VERSION]));
1683 r = PK_WARN;
1684 break;
1685 default:
1686 if ((r & 0xff) != PK_ERR)
1687 Info(slide, 1, ((char *)slide,
1688 LoadFarString(UnknErrorEAs)));
1689 else {
1690 ush m = (ush)(r >> 8);
1691 if (m == DEFLATED) /* GRR KLUDGE! */
1692 Info(slide, 1, ((char *)slide,
1693 LoadFarString(BadCRC_EAs)));
1694 else
1695 Info(slide, 1, ((char *)slide,
1696 LoadFarString(UnknComprMethodEAs), m));
1697 }
1698 break;
1699 }
1700 return r;
1701 }
1702 break;
1703 case EF_PKVMS:
1704 case EF_PKW32:
1705 case EF_PKUNIX:
1706 case EF_ASIUNIX:
1707 case EF_IZVMS:
1708 case EF_IZUNIX:
1709 case EF_VMCMS:
1710 case EF_MVS:
1711 case EF_SPARK:
1712 case EF_AV:
1713 default:
1714 break;
1715 }
1716 ef_len -= (ebLen + EB_HEADSIZE);
1717 ef += (ebLen + EB_HEADSIZE);
1718 }
1719
1720 if (!uO.qflag)
1721 Info(slide, 0, ((char *)slide, " OK\n"));
1722
1723 return PK_COOL;
1724
1725 } /* end function TestExtraField() */
1726
1727
1728
1729
1730
1731 /******************************/
1732 /* Function test_compr_eb() */
1733 /******************************/
1734
1735 #ifdef PROTO
1736 static int test_compr_eb(
1737 __GPRO__
1738 uch *eb,
1739 unsigned eb_size,
1740 unsigned compr_offset,
1741 int (*test_uc_ebdata)(__GPRO__ uch *eb, unsigned eb_size,
1742 uch *eb_ucptr, ulg eb_ucsize))
1743 #else /* !PROTO */
1744 static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
1745 __GDEF
1746 uch *eb;
1747 unsigned eb_size;
1748 unsigned compr_offset;
1749 int (*test_uc_ebdata)();
1750 #endif /* ?PROTO */
1751 {
1752 ulg eb_ucsize;
1753 uch *eb_ucptr;
1754 int r;
1755
1756 if (compr_offset < 4) /* field is not compressed: */
1757 return PK_OK; /* do nothing and signal OK */
1758
1759 if ((eb_size < (EB_UCSIZE_P + 4)) ||
1760 ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
1761 eb_size <= (compr_offset + EB_CMPRHEADLEN)))
1762 return IZ_EF_TRUNC; /* no compressed data! */
1763
1764 if ((eb_ucptr = (uch *)malloc((extent)eb_ucsize)) == (uch *)NULL)
1765 return PK_MEM4;
1766
1767 r = memextract(__G__ eb_ucptr, eb_ucsize,
1768 eb + (EB_HEADSIZE + compr_offset),
1769 (ulg)(eb_size - compr_offset));
1770
1771 if (r == PK_OK && test_uc_ebdata != NULL)
1772 r = (*test_uc_ebdata)(__G__ eb, eb_size, eb_ucptr, eb_ucsize);
1773
1774 free(eb_ucptr);
1775 return r;
1776
1777 } /* end function test_compr_eb() */
1778
1779 #endif /* !SFX */
1780
1781
1782
1783
1784
1785 /***************************/
1786 /* Function memextract() */
1787 /***************************/
1788
1789 int memextract(__G__ tgt, tgtsize, src, srcsize) /* extract compressed */
1790 __GDEF /* extra field block; */
1791 uch *tgt, *src; /* return PK-type error */
1792 ulg tgtsize, srcsize; /* level */
1793 {
1794 long old_csize=G.csize;
1795 uch *old_inptr=G.inptr;
1796 int old_incnt=G.incnt;
1797 int r, error=PK_OK;
1798 ush method;
1799 ulg extra_field_crc;
1800
1801
1802 method = makeword(src);
1803 extra_field_crc = makelong(src+2);
1804
1805 /* compressed extra field exists completely in memory at this location: */
1806 G.inptr = src + 2 + 4; /* method and extra_field_crc */
1807 G.incnt = (int)(G.csize = (long)(srcsize - (2 + 4)));
1808 G.mem_mode = TRUE;
1809 G.outbufptr = tgt;
1810 G.outsize = tgtsize;
1811
1812 switch (method) {
1813 case STORED:
1814 memcpy((char *)tgt, (char *)G.inptr, (extent)G.incnt);
1815 G.outcnt = G.csize; /* for CRC calculation */
1816 break;
1817 case DEFLATED:
1818 G.outcnt = 0L;
1819 if ((r = UZinflate(__G)) != 0) {
1820 if (!uO.tflag)
1821 Info(slide, 0x401, ((char *)slide,
1822 LoadFarStringSmall(ErrUnzipNoFile), r == 3?
1823 LoadFarString(NotEnoughMem) :
1824 LoadFarString(InvalidComprData),
1825 LoadFarStringSmall2(Inflate)));
1826 error = (r == 3)? PK_MEM3 : PK_ERR;
1827 }
1828 if (G.outcnt == 0L) /* inflate's final FLUSH sets outcnt */
1829 break;
1830 break;
1831 default:
1832 if (uO.tflag)
1833 error = PK_ERR | ((int)method << 8);
1834 else {
1835 Info(slide, 0x401, ((char *)slide,
1836 LoadFarString(UnsupportedExtraField), method));
1837 error = PK_ERR; /* GRR: should be passed on up via SetEAs() */
1838 }
1839 break;
1840 }
1841
1842 G.inptr = old_inptr;
1843 G.incnt = old_incnt;
1844 G.csize = old_csize;
1845 G.mem_mode = FALSE;
1846
1847 if (!error) {
1848 register ulg crcval = crc32(CRCVAL_INITIAL, tgt, (extent)G.outcnt);
1849
1850 if (crcval != extra_field_crc) {
1851 if (uO.tflag)
1852 error = PK_ERR | (DEFLATED << 8); /* kludge for now */
1853 else {
1854 Info(slide, 0x401, ((char *)slide,
1855 LoadFarString(BadExtraFieldCRC), G.zipfn, crcval,
1856 extra_field_crc));
1857 error = PK_ERR;
1858 }
1859 }
1860 }
1861 return error;
1862
1863 } /* end function memextract() */
1864
1865
1866
1867
1868
1869 /*************************/
1870 /* Function memflush() */
1871 /*************************/
1872
1873 int memflush(__G__ rawbuf, size)
1874 __GDEF
1875 uch *rawbuf;
1876 ulg size;
1877 {
1878 if (size > G.outsize)
1879 return 50; /* more data than output buffer can hold */
1880
1881 memcpy((char *)G.outbufptr, (char *)rawbuf, (extent)size);
1882 G.outbufptr += (unsigned int)size;
1883 G.outsize -= size;
1884 G.outcnt += size;
1885
1886 return 0;
1887
1888 } /* end function memflush() */
1889
1890
1891
1892
1893
1894 /*************************/
1895 /* Function fnfilter() */ /* here instead of in list.c for SFX */
1896 /*************************/
1897
1898 char *fnfilter(raw, space) /* convert name to safely printable form */
1899 ZCONST char *raw;
1900 uch *space;
1901 {
1902 #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
1903 uch *r=(uch *)raw, *s=space;
1904
1905 while (*r) {
1906 #ifdef QDOS
1907 if (qlflag & 2) {
1908 if (*r == '/' || *r == '.') {
1909 ++r;
1910 *s++ = '_';
1911 continue;
1912 }
1913 } else
1914 #endif
1915 if (*r < 32)
1916 *s++ = '^', *s++ = (uch)(64 + *r++);
1917 else
1918 *s++ = *r++;
1919 }
1920 *s = 0;
1921
1922 #ifdef WINDLL
1923 INTERN_TO_ISO((char *)space, (char *)space); /* translate to ANSI */
1924 #else
1925 #ifdef WIN32
1926 /* Win9x console always uses OEM character coding, and
1927 WinNT console is set to OEM charset by default, too */
1928 INTERN_TO_OEM((char *)space, (char *)space);
1929 #endif /* WIN32 */
1930 #endif /* ?WINDLL */
1931
1932 return (char *)space;
1933
1934 #else /* NATIVE: EBCDIC or whatever */
1935 return (char *)raw;
1936 #endif
1937
1938 } /* end function fnfilter() */
1939
1940
1941
1942
1943
1944 #ifdef SET_DIR_ATTRIB
1945 /* must sort saved directories so can set perms from bottom up */
1946
1947 /************************/
1948 /* Function dircomp() */
1949 /************************/
1950
1951 static int dircomp(a, b) /* used by qsort(); swiped from Zip */
1952 ZCONST zvoid *a, *b;
1953 {
1954 /* order is significant: this sorts in reverse order (deepest first) */
1955 return strcmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn);
1956 /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */
1957 }
1958
1959
1960
1961 #if 0 /* not used in Unix, but maybe for future OSes? */
1962
1963 /************************/
1964 /* Function namecmp() */
1965 /************************/
1966
1967 static int namecmp(s1, s2) /* [not] used by dircomp(); swiped from Zip */
1968 ZCONST char *s1, *s2;
1969 {
1970 int d;
1971
1972 for (;;) {
1973 d = (int)(uch)case_map(*s1)
1974 - (int)(uch)case_map(*s2);
1975
1976 if (d || *s1 == 0 || *s2 == 0)
1977 return d;
1978
1979 s1++;
1980 s2++;
1981 }
1982 }
1983
1984 #endif /* 0 */
1985 #endif /* SET_DIR_ATTRIB */