2 Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
4 See the accompanying file LICENSE, version 2000-Apr-09 or later
5 (the contents of which are also included in unzip.h) for terms of use.
6 If, for some reason, all these files are missing, the Info-ZIP license
7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
9 /*---------------------------------------------------------------------------
13 This file contains the high-level routines ("driver routines") for extrac-
14 ting and testing zipfile members. It calls the low-level routines in files
15 explode.c, inflate.c, unreduce.c and unshrink.c.
17 Contains: extract_or_test_files()
19 extract_or_test_entrylist()
20 extract_or_test_member()
25 extract_izvms_block() (VMS or VMS_TEXT_CONV)
28 ---------------------------------------------------------------------------*/
31 #define __EXTRACT_C /* identifies this source module */
32 #define UNZIP_INTERNAL
36 # include "wince/intrface.h"
38 # include "windll/windll.h"
43 #define GRRDUMP(buf,len) { \
46 for (j = 0; j < (len)/16; ++j) { \
48 for (i = 0; i < 16; ++i) \
49 printf("%02x ", (uch)(buf)[i+(j<<4)]); \
51 for (i = 0; i < 16; ++i) { \
52 char c = (char)(buf)[i+(j<<4)]; \
65 for (i = j<<4; i < (len); ++i) \
66 printf("%02x ", (uch)(buf)[i]); \
68 for (i = j<<4; i < (len); ++i) { \
69 char c = (char)(buf)[i]; \
82 static int store_info
OF((__GPRO
));
84 static int extract_or_test_entrylist
OF((__GPRO__
unsigned numchunk
,
85 ulg
*pfilnum
, ulg
*pnum_bad_pwd
, LONGINT
*pold_extra_bytes
,
86 unsigned *pnum_dirs
, dirtime
**pdirlist
,
87 int error_in_archive
));
89 static int extract_or_test_entrylist
OF((__GPRO__
unsigned numchunk
,
90 ulg
*pfilnum
, ulg
*pnum_bad_pwd
, LONGINT
*pold_extra_bytes
,
91 int error_in_archive
));
93 static int extract_or_test_member
OF((__GPRO
));
95 static int TestExtraField
OF((__GPRO__ uch
*ef
, unsigned ef_len
));
96 static int test_compr_eb
OF((__GPRO__ uch
*eb
, unsigned eb_size
,
97 unsigned compr_offset
,
98 int (*test_uc_ebdata
)(__GPRO__ uch
*eb
, unsigned eb_size
,
99 uch
*eb_ucptr
, ulg eb_ucsize
)));
101 #if (defined(VMS) || defined(VMS_TEXT_CONV))
102 static void decompress_bits
OF((uch
*outptr
, unsigned needlen
,
103 ZCONST uch
*bitptr
));
105 #ifdef SET_DIR_ATTRIB
106 static int dircomp
OF((ZCONST zvoid
*a
, ZCONST zvoid
*b
));
111 /*******************************/
112 /* Strings used in extract.c */
113 /*******************************/
115 static ZCONST
char Far VersionMsg
[] =
116 " skipping: %-22s need %s compat. v%u.%u (can do v%u.%u)\n";
117 static ZCONST
char Far ComprMsgNum
[] =
118 " skipping: %-22s unsupported compression method %u\n";
120 static ZCONST
char Far ComprMsgName
[] =
121 " skipping: %-22s `%s' method not supported\n";
122 static ZCONST
char Far CmprNone
[] = "store";
123 static ZCONST
char Far CmprShrink
[] = "shrink";
124 static ZCONST
char Far CmprReduce
[] = "reduce";
125 static ZCONST
char Far CmprImplode
[] = "implode";
126 static ZCONST
char Far CmprTokenize
[] = "tokenize";
127 static ZCONST
char Far CmprDeflate
[] = "deflate";
128 static ZCONST
char Far CmprDeflat64
[] = "deflate64";
129 static ZCONST
char Far CmprDCLImplode
[] = "DCL implode";
130 static ZCONST
char Far
*ComprNames
[NUM_METHODS
] = {
131 CmprNone
, CmprShrink
, CmprReduce
, CmprReduce
, CmprReduce
, CmprReduce
,
132 CmprImplode
, CmprTokenize
, CmprDeflate
, CmprDeflat64
, CmprDCLImplode
135 static ZCONST
char Far FilNamMsg
[] =
136 "%s: bad filename length (%s)\n";
137 static ZCONST
char Far ExtFieldMsg
[] =
138 "%s: bad extra field length (%s)\n";
139 static ZCONST
char Far OffsetMsg
[] =
140 "file #%lu: bad zipfile offset (%s): %ld\n";
141 static ZCONST
char Far ExtractMsg
[] =
142 "%8sing: %-22s %s%s";
144 static ZCONST
char Far LengthMsg
[] =
145 "%s %s: %ld bytes required to uncompress to %lu bytes;\n %s\
146 supposed to require %lu bytes%s%s%s\n";
149 static ZCONST
char Far BadFileCommLength
[] = "%s: bad file comment length\n";
150 static ZCONST
char Far LocalHdrSig
[] = "local header sig";
151 static ZCONST
char Far BadLocalHdr
[] = "file #%lu: bad local header\n";
152 static ZCONST
char Far AttemptRecompensate
[] =
153 " (attempting to re-compensate)\n";
155 static ZCONST
char Far BackslashPathSep
[] =
156 "warning: %s appears to use backslashes as path separators\n";
158 static ZCONST
char Far AbsolutePathWarning
[] =
159 "warning: stripped absolute path spec from %s\n";
160 static ZCONST
char Far SkipVolumeLabel
[] =
161 " skipping: %-22s %svolume label\n";
163 #ifdef SET_DIR_ATTRIB /* messages of code for setting directory attributes */
164 static ZCONST
char Far DirlistEntryNoMem
[] =
165 "warning: cannot alloc memory for dir times/permissions/UID/GID\n";
166 static ZCONST
char Far DirlistSortNoMem
[] =
167 "warning: cannot alloc memory to sort dir times/perms/etc.\n";
168 static ZCONST
char Far DirlistSetAttrFailed
[] =
169 "warning: set times/attribs failed for %s\n";
173 static ZCONST
char Far ReplaceQuery
[] =
174 "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ";
175 static ZCONST
char Far AssumeNone
[] = " NULL\n(assuming [N]one)\n";
176 static ZCONST
char Far NewNameQuery
[] = "new name: ";
177 static ZCONST
char Far InvalidResponse
[] = "error: invalid response [%c]\n";
180 static ZCONST
char Far ErrorInArchive
[] =
181 "At least one %serror was detected in %s.\n";
182 static ZCONST
char Far ZeroFilesTested
[] =
183 "Caution: zero files tested in %s.\n";
186 static ZCONST
char Far VMSFormatQuery
[] =
187 "\n%s: stored in VMS format. Extract anyway? (y/n) ";
191 static ZCONST
char Far SkipCannotGetPasswd
[] =
192 " skipping: %-22s unable to get password\n";
193 static ZCONST
char Far SkipIncorrectPasswd
[] =
194 " skipping: %-22s incorrect password\n";
195 static ZCONST
char Far FilesSkipBadPasswd
[] =
196 "%lu file%s skipped because of incorrect password.\n";
197 static ZCONST
char Far MaybeBadPasswd
[] =
198 " (may instead be incorrect password)\n";
200 static ZCONST
char Far SkipEncrypted
[] =
201 " skipping: %-22s encrypted (not supported)\n";
204 static ZCONST
char Far NoErrInCompData
[] =
205 "No errors detected in compressed data of %s.\n";
206 static ZCONST
char Far NoErrInTestedFiles
[] =
207 "No errors detected in %s for the %lu file%s tested.\n";
208 static ZCONST
char Far FilesSkipped
[] =
209 "%lu file%s skipped because of unsupported compression or encoding.\n";
211 static ZCONST
char Far ErrUnzipFile
[] = " error: %s%s %s\n";
212 static ZCONST
char Far ErrUnzipNoFile
[] = "\n error: %s%s\n";
213 static ZCONST
char Far NotEnoughMem
[] = "not enough memory to ";
214 static ZCONST
char Far InvalidComprData
[] = "invalid compressed data to ";
215 static ZCONST
char Far Inflate
[] = "inflate";
218 static ZCONST
char Far Explode
[] = "explode";
220 static ZCONST
char Far Unshrink
[] = "unshrink";
224 #if (!defined(DELETE_IF_FULL) || !defined(HAVE_UNLINK))
225 static ZCONST
char Far FileTruncated
[] =
226 "warning: %s is probably truncated\n";
229 static ZCONST
char Far FileUnknownCompMethod
[] =
230 "%s: unknown compression method\n";
231 static ZCONST
char Far BadCRC
[] = " bad CRC %08lx (should be %08lx)\n";
233 /* TruncEAs[] also used in OS/2 mapname(), close_outfile() */
234 char ZCONST Far TruncEAs
[] = " compressed EA data missing (%d bytes)%s";
235 char ZCONST Far TruncNTSD
[] =
236 " compressed WinNT security data missing (%d bytes)%s";
239 static ZCONST
char Far InconsistEFlength
[] = "bad extra-field entry:\n \
240 EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
241 static ZCONST
char Far InvalidComprDataEAs
[] =
242 " invalid compressed data for EAs\n";
243 # if (defined(WIN32) && defined(NTSD_EAS))
244 static ZCONST
char Far InvalidSecurityEAs
[] =
245 " EAs fail security check\n";
247 static ZCONST
char Far UnsuppNTSDVersEAs
[] =
248 " unsupported NTSD EAs version %d\n";
249 static ZCONST
char Far BadCRC_EAs
[] = " bad CRC for extended attributes\n";
250 static ZCONST
char Far UnknComprMethodEAs
[] =
251 " unknown compression method for EAs (%u)\n";
252 static ZCONST
char Far NotEnoughMemEAs
[] =
253 " out of memory while inflating EAs\n";
254 static ZCONST
char Far UnknErrorEAs
[] =
255 " unknown error on extended attributes\n";
258 static ZCONST
char Far UnsupportedExtraField
[] =
259 "\nerror: unsupported extra-field compression type (%u)--skipping\n";
260 static ZCONST
char Far BadExtraFieldCRC
[] =
261 "error [%s]: bad extra-field CRC %08lx (should be %08lx)\n";
267 /**************************************/
268 /* Function extract_or_test_files() */
269 /**************************************/
271 int extract_or_test_files(__G
) /* return PK-type error code */
278 ulg filnum
=0L, blknum
=0L;
279 int reached_end
, no_endsig_found
;
280 int error
, error_in_archive
=PK_COOL
;
281 int *fn_matched
=NULL
, *xn_matched
=NULL
;
282 unsigned members_processed
;
283 ulg num_skipped
=0L, num_bad_pwd
=0L;
284 LONGINT old_extra_bytes
= 0L;
285 #ifdef SET_DIR_ATTRIB
287 dirtime
*dirlist
=(dirtime
*)NULL
, **sorted_dirlist
=(dirtime
**)NULL
;
290 /*---------------------------------------------------------------------------
291 The basic idea of this function is as follows. Since the central di-
292 rectory lies at the end of the zipfile and the member files lie at the
293 beginning or middle or wherever, it is not very desirable to simply
294 read a central directory entry, jump to the member and extract it, and
295 then jump back to the central directory. In the case of a large zipfile
296 this would lead to a whole lot of disk-grinding, especially if each mem-
297 ber file is small. Instead, we read from the central directory the per-
298 tinent information for a block of files, then go extract/test the whole
299 block. Thus this routine contains two small(er) loops within a very
300 large outer loop: the first of the small ones reads a block of files
301 from the central directory; the second extracts or tests each file; and
302 the outer one loops over blocks. There's some file-pointer positioning
303 stuff in between, but that's about it. Btw, it's because of this jump-
304 ing around that we can afford to be lenient if an error occurs in one of
305 the member files: we should still be able to go find the other members,
306 since we know the offset of each from the beginning of the zipfile.
307 ---------------------------------------------------------------------------*/
315 G
.reported_backslash
= FALSE
;
318 /* malloc space for check on unmatched filespecs (OK if one or both NULL) */
319 if (G
.filespecs
> 0 &&
320 (fn_matched
=(int *)malloc(G
.filespecs
*sizeof(int))) != (int *)NULL
)
321 for (i
= 0; i
< G
.filespecs
; ++i
)
322 fn_matched
[i
] = FALSE
;
323 if (G
.xfilespecs
> 0 &&
324 (xn_matched
=(int *)malloc(G
.xfilespecs
*sizeof(int))) != (int *)NULL
)
325 for (i
= 0; i
< G
.xfilespecs
; ++i
)
326 xn_matched
[i
] = FALSE
;
328 /*---------------------------------------------------------------------------
329 Begin main loop over blocks of member files. We know the entire central
330 directory is on this disk: we would not have any of this information un-
331 less the end-of-central-directory record was on this disk, and we would
332 not have gotten to this routine unless this is also the disk on which
333 the central directory starts. In practice, this had better be the ONLY
334 disk in the archive, but we'll add multi-disk support soon.
335 ---------------------------------------------------------------------------*/
337 members_processed
= 0;
338 no_endsig_found
= FALSE
;
340 while (!reached_end
) {
343 memzero(G
.filenotes
, DIR_BLKSIZ
* sizeof(char *));
347 * Loop through files in central directory, storing offsets, file
348 * attributes, case-conversion and text-conversion flags until block
352 while ((j
< DIR_BLKSIZ
)) {
353 G
.pInfo
= &G
.info
[j
];
355 if (readbuf(__G__ G
.sig
, 4) == 0) {
356 error_in_archive
= PK_EOF
;
357 reached_end
= TRUE
; /* ...so no more left to do */
360 if (strncmp(G
.sig
, central_hdr_sig
, 4)) { /* is it a new entry? */
361 /* no new central directory entry
362 * -> is the number of processed entries compatible with the
363 * number of entries as stored in the end_central record?
365 if ((members_processed
& (unsigned)0xFFFF) ==
366 (unsigned)G
.ecrec
.total_entries_central_dir
) {
367 /* yes, so look if we ARE back at the end_central record
370 (strncmp(G
.sig
, end_central_sig
, 4) != 0);
372 /* no; we have found an error in the central directory
373 * -> report it and stop searching for more Zip entries
375 Info(slide
, 0x401, ((char *)slide
,
376 LoadFarString(CentSigMsg
), j
+ blknum
*DIR_BLKSIZ
+ 1));
377 Info(slide
, 0x401, ((char *)slide
,
378 LoadFarString(ReportMsg
)));
379 error_in_archive
= PK_BADERR
;
381 reached_end
= TRUE
; /* ...so no more left to do */
384 /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
385 if ((error
= process_cdir_file_hdr(__G
)) != PK_COOL
) {
386 error_in_archive
= error
; /* only PK_EOF defined */
387 reached_end
= TRUE
; /* ...so no more left to do */
390 if ((error
= do_string(__G__ G
.crec
.filename_length
, DS_FN
)) !=
393 if (error
> error_in_archive
)
394 error_in_archive
= error
;
395 if (error
> PK_WARN
) { /* fatal: no more left to do */
396 Info(slide
, 0x401, ((char *)slide
, LoadFarString(FilNamMsg
),
397 FnFilter1(G
.filename
), "central"));
402 if ((error
= do_string(__G__ G
.crec
.extra_field_length
,
405 if (error
> error_in_archive
)
406 error_in_archive
= error
;
407 if (error
> PK_WARN
) { /* fatal */
408 Info(slide
, 0x401, ((char *)slide
,
409 LoadFarString(ExtFieldMsg
),
410 FnFilter1(G
.filename
), "central"));
417 if ((error
= do_string(__G__ G
.crec
.file_comment_length
,
418 uO
.N_flag
? FILENOTE
: SKIP
)) != PK_COOL
)
420 if ((error
= do_string(__G__ G
.crec
.file_comment_length
, SKIP
))
424 if (error
> error_in_archive
)
425 error_in_archive
= error
;
426 if (error
> PK_WARN
) { /* fatal */
427 Info(slide
, 0x421, ((char *)slide
,
428 LoadFarString(BadFileCommLength
),
429 FnFilter1(G
.filename
)));
434 if (G
.process_all_files
) {
436 ++j
; /* file is OK; info[] stored; continue with next */
442 if (G
.filespecs
== 0)
444 else { /* check if this entry matches an `include' argument */
445 do_this_file
= FALSE
;
446 for (i
= 0; i
< G
.filespecs
; i
++)
447 if (match(G
.filename
, G
.pfnames
[i
], uO
.C_flag
)) {
448 do_this_file
= TRUE
; /* ^-- ignore case or not? */
450 fn_matched
[i
] = TRUE
;
451 break; /* found match, so stop looping */
454 if (do_this_file
) { /* check if this is an excluded file */
455 for (i
= 0; i
< G
.xfilespecs
; i
++)
456 if (match(G
.filename
, G
.pxnames
[i
], uO
.C_flag
)) {
457 do_this_file
= FALSE
; /* ^-- ignore case or not? */
459 xn_matched
[i
] = TRUE
;
465 ++j
; /* file is OK */
467 ++num_skipped
; /* unsupp. compression or encryption */
469 } /* end if (process_all_files) */
473 } /* end while-loop (adding files to current block) */
475 /* save position in central directory so can come back later */
476 cd_bufstart
= G
.cur_zipfile_bufstart
;
480 /*-----------------------------------------------------------------------
481 Second loop: process files in current block, extracting or testing
483 -----------------------------------------------------------------------*/
485 error
= extract_or_test_entrylist(__G__ j
,
486 &filnum
, &num_bad_pwd
, &old_extra_bytes
,
487 #ifdef SET_DIR_ATTRIB
491 if (error
!= PK_COOL
) {
492 if (error
> error_in_archive
)
493 error_in_archive
= error
; /* ...and keep going */
494 if (G
.disk_full
> 1 || error_in_archive
== IZ_CTRLC
) {
496 free((zvoid
*)fn_matched
);
498 free((zvoid
*)xn_matched
);
499 return error_in_archive
; /* (unless disk full) */
505 * Jump back to where we were in the central directory, then go and do
506 * the next batch of files.
509 #ifdef USE_STRM_INPUT
510 fseek((FILE *)G
.zipfd
, (LONGINT
)cd_bufstart
, SEEK_SET
);
511 G
.cur_zipfile_bufstart
= ftell((FILE *)G
.zipfd
);
512 #else /* !USE_STRM_INPUT */
513 G
.cur_zipfile_bufstart
=
514 lseek(G
.zipfd
, (LONGINT
)cd_bufstart
, SEEK_SET
);
515 #endif /* ?USE_STRM_INPUT */
516 read(G
.zipfd
, (char *)G
.inbuf
, INBUFSIZ
); /* been here before... */
522 printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart
, cd_bufstart
);
523 printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart
,
524 cur_zipfile_bufstart
);
525 printf("inptr-inbuf = %d\n", G
.inptr
-G
.inbuf
);
526 printf("incnt = %d\n\n", G
.incnt
);
529 } /* end while-loop (blocks of files in central directory) */
531 /*---------------------------------------------------------------------------
532 Go back through saved list of directories, sort and set times/perms/UIDs
533 and GIDs from the deepest level on up.
534 ---------------------------------------------------------------------------*/
536 #ifdef SET_DIR_ATTRIB
538 sorted_dirlist
= (dirtime
**)malloc(num_dirs
*sizeof(dirtime
*));
539 if (sorted_dirlist
== (dirtime
**)NULL
) {
540 Info(slide
, 0x401, ((char *)slide
,
541 LoadFarString(DirlistSortNoMem
)));
542 while (dirlist
!= (dirtime
*)NULL
) {
543 dirtime
*d
= dirlist
;
545 dirlist
= dirlist
->next
;
550 sorted_dirlist
[0] = dirlist
;
552 for (i
= 0; i
< num_dirs
; ++i
) {
553 sorted_dirlist
[i
] = dirlist
;
554 dirlist
= dirlist
->next
;
556 qsort((char *)sorted_dirlist
, num_dirs
, sizeof(dirtime
*),
560 Trace((stderr
, "setting directory times/perms/attributes\n"));
561 for (i
= 0; i
< num_dirs
; ++i
) {
562 dirtime
*d
= sorted_dirlist
[i
];
564 Trace((stderr
, "dir = %s\n", d
->fn
));
565 if ((error
= set_direc_attribs(__G__ d
)) != PK_OK
) {
566 Info(slide
, 0x201, ((char *)slide
,
567 LoadFarString(DirlistSetAttrFailed
), d
->fn
));
568 if (!error_in_archive
)
569 error_in_archive
= error
;
574 free(sorted_dirlist
);
577 #endif /* SET_DIR_ATTRIB */
579 #if (defined(WIN32) && defined(NTSD_EAS))
580 process_defer_NT(__G
); /* process any deferred items for this .zip file */
583 /*---------------------------------------------------------------------------
584 Check for unmatched filespecs on command line and print warning if any
585 found. Free allocated memory.
586 ---------------------------------------------------------------------------*/
589 for (i
= 0; i
< G
.filespecs
; ++i
)
590 if (!fn_matched
[i
]) {
592 if (!G
.redirect_data
&& !G
.redirect_text
)
593 Info(slide
, 0x401, ((char *)slide
,
594 LoadFarString(FilenameNotMatched
), G
.pfnames
[i
]));
596 setFileNotFound(__G
);
598 Info(slide
, 1, ((char *)slide
,
599 LoadFarString(FilenameNotMatched
), G
.pfnames
[i
]));
601 if (error_in_archive
<= PK_WARN
)
602 error_in_archive
= PK_FIND
; /* some files not found */
604 free((zvoid
*)fn_matched
);
607 for (i
= 0; i
< G
.xfilespecs
; ++i
)
609 Info(slide
, 0x401, ((char *)slide
,
610 LoadFarString(ExclFilenameNotMatched
), G
.pxnames
[i
]));
611 free((zvoid
*)xn_matched
);
614 /*---------------------------------------------------------------------------
615 Double-check that we're back at the end-of-central-directory record, and
616 print quick summary of results, if we were just testing the archive. We
617 send the summary to stdout so that people doing the testing in the back-
618 ground and redirecting to a file can just do a "tail" on the output file.
619 ---------------------------------------------------------------------------*/
622 if (no_endsig_found
) { /* just to make sure */
623 Info(slide
, 0x401, ((char *)slide
, LoadFarString(EndSigMsg
)));
624 Info(slide
, 0x401, ((char *)slide
, LoadFarString(ReportMsg
)));
625 if (!error_in_archive
) /* don't overwrite stronger error */
626 error_in_archive
= PK_WARN
;
630 ulg num
= filnum
- num_bad_pwd
;
632 if (uO
.qflag
< 2) { /* GRR 930710: was (uO.qflag == 1) */
633 if (error_in_archive
)
634 Info(slide
, 0, ((char *)slide
, LoadFarString(ErrorInArchive
),
635 (error_in_archive
== PK_WARN
)? "warning-" : "", G
.zipfn
));
637 Info(slide
, 0, ((char *)slide
, LoadFarString(ZeroFilesTested
),
639 else if (G
.process_all_files
&& (num_skipped
+num_bad_pwd
== 0L))
640 Info(slide
, 0, ((char *)slide
, LoadFarString(NoErrInCompData
),
643 Info(slide
, 0, ((char *)slide
, LoadFarString(NoErrInTestedFiles
)
644 , G
.zipfn
, num
, (num
==1L)? "":"s"));
645 if (num_skipped
> 0L)
646 Info(slide
, 0, ((char *)slide
, LoadFarString(FilesSkipped
),
647 num_skipped
, (num_skipped
==1L)? "":"s"));
649 if (num_bad_pwd
> 0L)
650 Info(slide
, 0, ((char *)slide
, LoadFarString(FilesSkipBadPasswd
)
651 , num_bad_pwd
, (num_bad_pwd
==1L)? "":"s"));
653 } else if ((uO
.qflag
== 0) && !error_in_archive
&& (num
== 0))
654 Info(slide
, 0, ((char *)slide
, LoadFarString(ZeroFilesTested
),
658 /* give warning if files not tested or extracted (first condition can still
659 * happen if zipfile is empty and no files specified on command line) */
661 if ((filnum
== 0) && error_in_archive
<= PK_WARN
) {
662 if (num_skipped
> 0L)
663 error_in_archive
= IZ_UNSUP
; /* unsupport. compression/encryption */
665 error_in_archive
= PK_FIND
; /* no files found at all */
668 else if ((filnum
== num_bad_pwd
) && error_in_archive
<= PK_WARN
)
669 error_in_archive
= IZ_BADPWD
; /* bad passwd => all files skipped */
671 else if ((num_skipped
> 0L) && error_in_archive
<= PK_WARN
)
672 error_in_archive
= IZ_UNSUP
; /* was PK_WARN; Jean-loup complained */
674 else if ((num_bad_pwd
> 0L) && !error_in_archive
)
675 error_in_archive
= PK_WARN
;
678 return error_in_archive
;
680 } /* end function extract_or_test_files() */
686 /***************************/
687 /* Function store_info() */
688 /***************************/
690 static int store_info(__G
) /* return 0 if skipping, 1 if OK */
694 # ifdef USE_DEFLATE64
695 # define UNKN_COMPR \
696 (G.crec.compression_method!=STORED && G.crec.compression_method<DEFLATED \
697 && G.crec.compression_method>ENHDEFLATED)
699 # define UNKN_COMPR \
700 (G.crec.compression_method!=STORED && G.crec.compression_method!=DEFLATED)
703 # ifdef COPYRIGHT_CLEAN /* no reduced files */
704 # define UNKN_RED (G.crec.compression_method >= REDUCED1 && \
705 G.crec.compression_method <= REDUCED4)
707 # define UNKN_RED FALSE /* reducing not unknown */
709 # ifdef LZW_CLEAN /* no shrunk files */
710 # define UNKN_SHR (G.crec.compression_method == SHRUNK)
712 # define UNKN_SHR FALSE /* unshrinking not unknown */
714 # ifdef USE_DEFLATE64
715 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
716 G.crec.compression_method==TOKENIZED || \
717 G.crec.compression_method>ENHDEFLATED)
719 # define UNKN_COMPR (UNKN_RED || UNKN_SHR || \
720 G.crec.compression_method==TOKENIZED || \
721 G.crec.compression_method>DEFLATED)
725 /*---------------------------------------------------------------------------
726 Check central directory info for version/compatibility requirements.
727 ---------------------------------------------------------------------------*/
729 G
.pInfo
->encrypted
= G
.crec
.general_purpose_bit_flag
& 1; /* bit field */
730 G
.pInfo
->ExtLocHdr
= (G
.crec
.general_purpose_bit_flag
& 8) == 8; /* bit */
731 G
.pInfo
->textfile
= G
.crec
.internal_file_attributes
& 1; /* bit field */
732 G
.pInfo
->crc
= G
.crec
.crc32
;
733 G
.pInfo
->compr_size
= G
.crec
.csize
;
734 G
.pInfo
->uncompr_size
= G
.crec
.ucsize
;
738 G
.pInfo
->textmode
= FALSE
; /* bit field */
741 G
.pInfo
->textmode
= G
.pInfo
->textfile
; /* auto-convert mode */
743 default: /* case 2: */
744 G
.pInfo
->textmode
= TRUE
;
748 if (G
.crec
.version_needed_to_extract
[1] == VMS_
) {
749 if (G
.crec
.version_needed_to_extract
[0] > VMS_UNZIP_VERSION
) {
750 if (!((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
)))
751 Info(slide
, 0x401, ((char *)slide
, LoadFarString(VersionMsg
),
752 FnFilter1(G
.filename
), "VMS",
753 G
.crec
.version_needed_to_extract
[0] / 10,
754 G
.crec
.version_needed_to_extract
[0] % 10,
755 VMS_UNZIP_VERSION
/ 10, VMS_UNZIP_VERSION
% 10));
758 #ifndef VMS /* won't be able to use extra field, but still have data */
759 else if (!uO
.tflag
&& !IS_OVERWRT_ALL
) { /* if -o, extract anyway */
760 Info(slide
, 0x481, ((char *)slide
, LoadFarString(VMSFormatQuery
),
761 FnFilter1(G
.filename
)));
762 fgets(G
.answerbuf
, 9, stdin
);
763 if ((*G
.answerbuf
!= 'y') && (*G
.answerbuf
!= 'Y'))
767 /* usual file type: don't need VMS to extract */
768 } else if (G
.crec
.version_needed_to_extract
[0] > UNZIP_VERSION
) {
769 if (!((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
)))
770 Info(slide
, 0x401, ((char *)slide
, LoadFarString(VersionMsg
),
771 FnFilter1(G
.filename
), "PK",
772 G
.crec
.version_needed_to_extract
[0] / 10,
773 G
.crec
.version_needed_to_extract
[0] % 10,
774 UNZIP_VERSION
/ 10, UNZIP_VERSION
% 10));
779 if (!((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
))) {
781 if (G
.crec
.compression_method
< NUM_METHODS
)
782 Info(slide
, 0x401, ((char *)slide
, LoadFarString(ComprMsgName
),
783 FnFilter1(G
.filename
),
784 LoadFarStringSmall(ComprNames
[G
.crec
.compression_method
])));
787 Info(slide
, 0x401, ((char *)slide
, LoadFarString(ComprMsgNum
),
788 FnFilter1(G
.filename
),
789 G
.crec
.compression_method
));
794 if (G
.pInfo
->encrypted
) {
795 if (!((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
)))
796 Info(slide
, 0x401, ((char *)slide
, LoadFarString(SkipEncrypted
),
797 FnFilter1(G
.filename
)));
802 /* map whatever file attributes we have into the local format */
803 mapattr(__G
); /* GRR: worry about return value later */
805 G
.pInfo
->diskstart
= G
.crec
.disk_number_start
;
806 G
.pInfo
->offset
= (long)G
.crec
.relative_offset_local_header
;
809 } /* end function store_info() */
815 /******************************************/
816 /* Function extract_or_test_entrylist() */
817 /******************************************/
819 static int extract_or_test_entrylist(__G__ numchunk
,
820 pfilnum
, pnum_bad_pwd
, pold_extra_bytes
,
821 #ifdef SET_DIR_ATTRIB
824 error_in_archive
) /* return PK-type error code */
829 LONGINT
*pold_extra_bytes
;
830 #ifdef SET_DIR_ATTRIB
834 int error_in_archive
;
839 long bufstart
, inbuf_offset
, request
;
842 /* possible values for local skip_entry flag: */
843 #define SKIP_NO 0 /* do not skip this entry */
844 #define SKIP_Y_EXISTING 1 /* skip this entry, do not overwrite file */
845 #define SKIP_Y_NONEXIST 2 /* skip this entry, do not create new file */
847 /*-----------------------------------------------------------------------
848 Second loop: process files in current block, extracting or testing
850 -----------------------------------------------------------------------*/
852 for (i
= 0; i
< numchunk
; ++i
) {
853 (*pfilnum
)++; /* *pfilnum = i + blknum*DIR_BLKSIZ + 1; */
854 G
.pInfo
= &G
.info
[i
];
855 #ifdef NOVELL_BUG_FAILSAFE
856 G
.dne
= FALSE
; /* assume file exists until stat() says otherwise */
859 /* if the target position is not within the current input buffer
860 * (either haven't yet read far enough, or (maybe) skipping back-
861 * ward), skip to the target position and reset readbuf(). */
863 /* seek_zipf(__G__ pInfo->offset); */
864 request
= G
.pInfo
->offset
+ G
.extra_bytes
;
865 inbuf_offset
= request
% INBUFSIZ
;
866 bufstart
= request
- inbuf_offset
;
868 Trace((stderr
, "\ndebug: request = %ld, inbuf_offset = %ld\n",
869 request
, inbuf_offset
));
871 "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
872 bufstart
, G
.cur_zipfile_bufstart
));
874 Info(slide
, 0x401, ((char *)slide
, LoadFarStringSmall(SeekMsg
),
875 G
.zipfn
, LoadFarString(ReportMsg
)));
876 error_in_archive
= PK_ERR
;
877 if (*pfilnum
== 1 && G
.extra_bytes
!= 0L) {
878 Info(slide
, 0x401, ((char *)slide
,
879 LoadFarString(AttemptRecompensate
)));
880 *pold_extra_bytes
= G
.extra_bytes
;
882 request
= G
.pInfo
->offset
; /* could also check if != 0 */
883 inbuf_offset
= request
% INBUFSIZ
;
884 bufstart
= request
- inbuf_offset
;
885 Trace((stderr
, "debug: request = %ld, inbuf_offset = %ld\n",
886 request
, inbuf_offset
));
888 "debug: bufstart = %ld, cur_zipfile_bufstart = %ld\n",
889 bufstart
, G
.cur_zipfile_bufstart
));
893 "debug: recompensated request still < 0\n"));
894 Info(slide
, 0x401, ((char *)slide
,
895 LoadFarStringSmall(SeekMsg
),
896 G
.zipfn
, LoadFarString(ReportMsg
)));
897 error_in_archive
= PK_BADERR
;
901 error_in_archive
= PK_BADERR
;
902 continue; /* this one hosed; try next */
906 if (bufstart
!= G
.cur_zipfile_bufstart
) {
907 Trace((stderr
, "debug: bufstart != cur_zipfile_bufstart\n"));
908 #ifdef USE_STRM_INPUT
909 fseek((FILE *)G
.zipfd
, (LONGINT
)bufstart
, SEEK_SET
);
910 G
.cur_zipfile_bufstart
= ftell((FILE *)G
.zipfd
);
911 #else /* !USE_STRM_INPUT */
912 G
.cur_zipfile_bufstart
=
913 lseek(G
.zipfd
, (LONGINT
)bufstart
, SEEK_SET
);
914 #endif /* ?USE_STRM_INPUT */
915 if ((G
.incnt
= read(G
.zipfd
,(char *)G
.inbuf
,INBUFSIZ
)) <= 0)
917 Info(slide
, 0x401, ((char *)slide
, LoadFarString(OffsetMsg
),
918 *pfilnum
, "lseek", bufstart
));
919 error_in_archive
= PK_BADERR
;
920 continue; /* can still do next file */
922 G
.inptr
= G
.inbuf
+ (int)inbuf_offset
;
923 G
.incnt
-= (int)inbuf_offset
;
925 G
.incnt
+= (int)(G
.inptr
-G
.inbuf
) - (int)inbuf_offset
;
926 G
.inptr
= G
.inbuf
+ (int)inbuf_offset
;
929 /* should be in proper position now, so check for sig */
930 if (readbuf(__G__ G
.sig
, 4) == 0) { /* bad offset */
931 Info(slide
, 0x401, ((char *)slide
, LoadFarString(OffsetMsg
),
932 *pfilnum
, "EOF", request
));
933 error_in_archive
= PK_BADERR
;
934 continue; /* but can still try next one */
936 if (strncmp(G
.sig
, local_hdr_sig
, 4)) {
937 Info(slide
, 0x401, ((char *)slide
, LoadFarString(OffsetMsg
),
938 *pfilnum
, LoadFarStringSmall(LocalHdrSig
), request
));
941 GRRDUMP(local_hdr_sig, 4)
943 error_in_archive
= PK_ERR
;
944 if ((*pfilnum
== 1 && G
.extra_bytes
!= 0L) ||
945 (G
.extra_bytes
== 0L && *pold_extra_bytes
!= 0L)) {
946 Info(slide
, 0x401, ((char *)slide
,
947 LoadFarString(AttemptRecompensate
)));
949 *pold_extra_bytes
= G
.extra_bytes
;
952 G
.extra_bytes
= *pold_extra_bytes
; /* third attempt */
953 if (((error
= seek_zipf(__G__ G
.pInfo
->offset
)) != PK_OK
) ||
954 (readbuf(__G__ G
.sig
, 4) == 0)) { /* bad offset */
955 if (error
!= PK_BADERR
)
956 Info(slide
, 0x401, ((char *)slide
,
957 LoadFarString(OffsetMsg
), *pfilnum
, "EOF", request
));
958 error_in_archive
= PK_BADERR
;
959 continue; /* but can still try next one */
961 if (strncmp(G
.sig
, local_hdr_sig
, 4)) {
962 Info(slide
, 0x401, ((char *)slide
,
963 LoadFarString(OffsetMsg
), *pfilnum
,
964 LoadFarStringSmall(LocalHdrSig
), request
));
965 error_in_archive
= PK_BADERR
;
969 continue; /* this one hosed; try next */
971 if ((error
= process_local_file_hdr(__G
)) != PK_COOL
) {
972 Info(slide
, 0x421, ((char *)slide
, LoadFarString(BadLocalHdr
),
974 error_in_archive
= error
; /* only PK_EOF defined */
975 continue; /* can still try next one */
977 if ((error
= do_string(__G__ G
.lrec
.filename_length
, DS_FN_L
)) !=
980 if (error
> error_in_archive
)
981 error_in_archive
= error
;
982 if (error
> PK_WARN
) {
983 Info(slide
, 0x401, ((char *)slide
, LoadFarString(FilNamMsg
),
984 FnFilter1(G
.filename
), "local"));
985 continue; /* go on to next one */
988 if (G
.extra_field
!= (uch
*)NULL
) {
990 G
.extra_field
= (uch
*)NULL
;
993 do_string(__G__ G
.lrec
.extra_field_length
, EXTRA_FIELD
)) != 0)
995 if (error
> error_in_archive
)
996 error_in_archive
= error
;
997 if (error
> PK_WARN
) {
998 Info(slide
, 0x401, ((char *)slide
,
999 LoadFarString(ExtFieldMsg
),
1000 FnFilter1(G
.filename
), "local"));
1001 continue; /* go on */
1006 if (G
.pInfo
->encrypted
&&
1007 (error
= decrypt(__G__ uO
.pwdarg
)) != PK_COOL
) {
1008 if (error
== PK_WARN
) {
1009 if (!((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
)))
1010 Info(slide
, 0x401, ((char *)slide
,
1011 LoadFarString(SkipIncorrectPasswd
),
1012 FnFilter1(G
.filename
)));
1014 } else { /* (error > PK_WARN) */
1015 if (error
> error_in_archive
)
1016 error_in_archive
= error
;
1017 Info(slide
, 0x401, ((char *)slide
,
1018 LoadFarString(SkipCannotGetPasswd
),
1019 FnFilter1(G
.filename
)));
1021 continue; /* go on to next file */
1026 * just about to extract file: if extracting to disk, check if
1027 * already exists, and if so, take appropriate action according to
1028 * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
1029 * loop because we don't store the possibly renamed filename[] in
1033 if (!uO
.tflag
&& !uO
.cflag
&& !G
.redirect_data
)
1035 if (!uO
.tflag
&& !uO
.cflag
)
1038 renamed
= FALSE
; /* user hasn't renamed output file yet */
1042 skip_entry
= SKIP_NO
;
1043 /* for files from DOS FAT, check for use of backslash instead
1044 * of slash as directory separator (bug in some zipper(s); so
1045 * far, not a problem in HPFS, NTFS or VFAT systems)
1048 if (G
.pInfo
->hostnum
== FS_FAT_
&& !MBSCHR(G
.filename
, '/')) {
1053 if (!G
.reported_backslash
) {
1054 Info(slide
, 0x21, ((char *)slide
,
1055 LoadFarString(BackslashPathSep
), G
.zipfn
));
1056 G
.reported_backslash
= TRUE
;
1057 if (!error_in_archive
)
1058 error_in_archive
= PK_WARN
;
1062 } while (*PREINCSTR(p
));
1067 /* remove absolute path specs */
1068 if (G
.filename
[0] == '/') {
1069 Info(slide
, 0x401, ((char *)slide
,
1070 LoadFarString(AbsolutePathWarning
),
1071 FnFilter1(G
.filename
)));
1072 if (!error_in_archive
)
1073 error_in_archive
= PK_WARN
;
1075 char *p
= G
.filename
+ 1;
1078 } while (*p
++ != '\0');
1079 } while (G
.filename
[0] == '/');
1083 /* mapname can create dirs if not freshening or if renamed */
1084 error
= mapname(__G__ renamed
);
1085 if ((errcode
= error
& ~MPN_MASK
) != PK_OK
&&
1086 error_in_archive
< errcode
)
1087 error_in_archive
= errcode
;
1088 if ((errcode
= error
& MPN_MASK
) > MPN_INF_TRUNC
) {
1089 if (errcode
== MPN_CREATED_DIR
) {
1090 #ifdef SET_DIR_ATTRIB
1093 d_entry
= (dirtime
*)malloc(sizeof(dirtime
));
1094 if (d_entry
== (dirtime
*)NULL
) {
1095 Info(slide
, 0x401, ((char *)slide
,
1096 LoadFarString(DirlistEntryNoMem
)));
1098 unsigned eb_izux_flg
;
1100 d_entry
->next
= (*pdirlist
);
1101 (*pdirlist
) = d_entry
;
1103 (char *)malloc(strlen(G
.filename
) + 1);
1104 if ((*pdirlist
)->fn
== (char *)NULL
) {
1105 Info(slide
, 0x401, ((char *)slide
,
1106 LoadFarString(DirlistEntryNoMem
)));
1107 (*pdirlist
) = d_entry
->next
;
1109 if (!error_in_archive
)
1110 error_in_archive
= PK_WARN
;
1113 strcpy((*pdirlist
)->fn
, G
.filename
);
1114 (*pdirlist
)->perms
= G
.pInfo
->file_attr
;
1115 #ifdef USE_EF_UT_TIME
1116 eb_izux_flg
= G
.extra_field
? ef_scan_for_izux(
1117 G
.extra_field
, G
.lrec
.extra_field_length
, 0,
1118 G
.lrec
.last_mod_dos_datetime
,
1120 (G
.tz_is_valid
? &((*pdirlist
)->u
.t3
) : NULL
),
1122 &((*pdirlist
)->u
.t3
),
1124 (*pdirlist
)->uidgid
)
1126 #else /* !USE_EF_UT_TIME */
1128 #endif /* ?USE_EF_UT_TIME */
1129 if (eb_izux_flg
& EB_UT_FL_MTIME
) {
1131 "\nextract: Unix dir e.f. modtime = %ld\n",
1132 (*pdirlist
)->u
.t3
.mtime
));
1134 (*pdirlist
)->u
.t3
.mtime
= dos_to_unix_time(
1135 G
.lrec
.last_mod_dos_datetime
);
1137 if (eb_izux_flg
& EB_UT_FL_ATIME
) {
1139 "\nextract: Unix dir e.f. actime = %ld\n",
1140 (*pdirlist
)->u
.t3
.atime
));
1142 (*pdirlist
)->u
.t3
.atime
=
1143 (*pdirlist
)->u
.t3
.mtime
;
1145 (*pdirlist
)->have_uidgid
=
1146 #ifdef RESTORE_UIDGID
1147 (uO
.X_flag
&& (eb_izux_flg
& EB_UX2_VALID
));
1153 #endif /* SET_DIR_ATTRIB */
1154 } else if (errcode
== MPN_VOL_LABEL
) {
1156 Info(slide
, 0x401, ((char *)slide
,
1157 LoadFarString(SkipVolumeLabel
),
1158 FnFilter1(G
.filename
),
1159 uO
.volflag
? "hard disk " : ""));
1161 Info(slide
, 1, ((char *)slide
,
1162 LoadFarString(SkipVolumeLabel
),
1163 FnFilter1(G
.filename
), ""));
1165 } else if (errcode
> MPN_INF_SKIP
&&
1166 error_in_archive
< PK_ERR
)
1167 error_in_archive
= PK_ERR
;
1168 Trace((stderr
, "mapname(%s) returns error code = %d\n",
1169 FnFilter1(G
.filename
), error
));
1170 continue; /* go on to next file */
1174 QFilename(__G__ G
.filename
);
1176 switch (check_for_newer(__G__ G
.filename
)) {
1177 case DOES_NOT_EXIST
:
1178 #ifdef NOVELL_BUG_FAILSAFE
1179 G
.dne
= TRUE
; /* stat() says file DOES NOT EXIST */
1181 /* freshen (no new files): skip unless just renamed */
1182 if (uO
.fflag
&& !renamed
)
1183 skip_entry
= SKIP_Y_NONEXIST
;
1185 case EXISTS_AND_OLDER
:
1190 if (IS_OVERWRT_NONE
)
1191 /* never overwrite: skip file */
1192 skip_entry
= SKIP_Y_EXISTING
;
1193 else if (!IS_OVERWRT_ALL
)
1197 case EXISTS_AND_NEWER
: /* (or equal) */
1199 if ((!uO
.B_flag
&& IS_OVERWRT_NONE
) ||
1201 if (IS_OVERWRT_NONE
||
1203 (uO
.uflag
&& !renamed
)) {
1204 /* skip if update/freshen & orig name */
1205 skip_entry
= SKIP_Y_EXISTING
;
1208 if (!IS_OVERWRT_ALL
&& !uO
.B_flag
)
1210 if (!IS_OVERWRT_ALL
)
1218 switch (G
.lpUserFunctions
->replace
!= NULL
?
1219 (*G
.lpUserFunctions
->replace
)(G
.filename
) :
1221 case IDM_REPLACE_RENAME
:
1222 _ISO_INTERN(G
.filename
);
1225 case IDM_REPLACE_ALL
:
1226 G
.overwrite_mode
= OVERWRT_ALWAYS
;
1227 /* FALL THROUGH, extract */
1228 case IDM_REPLACE_YES
:
1230 case IDM_REPLACE_NONE
:
1231 G
.overwrite_mode
= OVERWRT_NEVER
;
1232 /* FALL THROUGH, skip */
1233 case IDM_REPLACE_NO
:
1234 skip_entry
= SKIP_Y_EXISTING
;
1240 Info(slide
, 0x81, ((char *)slide
,
1241 LoadFarString(ReplaceQuery
),
1242 FnFilter1(G
.filename
)));
1243 if (fgets(G
.answerbuf
, 9, stdin
) == (char *)NULL
) {
1244 Info(slide
, 1, ((char *)slide
,
1245 LoadFarString(AssumeNone
)));
1247 if (!error_in_archive
)
1248 error_in_archive
= 1; /* not extracted: warning */
1250 switch (*G
.answerbuf
) {
1254 Info(slide
, 0x81, ((char *)slide
,
1255 LoadFarString(NewNameQuery
)));
1256 fgets(G
.filename
, FILNAMSIZ
, stdin
);
1257 /* usually get \n here: better check for it */
1258 fnlen
= strlen(G
.filename
);
1259 if (lastchar(G
.filename
, fnlen
) == '\n')
1260 G
.filename
[--fnlen
] = '\0';
1261 } while (fnlen
== 0);
1262 #ifdef WIN32 /* WIN32 fgets( ... , stdin) returns OEM coded strings */
1263 _OEM_INTERN(G
.filename
);
1266 goto startover
; /* sorry for a goto */
1267 case 'A': /* dangerous option: force caps */
1268 G
.overwrite_mode
= OVERWRT_ALWAYS
;
1269 /* FALL THROUGH, extract */
1274 G
.overwrite_mode
= OVERWRT_NEVER
;
1275 /* FALL THROUGH, skip */
1278 skip_entry
= SKIP_Y_EXISTING
;
1281 Info(slide
, 1, ((char *)slide
,
1282 LoadFarString(InvalidResponse
), *G
.answerbuf
));
1283 goto reprompt
; /* yet another goto? */
1284 } /* end switch (*answerbuf) */
1285 #endif /* ?WINDLL */
1286 } /* end if (query) */
1287 if (skip_entry
!= SKIP_NO
) {
1289 if (skip_entry
== SKIP_Y_EXISTING
) {
1290 /* report skipping of an existing entry */
1291 Info(slide
, 0, ((char *)slide
,
1292 ((IS_OVERWRT_NONE
|| !uO
.uflag
|| renamed
) ?
1293 "Target file exists.\nSkipping %s\n" :
1294 "Target file newer.\nSkipping %s\n"),
1295 FnFilter1(G
.filename
)));
1300 } /* end if (extracting to disk) */
1303 if ((G
.statreportcb
!= NULL
) &&
1304 (*G
.statreportcb
)(__G__ UZ_ST_START_EXTRACT
, G
.zipfn
,
1305 G
.filename
, NULL
)) {
1306 return IZ_CTRLC
; /* cancel operation by user request */
1309 #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
1313 G
.filenote_slot
= i
;
1316 if ((error
= extract_or_test_member(__G
)) != PK_COOL
) {
1317 if (error
> error_in_archive
)
1318 error_in_archive
= error
; /* ...and keep going */
1320 if (G
.disk_full
> 1 || error_in_archive
== IZ_CTRLC
) {
1322 if (G
.disk_full
> 1) {
1324 return error_in_archive
; /* (unless disk full) */
1328 if ((G
.statreportcb
!= NULL
) &&
1329 (*G
.statreportcb
)(__G__ UZ_ST_FINISH_MEMBER
, G
.zipfn
,
1330 G
.filename
, (zvoid
*)&G
.lrec
.ucsize
)) {
1331 return IZ_CTRLC
; /* cancel operation by user request */
1334 #ifdef MACOS /* MacOS is no preemptive OS, thus call event-handling by hand */
1337 } /* end for-loop (i: files in current block) */
1339 return error_in_archive
;
1341 } /* end function extract_or_test_entrylist() */
1347 /***************************************/
1348 /* Function extract_or_test_member() */
1349 /***************************************/
1351 static int extract_or_test_member(__G
) /* return PK-type error code */
1354 char *nul
="[empty] ", *txt
="[text] ", *bin
="[binary]";
1356 char *ebc
="[ebcdic]";
1359 int r
, error
=PK_COOL
;
1360 #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
1363 # define wsize WSIZE
1367 /*---------------------------------------------------------------------------
1368 Initialize variables, buffers, etc.
1369 ---------------------------------------------------------------------------*/
1372 G
.bitbuf
= 0L; /* unreduce and unshrink only */
1375 G
.crc32val
= CRCVAL_INITIAL
;
1378 /* if file came from Unix and is a symbolic link and we are extracting
1379 * to disk, prepare to restore the link */
1380 if (S_ISLNK(G
.pInfo
->file_attr
) &&
1381 (G
.pInfo
->hostnum
== UNIX_
|| G
.pInfo
->hostnum
== ATARI_
||
1382 G
.pInfo
->hostnum
== BEOS_
) &&
1383 !uO
.tflag
&& !uO
.cflag
&& (G
.lrec
.ucsize
> 0))
1387 #endif /* SYMLINKS */
1391 Info(slide
, 0, ((char *)slide
, LoadFarString(ExtractMsg
), "test",
1392 FnFilter1(G
.filename
), "", ""));
1395 if (uO
.cflag
&& !G
.redirect_data
)
1400 #if (defined(OS2) && defined(__IBMC__) && (__IBMC__ >= 200))
1401 G
.outfile
= freopen("", "wb", stdout
); /* VAC++ ignores setmode */
1405 #ifdef DOS_FLX_NLM_OS2_W32
1406 #if (defined(__HIGHC__) && !defined(FLEXOS))
1407 setmode(G
.outfile
, _BINARY
);
1408 #else /* !(defined(__HIGHC__) && !defined(FLEXOS)) */
1409 setmode(fileno(G
.outfile
), O_BINARY
);
1410 #endif /* ?(defined(__HIGHC__) && !defined(FLEXOS)) */
1411 # define NEWLINE "\r\n"
1412 #else /* !DOS_FLX_NLM_OS2_W32 */
1413 # define NEWLINE "\n"
1414 #endif /* ?DOS_FLX_NLM_OS2_W32 */
1416 if (open_outfile(__G
)) /* VMS: required even for stdout! */
1419 } else if (open_outfile(__G
))
1423 /*---------------------------------------------------------------------------
1425 ---------------------------------------------------------------------------*/
1427 defer_leftover_input(__G
); /* so NEXTBYTE bounds check will work */
1428 switch (G
.lrec
.compression_method
) {
1430 if (!uO
.tflag
&& QCOND2
) {
1432 if (G
.symlnk
) /* can also be deflated, but rarer... */
1433 Info(slide
, 0, ((char *)slide
, LoadFarString(ExtractMsg
),
1434 "link", FnFilter1(G
.filename
), "", ""));
1436 #endif /* SYMLINKS */
1437 Info(slide
, 0, ((char *)slide
, LoadFarString(ExtractMsg
),
1438 "extract", FnFilter1(G
.filename
),
1439 (uO
.aflag
!= 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1440 "" : (G
.lrec
.ucsize
== 0L? nul
: (G
.pInfo
->textfile
? txt
:
1441 bin
)), uO
.cflag
? NEWLINE
: ""));
1443 #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
1444 if (G
.redirect_slide
) {
1445 wsize
= G
.redirect_size
; redirSlide
= G
.redirect_buffer
;
1447 wsize
= WSIZE
; redirSlide
= slide
;
1450 G
.outptr
= redirSlide
;
1452 while ((b
= NEXTBYTE
) != EOF
) {
1453 *G
.outptr
++ = (uch
)b
;
1454 if (++G
.outcnt
== wsize
) {
1455 error
= flush(__G__ redirSlide
, G
.outcnt
, 0);
1456 G
.outptr
= redirSlide
;
1458 if (error
!= PK_COOL
|| G
.disk_full
) break;
1461 if (G
.outcnt
) /* flush final (partial) buffer */
1462 flush(__G__ redirSlide
, G
.outcnt
, 0);
1468 if (!uO
.tflag
&& QCOND2
) {
1469 Info(slide
, 0, ((char *)slide
, LoadFarString(ExtractMsg
),
1470 LoadFarStringSmall(Unshrink
), FnFilter1(G
.filename
),
1471 (uO
.aflag
!= 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1472 "" : (G
.pInfo
->textfile
? txt
: bin
), uO
.cflag
? NEWLINE
: ""));
1474 if ((r
= unshrink(__G
)) != PK_COOL
) {
1476 if ((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
))
1477 Info(slide
, 0x401, ((char *)slide
,
1478 LoadFarStringSmall(ErrUnzipFile
),
1479 LoadFarString(NotEnoughMem
),
1480 LoadFarStringSmall2(Unshrink
),
1481 FnFilter1(G
.filename
)));
1483 Info(slide
, 0x401, ((char *)slide
,
1484 LoadFarStringSmall(ErrUnzipNoFile
),
1485 LoadFarString(NotEnoughMem
),
1486 LoadFarStringSmall2(Unshrink
)));
1491 #endif /* !LZW_CLEAN */
1493 #ifndef COPYRIGHT_CLEAN
1498 if (!uO
.tflag
&& QCOND2
) {
1499 Info(slide
, 0, ((char *)slide
, LoadFarString(ExtractMsg
),
1500 "unreduc", FnFilter1(G
.filename
),
1501 (uO
.aflag
!= 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1502 "" : (G
.pInfo
->textfile
? txt
: bin
), uO
.cflag
? NEWLINE
: ""));
1504 if ((r
= unreduce(__G
)) != PK_COOL
) {
1505 /* unreduce() returns only PK_COOL, PK_DISK, or IZ_CTRLC */
1509 #endif /* !COPYRIGHT_CLEAN */
1512 if (!uO
.tflag
&& QCOND2
) {
1513 Info(slide
, 0, ((char *)slide
, LoadFarString(ExtractMsg
),
1514 "explod", FnFilter1(G
.filename
),
1515 (uO
.aflag
!= 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1516 "" : (G
.pInfo
->textfile
? txt
: bin
), uO
.cflag
? NEWLINE
: ""));
1518 if (((r
= explode(__G
)) != 0) && (r
!= 5)) { /* treat 5 specially */
1520 if ((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
))
1521 Info(slide
, 0x401, ((char *)slide
,
1522 LoadFarStringSmall(ErrUnzipFile
), r
== 3?
1523 LoadFarString(NotEnoughMem
) :
1524 LoadFarString(InvalidComprData
),
1525 LoadFarStringSmall2(Explode
),
1526 FnFilter1(G
.filename
)));
1528 Info(slide
, 0x401, ((char *)slide
,
1529 LoadFarStringSmall(ErrUnzipNoFile
), r
== 3?
1530 LoadFarString(NotEnoughMem
) :
1531 LoadFarString(InvalidComprData
),
1532 LoadFarStringSmall2(Explode
)));
1533 error
= (r
== 3)? PK_MEM3
: PK_ERR
;
1539 int warning
= ((ulg
)G
.used_csize
<= G
.lrec
.csize
);
1541 if ((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
))
1542 Info(slide
, 0x401, ((char *)slide
, LoadFarString(LengthMsg
),
1543 "", warning
? "warning" : "error", G
.used_csize
,
1544 G
.lrec
.ucsize
, warning
? " " : "", G
.lrec
.csize
,
1545 " [", FnFilter1(G
.filename
), "]"));
1547 Info(slide
, 0x401, ((char *)slide
, LoadFarString(LengthMsg
),
1548 "\n", warning
? "warning" : "error", G
.used_csize
,
1549 G
.lrec
.ucsize
, warning
? " ":"", G
.lrec
.csize
,
1551 error
= warning
? PK_WARN
: PK_ERR
;
1557 #ifdef USE_DEFLATE64
1560 if (!uO
.tflag
&& QCOND2
) {
1561 Info(slide
, 0, ((char *)slide
, LoadFarString(ExtractMsg
),
1562 "inflat", FnFilter1(G
.filename
),
1563 (uO
.aflag
!= 1 /* && G.pInfo->textfile==G.pInfo->textmode */)?
1564 "" : (G
.pInfo
->textfile
? txt
: bin
), uO
.cflag
? NEWLINE
: ""));
1566 #ifndef USE_ZLIB /* zlib's function is called inflate(), too */
1567 # define UZinflate inflate
1569 if ((r
= UZinflate(__G__
1570 (G
.lrec
.compression_method
== ENHDEFLATED
)))
1573 if ((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
))
1574 Info(slide
, 0x401, ((char *)slide
,
1575 LoadFarStringSmall(ErrUnzipFile
), r
== 3?
1576 LoadFarString(NotEnoughMem
) :
1577 LoadFarString(InvalidComprData
),
1578 LoadFarStringSmall2(Inflate
),
1579 FnFilter1(G
.filename
)));
1581 Info(slide
, 0x401, ((char *)slide
,
1582 LoadFarStringSmall(ErrUnzipNoFile
), r
== 3?
1583 LoadFarString(NotEnoughMem
) :
1584 LoadFarString(InvalidComprData
),
1585 LoadFarStringSmall2(Inflate
)));
1586 error
= (r
== 3)? PK_MEM3
: PK_ERR
;
1593 default: /* should never get to this point */
1594 Info(slide
, 0x401, ((char *)slide
,
1595 LoadFarString(FileUnknownCompMethod
), FnFilter1(G
.filename
)));
1596 /* close and delete file before return? */
1600 } /* end switch (compression method) */
1602 /*---------------------------------------------------------------------------
1603 Close the file and set its date and time (not necessarily in that order),
1604 and make sure the CRC checked out OK. Logical-AND the CRC for 64-bit
1605 machines (redundant on 32-bit machines).
1606 ---------------------------------------------------------------------------*/
1608 #ifdef VMS /* VMS: required even for stdout! (final flush) */
1609 if (!uO
.tflag
) /* don't close NULL file */
1613 if (!uO
.tflag
&& (!uO
.cflag
|| G
.redirect_data
)) {
1614 if (G
.redirect_data
)
1620 if (!uO
.tflag
&& !uO
.cflag
) /* don't close NULL file or stdout */
1625 /* GRR: CONVERT close_outfile() TO NON-VOID: CHECK FOR ERRORS! */
1628 if (G
.disk_full
) { /* set by flush() */
1629 if (G
.disk_full
> 1) {
1630 #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
1631 /* delete the incomplete file if we can */
1632 if (unlink(G
.filename
) != 0)
1633 Trace((stderr
, "extract.c: could not delete %s\n",
1634 FnFilter1(G
.filename
)));
1636 /* warn user about the incomplete file */
1637 Info(slide
, 0x421, ((char *)slide
, LoadFarString(FileTruncated
),
1638 FnFilter1(G
.filename
)));
1646 if (error
> PK_WARN
) {/* don't print redundant CRC error if error already */
1650 if (G
.crc32val
!= G
.lrec
.crc32
) {
1651 /* if quiet enough, we haven't output the filename yet: do it */
1652 if ((uO
.tflag
&& uO
.qflag
) || (!uO
.tflag
&& !QCOND2
))
1653 Info(slide
, 0x401, ((char *)slide
, "%-22s ",
1654 FnFilter1(G
.filename
)));
1655 Info(slide
, 0x401, ((char *)slide
, LoadFarString(BadCRC
), G
.crc32val
,
1658 if (G
.pInfo
->encrypted
)
1659 Info(slide
, 0x401, ((char *)slide
, LoadFarString(MaybeBadPasswd
)));
1662 } else if (uO
.tflag
) {
1664 if (G
.extra_field
) {
1665 if ((r
= TestExtraField(__G__ G
.extra_field
,
1666 G
.lrec
.extra_field_length
)) > error
)
1671 Info(slide
, 0, ((char *)slide
, " OK\n"));
1673 if (QCOND2
&& !error
) /* GRR: is stdout reset to text mode yet? */
1674 Info(slide
, 0, ((char *)slide
, "\n"));
1680 } /* end function extract_or_test_member() */
1688 /*******************************/
1689 /* Function TestExtraField() */
1690 /*******************************/
1692 static int TestExtraField(__G__ ef
, ef_len
)
1699 unsigned eb_cmpr_offs
= 0;
1702 /* we know the regular compressed file data tested out OK, or else we
1703 * wouldn't be here ==> print filename if any extra-field errors found
1705 while (ef_len
>= EB_HEADSIZE
) {
1706 ebID
= makeword(ef
);
1707 ebLen
= (unsigned)makeword(ef
+EB_LEN
);
1709 if (ebLen
> (ef_len
- EB_HEADSIZE
)) {
1710 /* Discovered some extra field inconsistency! */
1712 Info(slide
, 1, ((char *)slide
, "%-22s ",
1713 FnFilter1(G
.filename
)));
1714 Info(slide
, 1, ((char *)slide
, LoadFarString(InconsistEFlength
),
1715 ebLen
, (ef_len
- EB_HEADSIZE
)));
1727 eb_cmpr_offs
= EB_OS2_HLEN
;
1730 if (ebLen
>= EB_MAC3_HLEN
&&
1731 (makeword(ef
+(EB_HEADSIZE
+EB_FLGS_OFFS
))
1732 & EB_M3_FL_UNCMPR
) &&
1733 (makelong(ef
+EB_HEADSIZE
) == ebLen
- EB_MAC3_HLEN
))
1736 eb_cmpr_offs
= EB_MAC3_HLEN
;
1739 if (ebLen
>= EB_BEOS_HLEN
&&
1740 (*(ef
+(EB_HEADSIZE
+EB_FLGS_OFFS
)) & EB_BE_FL_UNCMPR
) &&
1741 (makelong(ef
+EB_HEADSIZE
) == ebLen
- EB_BEOS_HLEN
))
1744 eb_cmpr_offs
= EB_BEOS_HLEN
;
1747 if ((r
= test_compr_eb(__G__ ef
, ebLen
, eb_cmpr_offs
, NULL
))
1750 Info(slide
, 1, ((char *)slide
, "%-22s ",
1751 FnFilter1(G
.filename
)));
1754 Info(slide
, 1, ((char *)slide
,
1755 LoadFarString(TruncEAs
),
1756 ebLen
-(eb_cmpr_offs
+EB_CMPRHEADLEN
), "\n"));
1759 Info(slide
, 1, ((char *)slide
,
1760 LoadFarString(InvalidComprDataEAs
)));
1764 Info(slide
, 1, ((char *)slide
,
1765 LoadFarString(NotEnoughMemEAs
)));
1768 if ((r
& 0xff) != PK_ERR
)
1769 Info(slide
, 1, ((char *)slide
,
1770 LoadFarString(UnknErrorEAs
)));
1772 ush m
= (ush
)(r
>> 8);
1773 if (m
== DEFLATED
) /* GRR KLUDGE! */
1774 Info(slide
, 1, ((char *)slide
,
1775 LoadFarString(BadCRC_EAs
)));
1777 Info(slide
, 1, ((char *)slide
,
1778 LoadFarString(UnknComprMethodEAs
), m
));
1787 Trace((stderr
, "ebID: %i / ebLen: %u\n", ebID
, ebLen
));
1788 r
= ebLen
< EB_NTSD_L_LEN
? IZ_EF_TRUNC
:
1789 ((ef
[EB_HEADSIZE
+EB_NTSD_VERSION
] > EB_NTSD_MAX_VER
) ?
1790 (PK_WARN
| 0x4000) :
1791 test_compr_eb(__G__ ef
, ebLen
, EB_NTSD_L_LEN
, TEST_NTSD
));
1794 Info(slide
, 1, ((char *)slide
, "%-22s ",
1795 FnFilter1(G
.filename
)));
1798 Info(slide
, 1, ((char *)slide
,
1799 LoadFarString(TruncNTSD
),
1800 ebLen
-(EB_NTSD_L_LEN
+EB_CMPRHEADLEN
), "\n"));
1802 #if (defined(WIN32) && defined(NTSD_EAS))
1804 Info(slide
, 1, ((char *)slide
,
1805 LoadFarString(InvalidSecurityEAs
)));
1809 Info(slide
, 1, ((char *)slide
,
1810 LoadFarString(InvalidComprDataEAs
)));
1814 Info(slide
, 1, ((char *)slide
,
1815 LoadFarString(NotEnoughMemEAs
)));
1817 case (PK_WARN
| 0x4000):
1818 Info(slide
, 1, ((char *)slide
,
1819 LoadFarString(UnsuppNTSDVersEAs
),
1820 (int)ef
[EB_HEADSIZE
+EB_NTSD_VERSION
]));
1824 if ((r
& 0xff) != PK_ERR
)
1825 Info(slide
, 1, ((char *)slide
,
1826 LoadFarString(UnknErrorEAs
)));
1828 ush m
= (ush
)(r
>> 8);
1829 if (m
== DEFLATED
) /* GRR KLUDGE! */
1830 Info(slide
, 1, ((char *)slide
,
1831 LoadFarString(BadCRC_EAs
)));
1833 Info(slide
, 1, ((char *)slide
,
1834 LoadFarString(UnknComprMethodEAs
), m
));
1842 if (makelong(ef
+EB_HEADSIZE
) !=
1843 crc32(CRCVAL_INITIAL
, ef
+(EB_HEADSIZE
+4),
1845 Info(slide
, 1, ((char *)slide
,
1846 LoadFarString(BadCRC_EAs
)));
1862 ef_len
-= (ebLen
+ EB_HEADSIZE
);
1863 ef
+= (ebLen
+ EB_HEADSIZE
);
1867 Info(slide
, 0, ((char *)slide
, " OK\n"));
1871 } /* end function TestExtraField() */
1877 /******************************/
1878 /* Function test_compr_eb() */
1879 /******************************/
1882 static int test_compr_eb(
1886 unsigned compr_offset
,
1887 int (*test_uc_ebdata
)(__GPRO__ uch
*eb
, unsigned eb_size
,
1888 uch
*eb_ucptr
, ulg eb_ucsize
))
1890 static int test_compr_eb(__G__ eb
, eb_size
, compr_offset
, test_uc_ebdata
)
1894 unsigned compr_offset
;
1895 int (*test_uc_ebdata
)();
1902 if (compr_offset
< 4) /* field is not compressed: */
1903 return PK_OK
; /* do nothing and signal OK */
1905 if ((eb_size
< (EB_UCSIZE_P
+ 4)) ||
1906 ((eb_ucsize
= makelong(eb
+(EB_HEADSIZE
+EB_UCSIZE_P
))) > 0L &&
1907 eb_size
<= (compr_offset
+ EB_CMPRHEADLEN
)))
1908 return IZ_EF_TRUNC
; /* no compressed data! */
1910 if ((eb_ucptr
= (uch
*)malloc((extent
)eb_ucsize
)) == (uch
*)NULL
)
1913 r
= memextract(__G__ eb_ucptr
, eb_ucsize
,
1914 eb
+ (EB_HEADSIZE
+ compr_offset
),
1915 (ulg
)(eb_size
- compr_offset
));
1917 if (r
== PK_OK
&& test_uc_ebdata
!= NULL
)
1918 r
= (*test_uc_ebdata
)(__G__ eb
, eb_size
, eb_ucptr
, eb_ucsize
);
1923 } /* end function test_compr_eb() */
1931 /***************************/
1932 /* Function memextract() */
1933 /***************************/
1935 int memextract(__G__ tgt
, tgtsize
, src
, srcsize
) /* extract compressed */
1936 __GDEF
/* extra field block; */
1937 uch
*tgt
; /* return PK-type error */
1938 ulg tgtsize
; /* level */
1942 long old_csize
=G
.csize
;
1943 uch
*old_inptr
=G
.inptr
;
1944 int old_incnt
=G
.incnt
;
1947 ulg extra_field_crc
;
1950 method
= makeword(src
);
1951 extra_field_crc
= makelong(src
+2);
1953 /* compressed extra field exists completely in memory at this location: */
1954 G
.inptr
= (uch
*)src
+ (2 + 4); /* method and extra_field_crc */
1955 G
.incnt
= (int)(G
.csize
= (long)(srcsize
- (2 + 4)));
1958 G
.outsize
= tgtsize
;
1962 memcpy((char *)tgt
, (char *)G
.inptr
, (extent
)G
.incnt
);
1963 G
.outcnt
= G
.csize
; /* for CRC calculation */
1966 #ifdef USE_DEFLATE64
1970 if ((r
= UZinflate(__G__ (method
== ENHDEFLATED
))) != 0) {
1972 Info(slide
, 0x401, ((char *)slide
,
1973 LoadFarStringSmall(ErrUnzipNoFile
), r
== 3?
1974 LoadFarString(NotEnoughMem
) :
1975 LoadFarString(InvalidComprData
),
1976 LoadFarStringSmall2(Inflate
)));
1977 error
= (r
== 3)? PK_MEM3
: PK_ERR
;
1979 if (G
.outcnt
== 0L) /* inflate's final FLUSH sets outcnt */
1984 error
= PK_ERR
| ((int)method
<< 8);
1986 Info(slide
, 0x401, ((char *)slide
,
1987 LoadFarString(UnsupportedExtraField
), method
));
1988 error
= PK_ERR
; /* GRR: should be passed on up via SetEAs() */
1993 G
.inptr
= old_inptr
;
1994 G
.incnt
= old_incnt
;
1995 G
.csize
= old_csize
;
1999 register ulg crcval
= crc32(CRCVAL_INITIAL
, tgt
, (extent
)G
.outcnt
);
2001 if (crcval
!= extra_field_crc
) {
2003 error
= PK_ERR
| (DEFLATED
<< 8); /* kludge for now */
2005 Info(slide
, 0x401, ((char *)slide
,
2006 LoadFarString(BadExtraFieldCRC
), G
.zipfn
, crcval
,
2014 } /* end function memextract() */
2020 /*************************/
2021 /* Function memflush() */
2022 /*************************/
2024 int memflush(__G__ rawbuf
, size
)
2029 if (size
> G
.outsize
)
2030 /* Here, PK_DISK is a bit off-topic, but in the sense of marking
2031 "overflow of output space", its use may be tolerated. */
2032 return PK_DISK
; /* more data than output buffer can hold */
2036 memcpy((char *)G
.outbufptr
, (char *)rawbuf
, (extent
)size
);
2037 G
.outbufptr
+= (unsigned int)size
;
2043 } /* end function memflush() */
2049 #if (defined(VMS) || defined(VMS_TEXT_CONV))
2051 /************************************/
2052 /* Function extract_izvms_block() */
2053 /************************************/
2056 * Extracts block from p. If resulting length is less then needed, fill
2057 * extra space with corresponding bytes from 'init'.
2058 * Currently understands 3 formats of block compression:
2060 * - Compression of zero bytes to zero bits
2061 * - Deflation (see memextract())
2062 * The IZVMS block data is returned in malloc'd space.
2064 uch
*extract_izvms_block(__G__ ebdata
, size
, retlen
, init
, needlen
)
2072 uch
*ucdata
; /* Pointer to block allocated */
2074 unsigned usiz
, csiz
;
2076 cmptype
= (makeword(ebdata
+EB_IZVMS_FLGS
) & EB_IZVMS_BCMASK
);
2077 csiz
= size
- EB_IZVMS_HLEN
;
2078 usiz
= (cmptype
== EB_IZVMS_BCSTOR
?
2079 csiz
: makeword(ebdata
+EB_IZVMS_UCSIZ
));
2084 if ((ucdata
= (uch
*)malloc(MAX(needlen
, usiz
))) == NULL
)
2087 if (init
&& (usiz
< needlen
))
2088 memcpy((char *)ucdata
, (ZCONST
char *)init
, needlen
);
2092 case EB_IZVMS_BCSTOR
: /* The simplest case */
2093 memcpy(ucdata
, ebdata
+EB_IZVMS_HLEN
, usiz
);
2096 decompress_bits(ucdata
, usiz
, ebdata
+EB_IZVMS_HLEN
);
2098 case EB_IZVMS_BCDEFL
:
2099 memextract(__G__ ucdata
, (ulg
)usiz
,
2100 ebdata
+EB_IZVMS_HLEN
, (ulg
)csiz
);
2108 } /* end of extract_izvms_block */
2114 /********************************/
2115 /* Function decompress_bits() */
2116 /********************************/
2118 * Simple uncompression routine. The compression uses bit stream.
2119 * Compression scheme:
2122 * putbit(1),putbyte(byte)
2126 static void decompress_bits(outptr
, needlen
, bitptr
)
2127 uch
*outptr
; /* Pointer into output block */
2128 unsigned needlen
; /* Size of uncompressed block */
2129 ZCONST uch
*bitptr
; /* Pointer into compressed data */
2134 #define _FILL { bitbuf |= (*bitptr++) << bitcnt;\
2146 if ((bitcnt
-= 1) < 8)
2148 *outptr
++ = (uch
)bitbuf
;
2159 } /* end function decompress_bits() */
2161 #endif /* VMS || VMS_TEXT_CONV */
2167 /*************************/
2168 /* Function fnfilter() */ /* here instead of in list.c for SFX */
2169 /*************************/
2171 char *fnfilter(raw
, space
) /* convert name to safely printable form */
2175 #ifndef NATIVE /* ASCII: filter ANSI escape codes, etc. */
2176 ZCONST uch
*r
=(ZCONST uch
*)raw
;
2182 if (*r
== '/' || *r
== '.') {
2190 *s
++ = '^', *s
++ = (uch
)(64 + *r
++);
2194 for (i
= CLEN(r
); i
> 0; i
--)
2204 INTERN_TO_ISO((char *)space
, (char *)space
); /* translate to ANSI */
2207 /* Win9x console always uses OEM character coding, and
2208 WinNT console is set to OEM charset by default, too */
2209 INTERN_TO_OEM((char *)space
, (char *)space
);
2211 #endif /* ?WINDLL */
2213 return (char *)space
;
2215 #else /* NATIVE: EBCDIC or whatever */
2219 } /* end function fnfilter() */
2225 #ifdef SET_DIR_ATTRIB
2226 /* must sort saved directories so can set perms from bottom up */
2228 /************************/
2229 /* Function dircomp() */
2230 /************************/
2232 static int dircomp(a
, b
) /* used by qsort(); swiped from Zip */
2233 ZCONST zvoid
*a
, *b
;
2235 /* order is significant: this sorts in reverse order (deepest first) */
2236 return strcmp((*(dirtime
**)b
)->fn
, (*(dirtime
**)a
)->fn
);
2237 /* return namecmp((*(dirtime **)b)->fn, (*(dirtime **)a)->fn); */
2242 #if 0 /* not used in Unix, but maybe for future OSes? */
2244 /************************/
2245 /* Function namecmp() */
2246 /************************/
2248 static int namecmp(s1
, s2
) /* [not] used by dircomp(); swiped from Zip */
2249 ZCONST
char *s1
, *s2
;
2254 d
= (int)(uch
)case_map(*s1
)
2255 - (int)(uch
)case_map(*s2
);
2257 if (d
|| *s1
== 0 || *s2
== 0)
2266 #endif /* SET_DIR_ATTRIB */