Update install docs
[carla.git] / data / windows / unzipfx-carla-control / fileio.c
blobba0a1d00f5788ec5360c00d1db3e8431bcdc3764
1 /*
2 Copyright (c) 1990-2009 Info-ZIP. All rights reserved.
4 See the accompanying file LICENSE, version 2009-Jan-02 or later
5 (the contents of which are also included in unzip.h) for terms of use.
6 If, for some reason, all these files are missing, the Info-ZIP license
7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
8 */
9 /*---------------------------------------------------------------------------
11 fileio.c
13 This file contains routines for doing direct but relatively generic input/
14 output, file-related sorts of things, plus some miscellaneous stuff. Most
15 of the stuff has to do with opening, closing, reading and/or writing files.
17 Contains: open_input_file()
18 open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM)
19 undefer_input()
20 defer_leftover_input()
21 readbuf()
22 readbyte()
23 fillinbuf()
24 seek_zipf()
25 flush() (non-VMS)
26 is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only)
27 disk_error() (non-VMS)
28 UzpMessagePrnt()
29 UzpMessageNull() (DLL only)
30 UzpInput()
31 UzpMorePause()
32 UzpPassword() (non-WINDLL)
33 handler()
34 dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS)
35 check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
36 do_string()
37 makeword()
38 makelong()
39 makeint64()
40 fzofft()
41 str2iso() (CRYPT && NEED_STR2ISO, only)
42 str2oem() (CRYPT && NEED_STR2OEM, only)
43 memset() (ZMEM only)
44 memcpy() (ZMEM only)
45 zstrnicmp() (NO_STRNICMP only)
46 zstat() (REGULUS only)
47 plastchar() (_MBCS only)
48 uzmbclen() (_MBCS && NEED_UZMBCLEN, only)
49 uzmbschr() (_MBCS && NEED_UZMBSCHR, only)
50 uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only)
51 fLoadFarString() (SMALL_MEM only)
52 fLoadFarStringSmall() (SMALL_MEM only)
53 fLoadFarStringSmall2() (SMALL_MEM only)
54 zfstrcpy() (SMALL_MEM only)
55 zfstrcmp() (SMALL_MEM && !(SFX || FUNZIP) only)
57 ---------------------------------------------------------------------------*/
60 #define __FILEIO_C /* identifies this source module */
61 #define UNZIP_INTERNAL
62 #include "unzip.h"
63 #ifdef WINDLL
64 # ifdef POCKET_UNZIP
65 # include "wince/intrface.h"
66 # else
67 # include "windll/windll.h"
68 # endif
69 # include <setjmp.h>
70 #endif
71 #include "crc32.h"
72 #include "crypt.h"
73 #include "ttyio.h"
75 /* setup of codepage conversion for decryption passwords */
76 #if CRYPT
77 # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
78 # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
79 # endif
80 # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
81 # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
82 # endif
83 #endif
84 #include "ebcdic.h" /* definition/initialization of ebcdic[] */
88 Note: Under Windows, the maximum size of the buffer that can be used
89 with any of the *printf calls is 16,384, so win_fprintf was used to
90 feed the fprintf clone no more than 16K chunks at a time. This should
91 be valid for anything up to 64K (and probably beyond, assuming your
92 buffers are that big).
94 #ifdef WINDLL
95 # define WriteError(buf,len,strm) \
96 (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
97 #else /* !WINDLL */
98 # ifdef USE_FWRITE
99 # define WriteError(buf,len,strm) \
100 ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
101 # else
102 # define WriteError(buf,len,strm) \
103 ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
104 # endif
105 #endif /* ?WINDLL */
108 2005-09-16 SMS.
109 On VMS, when output is redirected to a file, as in a command like
110 "PIPE UNZIP -v > X.OUT", the output file is created with VFC record
111 format, and multiple calls to write() or fwrite() will produce multiple
112 records, even when there's no newline terminator in the buffer.
113 The result is unsightly output with spurious newlines. Using fprintf()
114 instead of write() here, and disabling a fflush(stdout) in UzpMessagePrnt()
115 below, together seem to solve the problem.
117 According to the C RTL manual, "The write and decc$record_write
118 functions always generate at least one record." Also, "[T]he fwrite
119 function always generates at least <number_items> records." So,
120 "fwrite(buf, len, 1, strm)" is much better ("1" record) than
121 "fwrite(buf, 1, len, strm)" ("len" (1-character) records, _really_
122 ugly), but neither is better than write(). Similarly, "The fflush
123 function always generates a record if there is unwritten data in the
124 buffer." Apparently fprintf() buffers the stuff somewhere, and puts
125 out a record (only) when it sees a newline.
127 #ifdef VMS
128 # define WriteTxtErr(buf,len,strm) \
129 ((extent)fprintf(strm, "%.*s", len, buf) != (extent)(len))
130 #else
131 # define WriteTxtErr(buf,len,strm) WriteError(buf,len,strm)
132 #endif
134 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
135 static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink));
136 #endif
137 #ifdef VMS_TEXT_CONV
138 static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len));
139 #endif
140 static int disk_error OF((__GPRO));
143 /****************************/
144 /* Strings used in fileio.c */
145 /****************************/
147 static ZCONST char Far CannotOpenZipfile[] =
148 "error: cannot open zipfile [ %s ]\n %s\n";
150 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
151 #if (!defined(TANDEM))
152 #if (defined(ATH_BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32))
153 static ZCONST char Far CannotDeleteOldFile[] =
154 "error: cannot delete old %s\n %s\n";
155 #ifdef UNIXBACKUP
156 static ZCONST char Far CannotRenameOldFile[] =
157 "error: cannot rename old %s\n %s\n";
158 static ZCONST char Far BackupSuffix[] = "~";
159 #endif
160 #endif /* ATH_BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */
161 #ifdef NOVELL_BUG_FAILSAFE
162 static ZCONST char Far NovellBug[] =
163 "error: %s: stat() says does not exist, but fopen() found anyway\n";
164 #endif
165 static ZCONST char Far CannotCreateFile[] =
166 "error: cannot create %s\n %s\n";
167 #endif /* !TANDEM */
168 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
170 static ZCONST char Far ReadError[] = "error: zipfile read error\n";
171 static ZCONST char Far FilenameTooLongTrunc[] =
172 "warning: filename too long--truncating.\n";
173 #ifdef UNICODE_SUPPORT
174 static ZCONST char Far UFilenameTooLongTrunc[] =
175 "warning: Converted unicode filename too long--truncating.\n";
176 #endif
177 static ZCONST char Far ExtraFieldTooLong[] =
178 "warning: extra field too long (%d). Ignoring...\n";
180 #ifdef WINDLL
181 static ZCONST char Far DiskFullQuery[] =
182 "%s: write error (disk full?).\n";
183 #else
184 static ZCONST char Far DiskFullQuery[] =
185 "%s: write error (disk full?). Continue? (y/n/^C) ";
186 static ZCONST char Far ZipfileCorrupt[] =
187 "error: zipfile probably corrupt (%s)\n";
188 # ifdef SYMLINKS
189 static ZCONST char Far FileIsSymLink[] =
190 "%s exists and is a symbolic link%s.\n";
191 # endif
192 # ifdef MORE
193 static ZCONST char Far MorePrompt[] = "--More--(%lu)";
194 # endif
195 static ZCONST char Far QuitPrompt[] =
196 "--- Press `Q' to quit, or any other key to continue ---";
197 static ZCONST char Far HidePrompt[] = /* "\r \r"; */
198 "\r \r";
199 # if CRYPT
200 # ifdef MACOS
201 /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
202 static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
203 # else
204 static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
205 # endif
206 static ZCONST char Far PasswPrompt2[] = "Enter password: ";
207 static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
208 # endif /* CRYPT */
209 #endif /* !WINDLL */
215 /******************************/
216 /* Function open_input_file() */
217 /******************************/
219 int open_input_file(__G) /* return 1 if open failed */
220 __GDEF
223 * open the zipfile for reading and in BINARY mode to prevent cr/lf
224 * translation, which would corrupt the bitstreams
227 #ifdef VMS
228 G.zipfd = open(G.zipfn, O_RDONLY, 0, OPNZIP_RMS_ARGS);
229 #else /* !VMS */
230 #ifdef MACOS
231 G.zipfd = open(G.zipfn, 0);
232 #else /* !MACOS */
233 #ifdef CMS_MVS
234 G.zipfd = vmmvs_open_infile(__G);
235 #else /* !CMS_MVS */
236 #ifdef USE_STRM_INPUT
237 G.zipfd = fopen(G.zipfn, FOPR);
238 #else /* !USE_STRM_INPUT */
239 G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);
240 #endif /* ?USE_STRM_INPUT */
241 #endif /* ?CMS_MVS */
242 #endif /* ?MACOS */
243 #endif /* ?VMS */
245 #ifdef USE_STRM_INPUT
246 if (G.zipfd == NULL)
247 #else
248 /* if (G.zipfd < 0) */ /* no good for Windows CE port */
249 if (G.zipfd == -1)
250 #endif
252 Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
253 G.zipfn, strerror(errno)));
254 return 1;
256 return 0;
258 } /* end function open_input_file() */
263 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
264 #if (!defined(TANDEM))
266 /***************************/
267 /* Function open_outfile() */
268 /***************************/
270 int open_outfile(__G) /* return 1 if fail */
271 __GDEF
273 #ifdef DLL
274 if (G.redirect_data)
275 return (redirect_outfile(__G) == FALSE);
276 #endif
277 #ifdef QDOS
278 QFilename(__G__ G.filename);
279 #endif
280 #if (defined(DOS_FLX_NLM_OS2_W32) || defined(ATH_BEO_THS_UNX))
281 #ifdef BORLAND_STAT_BUG
282 /* Borland 5.0's stat() barfs if the filename has no extension and the
283 * file doesn't exist. */
284 if (access(G.filename, 0) == -1) {
285 FILE *tmp = fopen(G.filename, "wb+");
287 /* file doesn't exist, so create a dummy file to keep stat() from
288 * failing (will be over-written anyway) */
289 fputc('0', tmp); /* just to have something in the file */
290 fclose(tmp);
292 #endif /* BORLAND_STAT_BUG */
293 #ifdef SYMLINKS
294 if (SSTAT(G.filename, &G.statbuf) == 0 ||
295 lstat(G.filename, &G.statbuf) == 0)
296 #else
297 if (SSTAT(G.filename, &G.statbuf) == 0)
298 #endif /* ?SYMLINKS */
300 Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n",
301 FnFilter1(G.filename)));
302 #ifdef UNIXBACKUP
303 if (uO.B_flag) { /* do backup */
304 char *tname;
305 z_stat tmpstat;
306 int blen, flen, tlen;
308 blen = strlen(BackupSuffix);
309 flen = strlen(G.filename);
310 tlen = flen + blen + 6; /* includes space for 5 digits */
311 if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */
312 tname = (char *)malloc(FILNAMSIZ);
313 if (tname == NULL)
314 return 1; /* in case we run out of space */
315 tlen = FILNAMSIZ - 1 - blen;
316 strcpy(tname, G.filename); /* make backup name */
317 tname[tlen] = '\0';
318 if (flen > tlen) flen = tlen;
319 tlen = FILNAMSIZ;
320 } else {
321 tname = (char *)malloc(tlen);
322 if (tname == NULL)
323 return 1; /* in case we run out of space */
324 strcpy(tname, G.filename); /* make backup name */
326 strcpy(tname+flen, BackupSuffix);
328 if (IS_OVERWRT_ALL) {
329 /* If there is a previous backup file, delete it,
330 * otherwise the following rename operation may fail.
332 if (SSTAT(tname, &tmpstat) == 0)
333 unlink(tname);
334 } else {
335 /* Check if backupname exists, and, if it's true, try
336 * appending numbers of up to 5 digits (or the maximum
337 * "unsigned int" number on 16-bit systems) to the
338 * BackupSuffix, until an unused name is found.
340 unsigned maxtail, i;
341 char *numtail = tname + flen + blen;
343 /* take account of the "unsigned" limit on 16-bit systems: */
344 maxtail = ( ((~0) >= 99999L) ? 99999 : (~0) );
345 switch (tlen - flen - blen - 1) {
346 case 4: maxtail = 9999; break;
347 case 3: maxtail = 999; break;
348 case 2: maxtail = 99; break;
349 case 1: maxtail = 9; break;
350 case 0: maxtail = 0; break;
352 /* while filename exists */
353 for (i = 0; (i < maxtail) && (SSTAT(tname, &tmpstat) == 0);)
354 sprintf(numtail,"%u", ++i);
357 if (rename(G.filename, tname) != 0) { /* move file */
358 Info(slide, 0x401, ((char *)slide,
359 LoadFarString(CannotRenameOldFile),
360 FnFilter1(G.filename), strerror(errno)));
361 free(tname);
362 return 1;
364 Trace((stderr, "open_outfile: %s now renamed into %s\n",
365 FnFilter1(G.filename), FnFilter2(tname)));
366 free(tname);
367 } else
368 #endif /* UNIXBACKUP */
370 #ifdef DOS_FLX_OS2_W32
371 if (!(G.statbuf.st_mode & S_IWRITE)) {
372 Trace((stderr,
373 "open_outfile: existing file %s is read-only\n",
374 FnFilter1(G.filename)));
375 chmod(G.filename, S_IREAD | S_IWRITE);
376 Trace((stderr, "open_outfile: %s now writable\n",
377 FnFilter1(G.filename)));
379 #endif /* DOS_FLX_OS2_W32 */
380 #ifdef NLM
381 /* Give the file read/write permission (non-POSIX shortcut) */
382 chmod(G.filename, 0);
383 #endif /* NLM */
384 if (unlink(G.filename) != 0) {
385 Info(slide, 0x401, ((char *)slide,
386 LoadFarString(CannotDeleteOldFile),
387 FnFilter1(G.filename), strerror(errno)));
388 return 1;
390 Trace((stderr, "open_outfile: %s now deleted\n",
391 FnFilter1(G.filename)));
394 #endif /* DOS_FLX_NLM_OS2_W32 || ATH_BEO_THS_UNX */
395 #ifdef RISCOS
396 if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
397 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
398 FnFilter1(G.filename), strerror(errno)));
399 return 1;
401 #endif /* RISCOS */
402 #ifdef TOPS20
403 char *tfilnam;
405 if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
406 return 1;
407 strcpy(tfilnam, G.filename);
408 upper(tfilnam);
409 enquote(tfilnam);
410 if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
411 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
412 tfilnam, strerror(errno)));
413 free(tfilnam);
414 return 1;
416 free(tfilnam);
417 #else /* !TOPS20 */
418 #ifdef MTS
419 if (uO.aflag)
420 G.outfile = zfopen(G.filename, FOPWT);
421 else
422 G.outfile = zfopen(G.filename, FOPW);
423 if (G.outfile == (FILE *)NULL) {
424 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
425 FnFilter1(G.filename), strerror(errno)));
426 return 1;
428 #else /* !MTS */
429 #ifdef DEBUG
430 Info(slide, 1, ((char *)slide,
431 "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename)));
432 if ((G.outfile = zfopen(G.filename, FOPR)) == (FILE *)NULL)
433 Info(slide, 1, ((char *)slide,
434 "open_outfile: fopen(%s) for reading failed: does not exist\n",
435 FnFilter1(G.filename)));
436 else {
437 Info(slide, 1, ((char *)slide,
438 "open_outfile: fopen(%s) for reading succeeded: file exists\n",
439 FnFilter1(G.filename)));
440 fclose(G.outfile);
442 #endif /* DEBUG */
443 #ifdef NOVELL_BUG_FAILSAFE
444 if (G.dne && ((G.outfile = zfopen(G.filename, FOPR)) != (FILE *)NULL)) {
445 Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
446 FnFilter1(G.filename)));
447 fclose(G.outfile);
448 return 1; /* with "./" fix in checkdir(), should never reach here */
450 #endif /* NOVELL_BUG_FAILSAFE */
451 Trace((stderr, "open_outfile: doing fopen(%s) for writing\n",
452 FnFilter1(G.filename)));
454 #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)
455 mode_t umask_sav = umask(0077);
456 #endif
457 #if defined(SYMLINKS) || defined(QLZIP)
458 /* These features require the ability to re-read extracted data from
459 the output files. Output files are created with Read&Write access.
461 G.outfile = zfopen(G.filename, FOPWR);
462 #else
463 G.outfile = zfopen(G.filename, FOPW);
464 #endif
465 #if defined(ATH_BE_UNX) || defined(AOS_VS) || defined(QDOS) || defined(TANDEM)
466 umask(umask_sav);
467 #endif
469 if (G.outfile == (FILE *)NULL) {
470 Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
471 FnFilter1(G.filename), strerror(errno)));
472 return 1;
474 Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n",
475 FnFilter1(G.filename)));
476 #endif /* !MTS */
477 #endif /* !TOPS20 */
479 #ifdef USE_FWRITE
480 #ifdef DOS_NLM_OS2_W32
481 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
482 setbuf(G.outfile, (char *)NULL); /* make output unbuffered */
483 #else /* !DOS_NLM_OS2_W32 */
484 #ifndef RISCOS
485 #ifdef _IOFBF /* make output fully buffered (works just about like write()) */
486 setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
487 #else
488 setbuf(G.outfile, (char *)slide);
489 #endif
490 #endif /* !RISCOS */
491 #endif /* ?DOS_NLM_OS2_W32 */
492 #endif /* USE_FWRITE */
493 #ifdef OS2_W32
494 /* preallocate the final file size to prevent file fragmentation */
495 SetFileSize(G.outfile, G.lrec.ucsize);
496 #endif
497 return 0;
499 } /* end function open_outfile() */
501 #endif /* !TANDEM */
502 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
509 * These functions allow NEXTBYTE to function without needing two bounds
510 * checks. Call defer_leftover_input() if you ever have filled G.inbuf
511 * by some means other than readbyte(), and you then want to start using
512 * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
513 * undefer_input(). For example, extract_or_test_member brackets its
514 * central section that does the decompression with these two functions.
515 * If you need to check the number of bytes remaining in the current
516 * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
519 /****************************/
520 /* function undefer_input() */
521 /****************************/
523 void undefer_input(__G)
524 __GDEF
526 if (G.incnt > 0)
527 G.csize += G.incnt;
528 if (G.incnt_leftover > 0) {
529 /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
530 * This condition was checked when G.incnt_leftover was set > 0 in
531 * defer_leftover_input(), and it is NOT allowed to touch G.csize
532 * before calling undefer_input() when (G.incnt_leftover > 0)
533 * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
535 G.incnt = G.incnt_leftover + (int)G.csize;
536 G.inptr = G.inptr_leftover - (int)G.csize;
537 G.incnt_leftover = 0;
538 } else if (G.incnt < 0)
539 G.incnt = 0;
540 } /* end function undefer_input() */
546 /***********************************/
547 /* function defer_leftover_input() */
548 /***********************************/
550 void defer_leftover_input(__G)
551 __GDEF
553 if ((zoff_t)G.incnt > G.csize) {
554 /* (G.csize < MAXINT), we can safely cast it to int !! */
555 if (G.csize < 0L)
556 G.csize = 0L;
557 G.inptr_leftover = G.inptr + (int)G.csize;
558 G.incnt_leftover = G.incnt - (int)G.csize;
559 G.incnt = (int)G.csize;
560 } else
561 G.incnt_leftover = 0;
562 G.csize -= G.incnt;
563 } /* end function defer_leftover_input() */
569 /**********************/
570 /* Function readbuf() */
571 /**********************/
573 unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */
574 __GDEF
575 char *buf;
576 register unsigned size;
578 register unsigned count;
579 unsigned n;
581 n = size;
582 while (size) {
583 if (G.incnt <= 0) {
584 if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)
585 return (n-size);
586 else if (G.incnt < 0) {
587 /* another hack, but no real harm copying same thing twice */
588 (*G.message)((zvoid *)&G,
589 (uch *)LoadFarString(ReadError), /* CANNOT use slide */
590 (ulg)strlen(LoadFarString(ReadError)), 0x401);
591 return 0; /* discarding some data; better than lock-up */
593 /* buffer ALWAYS starts on a block boundary: */
594 G.cur_zipfile_bufstart += INBUFSIZ;
595 G.inptr = G.inbuf;
597 count = MIN(size, (unsigned)G.incnt);
598 memcpy(buf, G.inptr, count);
599 buf += count;
600 G.inptr += count;
601 G.incnt -= count;
602 size -= count;
604 return n;
606 } /* end function readbuf() */
612 /***********************/
613 /* Function readbyte() */
614 /***********************/
616 int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */
617 __GDEF
619 if (G.mem_mode)
620 return EOF;
621 if (G.csize <= 0) {
622 G.csize--; /* for tests done after exploding */
623 G.incnt = 0;
624 return EOF;
626 if (G.incnt <= 0) {
627 if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {
628 return EOF;
629 } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */
630 /* another hack, but no real harm copying same thing twice */
631 (*G.message)((zvoid *)&G,
632 (uch *)LoadFarString(ReadError),
633 (ulg)strlen(LoadFarString(ReadError)), 0x401);
634 echon();
635 #ifdef WINDLL
636 longjmp(dll_error_return, 1);
637 #else
638 DESTROYGLOBALS();
639 EXIT(PK_BADERR); /* totally bailing; better than lock-up */
640 #endif
642 G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
643 G.inptr = G.inbuf;
644 defer_leftover_input(__G); /* decrements G.csize */
647 #if CRYPT
648 if (G.pInfo->encrypted) {
649 uch *p;
650 int n;
652 /* This was previously set to decrypt one byte beyond G.csize, when
653 * incnt reached that far. GRR said, "but it's required: why?" This
654 * was a bug in fillinbuf() -- was it also a bug here?
656 for (n = G.incnt, p = G.inptr; n--; p++)
657 zdecode(*p);
659 #endif /* CRYPT */
661 --G.incnt;
662 return *G.inptr++;
664 } /* end function readbyte() */
670 #if defined(USE_ZLIB) || defined(USE_BZIP2)
672 /************************/
673 /* Function fillinbuf() */
674 /************************/
676 int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
677 __GDEF
679 if (G.mem_mode ||
680 (G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
681 return 0;
682 G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */
683 G.inptr = G.inbuf;
684 defer_leftover_input(__G); /* decrements G.csize */
686 #if CRYPT
687 if (G.pInfo->encrypted) {
688 uch *p;
689 int n;
691 for (n = G.incnt, p = G.inptr; n--; p++)
692 zdecode(*p);
694 #endif /* CRYPT */
696 return G.incnt;
698 } /* end function fillinbuf() */
700 #endif /* USE_ZLIB || USE_BZIP2 */
706 /************************/
707 /* Function seek_zipf() */
708 /************************/
710 int seek_zipf(__G__ abs_offset)
711 __GDEF
712 zoff_t abs_offset;
715 * Seek to the block boundary of the block which includes abs_offset,
716 * then read block into input buffer and set pointers appropriately.
717 * If block is already in the buffer, just set the pointers. This function
718 * is used by do_seekable (process.c), extract_or_test_entrylist (extract.c)
719 * and do_string (fileio.c). Also, a slightly modified version is embedded
720 * within extract_or_test_entrylist (extract.c). readbyte() and readbuf()
721 * (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the
722 * "proper offset" (i.e., if there were no extra bytes prepended);
723 * cur_zipfile_bufstart contains the corrected offset.
725 * Since seek_zipf() is never used during decompression, it is safe to
726 * use the slide[] buffer for the error message.
728 * returns PK error codes:
729 * PK_BADERR if effective offset in zipfile is negative
730 * PK_EOF if seeking past end of zipfile
731 * PK_OK when seek was successful
733 zoff_t request = abs_offset + G.extra_bytes;
734 zoff_t inbuf_offset = request % INBUFSIZ;
735 zoff_t bufstart = request - inbuf_offset;
737 if (request < 0) {
738 Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg),
739 G.zipfn, LoadFarString(ReportMsg)));
740 return(PK_BADERR);
741 } else if (bufstart != G.cur_zipfile_bufstart) {
742 Trace((stderr,
743 "fpos_zip: abs_offset = %s, G.extra_bytes = %s\n",
744 FmZofft(abs_offset, NULL, NULL),
745 FmZofft(G.extra_bytes, NULL, NULL)));
746 #ifdef USE_STRM_INPUT
747 zfseeko(G.zipfd, bufstart, SEEK_SET);
748 G.cur_zipfile_bufstart = zftello(G.zipfd);
749 #else /* !USE_STRM_INPUT */
750 G.cur_zipfile_bufstart = zlseek(G.zipfd, bufstart, SEEK_SET);
751 #endif /* ?USE_STRM_INPUT */
752 Trace((stderr,
753 " request = %s, (abs+extra) = %s, inbuf_offset = %s\n",
754 FmZofft(request, NULL, NULL),
755 FmZofft((abs_offset+G.extra_bytes), NULL, NULL),
756 FmZofft(inbuf_offset, NULL, NULL)));
757 Trace((stderr, " bufstart = %s, cur_zipfile_bufstart = %s\n",
758 FmZofft(bufstart, NULL, NULL),
759 FmZofft(G.cur_zipfile_bufstart, NULL, NULL)));
760 if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
761 return(PK_EOF);
762 G.incnt -= (int)inbuf_offset;
763 G.inptr = G.inbuf + (int)inbuf_offset;
764 } else {
765 G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset;
766 G.inptr = G.inbuf + (int)inbuf_offset;
768 return(PK_OK);
769 } /* end function seek_zipf() */
775 #ifndef VMS /* for VMS use code in vms.c */
777 /********************/
778 /* Function flush() */ /* returns PK error codes: */
779 /********************/ /* if tflag => always 0; PK_DISK if write error */
781 int flush(__G__ rawbuf, size, unshrink)
782 __GDEF
783 uch *rawbuf;
784 ulg size;
785 int unshrink;
786 #if (defined(USE_DEFLATE64) && defined(__16BIT__))
788 int ret;
790 /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions
791 * cannot handle writes of 64k blocks at once. For these systems, the
792 * blocks to flush are split into pieces of 32k or less.
794 while (size > 0x8000L) {
795 ret = partflush(__G__ rawbuf, 0x8000L, unshrink);
796 if (ret != PK_OK)
797 return ret;
798 size -= 0x8000L;
799 rawbuf += (extent)0x8000;
801 return partflush(__G__ rawbuf, size, unshrink);
802 } /* end function flush() */
805 /************************/
806 /* Function partflush() */ /* returns PK error codes: */
807 /************************/ /* if tflag => always 0; PK_DISK if write error */
809 static int partflush(__G__ rawbuf, size, unshrink)
810 __GDEF
811 uch *rawbuf; /* cannot be ZCONST, gets passed to (*G.message)() */
812 ulg size;
813 int unshrink;
814 #endif /* USE_DEFLATE64 && __16BIT__ */
816 register uch *p;
817 register uch *q;
818 uch *transbuf;
819 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
820 ulg transbufsiz;
821 #endif
822 /* static int didCRlast = FALSE; moved to globals.h */
825 /*---------------------------------------------------------------------------
826 Compute the CRC first; if testing or if disk is full, that's it.
827 ---------------------------------------------------------------------------*/
829 G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
831 #ifdef DLL
832 if ((G.statreportcb != NULL) &&
833 (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))
834 return IZ_CTRLC; /* cancel operation by user request */
835 #endif
837 if (uO.tflag || size == 0L) /* testing or nothing to write: all done */
838 return PK_OK;
840 if (G.disk_full)
841 return PK_DISK; /* disk already full: ignore rest of file */
843 /*---------------------------------------------------------------------------
844 Write the bytes rawbuf[0..size-1] to the output device, first converting
845 end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
846 defined, outbuf is assumed to be at least as large as rawbuf and is not
847 necessarily checked for overflow.
848 ---------------------------------------------------------------------------*/
850 if (!G.pInfo->textmode) { /* write raw binary data */
851 /* GRR: note that for standard MS-DOS compilers, size argument to
852 * fwrite() can never be more than 65534, so WriteError macro will
853 * have to be rewritten if size can ever be that large. For now,
854 * never more than 32K. Also note that write() returns an int, which
855 * doesn't necessarily limit size to 32767 bytes if write() is used
856 * on 16-bit systems but does make it more of a pain; however, because
857 * at least MSC 5.1 has a lousy implementation of fwrite() (as does
858 * DEC Ultrix cc), write() is used anyway.
860 #ifdef DLL
861 if (G.redirect_data) {
862 #ifdef NO_SLIDE_REDIR
863 if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR;
864 #else
865 writeToMemory(__G__ rawbuf, (extent)size);
866 #endif
867 } else
868 #endif
869 if (!uO.cflag && WriteError(rawbuf, size, G.outfile))
870 return disk_error(__G);
871 else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
872 return PK_OK;
873 } else { /* textmode: aflag is true */
874 if (unshrink) {
875 /* rawbuf = outbuf */
876 transbuf = G.outbuf2;
877 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
878 transbufsiz = TRANSBUFSIZ;
879 #endif
880 } else {
881 /* rawbuf = slide */
882 transbuf = G.outbuf;
883 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
884 transbufsiz = OUTBUFSIZ;
885 Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n",
886 (unsigned)OUTBUFSIZ));
887 #endif
889 if (G.newfile) {
890 #ifdef VMS_TEXT_CONV
891 if (G.pInfo->hostnum == VMS_ && G.extra_field &&
892 is_vms_varlen_txt(__G__ G.extra_field,
893 G.lrec.extra_field_length))
894 G.VMS_line_state = 0; /* 0: ready to read line length */
895 else
896 G.VMS_line_state = -1; /* -1: don't treat as VMS text */
897 #endif
898 G.didCRlast = FALSE; /* no previous buffers written */
899 G.newfile = FALSE;
902 #ifdef VMS_TEXT_CONV
903 if (G.VMS_line_state >= 0)
905 p = rawbuf;
906 q = transbuf;
907 while ((extent)(p-rawbuf) < (extent)size) {
908 switch (G.VMS_line_state) {
910 /* 0: ready to read line length */
911 case 0:
912 G.VMS_line_length = 0;
913 if ((extent)(p-rawbuf) == (extent)size-1) {
914 /* last char */
915 G.VMS_line_length = (unsigned)(*p++);
916 G.VMS_line_state = 1;
917 } else {
918 G.VMS_line_length = makeword(p);
919 p += 2;
920 G.VMS_line_state = 2;
922 G.VMS_line_pad =
923 ((G.VMS_line_length & 1) != 0); /* odd */
924 break;
926 /* 1: read one byte of length, need second */
927 case 1:
928 G.VMS_line_length += ((unsigned)(*p++) << 8);
929 G.VMS_line_state = 2;
930 break;
932 /* 2: ready to read VMS_line_length chars */
933 case 2:
935 extent remaining = (extent)size+(rawbuf-p);
936 extent outroom;
938 if (G.VMS_line_length < remaining) {
939 remaining = G.VMS_line_length;
940 G.VMS_line_state = 3;
943 outroom = transbuf+(extent)transbufsiz-q;
944 if (remaining >= outroom) {
945 remaining -= outroom;
946 for (;outroom > 0; p++, outroom--)
947 *q++ = native(*p);
948 #ifdef DLL
949 if (G.redirect_data) {
950 if (writeToMemory(__G__ transbuf,
951 (extent)(q-transbuf))) return PK_ERR;
952 } else
953 #endif
954 if (!uO.cflag && WriteError(transbuf,
955 (extent)(q-transbuf), G.outfile))
956 return disk_error(__G);
957 else if (uO.cflag && (*G.message)((zvoid *)&G,
958 transbuf, (ulg)(q-transbuf), 0))
959 return PK_OK;
960 q = transbuf;
961 /* fall through to normal case */
963 G.VMS_line_length -= remaining;
964 for (;remaining > 0; p++, remaining--)
965 *q++ = native(*p);
967 break;
969 /* 3: ready to PutNativeEOL */
970 case 3:
971 if (q > transbuf+(extent)transbufsiz-lenEOL) {
972 #ifdef DLL
973 if (G.redirect_data) {
974 if (writeToMemory(__G__ transbuf,
975 (extent)(q-transbuf))) return PK_ERR;
976 } else
977 #endif
978 if (!uO.cflag &&
979 WriteError(transbuf, (extent)(q-transbuf),
980 G.outfile))
981 return disk_error(__G);
982 else if (uO.cflag && (*G.message)((zvoid *)&G,
983 transbuf, (ulg)(q-transbuf), 0))
984 return PK_OK;
985 q = transbuf;
987 PutNativeEOL
988 G.VMS_line_state = G.VMS_line_pad ? 4 : 0;
989 break;
991 /* 4: ready to read pad byte */
992 case 4:
993 ++p;
994 G.VMS_line_state = 0;
995 break;
997 } /* end while */
999 } else
1000 #endif /* VMS_TEXT_CONV */
1002 /*-----------------------------------------------------------------------
1003 Algorithm: CR/LF => native; lone CR => native; lone LF => native.
1004 This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
1005 stream-oriented files, not record-oriented).
1006 -----------------------------------------------------------------------*/
1008 /* else not VMS text */ {
1009 p = rawbuf;
1010 if (*p == LF && G.didCRlast)
1011 ++p;
1012 G.didCRlast = FALSE;
1013 for (q = transbuf; (extent)(p-rawbuf) < (extent)size; ++p) {
1014 if (*p == CR) { /* lone CR or CR/LF: treat as EOL */
1015 PutNativeEOL
1016 if ((extent)(p-rawbuf) == (extent)size-1)
1017 /* last char in buffer */
1018 G.didCRlast = TRUE;
1019 else if (p[1] == LF) /* get rid of accompanying LF */
1020 ++p;
1021 } else if (*p == LF) /* lone LF */
1022 PutNativeEOL
1023 else
1024 #ifndef DOS_FLX_OS2_W32
1025 if (*p != CTRLZ) /* lose all ^Z's */
1026 #endif
1027 *q++ = native(*p);
1029 #if (defined(SMALL_MEM) || defined(MED_MEM))
1030 # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
1031 if (!unshrink)
1032 # endif
1033 /* check for danger of buffer overflow and flush */
1034 if (q > transbuf+(extent)transbufsiz-lenEOL) {
1035 Trace((stderr,
1036 "p - rawbuf = %u q-transbuf = %u size = %lu\n",
1037 (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
1038 if (!uO.cflag && WriteError(transbuf,
1039 (extent)(q-transbuf), G.outfile))
1040 return disk_error(__G);
1041 else if (uO.cflag && (*G.message)((zvoid *)&G,
1042 transbuf, (ulg)(q-transbuf), 0))
1043 return PK_OK;
1044 q = transbuf;
1045 continue;
1047 #endif /* SMALL_MEM || MED_MEM */
1051 /*-----------------------------------------------------------------------
1052 Done translating: write whatever we've got to file (or screen).
1053 -----------------------------------------------------------------------*/
1055 Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
1056 (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
1057 if (q > transbuf) {
1058 #ifdef DLL
1059 if (G.redirect_data) {
1060 if (writeToMemory(__G__ transbuf, (extent)(q-transbuf)))
1061 return PK_ERR;
1062 } else
1063 #endif
1064 if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf),
1065 G.outfile))
1066 return disk_error(__G);
1067 else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
1068 (ulg)(q-transbuf), 0))
1069 return PK_OK;
1073 return PK_OK;
1075 } /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */
1081 #ifdef VMS_TEXT_CONV
1083 /********************************/
1084 /* Function is_vms_varlen_txt() */
1085 /********************************/
1087 static int is_vms_varlen_txt(__G__ ef_buf, ef_len)
1088 __GDEF
1089 uch *ef_buf; /* buffer containing extra field */
1090 unsigned ef_len; /* total length of extra field */
1092 unsigned eb_id;
1093 unsigned eb_len;
1094 uch *eb_data;
1095 unsigned eb_datlen;
1096 #define VMSREC_C_UNDEF 0
1097 #define VMSREC_C_VAR 2
1098 uch vms_rectype = VMSREC_C_UNDEF;
1099 /* uch vms_fileorg = 0; */ /* currently, fileorg is not used... */
1101 #define VMSPK_ITEMID 0
1102 #define VMSPK_ITEMLEN 2
1103 #define VMSPK_ITEMHEADSZ 4
1105 #define VMSATR_C_RECATTR 4
1106 #define VMS_FABSIG 0x42414656 /* "VFAB" */
1107 /* offsets of interesting fields in VMS fabdef structure */
1108 #define VMSFAB_B_RFM 31 /* record format byte */
1109 #define VMSFAB_B_ORG 29 /* file organization byte */
1111 if (ef_len == 0 || ef_buf == NULL)
1112 return FALSE;
1114 while (ef_len >= EB_HEADSIZE) {
1115 eb_id = makeword(EB_ID + ef_buf);
1116 eb_len = makeword(EB_LEN + ef_buf);
1118 if (eb_len > (ef_len - EB_HEADSIZE)) {
1119 /* discovered some extra field inconsistency! */
1120 Trace((stderr,
1121 "is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len,
1122 ef_len - EB_HEADSIZE));
1123 break;
1126 switch (eb_id) {
1127 case EF_PKVMS:
1128 /* The PKVMS e.f. raw data part consists of:
1129 * a) 4 bytes CRC checksum
1130 * b) list of uncompressed variable-length data items
1131 * Each data item is introduced by a fixed header
1132 * - 2 bytes data type ID
1133 * - 2 bytes <size> of data
1134 * - <size> bytes of actual attribute data
1137 /* get pointer to start of data and its total length */
1138 eb_data = ef_buf+(EB_HEADSIZE+4);
1139 eb_datlen = eb_len-4;
1141 /* test the CRC checksum */
1142 if (makelong(ef_buf+EB_HEADSIZE) !=
1143 crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen))
1145 Info(slide, 1, ((char *)slide,
1146 "[Warning: CRC error, discarding PKWARE extra field]\n"));
1147 /* skip over the data analysis code */
1148 break;
1151 /* scan through the attribute data items */
1152 while (eb_datlen > 4)
1154 unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]);
1156 /* check the item type word */
1157 switch (makeword(&eb_data[VMSPK_ITEMID])) {
1158 case VMSATR_C_RECATTR:
1159 /* we have found the (currently only) interesting
1160 * data item */
1161 if (fldsize >= 1) {
1162 vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15;
1163 /* vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4; */
1165 break;
1166 default:
1167 break;
1169 /* skip to next data item */
1170 eb_datlen -= fldsize + VMSPK_ITEMHEADSZ;
1171 eb_data += fldsize + VMSPK_ITEMHEADSZ;
1173 break;
1175 case EF_IZVMS:
1176 if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) {
1177 if ((eb_data = extract_izvms_block(__G__
1178 ef_buf+EB_HEADSIZE, eb_len,
1179 &eb_datlen, NULL, 0))
1180 != NULL)
1182 if (eb_datlen >= VMSFAB_B_RFM+1) {
1183 vms_rectype = eb_data[VMSFAB_B_RFM] & 15;
1184 /* vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4; */
1186 free(eb_data);
1189 break;
1191 default:
1192 break;
1195 /* Skip this extra field block */
1196 ef_buf += (eb_len + EB_HEADSIZE);
1197 ef_len -= (eb_len + EB_HEADSIZE);
1200 return (vms_rectype == VMSREC_C_VAR);
1202 } /* end function is_vms_varlen_txtfile() */
1204 #endif /* VMS_TEXT_CONV */
1209 /*************************/
1210 /* Function disk_error() */
1211 /*************************/
1213 static int disk_error(__G)
1214 __GDEF
1216 /* OK to use slide[] here because this file is finished regardless */
1217 Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
1218 FnFilter1(G.filename)));
1220 #ifndef WINDLL
1221 fgets(G.answerbuf, sizeof(G.answerbuf), stdin);
1222 if (*G.answerbuf == 'y') /* stop writing to this file */
1223 G.disk_full = 1; /* (outfile bad?), but new OK */
1224 else
1225 #endif
1226 G.disk_full = 2; /* no: exit program */
1228 return PK_DISK;
1230 } /* end function disk_error() */
1232 #endif /* !VMS */
1238 /*****************************/
1239 /* Function UzpMessagePrnt() */
1240 /*****************************/
1242 int UZ_EXP UzpMessagePrnt(pG, buf, size, flag)
1243 zvoid *pG; /* globals struct: always passed */
1244 uch *buf; /* preformatted string to be printed */
1245 ulg size; /* length of string (may include nulls) */
1246 int flag; /* flag bits */
1248 /* IMPORTANT NOTE:
1249 * The name of the first parameter of UzpMessagePrnt(), which passes
1250 * the "Uz_Globs" address, >>> MUST <<< be identical to the string
1251 * expansion of the __G__ macro in the REENTRANT case (see globals.h).
1252 * This name identity is mandatory for the LoadFarString() macro
1253 * (in the SMALL_MEM case) !!!
1255 int error;
1256 uch *q=buf, *endbuf=buf+(unsigned)size;
1257 #ifdef MORE
1258 uch *p=buf;
1259 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1260 int islinefeed = FALSE;
1261 #endif
1262 #endif
1263 FILE *outfp;
1266 /*---------------------------------------------------------------------------
1267 These tests are here to allow fine-tuning of UnZip's output messages,
1268 but none of them will do anything without setting the appropriate bit
1269 in the flag argument of every Info() statement which is to be turned
1270 *off*. That is, all messages are currently turned on for all ports.
1271 To turn off *all* messages, use the UzpMessageNull() function instead
1272 of this one.
1273 ---------------------------------------------------------------------------*/
1275 #if (defined(OS2) && defined(DLL))
1276 if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */
1277 return 0;
1278 #endif
1279 #ifdef WINDLL
1280 if (MSG_NO_WDLL(flag))
1281 return 0;
1282 #endif
1283 #ifdef WINDLL
1284 if (MSG_NO_WGUI(flag))
1285 return 0;
1286 #endif
1288 #ifdef ACORN_GUI
1289 if (MSG_NO_AGUI(flag))
1290 return 0;
1291 #endif
1293 #ifdef DLL /* don't display message if data is redirected */
1294 if (((Uz_Globs *)pG)->redirect_data &&
1295 !((Uz_Globs *)pG)->redirect_text)
1296 return 0;
1297 #endif
1299 if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
1300 outfp = (FILE *)stderr;
1301 else
1302 outfp = (FILE *)stdout;
1304 #ifdef QUERY_TRNEWLN
1305 /* some systems require termination of query prompts with '\n' to force
1306 * immediate display */
1307 if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */
1308 *endbuf++ = '\n'; /* with room for one more char at end of buf */
1309 ++size; /* (safe assumption: only used for four */
1310 } /* short queries in extract.c and fileio.c) */
1311 #endif
1313 if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */
1314 if ((!size && !((Uz_Globs *)pG)->sol) ||
1315 (size && (endbuf[-1] != '\n')))
1317 *endbuf++ = '\n';
1318 ++size;
1322 #ifdef MORE
1323 # ifdef SCREENSIZE
1324 /* room for --More-- and one line of overlap: */
1325 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1326 SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width);
1327 # else
1328 SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL);
1329 # endif
1330 ((Uz_Globs *)pG)->height -= 2;
1331 # else
1332 /* room for --More-- and one line of overlap: */
1333 ((Uz_Globs *)pG)->height = SCREENLINES - 2;
1334 # if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1335 ((Uz_Globs *)pG)->width = SCREENWIDTH;
1336 # endif
1337 # endif
1338 #endif /* MORE */
1340 if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
1341 /* not at start of line: want newline */
1342 #ifdef OS2DLL
1343 if (!((Uz_Globs *)pG)->redirect_text) {
1344 #endif
1345 putc('\n', outfp);
1346 fflush(outfp);
1347 #ifdef MORE
1348 if (((Uz_Globs *)pG)->M_flag)
1350 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1351 ((Uz_Globs *)pG)->chars = 0;
1352 #endif
1353 ++((Uz_Globs *)pG)->numlines;
1354 ++((Uz_Globs *)pG)->lines;
1355 if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height)
1356 (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
1357 LoadFarString(MorePrompt), 1);
1359 #endif /* MORE */
1360 if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1361 !isatty(1) && isatty(2))
1363 /* error output from testing redirected: also send to stderr */
1364 putc('\n', stderr);
1365 fflush(stderr);
1367 #ifdef OS2DLL
1368 } else
1369 REDIRECTC('\n');
1370 #endif
1371 ((Uz_Globs *)pG)->sol = TRUE;
1374 /* put zipfile name, filename and/or error/warning keywords here */
1376 #ifdef MORE
1377 if (((Uz_Globs *)pG)->M_flag
1378 #ifdef OS2DLL
1379 && !((Uz_Globs *)pG)->redirect_text
1380 #endif
1383 while (p < endbuf) {
1384 if (*p == '\n') {
1385 #if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1386 islinefeed = TRUE;
1387 } else if (SCREENLWRAP) {
1388 if (*p == '\r') {
1389 ((Uz_Globs *)pG)->chars = 0;
1390 } else {
1391 # ifdef TABSIZE
1392 if (*p == '\t')
1393 ((Uz_Globs *)pG)->chars +=
1394 (TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE));
1395 else
1396 # endif
1397 ++((Uz_Globs *)pG)->chars;
1399 if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width)
1400 islinefeed = TRUE;
1403 if (islinefeed) {
1404 islinefeed = FALSE;
1405 ((Uz_Globs *)pG)->chars = 0;
1406 #endif /* (SCREENWIDTH && SCREEN_LWRAP) */
1407 ++((Uz_Globs *)pG)->numlines;
1408 ++((Uz_Globs *)pG)->lines;
1409 if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height)
1411 if ((error = WriteTxtErr(q, p-q+1, outfp)) != 0)
1412 return error;
1413 fflush(outfp);
1414 ((Uz_Globs *)pG)->sol = TRUE;
1415 q = p + 1;
1416 (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
1417 LoadFarString(MorePrompt), 1);
1420 INCSTR(p);
1421 } /* end while */
1422 size = (ulg)(p - q); /* remaining text */
1424 #endif /* MORE */
1426 if (size) {
1427 #ifdef OS2DLL
1428 if (!((Uz_Globs *)pG)->redirect_text) {
1429 #endif
1430 if ((error = WriteTxtErr(q, size, outfp)) != 0)
1431 return error;
1432 #ifndef VMS /* 2005-09-16 SMS. See note at "WriteTxtErr()", above. */
1433 fflush(outfp);
1434 #endif
1435 if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1436 !isatty(1) && isatty(2))
1438 /* error output from testing redirected: also send to stderr */
1439 if ((error = WriteTxtErr(q, size, stderr)) != 0)
1440 return error;
1441 fflush(stderr);
1443 #ifdef OS2DLL
1444 } else { /* GRR: this is ugly: hide with macro */
1445 if ((error = REDIRECTPRINT(q, size)) != 0)
1446 return error;
1448 #endif /* OS2DLL */
1449 ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
1451 return 0;
1453 } /* end function UzpMessagePrnt() */
1459 #ifdef DLL
1461 /*****************************/
1462 /* Function UzpMessageNull() */ /* convenience routine for no output at all */
1463 /*****************************/
1465 int UZ_EXP UzpMessageNull(pG, buf, size, flag)
1466 zvoid *pG; /* globals struct: always passed */
1467 uch *buf; /* preformatted string to be printed */
1468 ulg size; /* length of string (may include nulls) */
1469 int flag; /* flag bits */
1471 return 0;
1473 } /* end function UzpMessageNull() */
1475 #endif /* DLL */
1481 /***********************/
1482 /* Function UzpInput() */ /* GRR: this is a placeholder for now */
1483 /***********************/
1485 int UZ_EXP UzpInput(pG, buf, size, flag)
1486 zvoid *pG; /* globals struct: always passed */
1487 uch *buf; /* preformatted string to be printed */
1488 int *size; /* (address of) size of buf and of returned string */
1489 int flag; /* flag bits (bit 0: no echo) */
1491 /* tell picky compilers to shut up about "unused variable" warnings */
1492 pG = pG; buf = buf; flag = flag;
1494 *size = 0;
1495 return 0;
1497 } /* end function UzpInput() */
1503 #if (!defined(WINDLL) && !defined(MACOS))
1505 /***************************/
1506 /* Function UzpMorePause() */
1507 /***************************/
1509 void UZ_EXP UzpMorePause(pG, prompt, flag)
1510 zvoid *pG; /* globals struct: always passed */
1511 ZCONST char *prompt; /* "--More--" prompt */
1512 int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
1514 uch c;
1516 /*---------------------------------------------------------------------------
1517 Print a prompt and wait for the user to press a key, then erase prompt
1518 if possible.
1519 ---------------------------------------------------------------------------*/
1521 if (!((Uz_Globs *)pG)->sol)
1522 fprintf(stderr, "\n");
1523 /* numlines may or may not be used: */
1524 fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);
1525 fflush(stderr);
1526 if (flag & 1) {
1527 do {
1528 c = (uch)FGETCH(0);
1529 } while (
1530 #ifdef THEOS
1531 c != 17 && /* standard QUIT key */
1532 #endif
1533 c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
1534 } else
1535 c = (uch)FGETCH(0);
1537 /* newline was not echoed, so cover up prompt line */
1538 fprintf(stderr, LoadFarString(HidePrompt));
1539 fflush(stderr);
1541 if (
1542 #ifdef THEOS
1543 (c == 17) || /* standard QUIT key */
1544 #endif
1545 (ToLower(c) == 'q')) {
1546 DESTROYGLOBALS();
1547 EXIT(PK_COOL);
1550 ((Uz_Globs *)pG)->sol = TRUE;
1552 #ifdef MORE
1553 /* space for another screen, enter for another line. */
1554 if ((flag & 1) && c == ' ')
1555 ((Uz_Globs *)pG)->lines = 0;
1556 #endif /* MORE */
1558 } /* end function UzpMorePause() */
1560 #endif /* !WINDLL && !MACOS */
1565 #ifndef WINDLL
1567 /**************************/
1568 /* Function UzpPassword() */
1569 /**************************/
1571 int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)
1572 zvoid *pG; /* pointer to UnZip's internal global vars */
1573 int *rcnt; /* retry counter */
1574 char *pwbuf; /* buffer for password */
1575 int size; /* size of password buffer */
1576 ZCONST char *zfn; /* name of zip archive */
1577 ZCONST char *efn; /* name of archive entry being processed */
1579 #if CRYPT
1580 int r = IZ_PW_ENTERED;
1581 char *m;
1582 char *prompt;
1584 #ifndef REENTRANT
1585 /* tell picky compilers to shut up about "unused variable" warnings */
1586 pG = pG;
1587 #endif
1589 if (*rcnt == 0) { /* First call for current entry */
1590 *rcnt = 2;
1591 if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
1592 sprintf(prompt, LoadFarString(PasswPrompt),
1593 FnFilter1(zfn), FnFilter2(efn));
1594 m = prompt;
1595 } else
1596 m = (char *)LoadFarString(PasswPrompt2);
1597 } else { /* Retry call, previous password was wrong */
1598 (*rcnt)--;
1599 prompt = NULL;
1600 m = (char *)LoadFarString(PasswRetry);
1603 m = getp(__G__ m, pwbuf, size);
1604 if (prompt != (char *)NULL) {
1605 free(prompt);
1607 if (m == (char *)NULL) {
1608 r = IZ_PW_ERROR;
1610 else if (*pwbuf == '\0') {
1611 r = IZ_PW_CANCELALL;
1613 return r;
1615 #else /* !CRYPT */
1616 /* tell picky compilers to shut up about "unused variable" warnings */
1617 pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
1619 return IZ_PW_ERROR; /* internal error; function should never get called */
1620 #endif /* ?CRYPT */
1622 } /* end function UzpPassword() */
1628 /**********************/
1629 /* Function handler() */
1630 /**********************/
1632 void handler(signal) /* upon interrupt, turn on echo and exit cleanly */
1633 int signal;
1635 GETGLOBALS();
1637 #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
1638 (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */
1639 #endif /* slide[] should be safe) */
1641 echon();
1643 #ifdef SIGBUS
1644 if (signal == SIGBUS) {
1645 Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1646 "bus error"));
1647 DESTROYGLOBALS();
1648 EXIT(PK_BADERR);
1650 #endif /* SIGBUS */
1652 #ifdef SIGILL
1653 if (signal == SIGILL) {
1654 Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1655 "illegal instruction"));
1656 DESTROYGLOBALS();
1657 EXIT(PK_BADERR);
1659 #endif /* SIGILL */
1661 #ifdef SIGSEGV
1662 if (signal == SIGSEGV) {
1663 Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1664 "segmentation violation"));
1665 DESTROYGLOBALS();
1666 EXIT(PK_BADERR);
1668 #endif /* SIGSEGV */
1670 /* probably ctrl-C */
1671 DESTROYGLOBALS();
1672 #if defined(AMIGA) && defined(__SASC)
1673 _abort();
1674 #endif
1675 EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */
1678 #endif /* !WINDLL */
1683 #if (!defined(VMS) && !defined(CMS_MVS))
1684 #if (!defined(OS2) || defined(TIMESTAMP))
1686 #if (!defined(HAVE_MKTIME) || defined(WIN32))
1687 /* also used in amiga/filedate.c and win32/win32.c */
1688 ZCONST ush ydays[] =
1689 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
1690 #endif
1692 /*******************************/
1693 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1694 /*******************************/
1696 time_t dos_to_unix_time(dosdatetime)
1697 ulg dosdatetime;
1699 time_t m_time;
1701 #ifdef HAVE_MKTIME
1703 ZCONST time_t now = time(NULL);
1704 struct tm *tm;
1705 # define YRBASE 1900
1707 tm = localtime(&now);
1708 tm->tm_isdst = -1; /* let mktime determine if DST is in effect */
1710 /* dissect date */
1711 tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
1712 tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1;
1713 tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);
1715 /* dissect time */
1716 tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;
1717 tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f;
1718 tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e;
1720 m_time = mktime(tm);
1721 NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
1722 TTrace((stderr, " final m_time = %lu\n", (ulg)m_time));
1724 #else /* !HAVE_MKTIME */
1726 int yr, mo, dy, hh, mm, ss;
1727 #ifdef TOPS20
1728 # define YRBASE 1900
1729 struct tmx *tmx;
1730 char temp[20];
1731 #else /* !TOPS20 */
1732 # define YRBASE 1970
1733 int leap;
1734 unsigned days;
1735 struct tm *tm;
1736 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1737 #ifdef WIN32
1738 TIME_ZONE_INFORMATION tzinfo;
1739 DWORD res;
1740 #else /* ! WIN32 */
1741 #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
1742 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1743 struct timeb tbp;
1744 #else /* !(BSD || MTS || __GO32__) */
1745 #ifdef DECLARE_TIMEZONE
1746 extern time_t timezone;
1747 #endif
1748 #endif /* ?(BSD || MTS || __GO32__) */
1749 #endif /* !BSD4_4 */
1750 #endif /* ?WIN32 */
1751 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1752 #endif /* ?TOPS20 */
1755 /* dissect date */
1756 yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
1757 mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
1758 dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
1760 /* dissect time */
1761 hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
1762 mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
1763 ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
1765 #ifdef TOPS20
1766 tmx = (struct tmx *)malloc(sizeof(struct tmx));
1767 sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
1768 time_parse(temp, tmx, (char *)0);
1769 m_time = time_make(tmx);
1770 free(tmx);
1772 #else /* !TOPS20 */
1774 /*---------------------------------------------------------------------------
1775 Calculate the number of seconds since the epoch, usually 1 January 1970.
1776 ---------------------------------------------------------------------------*/
1778 /* leap = # of leap yrs from YRBASE up to but not including current year */
1779 leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
1781 /* calculate days from BASE to this year and add expired days this year */
1782 days = (yr * 365) + (leap - 492) + ydays[mo];
1784 /* if year is a leap year and month is after February, add another day */
1785 if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
1786 ++days; /* OK through 2199 */
1788 /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
1789 m_time = (time_t)((unsigned long)(days + dy) * 86400L +
1790 (unsigned long)hh * 3600L +
1791 (unsigned long)(mm * 60 + ss));
1792 /* - 1; MS-DOS times always rounded up to nearest even second */
1793 TTrace((stderr, "dos_to_unix_time:\n"));
1794 TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time));
1796 /*---------------------------------------------------------------------------
1797 Adjust for local standard timezone offset.
1798 ---------------------------------------------------------------------------*/
1800 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1801 #ifdef WIN32
1802 /* account for timezone differences */
1803 res = GetTimeZoneInformation(&tzinfo);
1804 if (res != TIME_ZONE_ID_INVALID)
1806 m_time += 60*(tzinfo.Bias);
1807 #else /* !WIN32 */
1808 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1809 #ifdef BSD4_4
1810 if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1811 (m_time < (time_t)0x70000000L) )
1812 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1813 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1814 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1815 if ((tm = localtime(&m_time)) != (struct tm *)NULL)
1816 m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */
1817 #else /* !(BSD4_4 */
1818 ftime(&tbp); /* get `timezone' */
1819 m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */
1820 #endif /* ?(BSD4_4 || __EMX__) */
1821 #else /* !(BSD || MTS || __GO32__) */
1822 /* tzset was already called at start of process_zipfiles() */
1823 /* tzset(); */ /* set `timezone' variable */
1824 #ifndef __BEOS__ /* BeOS DR8 has no timezones... */
1825 m_time += timezone; /* seconds WEST of GMT: add */
1826 #endif
1827 #endif /* ?(BSD || MTS || __GO32__) */
1828 #endif /* ?WIN32 */
1829 TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time));
1831 /*---------------------------------------------------------------------------
1832 Adjust for local daylight savings (summer) time.
1833 ---------------------------------------------------------------------------*/
1835 #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
1836 if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1837 (m_time < (time_t)0x70000000L) )
1838 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1839 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1840 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1841 TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */
1842 if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)
1843 #ifdef WIN32
1844 m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */
1845 else
1846 m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */
1847 #else
1848 m_time -= 60L * 60L; /* adjust for daylight savings time */
1849 #endif
1850 NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
1851 TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time));
1852 #endif /* !BSD4_4 */
1853 #ifdef WIN32
1855 #endif
1856 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1857 #endif /* ?TOPS20 */
1859 #endif /* ?HAVE_MKTIME */
1861 if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1862 (m_time < (time_t)0x70000000L) )
1863 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1864 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1865 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1867 return m_time;
1869 } /* end function dos_to_unix_time() */
1871 #endif /* !OS2 || TIMESTAMP */
1872 #endif /* !VMS && !CMS_MVS */
1876 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1878 /******************************/
1879 /* Function check_for_newer() */ /* used for overwriting/freshening/updating */
1880 /******************************/
1882 int check_for_newer(__G__ filename) /* return 1 if existing file is newer */
1883 __GDEF /* or equal; 0 if older; -1 if doesn't */
1884 char *filename; /* exist yet */
1886 time_t existing, archive;
1887 #ifdef USE_EF_UT_TIME
1888 iztimes z_utime;
1889 #endif
1890 #ifdef AOS_VS
1891 long dyy, dmm, ddd, dhh, dmin, dss;
1894 dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
1895 dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
1896 ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
1897 dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
1898 dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
1899 dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
1901 /* under AOS/VS, file times can only be set at creation time,
1902 * with the info in a special DG format. Make sure we can create
1903 * it here - we delete it later & re-create it, whether or not
1904 * it exists now.
1906 if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
1907 (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
1908 return DOES_NOT_EXIST;
1909 #endif /* AOS_VS */
1911 Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename)));
1912 if (SSTAT(filename, &G.statbuf)) {
1913 Trace((stderr,
1914 "check_for_newer: stat(%s) returns %d: file does not exist\n",
1915 FnFilter1(filename), SSTAT(filename, &G.statbuf)));
1916 #ifdef SYMLINKS
1917 Trace((stderr, "check_for_newer: doing lstat(%s)\n",
1918 FnFilter1(filename)));
1919 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1920 if (lstat(filename, &G.statbuf) == 0) {
1921 Trace((stderr,
1922 "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
1923 FnFilter1(filename)));
1924 if (QCOND2 && !IS_OVERWRT_ALL)
1925 Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
1926 FnFilter1(filename), " with no real file"));
1927 return EXISTS_AND_OLDER; /* symlink dates are meaningless */
1929 #endif /* SYMLINKS */
1930 return DOES_NOT_EXIST;
1932 Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n",
1933 FnFilter1(filename)));
1935 #ifdef SYMLINKS
1936 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1937 if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
1938 Trace((stderr, "check_for_newer: %s is a symbolic link\n",
1939 FnFilter1(filename)));
1940 if (QCOND2 && !IS_OVERWRT_ALL)
1941 Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
1942 FnFilter1(filename), ""));
1943 return EXISTS_AND_OLDER; /* symlink dates are meaningless */
1945 #endif /* SYMLINKS */
1947 NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */
1949 #ifdef USE_EF_UT_TIME
1950 /* The `Unix extra field mtime' should be used for comparison with the
1951 * time stamp of the existing file >>>ONLY<<< when the EF info is also
1952 * used to set the modification time of the extracted file.
1954 if (G.extra_field &&
1955 #ifdef IZ_CHECK_TZ
1956 G.tz_is_valid &&
1957 #endif
1958 (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
1959 G.lrec.last_mod_dos_datetime, &z_utime, NULL)
1960 & EB_UT_FL_MTIME))
1962 TTrace((stderr, "check_for_newer: using Unix extra field mtime\n"));
1963 existing = G.statbuf.st_mtime;
1964 archive = z_utime.mtime;
1965 } else {
1966 /* round up existing filetime to nearest 2 seconds for comparison,
1967 * but saturate in case of arithmetic overflow
1969 existing = ((G.statbuf.st_mtime & 1) &&
1970 (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
1971 G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
1972 archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
1974 #else /* !USE_EF_UT_TIME */
1975 /* round up existing filetime to nearest 2 seconds for comparison,
1976 * but saturate in case of arithmetic overflow
1978 existing = ((G.statbuf.st_mtime & 1) &&
1979 (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
1980 G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
1981 archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
1982 #endif /* ?USE_EF_UT_TIME */
1984 TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
1985 (ulg)existing, (ulg)archive, (long)(existing-archive)));
1987 return (existing >= archive);
1989 } /* end function check_for_newer() */
1991 #endif /* !VMS && !OS2 && !CMS_MVS */
1997 /************************/
1998 /* Function do_string() */
1999 /************************/
2001 int do_string(__G__ length, option) /* return PK-type error code */
2002 __GDEF
2003 unsigned int length; /* without prototype, ush converted to this */
2004 int option;
2006 unsigned comment_bytes_left;
2007 unsigned int block_len;
2008 int error=PK_OK;
2009 #ifdef AMIGA
2010 char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */
2011 #endif
2014 /*---------------------------------------------------------------------------
2015 This function processes arbitrary-length (well, usually) strings. Four
2016 major options are allowed: SKIP, wherein the string is skipped (pretty
2017 logical, eh?); DISPLAY, wherein the string is printed to standard output
2018 after undergoing any necessary or unnecessary character conversions;
2019 DS_FN, wherein the string is put into the filename[] array after under-
2020 going appropriate conversions (including case-conversion, if that is
2021 indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD,
2022 wherein the `string' is assumed to be an extra field and is copied to
2023 the (freshly malloced) buffer G.extra_field. The third option should
2024 be OK since filename is dimensioned at 1025, but we check anyway.
2026 The string, by the way, is assumed to start at the current file-pointer
2027 position; its length is given by 'length'. So start off by checking the
2028 length of the string: if zero, we're already done.
2029 ---------------------------------------------------------------------------*/
2031 if (!length)
2032 return PK_COOL;
2034 switch (option) {
2036 #if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
2038 * Special case: See if the comment begins with an autorun command line.
2039 * Save that and display (or skip) the remainder.
2042 case CHECK_AUTORUN:
2043 case CHECK_AUTORUN_Q:
2044 comment_bytes_left = length;
2045 if (length >= 10)
2047 block_len = readbuf(__G__ (char *)G.outbuf, 10);
2048 if (block_len == 0)
2049 return PK_EOF;
2050 comment_bytes_left -= block_len;
2051 G.outbuf[block_len] = '\0';
2052 if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) {
2053 char *eol;
2054 length -= 10;
2055 block_len = readbuf(__G__ G.autorun_command,
2056 MIN(length, sizeof(G.autorun_command)-1));
2057 if (block_len == 0)
2058 return PK_EOF;
2059 comment_bytes_left -= block_len;
2060 G.autorun_command[block_len] = '\0';
2061 A_TO_N(G.autorun_command);
2062 eol = strchr(G.autorun_command, '\n');
2063 if (!eol)
2064 eol = G.autorun_command + strlen(G.autorun_command) - 1;
2065 length -= eol + 1 - G.autorun_command;
2066 while (eol >= G.autorun_command && isspace(*eol))
2067 *eol-- = '\0';
2068 #if (defined(WIN32) && !defined(_WIN32_WCE))
2069 /* Win9x console always uses OEM character coding, and
2070 WinNT console is set to OEM charset by default, too */
2071 INTERN_TO_OEM(G.autorun_command, G.autorun_command);
2072 #endif /* (WIN32 && !_WIN32_WCE) */
2075 if (option == CHECK_AUTORUN_Q) /* don't display the remainder */
2076 length = 0;
2077 /* seek to beginning of remaining part of comment -- rewind if */
2078 /* displaying entire comment, or skip to end if discarding it */
2079 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
2080 (G.inptr - G.inbuf) + comment_bytes_left - length);
2081 if (!length)
2082 break;
2083 /* FALL THROUGH... */
2084 #endif /* SFX && CHEAP_SFX_AUTORUN */
2087 * First normal case: print string on standard output. First set loop
2088 * variables, then loop through the comment in chunks of OUTBUFSIZ bytes,
2089 * converting formats and printing as we go. The second half of the
2090 * loop conditional was added because the file might be truncated, in
2091 * which case comment_bytes_left will remain at some non-zero value for
2092 * all time. outbuf and slide are used as scratch buffers because they
2093 * are available (we should be either before or in between any file pro-
2094 * cessing).
2097 case DISPLAY:
2098 case DISPL_8:
2099 comment_bytes_left = length;
2100 block_len = OUTBUFSIZ; /* for the while statement, first time */
2101 while (comment_bytes_left > 0 && block_len > 0) {
2102 register uch *p = G.outbuf;
2103 register uch *q = G.outbuf;
2105 if ((block_len = readbuf(__G__ (char *)G.outbuf,
2106 MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0)
2107 return PK_EOF;
2108 comment_bytes_left -= block_len;
2110 /* this is why we allocated an extra byte for outbuf: terminate
2111 * with zero (ASCIIZ) */
2112 G.outbuf[block_len] = '\0';
2114 /* remove all ASCII carriage returns from comment before printing
2115 * (since used before A_TO_N(), check for CR instead of '\r')
2117 while (*p) {
2118 while (*p == CR)
2119 ++p;
2120 *q++ = *p++;
2122 /* could check whether (p - outbuf) == block_len here */
2123 *q = '\0';
2125 if (option == DISPL_8) {
2126 /* translate the text coded in the entry's host-dependent
2127 "extended ASCII" charset into the compiler's (system's)
2128 internal text code page */
2129 Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,
2130 G.pInfo->hostver, G.pInfo->HasUxAtt,
2131 FALSE);
2132 #ifdef WINDLL
2133 /* translate to ANSI (RTL internal codepage may be OEM) */
2134 INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
2135 #else /* !WINDLL */
2136 #if (defined(WIN32) && !defined(_WIN32_WCE))
2137 /* Win9x console always uses OEM character coding, and
2138 WinNT console is set to OEM charset by default, too */
2139 INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);
2140 #endif /* (WIN32 && !_WIN32_WCE) */
2141 #endif /* ?WINDLL */
2142 } else {
2143 A_TO_N(G.outbuf); /* translate string to native */
2146 #ifdef WINDLL
2147 /* ran out of local mem -- had to cheat */
2148 win_fprintf((zvoid *)&G, stdout, (extent)(q-G.outbuf),
2149 (char *)G.outbuf);
2150 win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
2151 #else /* !WINDLL */
2152 #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
2153 (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
2154 #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
2155 p = G.outbuf - 1;
2156 q = slide;
2157 while (*++p) {
2158 int pause = FALSE;
2160 if (*p == 0x1B) { /* ASCII escape char */
2161 *q++ = '^';
2162 *q++ = '[';
2163 } else if (*p == 0x13) { /* ASCII ^S (pause) */
2164 pause = TRUE;
2165 if (p[1] == LF) /* ASCII LF */
2166 *q++ = *++p;
2167 else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */
2168 *q++ = *++p;
2169 *q++ = *++p;
2171 } else
2172 *q++ = *p;
2173 if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */
2174 (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
2175 q = slide;
2176 if (pause && G.extract_flag) /* don't pause for list/test */
2177 (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
2180 (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
2181 #endif /* ?NOANSIFILT */
2182 #endif /* ?WINDLL */
2184 /* add '\n' if not at start of line */
2185 (*G.message)((zvoid *)&G, slide, 0L, 0x40);
2186 break;
2189 * Second case: read string into filename[] array. The filename should
2190 * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
2191 * just to be sure.
2194 case DS_FN:
2195 case DS_FN_L:
2196 #ifdef UNICODE_SUPPORT
2197 /* get the whole filename as need it for Unicode checksum */
2198 if (G.fnfull_bufsize <= length) {
2199 extent fnbufsiz = FILNAMSIZ;
2201 if (fnbufsiz <= length)
2202 fnbufsiz = length + 1;
2203 if (G.filename_full)
2204 free(G.filename_full);
2205 G.filename_full = malloc(fnbufsiz);
2206 if (G.filename_full == NULL)
2207 return PK_MEM;
2208 G.fnfull_bufsize = fnbufsiz;
2210 if (readbuf(__G__ G.filename_full, length) == 0)
2211 return PK_EOF;
2212 G.filename_full[length] = '\0'; /* terminate w/zero: ASCIIZ */
2214 /* if needed, chop off end so standard filename is a valid length */
2215 if (length >= FILNAMSIZ) {
2216 Info(slide, 0x401, ((char *)slide,
2217 LoadFarString(FilenameTooLongTrunc)));
2218 error = PK_WARN;
2219 length = FILNAMSIZ - 1;
2221 /* no excess size */
2222 block_len = 0;
2223 strncpy(G.filename, G.filename_full, length);
2224 G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */
2225 #else /* !UNICODE_SUPPORT */
2226 if (length >= FILNAMSIZ) {
2227 Info(slide, 0x401, ((char *)slide,
2228 LoadFarString(FilenameTooLongTrunc)));
2229 error = PK_WARN;
2230 /* remember excess length in block_len */
2231 block_len = length - (FILNAMSIZ - 1);
2232 length = FILNAMSIZ - 1;
2233 } else
2234 /* no excess size */
2235 block_len = 0;
2236 if (readbuf(__G__ G.filename, length) == 0)
2237 return PK_EOF;
2238 G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */
2239 #endif /* ?UNICODE_SUPPORT */
2241 /* translate the Zip entry filename coded in host-dependent "extended
2242 ASCII" into the compiler's (system's) internal text code page */
2243 Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver,
2244 G.pInfo->HasUxAtt, (option == DS_FN_L));
2246 if (G.pInfo->lcflag) /* replace with lowercase filename */
2247 STRLOWER(G.filename, G.filename);
2249 if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') {
2250 char *p = G.filename+8;
2251 while (*p++)
2252 p[-1] = *p; /* disk label, and 8th char is dot: remove dot */
2255 if (!block_len) /* no overflow, we're done here */
2256 break;
2259 * We truncated the filename, so print what's left and then fall
2260 * through to the SKIP routine.
2262 Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
2263 length = block_len; /* SKIP the excess bytes... */
2264 /* FALL THROUGH... */
2267 * Third case: skip string, adjusting readbuf's internal variables
2268 * as necessary (and possibly skipping to and reading a new block of
2269 * data).
2272 case SKIP:
2273 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
2274 * correct for it twice: */
2275 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
2276 (G.inptr-G.inbuf) + length);
2277 break;
2280 * Fourth case: assume we're at the start of an "extra field"; malloc
2281 * storage for it and read data into the allocated space.
2284 case EXTRA_FIELD:
2285 if (G.extra_field != (uch *)NULL)
2286 free(G.extra_field);
2287 if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) {
2288 Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
2289 length));
2290 /* cur_zipfile_bufstart already takes account of extra_bytes,
2291 * so don't correct for it twice: */
2292 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
2293 (G.inptr-G.inbuf) + length);
2294 } else {
2295 if (readbuf(__G__ (char *)G.extra_field, length) == 0)
2296 return PK_EOF;
2297 /* Looks like here is where extra fields are read */
2298 getZip64Data(__G__ G.extra_field, length);
2299 #ifdef UNICODE_SUPPORT
2300 G.unipath_filename = NULL;
2301 if (G.UzO.U_flag < 2) {
2302 /* check if GPB11 (General Purpuse Bit 11) is set indicating
2303 the standard path and comment are UTF-8 */
2304 if (G.pInfo->GPFIsUTF8) {
2305 /* if GPB11 set then filename_full is untruncated UTF-8 */
2306 G.unipath_filename = G.filename_full;
2307 } else {
2308 /* Get the Unicode fields if exist */
2309 getUnicodeData(__G__ G.extra_field, length);
2310 if (G.unipath_filename && strlen(G.unipath_filename) == 0) {
2311 /* the standard filename field is UTF-8 */
2312 free(G.unipath_filename);
2313 G.unipath_filename = G.filename_full;
2316 if (G.unipath_filename) {
2317 # ifdef UTF8_MAYBE_NATIVE
2318 if (G.native_is_utf8
2319 # ifdef UNICODE_WCHAR
2320 && (!G.unicode_escape_all)
2321 # endif
2323 strncpy(G.filename, G.unipath_filename, FILNAMSIZ - 1);
2324 /* make sure filename is short enough */
2325 if (strlen(G.unipath_filename) >= FILNAMSIZ) {
2326 G.filename[FILNAMSIZ - 1] = '\0';
2327 Info(slide, 0x401, ((char *)slide,
2328 LoadFarString(UFilenameTooLongTrunc)));
2329 error = PK_WARN;
2332 # ifdef UNICODE_WCHAR
2333 else
2334 # endif
2335 # endif /* UTF8_MAYBE_NATIVE */
2336 # ifdef UNICODE_WCHAR
2338 char *fn;
2340 /* convert UTF-8 to local character set */
2341 fn = utf8_to_local_string(G.unipath_filename,
2342 G.unicode_escape_all);
2343 /* make sure filename is short enough */
2344 if (strlen(fn) >= FILNAMSIZ) {
2345 fn[FILNAMSIZ - 1] = '\0';
2346 Info(slide, 0x401, ((char *)slide,
2347 LoadFarString(UFilenameTooLongTrunc)));
2348 error = PK_WARN;
2350 /* replace filename with converted UTF-8 */
2351 strcpy(G.filename, fn);
2352 free(fn);
2354 # endif /* UNICODE_WCHAR */
2355 if (G.unipath_filename != G.filename_full)
2356 free(G.unipath_filename);
2357 G.unipath_filename = NULL;
2360 #endif /* UNICODE_SUPPORT */
2362 break;
2364 #ifdef AMIGA
2366 * Fifth case, for the Amiga only: take the comment that would ordinarily
2367 * be skipped over, and turn it into a 79 character string that will be
2368 * attached to the file as a "filenote" after it is extracted.
2371 case FILENOTE:
2372 if ((block_len = readbuf(__G__ tmp_fnote, (unsigned)
2373 MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0)
2374 return PK_EOF;
2375 if ((length -= block_len) > 0) /* treat remainder as in case SKIP: */
2376 seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes
2377 + (G.inptr - G.inbuf) + length);
2378 /* convert multi-line text into single line with no ctl-chars: */
2379 tmp_fnote[block_len] = '\0';
2380 while ((short int) --block_len >= 0)
2381 if ((unsigned) tmp_fnote[block_len] < ' ')
2382 if (tmp_fnote[block_len+1] == ' ') /* no excess */
2383 strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1);
2384 else
2385 tmp_fnote[block_len] = ' ';
2386 tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0';
2387 if (G.filenotes[G.filenote_slot])
2388 free(G.filenotes[G.filenote_slot]); /* should not happen */
2389 G.filenotes[G.filenote_slot] = NULL;
2390 if (tmp_fnote[0]) {
2391 if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
2392 return PK_MEM;
2393 strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
2395 break;
2396 #endif /* AMIGA */
2398 } /* end switch (option) */
2400 return error;
2402 } /* end function do_string() */
2408 /***********************/
2409 /* Function makeword() */
2410 /***********************/
2412 ush makeword(b)
2413 ZCONST uch *b;
2416 * Convert Intel style 'short' integer to non-Intel non-16-bit
2417 * host format. This routine also takes care of byte-ordering.
2419 return (ush)((b[1] << 8) | b[0]);
2426 /***********************/
2427 /* Function makelong() */
2428 /***********************/
2430 ulg makelong(sig)
2431 ZCONST uch *sig;
2434 * Convert intel style 'long' variable to non-Intel non-16-bit
2435 * host format. This routine also takes care of byte-ordering.
2437 return (((ulg)sig[3]) << 24)
2438 + (((ulg)sig[2]) << 16)
2439 + (ulg)((((unsigned)sig[1]) << 8)
2440 + ((unsigned)sig[0]));
2447 /************************/
2448 /* Function makeint64() */
2449 /************************/
2451 zusz_t makeint64(sig)
2452 ZCONST uch *sig;
2454 #ifdef LARGE_FILE_SUPPORT
2456 * Convert intel style 'int64' variable to non-Intel non-16-bit
2457 * host format. This routine also takes care of byte-ordering.
2459 return (((zusz_t)sig[7]) << 56)
2460 + (((zusz_t)sig[6]) << 48)
2461 + (((zusz_t)sig[4]) << 32)
2462 + (zusz_t)((((ulg)sig[3]) << 24)
2463 + (((ulg)sig[2]) << 16)
2464 + (((unsigned)sig[1]) << 8)
2465 + (sig[0]));
2467 #else /* !LARGE_FILE_SUPPORT */
2469 if ((sig[7] | sig[6] | sig[5] | sig[4]) != 0)
2470 return (zusz_t)0xffffffffL;
2471 else
2472 return (zusz_t)((((ulg)sig[3]) << 24)
2473 + (((ulg)sig[2]) << 16)
2474 + (((unsigned)sig[1]) << 8)
2475 + (sig[0]));
2477 #endif /* ?LARGE_FILE_SUPPORT */
2484 /*********************/
2485 /* Function fzofft() */
2486 /*********************/
2488 /* Format a zoff_t value in a cylindrical buffer set. */
2489 char *fzofft(__G__ val, pre, post)
2490 __GDEF
2491 zoff_t val;
2492 ZCONST char *pre;
2493 ZCONST char *post;
2495 /* Storage cylinder. (now in globals.h) */
2496 /*static char fzofft_buf[FZOFFT_NUM][FZOFFT_LEN];*/
2497 /*static int fzofft_index = 0;*/
2499 /* Temporary format string storage. */
2500 char fmt[16];
2502 /* Assemble the format string. */
2503 fmt[0] = '%';
2504 fmt[1] = '\0'; /* Start after initial "%". */
2505 if (pre == FZOFFT_HEX_WID) /* Special hex width. */
2507 strcat(fmt, FZOFFT_HEX_WID_VALUE);
2509 else if (pre == FZOFFT_HEX_DOT_WID) /* Special hex ".width". */
2511 strcat(fmt, ".");
2512 strcat(fmt, FZOFFT_HEX_WID_VALUE);
2514 else if (pre != NULL) /* Caller's prefix (width). */
2516 strcat(fmt, pre);
2519 strcat(fmt, FZOFFT_FMT); /* Long or long-long or whatever. */
2521 if (post == NULL)
2522 strcat(fmt, "d"); /* Default radix = decimal. */
2523 else
2524 strcat(fmt, post); /* Caller's radix. */
2526 /* Advance the cylinder. */
2527 G.fzofft_index = (G.fzofft_index + 1) % FZOFFT_NUM;
2529 /* Write into the current chamber. */
2530 sprintf(G.fzofft_buf[G.fzofft_index], fmt, val);
2532 /* Return a pointer to this chamber. */
2533 return G.fzofft_buf[G.fzofft_index];
2539 #if CRYPT
2541 #ifdef NEED_STR2ISO
2542 /**********************/
2543 /* Function str2iso() */
2544 /**********************/
2546 char *str2iso(dst, src)
2547 char *dst; /* destination buffer */
2548 register ZCONST char *src; /* source string */
2550 #ifdef INTERN_TO_ISO
2551 INTERN_TO_ISO(src, dst);
2552 #else
2553 register uch c;
2554 register char *dstp = dst;
2556 do {
2557 c = (uch)foreign(*src++);
2558 *dstp++ = (char)ASCII2ISO(c);
2559 } while (c != '\0');
2560 #endif
2562 return dst;
2564 #endif /* NEED_STR2ISO */
2567 #ifdef NEED_STR2OEM
2568 /**********************/
2569 /* Function str2oem() */
2570 /**********************/
2572 char *str2oem(dst, src)
2573 char *dst; /* destination buffer */
2574 register ZCONST char *src; /* source string */
2576 #ifdef INTERN_TO_OEM
2577 INTERN_TO_OEM(src, dst);
2578 #else
2579 register uch c;
2580 register char *dstp = dst;
2582 do {
2583 c = (uch)foreign(*src++);
2584 *dstp++ = (char)ASCII2OEM(c);
2585 } while (c != '\0');
2586 #endif
2588 return dst;
2590 #endif /* NEED_STR2OEM */
2592 #endif /* CRYPT */
2595 #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
2596 /* bzero/bcmp/bcopy */
2597 /* (no known systems as of 960211) */
2599 /*********************/
2600 /* Function memset() */
2601 /*********************/
2603 zvoid *memset(buf, init, len)
2604 register zvoid *buf; /* buffer location */
2605 register int init; /* initializer character */
2606 register unsigned int len; /* length of the buffer */
2608 zvoid *start;
2610 start = buf;
2611 while (len--)
2612 *((char *)buf++) = (char)init;
2613 return start;
2618 /*********************/
2619 /* Function memcmp() */
2620 /*********************/
2622 int memcmp(b1, b2, len)
2623 register ZCONST zvoid *b1;
2624 register ZCONST zvoid *b2;
2625 register unsigned int len;
2627 register int c;
2629 if (len > 0) do {
2630 if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
2631 (int)(*((ZCONST unsigned char *)b2)++)) != 0)
2632 return c;
2633 } while (--len > 0)
2634 return 0;
2639 /*********************/
2640 /* Function memcpy() */
2641 /*********************/
2643 zvoid *memcpy(dst, src, len)
2644 register zvoid *dst;
2645 register ZCONST zvoid *src;
2646 register unsigned int len;
2648 zvoid *start;
2650 start = dst;
2651 while (len-- > 0)
2652 *((char *)dst)++ = *((ZCONST char *)src)++;
2653 return start;
2656 #endif /* ZMEM */
2661 #ifdef NO_STRNICMP
2663 /************************/
2664 /* Function zstrnicmp() */
2665 /************************/
2667 int zstrnicmp(s1, s2, n)
2668 register ZCONST char *s1, *s2;
2669 register unsigned n;
2671 for (; n > 0; --n, ++s1, ++s2) {
2673 if (ToLower(*s1) != ToLower(*s2))
2674 /* test includes early termination of one string */
2675 return ((uch)ToLower(*s1) < (uch)ToLower(*s2))? -1 : 1;
2677 if (*s1 == '\0') /* both strings terminate early */
2678 return 0;
2680 return 0;
2683 #endif /* NO_STRNICMP */
2688 #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
2689 # undef stat
2691 /********************/
2692 /* Function zstat() */
2693 /********************/
2695 int zstat(p, s)
2696 ZCONST char *p;
2697 struct stat *s;
2699 return (stat((char *)p,s) >= 0? 0 : (-1));
2702 #endif /* REGULUS */
2707 #ifdef _MBCS
2709 /* DBCS support for Info-ZIP's zip (mainly for japanese (-: )
2710 * by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
2711 * This code is public domain! Date: 1998/12/20
2714 /************************/
2715 /* Function plastchar() */
2716 /************************/
2718 char *plastchar(ptr, len)
2719 ZCONST char *ptr;
2720 extent len;
2722 unsigned clen;
2723 ZCONST char *oldptr = ptr;
2724 while(*ptr != '\0' && len > 0){
2725 oldptr = ptr;
2726 clen = CLEN(ptr);
2727 ptr += clen;
2728 len -= clen;
2730 return (char *)oldptr;
2734 #ifdef NEED_UZMBCLEN
2735 /***********************/
2736 /* Function uzmbclen() */
2737 /***********************/
2739 extent uzmbclen(ptr)
2740 ZCONST unsigned char *ptr;
2742 int mbl;
2744 mbl = mblen((ZCONST char *)ptr, MB_CUR_MAX);
2745 /* For use in code scanning through MBCS strings, we need a strictly
2746 positive "MB char bytes count". For our scanning purpose, it is not
2747 not relevant whether the MB character is valid or not. And, the NUL
2748 char '\0' has a byte count of 1, but mblen() returns 0. So, we make
2749 sure that the uzmbclen() return value is not less than 1.
2751 return (extent)(mbl > 0 ? mbl : 1);
2753 #endif /* NEED_UZMBCLEN */
2756 #ifdef NEED_UZMBSCHR
2757 /***********************/
2758 /* Function uzmbschr() */
2759 /***********************/
2761 unsigned char *uzmbschr(str, c)
2762 ZCONST unsigned char *str;
2763 unsigned int c;
2765 while(*str != '\0'){
2766 if (*str == c) {return (unsigned char *)str;}
2767 INCSTR(str);
2769 return NULL;
2771 #endif /* NEED_UZMBSCHR */
2774 #ifdef NEED_UZMBSRCHR
2775 /************************/
2776 /* Function uzmbsrchr() */
2777 /************************/
2779 unsigned char *uzmbsrchr(str, c)
2780 ZCONST unsigned char *str;
2781 unsigned int c;
2783 unsigned char *match = NULL;
2784 while(*str != '\0'){
2785 if (*str == c) {match = (unsigned char *)str;}
2786 INCSTR(str);
2788 return match;
2790 #endif /* NEED_UZMBSRCHR */
2791 #endif /* _MBCS */
2797 #ifdef SMALL_MEM
2799 /*******************************/
2800 /* Function fLoadFarString() */ /* (and friends...) */
2801 /*******************************/
2803 char *fLoadFarString(__GPRO__ const char Far *sz)
2805 (void)zfstrcpy(G.rgchBigBuffer, sz);
2806 return G.rgchBigBuffer;
2809 char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
2811 (void)zfstrcpy(G.rgchSmallBuffer, sz);
2812 return G.rgchSmallBuffer;
2815 char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
2817 (void)zfstrcpy(G.rgchSmallBuffer2, sz);
2818 return G.rgchSmallBuffer2;
2824 #if (!defined(_MSC_VER) || (_MSC_VER < 600))
2825 /*************************/
2826 /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
2827 /*************************/
2829 char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
2831 char Far *p = s1;
2833 while ((*s1++ = *s2++) != '\0');
2834 return p;
2837 #if (!(defined(SFX) || defined(FUNZIP)))
2838 /*************************/
2839 /* Function zfstrcmp() */ /* portable clone of _fstrcmp() */
2840 /*************************/
2842 int Far zfstrcmp(const char Far *s1, const char Far *s2)
2844 int ret;
2846 while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0
2847 && *s2 != '\0') {
2848 ++s2; ++s1;
2850 return ret;
2852 #endif /* !(SFX || FUNZIP) */
2853 #endif /* !_MSC_VER || (_MSC_VER < 600) */
2855 #endif /* SMALL_MEM */