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