]> git.saurik.com Git - wxWidgets.git/blob - utils/Install/sfxzip/fileio.c
Added "set new icon" menu item to taskbar sample; updated some makefiles
[wxWidgets.git] / utils / Install / sfxzip / fileio.c
1 /*---------------------------------------------------------------------------
2
3 fileio.c
4
5 This file contains routines for doing direct but relatively generic input/
6 output, file-related sorts of things, plus some miscellaneous stuff. Most
7 of the stuff has to do with opening, closing, reading and/or writing files.
8
9 Contains: open_input_file()
10 open_outfile() (non-VMS, non-AOS/VS, non-CMS_MVS)
11 undefer_input()
12 defer_leftover_input()
13 readbuf()
14 readbyte()
15 fillinbuf()
16 flush() (non-VMS)
17 disk_error() (non-VMS)
18 UzpMessagePrnt()
19 UzpMessageNull() (DLL only)
20 UzpInput()
21 UzpMorePause()
22 UzpPassword() (non-WINDLL)
23 handler()
24 dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS)
25 check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
26 do_string()
27 makeword()
28 makelong()
29 str2iso() (CRYPT && NEED_STR2ISO, only)
30 str2oem() (CRYPT && NEED_STR2OEM, only)
31 memset() (ZMEM only)
32 memcpy() (ZMEM only)
33 zstrnicmp()
34 zstat() (REGULUS only)
35 fLoadFarString() (SMALL_MEM only)
36 fLoadFarStringSmall() (SMALL_MEM only)
37 fLoadFarStringSmall2() (SMALL_MEM only)
38 zfstrcpy() (SMALL_MEM only)
39
40 ---------------------------------------------------------------------------*/
41
42
43 #define FILEIO_C
44 #define UNZIP_INTERNAL
45 #include "unzip.h"
46 #ifdef WINDLL
47 # include "windll/windll.h"
48 # include <setjmp.h>
49 #endif
50 #include "crypt.h"
51 #include "ttyio.h"
52
53 off_t acelseek(off_t offset, int whence);
54 int aceread(void *buf, size_t count);
55 int aceopen(const char *path, int flags);
56 int aceclose(int fd);
57 int acesize(void);
58 int acetell(int fd);
59 char *replacestr(char *str1, char *str2, char *str3);
60
61 /* setup of codepage conversion for decryption passwords */
62 #if CRYPT
63 # if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
64 # define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
65 # endif
66 # if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
67 # define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
68 # endif
69 #endif
70 #include "ebcdic.h" /* definition/initialization of ebcdic[] */
71
72
73 /*
74 Note: Under Windows, the maximum size of the buffer that can be used
75 with any of the *printf calls is 16,384, so win_fprintf was used to
76 feed the fprintf clone no more than 16K chunks at a time. This should
77 be valid for anything up to 64K (and probably beyond, assuming your
78 buffers are that big).
79 */
80 #ifdef WINDLL
81 # define WriteError(buf,len,strm) \
82 (win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
83 #else /* !WINDLL */
84 # ifdef USE_FWRITE
85 # define WriteError(buf,len,strm) \
86 ((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
87 # else
88 # define WriteError(buf,len,strm) \
89 ((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
90 # endif
91 #endif /* ?WINDLL */
92
93 static int disk_error OF((__GPRO));
94
95
96 /****************************/
97 /* Strings used in fileio.c */
98 /****************************/
99
100 #if (defined(UNIX) || defined(DOS_FLX_OS2_W32) || defined(__BEOS__))
101 static ZCONST char Far CannotDeleteOldFile[] =
102 "error: cannot delete old %s\n";
103 #ifdef UNIXBACKUP
104 static ZCONST char Far CannotRenameOldFile[] =
105 "error: cannot rename old %s\n";
106 static ZCONST char Far BackupSuffix[] = "~";
107 #endif
108 #endif /* UNIX || DOS_FLX_OS2_W32 || __BEOS__ */
109
110 static ZCONST char Far CannotOpenZipfile[] =
111 "error: cannot open zipfile [ %s ]\n";
112 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
113 static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n";
114 #endif
115 #ifdef NOVELL_BUG_FAILSAFE
116 static ZCONST char Far NovellBug[] =
117 "error: %s: stat() says does not exist, but fopen() found anyway\n";
118 #endif
119 static ZCONST char Far ReadError[] = "error: zipfile read error\n";
120 static ZCONST char Far FilenameTooLongTrunc[] =
121 "warning: filename too long--truncating.\n";
122 static ZCONST char Far ExtraFieldTooLong[] =
123 "warning: extra field too long (%d). Ignoring...\n";
124
125 #ifdef WINDLL
126 static ZCONST char Far DiskFullQuery[] =
127 "%s: write error (disk full?).\n";
128 #else
129 static ZCONST char Far DiskFullQuery[] =
130 "%s: write error (disk full?). Continue? (y/n/^C) ";
131 static ZCONST char Far ZipfileCorrupt[] =
132 "error: zipfile probably corrupt (%s)\n";
133 # ifdef SYMLINKS
134 static ZCONST char Far FileIsSymLink[] =
135 "%s exists and is a symbolic link%s.\n";
136 # endif
137 # ifdef MORE
138 static ZCONST char Far MorePrompt[] = "--More--(%lu)";
139 # endif
140 static ZCONST char Far QuitPrompt[] =
141 "--- Press `Q' to quit, or any other key to continue ---";
142 static ZCONST char Far HidePrompt[] = /* "\r \r"; */
143 "\r \r";
144 # if CRYPT
145 # ifdef MACOS
146 /* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
147 static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
148 # else
149 static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
150 # endif
151 static ZCONST char Far PasswPrompt2[] = "Enter password: ";
152 static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
153 # endif /* CRYPT */
154 #endif /* !WINDLL */
155
156
157
158
159
160 /******************************/
161 /* Function open_input_file() */
162 /******************************/
163
164 int open_input_file(__G) /* return 1 if open failed */
165 __GDEF
166 {
167 /*
168 * open the zipfile for reading and in BINARY mode to prevent cr/lf
169 * translation, which would corrupt the bitstreams
170 */
171
172 #if (defined(UNIX) || defined(TOPS20) || defined(AOS_VS) || defined(__BEOS__))
173 G.zipfd = aceopen(G.zipfn, O_RDONLY);
174 #else /* !(UNIX || TOPS20 || AOS_VS || __BEOS__) */
175 #ifdef VMS
176 G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm");
177 #else /* !VMS */
178 #ifdef MACOS
179 G.zipfd = aceopen(G.zipfn, 0);
180 #else /* !MACOS */
181 #ifdef RISCOS
182 G.zipfd = fopen(G.zipfn, "rb");
183 #else /* !RISCOS */
184 #ifdef CMS_MVS
185 G.zipfd = vmmvs_open_infile(__G);
186 #else /* !CMS_MVS */
187 G.zipfd = aceopen(G.zipfn, O_RDONLY | O_BINARY);
188 #endif /* ?CMS_MVS */
189 #endif /* ?RISCOS */
190 #endif /* ?MACOS */
191 #endif /* ?VMS */
192 #endif /* ?(UNIX || TOPS20 || AOS_VS || __BEOS__) */
193
194 #ifdef USE_STRM_INPUT
195 if (G.zipfd == NULL)
196 #else
197 /* if (G.zipfd < 0) */ /* no good for Windows CE port */
198 if (G.zipfd == -1)
199 #endif
200 {
201 Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
202 G.zipfn));
203 return 1;
204 }
205 return 0;
206
207 } /* end function open_input_file() */
208
209
210
211
212 #if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
213
214 /***************************/
215 /* Function open_outfile() */
216 /***************************/
217
218 int open_outfile(__G) /* return 1 if fail */
219 __GDEF
220 {
221 #ifdef DLL
222 if (G.redirect_data)
223 return (redirect_outfile(__G) == FALSE);
224 #endif
225 #ifdef QDOS
226 QFilename(__G__ G.filename);
227 #endif
228 #if (defined(DOS_FLX_OS2_W32) || defined(UNIX) || defined(__BEOS__))
229 #ifdef BORLAND_STAT_BUG
230 /* Borland 5.0's stat() barfs if the filename has no extension and the
231 * file doesn't exist. */
232 if (access(G.filename, 0) == -1) {
233 FILE *tmp = fopen(G.filename, "wb+");
234
235 /* file doesn't exist, so create a dummy file to keep stat() from
236 * failing (will be over-written anyway) */
237 fputc('0', tmp); /* just to have something in the file */
238 fclose(tmp);
239 }
240 #endif /* BORLAND_STAT_BUG */
241 #ifdef SYMLINKS
242 if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0)
243 #else
244 if (SSTAT(G.filename, &G.statbuf) == 0)
245 #endif /* ?SYMLINKS */
246 {
247 Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n",
248 FnFilter1(G.filename)));
249 #ifdef UNIXBACKUP
250 if (uO.B_flag) { /* do backup */
251 char *tname;
252 int blen, flen, tlen;
253
254 blen = strlen(BackupSuffix);
255 flen = strlen(G.filename);
256 tlen = flen + blen + 1;
257 if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */
258 tname = (char *)malloc(FILNAMSIZ);
259 if (tname == NULL)
260 return 1; /* in case we run out of space */
261 tlen = FILNAMSIZ - 1 - blen;
262 strcpy(tname, G.filename); /* make backup name */
263 tname[tlen] = '\0';
264 } else {
265 tname = (char *)malloc(tlen);
266 if (tname == NULL)
267 return 1; /* in case we run out of space */
268 strcpy(tname, G.filename); /* make backup name */
269 }
270 strcpy(tname+flen, BackupSuffix);
271
272 /* GRR: should check if backup file exists, apply -n/-o to that */
273 if (rename(G.filename, tname) < 0) { /* move file */
274 Info(slide, 0x401, ((char *)slide,
275 LoadFarString(CannotRenameOldFile), FnFilter1(G.filename)));
276 free(tname);
277 return 1;
278 }
279 free(tname);
280 } else
281 #endif /* UNIXBACKUP */
282 #ifdef DOS_FLX_OS2_W32
283 if (!(G.statbuf.st_mode & S_IWRITE)) {
284 Trace((stderr, "open_outfile: existing file %s is read-only\n",
285 FnFilter1(G.filename)));
286 chmod(G.filename, S_IREAD | S_IWRITE);
287 Trace((stderr, "open_outfile: %s now writable\n",
288 FnFilter1(G.filename)));
289 }
290 #endif /* DOS_FLX_OS2_W32 */
291 if (unlink(G.filename) != 0) {
292 Info(slide, 0x401, ((char *)slide,
293 LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));
294 return 1;
295 }
296 Trace((stderr, "open_outfile: %s now deleted\n",
297 FnFilter1(G.filename)));
298 }
299 #endif /* DOS_FLX_OS2_W32 || UNIX || __BEOS__ */
300 #ifdef RISCOS
301 if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
302 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
303 FnFilter1(G.filename)));
304 return 1;
305 }
306 #endif /* RISCOS */
307 #ifdef TOPS20
308 char *tfilnam;
309
310 if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
311 return 1;
312 strcpy(tfilnam, G.filename);
313 upper(tfilnam);
314 enquote(tfilnam);
315 if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
316 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
317 tfilnam));
318 free(tfilnam);
319 return 1;
320 }
321 free(tfilnam);
322 #else /* !TOPS20 */
323 #ifdef MTS
324 if (uO.aflag)
325 G.outfile = fopen(G.filename, FOPWT);
326 else
327 G.outfile = fopen(G.filename, FOPW);
328 if (G.outfile == (FILE *)NULL) {
329 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
330 FnFilter1(G.filename)));
331 return 1;
332 }
333 #else /* !MTS */
334 #ifdef TANDEM
335 if (SSTAT(G.filename, &G.statbuf) == 0) {
336 Trace((stderr, "open_outfile: stat(%s) returns 0 (file exists)\n",
337 FnFilter1(G.filename)));
338 if (unlink(G.filename) != 0) {
339 Trace((stderr, "open_outfile: existing file %s is read-only\n",
340 FnFilter1(G.filename)));
341 chmod(G.filename, S_IRUSR | S_IWUSR);
342 Trace((stderr, "open_outfile: %s now writable\n",
343 FnFilter1(G.filename)));
344 if (unlink(G.filename) != 0)
345 return 1;
346 }
347 Trace((stderr, "open_outfile: %s now deleted\n",
348 FnFilter1(G.filename)));
349 }
350 if (G.pInfo->textmode)
351 G.outfile = fopen(G.filename, FOPWT);
352 else
353 G.outfile = fopen(G.filename, FOPW);
354 if (G.outfile == (FILE *)NULL) {
355 Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
356 FnFilter1(G.filename)));
357 return 1;
358 }
359 #else /* !TANDEM */
360 #ifdef DEBUG
361 Info(slide, 1, ((char *)slide,
362 "open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename)));
363 if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL)
364 Info(slide, 1, ((char *)slide,
365 "open_outfile: fopen(%s) for reading failed: does not exist\n",
366 FnFilter1(G.filename)));
367 else {
368 Info(slide, 1, ((char *)slide,
369 "open_outfile: fopen(%s) for reading succeeded: file exists\n",
370 FnFilter1(G.filename)));
371 fclose(G.outfile);
372 }
373 #endif /* DEBUG */
374 #ifdef NOVELL_BUG_FAILSAFE
375 if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) {
376 Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
377 FnFilter1(G.filename)));
378 fclose(G.outfile);
379 return 1; /* with "./" fix in checkdir(), should never reach here */
380 }
381 #endif /* NOVELL_BUG_FAILSAFE */
382 Trace((stderr, "open_outfile: doing fopen(%s) for writing\n",
383 FnFilter1(G.filename)));
384 if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {
385 Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
386 FnFilter1(G.filename)));
387 return 1;
388 }
389 Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n",
390 FnFilter1(G.filename)));
391 #endif /* !TANDEM */
392 #endif /* !MTS */
393 #endif /* !TOPS20 */
394
395 #ifdef USE_FWRITE
396 #ifdef DOS_OS2_W32
397 /* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
398 setbuf(G.outfile, (char *)NULL); /* make output unbuffered */
399 #else /* !DOS_OS2_W32 */
400 #ifndef RISCOS
401 #ifdef _IOFBF /* make output fully buffered (works just about like write()) */
402 setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
403 #else
404 setbuf(G.outfile, (char *)slide);
405 #endif
406 #endif /* !RISCOS */
407 #endif /* ?DOS_OS2_W32 */
408 #endif /* USE_FWRITE */
409 return 0;
410
411 } /* end function open_outfile() */
412
413 #endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
414
415
416
417
418
419 /*
420 * These functions allow NEXTBYTE to function without needing two bounds
421 * checks. Call defer_leftover_input() if you ever have filled G.inbuf
422 * by some means other than readbyte(), and you then want to start using
423 * NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
424 * undefer_input(). For example, extract_or_test_member brackets its
425 * central section that does the decompression with these two functions.
426 * If you need to check the number of bytes remaining in the current
427 * file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
428 */
429
430 /****************************/
431 /* function undefer_input() */
432 /****************************/
433
434 void undefer_input(__G)
435 __GDEF
436 {
437 if (G.incnt > 0)
438 G.csize += G.incnt;
439 if (G.incnt_leftover > 0) {
440 /* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
441 * This condition was checked when G.incnt_leftover was set > 0 in
442 * defer_leftover_input(), and it is NOT allowed to touch G.csize
443 * before calling undefer_input() when (G.incnt_leftover > 0)
444 * (single exception: see read_byte()'s "G.csize <= 0" handling) !!
445 */
446 G.incnt = G.incnt_leftover + (int)G.csize;
447 G.inptr = G.inptr_leftover - (int)G.csize;
448 G.incnt_leftover = 0;
449 } else if (G.incnt < 0)
450 G.incnt = 0;
451 } /* end function undefer_input() */
452
453
454
455
456
457 /***********************************/
458 /* function defer_leftover_input() */
459 /***********************************/
460
461 void defer_leftover_input(__G)
462 __GDEF
463 {
464 if ((long)G.incnt > G.csize) {
465 /* (G.csize < MAXINT), we can safely cast it to int !! */
466 if (G.csize < 0L)
467 G.csize = 0L;
468 G.inptr_leftover = G.inptr + (int)G.csize;
469 G.incnt_leftover = G.incnt - (int)G.csize;
470 G.incnt = (int)G.csize;
471 } else
472 G.incnt_leftover = 0;
473 G.csize -= G.incnt;
474 } /* end function defer_leftover_input() */
475
476
477
478
479
480 /**********************/
481 /* Function readbuf() */
482 /**********************/
483
484 unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */
485 __GDEF
486 char *buf;
487 register unsigned size;
488 {
489 register unsigned count;
490 unsigned n;
491
492 n = size;
493 while (size) {
494 if (G.incnt <= 0) {
495 if ((G.incnt = aceread((char *)G.inbuf, INBUFSIZ)) == 0)
496 return (n-size);
497 else if (G.incnt < 0) {
498 /* another hack, but no real harm copying same thing twice */
499 (*G.message)((zvoid *)&G,
500 (uch *)LoadFarString(ReadError), /* CANNOT use slide */
501 (ulg)strlen(LoadFarString(ReadError)), 0x401);
502 return 0; /* discarding some data; better than lock-up */
503 }
504 /* buffer ALWAYS starts on a block boundary: */
505 G.cur_zipfile_bufstart += INBUFSIZ;
506 G.inptr = G.inbuf;
507 }
508 count = MIN(size, (unsigned)G.incnt);
509 memcpy(buf, G.inptr, count);
510 buf += count;
511 G.inptr += count;
512 G.incnt -= count;
513 size -= count;
514 }
515 return n;
516
517 } /* end function readbuf() */
518
519
520
521
522
523 /***********************/
524 /* Function readbyte() */
525 /***********************/
526
527 int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */
528 __GDEF
529 {
530 if (G.mem_mode)
531 return EOF;
532 if (G.csize <= 0) {
533 G.csize--; /* for tests done after exploding */
534 G.incnt = 0;
535 return EOF;
536 }
537 if (G.incnt <= 0) {
538 if ((G.incnt = aceread((char *)G.inbuf, INBUFSIZ)) == 0) {
539 G.incnt = 0; /* do not allow negative value to affect stuff */
540 return EOF;
541 } else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */
542 /* another hack, but no real harm copying same thing twice */
543 (*G.message)((zvoid *)&G,
544 (uch *)LoadFarString(ReadError),
545 (ulg)strlen(LoadFarString(ReadError)), 0x401);
546 echon();
547 #ifdef WINDLL
548 longjmp(dll_error_return, 1);
549 #else
550 DESTROYGLOBALS()
551 EXIT(PK_BADERR); /* totally bailing; better than lock-up */
552 #endif
553 }
554 G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
555 G.inptr = G.inbuf;
556 defer_leftover_input(__G); /* decrements G.csize */
557 }
558
559 #if CRYPT
560 if (G.pInfo->encrypted) {
561 uch *p;
562 int n;
563
564 /* This was previously set to decrypt one byte beyond G.csize, when
565 * incnt reached that far. GRR said, "but it's required: why?" This
566 * was a bug in fillinbuf() -- was it also a bug here?
567 */
568 for (n = G.incnt, p = G.inptr; n--; p++)
569 zdecode(*p);
570 }
571 #endif /* CRYPT */
572
573 --G.incnt;
574 return *G.inptr++;
575
576 } /* end function readbyte() */
577
578
579
580
581
582 #ifdef USE_ZLIB
583
584 /************************/
585 /* Function fillinbuf() */
586 /************************/
587
588 int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
589 __GDEF
590 {
591 if (G.mem_mode ||
592 (G.incnt = aceread((char *)G.inbuf, INBUFSIZ)) <= 0)
593 return 0;
594 G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */
595 G.inptr = G.inbuf;
596 defer_leftover_input(__G); /* decrements G.csize */
597
598 #if CRYPT
599 if (G.pInfo->encrypted) {
600 uch *p;
601 int n;
602
603 for (n = G.incnt, p = G.inptr; n--; p++)
604 zdecode(*p);
605 }
606 #endif /* CRYPT */
607
608 return G.incnt;
609
610 } /* end function fillinbuf() */
611
612 #endif /* USE_ZLIB */
613
614
615
616
617
618 #ifndef VMS /* for VMS use code in vms.c */
619
620 /********************/
621 /* Function flush() */ /* returns PK error codes: */
622 /********************/ /* if cflag => always 0; PK_DISK if write error */
623
624 int flush(__G__ rawbuf, size, unshrink)
625 __GDEF
626 uch *rawbuf;
627 ulg size;
628 int unshrink;
629 {
630 register uch *p, *q;
631 uch *transbuf;
632 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
633 ulg transbufsiz;
634 #endif
635 /* static int didCRlast = FALSE; moved to globals.h */
636
637
638 /*---------------------------------------------------------------------------
639 Compute the CRC first; if testing or if disk is full, that's it.
640 ---------------------------------------------------------------------------*/
641
642 G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
643
644 #ifdef DLL
645 if ((G.statreportcb != NULL) &&
646 (*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))
647 return IZ_CTRLC; /* cancel operation by user request */
648 #endif
649
650 if (uO.tflag || size == 0L) /* testing or nothing to write: all done */
651 return PK_OK;
652
653 if (G.disk_full)
654 return PK_DISK; /* disk already full: ignore rest of file */
655
656 /*---------------------------------------------------------------------------
657 Write the bytes rawbuf[0..size-1] to the output device, first converting
658 end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
659 defined, outbuf is assumed to be at least as large as rawbuf and is not
660 necessarily checked for overflow.
661 ---------------------------------------------------------------------------*/
662
663 if (!G.pInfo->textmode) { /* write raw binary data */
664 /* GRR: note that for standard MS-DOS compilers, size argument to
665 * fwrite() can never be more than 65534, so WriteError macro will
666 * have to be rewritten if size can ever be that large. For now,
667 * never more than 32K. Also note that write() returns an int, which
668 * doesn't necessarily limit size to 32767 bytes if write() is used
669 * on 16-bit systems but does make it more of a pain; however, because
670 * at least MSC 5.1 has a lousy implementation of fwrite() (as does
671 * DEC Ultrix cc), write() is used anyway.
672 */
673 #ifdef DLL
674 if (G.redirect_data)
675 writeToMemory(__G__ rawbuf, size);
676 else
677 #endif
678 if (!uO.cflag && WriteError(rawbuf, size, G.outfile))
679 return disk_error(__G);
680 else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
681 return 0;
682 } else { /* textmode: aflag is true */
683 if (unshrink) {
684 /* rawbuf = outbuf */
685 transbuf = G.outbuf2;
686 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
687 transbufsiz = TRANSBUFSIZ;
688 #endif
689 } else {
690 /* rawbuf = slide */
691 transbuf = G.outbuf;
692 #if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
693 transbufsiz = OUTBUFSIZ;
694 Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n", OUTBUFSIZ));
695 #endif
696 }
697 if (G.newfile) {
698 #ifdef VMS_TEXT_CONV
699 /* GRR: really want to check if -aa (or -aaa?) was given... */
700 if (rawbuf[1]) { /* first line is more than 255 chars long */
701 Trace((stderr,
702 "\nfirst line of VMS `text' too long; switching to normal extraction\n"));
703 G.VMS_line_state = -1; /* -1: don't treat as VMS text */
704 } else
705 G.VMS_line_state = 0; /* 0: ready to read line length */
706 #endif
707 G.didCRlast = FALSE; /* no previous buffers written */
708 G.newfile = FALSE;
709 }
710
711 #ifdef VMS_TEXT_CONV
712 if (G.pInfo->hostnum == VMS_ && G.extra_field && G.VMS_line_state >= 0)
713 {
714 /* GRR: really want to check for actual VMS extra field, and
715 * ideally for variable-length record format */
716 /*
717 printf("\n>>>>>> GRR: file is VMS text and has an extra field\n");
718 */
719
720 p = rawbuf;
721 q = transbuf;
722 while(p < rawbuf+(unsigned)size) {
723 switch (G.VMS_line_state) {
724
725 /* 0: ready to read line length */
726 case 0:
727 G.VMS_line_length = 0;
728 G.VMS_line_pad = 0;
729 if (p == rawbuf+(unsigned)size-1) { /* last char */
730 G.VMS_line_length = (int)((uch)(*p++));
731 G.VMS_line_state = 1;
732 } else {
733 G.VMS_line_length = makeword(p);
734 p += 2;
735 G.VMS_line_state = 2;
736 }
737 if (G.VMS_line_length & 1) /* odd */
738 G.VMS_line_pad = 1;
739 break;
740
741 /* 1: read one byte of length, need second */
742 case 1:
743 G.VMS_line_length += ((int)((uch)(*p++)) << 8);
744 G.VMS_line_state = 2;
745 break;
746
747 /* 2: ready to read VMS_line_length chars */
748 case 2:
749 if (G.VMS_line_length < rawbuf+(unsigned)size-p) {
750 if (G.VMS_line_length >=
751 transbuf+(unsigned)transbufsiz-q)
752 {
753 int outroom = transbuf+(unsigned)transbufsiz-q;
754
755 /* GRR: need to change this to *q++ = native(*p++); loop or something */
756 memcpy(q, p, outroom);
757 #ifdef DLL
758 if (G.redirect_data)
759 writeToMemory(__G__ transbuf,
760 (unsigned)outroom);
761 else
762 #endif
763 if (!uO.cflag && WriteError(transbuf,
764 (unsigned)outroom, G.outfile))
765 return disk_error(__G);
766 else if (uO.cflag && (*G.message)((zvoid *)&G,
767 transbuf, (ulg)outroom, 0))
768 return 0;
769 q = transbuf;
770 p += outroom;
771 G.VMS_line_length -= outroom;
772 /* fall through to normal case */
773 }
774 /* GRR: need to change this to *q++ = native(*p++); loop or something */
775 memcpy(q, p, G.VMS_line_length);
776 q += G.VMS_line_length;
777 p += G.VMS_line_length;
778 G.VMS_line_length = 0; /* necessary?? */
779 G.VMS_line_state = 3;
780
781 } else { /* remaining input is less than full line */
782 int remaining = rawbuf+(unsigned)size-p;
783
784 if (remaining <
785 transbuf+(unsigned)transbufsiz-q)
786 {
787 int outroom = transbuf+(unsigned)transbufsiz-q;
788
789 /* GRR: need to change this to *q++ = native(*p++); loop or something */
790 memcpy(q, p, outroom);
791 #ifdef DLL
792 if (G.redirect_data)
793 writeToMemory(__G__ transbuf,
794 (unsigned)(outroom));
795 else
796 #endif
797 if (!uO.cflag && WriteError(transbuf,
798 (unsigned)outroom, G.outfile))
799 return disk_error(__G);
800 else if (uO.cflag && (*G.message)((zvoid *)&G,
801 transbuf, (ulg)outroom, 0))
802 return 0;
803 q = transbuf;
804 p += outroom;
805 remaining -= outroom;
806 }
807 /* GRR: need to change this to *q++ = native(*p++); loop or something */
808 memcpy(q, p, remaining);
809 q += remaining;
810 p += remaining;
811 G.VMS_line_length -= remaining;
812 /* no change in G.VMS_line_state */
813 }
814 break;
815
816 /* 3: ready to PutNativeEOL */
817 case 3:
818 if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
819 #ifdef DLL
820 if (G.redirect_data)
821 writeToMemory(__G__ transbuf,
822 (unsigned)(q-transbuf));
823 else
824 #endif
825 if (!uO.cflag &&
826 WriteError(transbuf, (unsigned)(q-transbuf),
827 G.outfile))
828 return disk_error(__G);
829 else if (uO.cflag && (*G.message)((zvoid *)&G,
830 transbuf, (ulg)(q-transbuf), 0))
831 return 0;
832 q = transbuf;
833 }
834 PutNativeEOL
835 if (G.VMS_line_pad)
836 if (p < rawbuf+(unsigned)size) {
837 ++p;
838 G.VMS_line_state = 0;
839 } else
840 G.VMS_line_state = 4;
841 else
842 G.VMS_line_state = 0;
843 break;
844
845 /* 4: ready to read pad byte */
846 case 4:
847 ++p;
848 G.VMS_line_state = 0;
849 break;
850 }
851 } /* end while */
852
853 } else
854 #endif /* VMS_TEXT_CONV */
855
856 /*-----------------------------------------------------------------------
857 Algorithm: CR/LF => native; lone CR => native; lone LF => native.
858 This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
859 stream-oriented files, not record-oriented).
860 -----------------------------------------------------------------------*/
861
862 /* else not VMS text */ {
863 p = rawbuf;
864 if (*p == LF && G.didCRlast)
865 ++p;
866 G.didCRlast = FALSE;
867 for (q = transbuf; p < rawbuf+(unsigned)size; ++p) {
868 if (*p == CR) { /* lone CR or CR/LF: EOL either way */
869 PutNativeEOL
870 if (p == rawbuf+(unsigned)size-1) /* last char in buffer */
871 G.didCRlast = TRUE;
872 else if (p[1] == LF) /* get rid of accompanying LF */
873 ++p;
874 } else if (*p == LF) /* lone LF */
875 PutNativeEOL
876 else
877 #ifndef DOS_FLX_OS2_W32
878 if (*p != CTRLZ) /* lose all ^Z's */
879 #endif
880 *q++ = native(*p);
881
882 #if (defined(SMALL_MEM) || defined(MED_MEM))
883 # if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
884 if (!unshrink)
885 # endif
886 /* check for danger of buffer overflow and flush */
887 if (q > transbuf+(unsigned)transbufsiz-lenEOL) {
888 Trace((stderr,
889 "p - rawbuf = %u q-transbuf = %u size = %lu\n",
890 (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
891 if (!uO.cflag && WriteError(transbuf,
892 (unsigned)(q-transbuf), G.outfile))
893 return disk_error(__G);
894 else if (uO.cflag && (*G.message)((zvoid *)&G,
895 transbuf, (ulg)(q-transbuf), 0))
896 return 0;
897 q = transbuf;
898 continue;
899 }
900 #endif /* SMALL_MEM || MED_MEM */
901 }
902 }
903
904 /*-----------------------------------------------------------------------
905 Done translating: write whatever we've got to file (or screen).
906 -----------------------------------------------------------------------*/
907
908 Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
909 (unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
910 if (q > transbuf) {
911 #ifdef DLL
912 if (G.redirect_data)
913 writeToMemory(__G__ transbuf, (unsigned)(q-transbuf));
914 else
915 #endif
916 if (!uO.cflag && WriteError(transbuf, (unsigned)(q-transbuf),
917 G.outfile))
918 return disk_error(__G);
919 else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
920 (ulg)(q-transbuf), 0))
921 return 0;
922 }
923 }
924
925 return 0;
926
927 } /* end function flush() */
928
929
930
931
932
933 /*************************/
934 /* Function disk_error() */
935 /*************************/
936
937 static int disk_error(__G)
938 __GDEF
939 {
940 /* OK to use slide[] here because this file is finished regardless */
941 Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
942 FnFilter1(G.filename)));
943
944 #ifndef WINDLL
945 fgets(G.answerbuf, 9, stdin);
946 if (*G.answerbuf == 'y') /* stop writing to this file */
947 G.disk_full = 1; /* (outfile bad?), but new OK */
948 else
949 #endif
950 G.disk_full = 2; /* no: exit program */
951
952 return PK_DISK;
953
954 } /* end function disk_error() */
955
956 #endif /* !VMS */
957
958
959
960
961
962 /*****************************/
963 /* Function UzpMessagePrnt() */
964 /*****************************/
965
966 int UZ_EXP UzpMessagePrnt(pG, buf, size, flag)
967 zvoid *pG; /* globals struct: always passed */
968 uch *buf; /* preformatted string to be printed */
969 ulg size; /* length of string (may include nulls) */
970 int flag; /* flag bits */
971 {
972 /* IMPORTANT NOTE:
973 * The name of the first parameter of UzpMessagePrnt(), which passes
974 * the "Uz_Globs" address, >>> MUST <<< be identical to the string
975 * expansion of the __G__ macro in the REENTRANT case (see globals.h).
976 * This name identity is mandatory for the LoadFarString() macro
977 * (in the SMALL_MEM case) !!!
978 */
979 int error;
980 uch *q=buf, *endbuf=buf+(unsigned)size;
981 #ifdef MORE
982 uch *p=buf-1;
983 #endif
984 FILE *outfp;
985
986
987 /*---------------------------------------------------------------------------
988 These tests are here to allow fine-tuning of UnZip's output messages,
989 but none of them will do anything without setting the appropriate bit
990 in the flag argument of every Info() statement which is to be turned
991 *off*. That is, all messages are currently turned on for all ports.
992 To turn off *all* messages, use the UzpMessageNull() function instead
993 of this one.
994 ---------------------------------------------------------------------------*/
995
996 #if (defined(OS2) && defined(DLL))
997 if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */
998 return 0;
999 #endif
1000 #ifdef WINDLL
1001 if (MSG_NO_WDLL(flag))
1002 return 0;
1003 #endif
1004 #ifdef WINDLL
1005 if (MSG_NO_WGUI(flag))
1006 return 0;
1007 #endif
1008 /*
1009 #ifdef ACORN_GUI
1010 if (MSG_NO_AGUI(flag))
1011 return 0;
1012 #endif
1013 */
1014 #ifdef DLL /* don't display message if data is redirected */
1015 if (((Uz_Globs *)pG)->redirect_data &&
1016 !((Uz_Globs *)pG)->redirect_text)
1017 return 0;
1018 #endif
1019
1020 if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
1021 outfp = (FILE *)stderr;
1022 else
1023 outfp = (FILE *)stdout;
1024
1025 #ifdef QUERY_TRNEWLN
1026 /* some systems require termination of query prompts with '\n' to force
1027 * immediate display */
1028 if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */
1029 *endbuf++ = '\n'; /* with room for one more char at end of buf */
1030 ++size; /* (safe assumption: only used for four */
1031 } /* short queries in extract.c and fileio.c) */
1032 #endif
1033
1034 if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */
1035 if ((!size && !((Uz_Globs *)pG)->sol) ||
1036 (size && (endbuf[-1] != '\n')))
1037 {
1038 *endbuf++ = '\n';
1039 ++size;
1040 }
1041 }
1042
1043 #ifdef MORE
1044 /* room for --More-- and one line of overlap: */
1045 ((Uz_Globs *)pG)->height = SCREENLINES - 2;
1046 #endif
1047
1048 if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
1049 /* not at start of line: want newline */
1050 #ifdef OS2DLL
1051 if (!((Uz_Globs *)pG)->redirect_text) {
1052 #endif
1053 putc('\n', outfp);
1054 fflush(outfp);
1055 #ifdef MORE
1056 if (((Uz_Globs *)pG)->M_flag)
1057 {
1058 ++((Uz_Globs *)pG)->numlines;
1059 if (((Uz_Globs *)pG)->numlines %
1060 ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */
1061 (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
1062 LoadFarString(MorePrompt), 1);
1063 }
1064 #endif /* MORE */
1065 if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1066 !isatty(1) && isatty(2))
1067 {
1068 /* error output from testing redirected: also send to stderr */
1069 putc('\n', stderr);
1070 fflush(stderr);
1071 }
1072 #ifdef OS2DLL
1073 } else
1074 REDIRECTC('\n');
1075 #endif
1076 ((Uz_Globs *)pG)->sol = TRUE;
1077 }
1078
1079 /* put zipfile name, filename and/or error/warning keywords here */
1080
1081 #ifdef MORE
1082 if (((Uz_Globs *)pG)->M_flag
1083 #ifdef OS2DLL
1084 && !((Uz_Globs *)pG)->redirect_text
1085 #endif
1086 )
1087 {
1088 while (++p < endbuf) {
1089 if (*p == '\n') {
1090 ++((Uz_Globs *)pG)->numlines;
1091 if (((Uz_Globs *)pG)->numlines %
1092 ((Uz_Globs *)pG)->height == 0L) /* GRR: fix */
1093 {
1094 if ((error = WriteError(q, p-q+1, outfp)) != 0)
1095 return error;
1096 fflush(outfp);
1097 ((Uz_Globs *)pG)->sol = TRUE;
1098 q = p + 1;
1099 (*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
1100 LoadFarString(MorePrompt), 1);
1101 }
1102 }
1103 } /* end while */
1104 size = (ulg)(p - q); /* remaining text */
1105 }
1106 #endif /* MORE */
1107
1108 if (size) {
1109 #ifdef OS2DLL
1110 if (!((Uz_Globs *)pG)->redirect_text) {
1111 #endif
1112 if ((error = WriteError(q, size, outfp)) != 0)
1113 return error;
1114 fflush(outfp);
1115 if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1116 !isatty(1) && isatty(2))
1117 {
1118 /* error output from testing redirected: also send to stderr */
1119 if ((error = WriteError(q, size, stderr)) != 0)
1120 return error;
1121 fflush(stderr);
1122 }
1123 #ifdef OS2DLL
1124 } else { /* GRR: this is ugly: hide with macro */
1125 if ((error = REDIRECTPRINT(q, size)) != 0)
1126 return error;
1127 }
1128 #endif
1129 ((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
1130 }
1131 return 0;
1132
1133 } /* end function UzpMessagePrnt() */
1134
1135
1136
1137
1138
1139 #ifdef DLL
1140
1141 /*****************************/
1142 /* Function UzpMessageNull() */ /* convenience routine for no output at all */
1143 /*****************************/
1144
1145 int UZ_EXP UzpMessageNull(pG, buf, size, flag)
1146 zvoid *pG; /* globals struct: always passed */
1147 uch *buf; /* preformatted string to be printed */
1148 ulg size; /* length of string (may include nulls) */
1149 int flag; /* flag bits */
1150 {
1151 return 0;
1152
1153 } /* end function UzpMessageNull() */
1154
1155 #endif /* DLL */
1156
1157
1158
1159
1160
1161 /***********************/
1162 /* Function UzpInput() */ /* GRR: this is a placeholder for now */
1163 /***********************/
1164
1165 int UZ_EXP UzpInput(pG, buf, size, flag)
1166 zvoid *pG; /* globals struct: always passed */
1167 uch *buf; /* preformatted string to be printed */
1168 int *size; /* (address of) size of buf and of returned string */
1169 int flag; /* flag bits (bit 0: no echo) */
1170 {
1171 /* tell picky compilers to shut up about "unused variable" warnings */
1172 pG = pG; buf = buf; flag = flag;
1173
1174 *size = 0;
1175 return 0;
1176
1177 } /* end function UzpInput() */
1178
1179
1180
1181
1182
1183 #if (!defined(WINDLL) && !defined(MACOS))
1184
1185 /***************************/
1186 /* Function UzpMorePause() */
1187 /***************************/
1188
1189 void UZ_EXP UzpMorePause(pG, prompt, flag)
1190 zvoid *pG; /* globals struct: always passed */
1191 ZCONST char *prompt; /* "--More--" prompt */
1192 int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
1193 {
1194 #if 0
1195 uch c;
1196
1197 /*---------------------------------------------------------------------------
1198 Print a prompt and wait for the user to press a key, then erase prompt
1199 if possible.
1200 ---------------------------------------------------------------------------*/
1201
1202 if (!((Uz_Globs *)pG)->sol)
1203 fprintf(stderr, "\n");
1204 /* numlines may or may not be used: */
1205 fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);
1206 fflush(stderr);
1207 if (flag & 1) {
1208 do {
1209 c = (uch)FGETCH(0);
1210 } while (c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
1211 } else
1212 c = (uch)FGETCH(0);
1213
1214 /* newline was not echoed, so cover up prompt line */
1215 fprintf(stderr, LoadFarString(HidePrompt));
1216 fflush(stderr);
1217
1218 if (ToLower(c) == 'q') {
1219 DESTROYGLOBALS()
1220 EXIT(PK_COOL);
1221 }
1222
1223 ((Uz_Globs *)pG)->sol = TRUE;
1224
1225 #endif
1226 } /* end function UzpMorePause() */
1227
1228 #endif /* !WINDLL && !MACOS */
1229
1230
1231
1232
1233 #ifndef WINDLL
1234
1235 /**************************/
1236 /* Function UzpPassword() */
1237 /**************************/
1238
1239 int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)
1240 zvoid *pG; /* pointer to UnZip's internal global vars */
1241 int *rcnt; /* retry counter */
1242 char *pwbuf; /* buffer for password */
1243 int size; /* size of password buffer */
1244 ZCONST char *zfn; /* name of zip archive */
1245 ZCONST char *efn; /* name of archive entry being processed */
1246 {
1247 #if CRYPT
1248 int r = IZ_PW_ENTERED;
1249 char *m;
1250 char *prompt;
1251
1252 #ifndef REENTRANT
1253 /* tell picky compilers to shut up about "unused variable" warnings */
1254 pG = pG;
1255 #endif
1256
1257 if (*rcnt == 0) { /* First call for current entry */
1258 *rcnt = 2;
1259 if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
1260 sprintf(prompt, LoadFarString(PasswPrompt),
1261 FnFilter1(zfn), FnFilter2(efn));
1262 m = prompt;
1263 } else
1264 m = (char *)LoadFarString(PasswPrompt2);
1265 } else { /* Retry call, previous password was wrong */
1266 (*rcnt)--;
1267 prompt = NULL;
1268 m = (char *)LoadFarString(PasswRetry);
1269 }
1270
1271 m = getp(__G__ m, pwbuf, size);
1272 if (prompt != (char *)NULL) {
1273 free(prompt);
1274 }
1275 if (m == (char *)NULL) {
1276 r = IZ_PW_ERROR;
1277 }
1278 else if (*pwbuf == '\0') {
1279 r = IZ_PW_CANCELALL;
1280 }
1281 return r;
1282
1283 #else /* !CRYPT */
1284 /* tell picky compilers to shut up about "unused variable" warnings */
1285 pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
1286
1287 return IZ_PW_ERROR; /* internal error; function should never get called */
1288 #endif /* ?CRYPT */
1289
1290 } /* end function UzpPassword() */
1291
1292
1293
1294
1295
1296 /**********************/
1297 /* Function handler() */
1298 /**********************/
1299
1300 void handler(signal) /* upon interrupt, turn on echo and exit cleanly */
1301 int signal;
1302 {
1303 GETGLOBALS();
1304
1305 #if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
1306 (*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */
1307 #endif /* slide[] should be safe) */
1308
1309 echon();
1310
1311 #ifdef SIGBUS
1312 if (signal == SIGBUS) {
1313 Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1314 "bus error"));
1315 DESTROYGLOBALS()
1316 EXIT(PK_BADERR);
1317 }
1318 #endif /* SIGBUS */
1319
1320 #ifdef SIGSEGV
1321 if (signal == SIGSEGV) {
1322 Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1323 "segmentation violation"));
1324 DESTROYGLOBALS()
1325 EXIT(PK_BADERR);
1326 }
1327 #endif /* SIGSEGV */
1328
1329 /* probably ctrl-C */
1330 DESTROYGLOBALS()
1331 #if defined(AMIGA) && defined(__SASC)
1332 _abort();
1333 #endif
1334 EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */
1335 }
1336
1337 #endif /* !WINDLL */
1338
1339
1340
1341
1342 #if (!defined(VMS) && !defined(CMS_MVS))
1343 #if (!defined(OS2) || defined(TIMESTAMP))
1344
1345 #if (!defined(HAVE_MKTIME) || defined(AMIGA) || defined(WIN32))
1346 /* also used in amiga/filedate.c and win32/win32.c */
1347 ZCONST ush ydays[] =
1348 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
1349 #endif
1350
1351 /*******************************/
1352 /* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1353 /*******************************/
1354
1355 time_t dos_to_unix_time(dosdatetime)
1356 ulg dosdatetime;
1357 {
1358 time_t m_time;
1359
1360 #ifdef HAVE_MKTIME
1361
1362 ZCONST time_t now = time(NULL);
1363 struct tm *tm;
1364 # define YRBASE 1900
1365
1366 tm = localtime(&now);
1367 tm->tm_isdst = -1; /* let mktime determine if DST is in effect */
1368
1369 /* dissect date */
1370 tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
1371 tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1;
1372 tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);
1373
1374 /* dissect time */
1375 tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;
1376 tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f;
1377 tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e;
1378
1379 m_time = mktime(tm);
1380 NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
1381 TTrace((stderr, " final m_time = %lu\n", (ulg)m_time));
1382
1383 #else /* !HAVE_MKTIME */
1384
1385 int yr, mo, dy, hh, mm, ss;
1386 #ifdef TOPS20
1387 # define YRBASE 1900
1388 struct tmx *tmx;
1389 char temp[20];
1390 #else /* !TOPS20 */
1391 # define YRBASE 1970
1392 int leap;
1393 unsigned days;
1394 struct tm *tm;
1395 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1396 #ifdef WIN32
1397 TIME_ZONE_INFORMATION tzinfo;
1398 DWORD res;
1399 #else /* ! WIN32 */
1400 #ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
1401 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1402 struct timeb tbp;
1403 #else /* !(BSD || MTS || __GO32__) */
1404 #ifdef DECLARE_TIMEZONE
1405 extern time_t timezone;
1406 #endif
1407 #endif /* ?(BSD || MTS || __GO32__) */
1408 #endif /* !BSD4_4 */
1409 #endif /* ?WIN32 */
1410 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1411 #endif /* ?TOPS20 */
1412
1413
1414 /* dissect date */
1415 yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
1416 mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
1417 dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
1418
1419 /* dissect time */
1420 hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
1421 mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
1422 ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
1423
1424 #ifdef TOPS20
1425 tmx = (struct tmx *)malloc(sizeof(struct tmx));
1426 sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
1427 time_parse(temp, tmx, (char *)0);
1428 m_time = time_make(tmx);
1429 free(tmx);
1430
1431 #else /* !TOPS20 */
1432
1433 /*---------------------------------------------------------------------------
1434 Calculate the number of seconds since the epoch, usually 1 January 1970.
1435 ---------------------------------------------------------------------------*/
1436
1437 /* leap = # of leap yrs from YRBASE up to but not including current year */
1438 leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
1439
1440 /* calculate days from BASE to this year and add expired days this year */
1441 days = (yr * 365) + (leap - 492) + ydays[mo];
1442
1443 /* if year is a leap year and month is after February, add another day */
1444 if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
1445 ++days; /* OK through 2199 */
1446
1447 /* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
1448 m_time = (time_t)((unsigned long)(days + dy) * 86400L +
1449 (unsigned long)hh * 3600L +
1450 (unsigned long)(mm * 60 + ss));
1451 /* - 1; MS-DOS times always rounded up to nearest even second */
1452 TTrace((stderr, "dos_to_unix_time:\n"));
1453 TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time));
1454
1455 /*---------------------------------------------------------------------------
1456 Adjust for local standard timezone offset.
1457 ---------------------------------------------------------------------------*/
1458
1459 #if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1460 #ifdef WIN32
1461 /* account for timezone differences */
1462 res = GetTimeZoneInformation(&tzinfo);
1463 if (res != TIME_ZONE_ID_UNKNOWN)
1464 {
1465 m_time += 60*(tzinfo.Bias);
1466 #else /* !WIN32 */
1467 #if (defined(BSD) || defined(MTS) || defined(__GO32__))
1468 #ifdef BSD4_4
1469 if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1470 (m_time < (time_t)0x70000000L) )
1471 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1472 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1473 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1474 if ((tm = localtime(&m_time)) != (struct tm *)NULL)
1475 m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */
1476 #else /* !(BSD4_4 */
1477 ftime(&tbp); /* get `timezone' */
1478 m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */
1479 #endif /* ?(BSD4_4 || __EMX__) */
1480 #else /* !(BSD || MTS || __GO32__) */
1481 /* tzset was already called at start of process_zipfiles() */
1482 /* tzset(); */ /* set `timezone' variable */
1483 #ifndef __BEOS__ /* BeOS DR8 has no timezones... */
1484 m_time += timezone; /* seconds WEST of GMT: add */
1485 #endif
1486 #endif /* ?(BSD || MTS || __GO32__) */
1487 #endif /* ?WIN32 */
1488 TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time));
1489
1490 /*---------------------------------------------------------------------------
1491 Adjust for local daylight savings (summer) time.
1492 ---------------------------------------------------------------------------*/
1493
1494 #ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
1495 if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1496 (m_time < (time_t)0x70000000L) )
1497 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1498 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1499 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1500 TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */
1501 if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)
1502 #ifdef WIN32
1503 m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */
1504 else
1505 m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */
1506 #else
1507 m_time -= 60L * 60L; /* adjust for daylight savings time */
1508 #endif
1509 NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
1510 TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time));
1511 #endif /* !BSD4_4 */
1512 #ifdef WIN32
1513 }
1514 #endif
1515 #endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1516 #endif /* ?TOPS20 */
1517
1518 #endif /* ?HAVE_MKTIME */
1519
1520 if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1521 (m_time < (time_t)0x70000000L) )
1522 m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1523 if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1524 m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1525
1526 return m_time;
1527
1528 } /* end function dos_to_unix_time() */
1529
1530 #endif /* !OS2 || TIMESTAMP */
1531 #endif /* !VMS && !CMS_MVS */
1532
1533
1534
1535 #if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1536
1537 /******************************/
1538 /* Function check_for_newer() */ /* used for overwriting/freshening/updating */
1539 /******************************/
1540
1541 int check_for_newer(__G__ filename) /* return 1 if existing file is newer */
1542 __GDEF /* or equal; 0 if older; -1 if doesn't */
1543 char *filename; /* exist yet */
1544 {
1545 time_t existing, archive;
1546 #ifdef USE_EF_UT_TIME
1547 iztimes z_utime;
1548 #endif
1549 #ifdef AOS_VS
1550 long dyy, dmm, ddd, dhh, dmin, dss;
1551
1552
1553 dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
1554 dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
1555 ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
1556 dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
1557 dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
1558 dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
1559
1560 /* under AOS/VS, file times can only be set at creation time,
1561 * with the info in a special DG format. Make sure we can create
1562 * it here - we delete it later & re-create it, whether or not
1563 * it exists now.
1564 */
1565 if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
1566 (dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
1567 return DOES_NOT_EXIST;
1568 #endif /* AOS_VS */
1569
1570 Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename)));
1571 if (SSTAT(filename, &G.statbuf)) {
1572 Trace((stderr,
1573 "check_for_newer: stat(%s) returns %d: file does not exist\n",
1574 FnFilter1(filename), SSTAT(filename, &G.statbuf)));
1575 #ifdef SYMLINKS
1576 Trace((stderr, "check_for_newer: doing lstat(%s)\n",
1577 FnFilter1(filename)));
1578 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1579 if (lstat(filename, &G.statbuf) == 0) {
1580 Trace((stderr,
1581 "check_for_newer: lstat(%s) returns 0: symlink does exist\n",
1582 FnFilter1(filename)));
1583 if (QCOND2 && !uO.overwrite_all)
1584 Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
1585 FnFilter1(filename), " with no real file"));
1586 return EXISTS_AND_OLDER; /* symlink dates are meaningless */
1587 }
1588 #endif /* SYMLINKS */
1589 return DOES_NOT_EXIST;
1590 }
1591 Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n",
1592 FnFilter1(filename)));
1593
1594 #ifdef SYMLINKS
1595 /* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1596 if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
1597 Trace((stderr, "check_for_newer: %s is a symbolic link\n",
1598 FnFilter1(filename)));
1599 if (QCOND2 && !uO.overwrite_all)
1600 Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
1601 FnFilter1(filename), ""));
1602 return EXISTS_AND_OLDER; /* symlink dates are meaningless */
1603 }
1604 #endif /* SYMLINKS */
1605
1606 NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */
1607
1608 #ifdef USE_EF_UT_TIME
1609 /* The `Unix extra field mtime' should be used for comparison with the
1610 * time stamp of the existing file >>>ONLY<<< when the EF info is also
1611 * used to set the modification time of the extracted file.
1612 */
1613 if (G.extra_field &&
1614 #ifdef IZ_CHECK_TZ
1615 G.tz_is_valid &&
1616 #endif
1617 (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
1618 G.lrec.last_mod_dos_datetime, &z_utime, NULL)
1619 & EB_UT_FL_MTIME))
1620 {
1621 TTrace((stderr, "check_for_newer: using Unix extra field mtime\n"));
1622 existing = G.statbuf.st_mtime;
1623 archive = z_utime.mtime;
1624 } else {
1625 /* round up existing filetime to nearest 2 seconds for comparison,
1626 * but saturate in case of arithmetic overflow
1627 */
1628 existing = ((G.statbuf.st_mtime & 1) &&
1629 (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
1630 G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
1631 archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
1632 }
1633 #else /* !USE_EF_UT_TIME */
1634 /* round up existing filetime to nearest 2 seconds for comparison,
1635 * but saturate in case of arithmetic overflow
1636 */
1637 existing = ((G.statbuf.st_mtime & 1) &&
1638 (G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
1639 G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
1640 archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
1641 #endif /* ?USE_EF_UT_TIME */
1642
1643 TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
1644 (ulg)existing, (ulg)archive, (long)(existing-archive)));
1645
1646 return (existing >= archive);
1647
1648 } /* end function check_for_newer() */
1649
1650 #endif /* !VMS && !OS2 && !CMS_MVS */
1651
1652
1653
1654
1655
1656 /************************/
1657 /* Function do_string() */
1658 /************************/
1659
1660 int do_string(__G__ len, option) /* return PK-type error code */
1661 __GDEF
1662 unsigned int len; /* without prototype, ush converted to this */
1663 int option;
1664 {
1665 long comment_bytes_left, block_length;
1666 int error=PK_OK;
1667 ush extra_len;
1668 #ifdef AMIGA
1669 char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */
1670 #endif
1671
1672
1673 /*---------------------------------------------------------------------------
1674 This function processes arbitrary-length (well, usually) strings. Four
1675 options are allowed: SKIP, wherein the string is skipped (pretty logical,
1676 eh?); DISPLAY, wherein the string is printed to standard output after un-
1677 dergoing any necessary or unnecessary character conversions; DS_FN,
1678 wherein the string is put into the filename[] array after undergoing ap-
1679 propriate conversions (including case-conversion, if that is indicated:
1680 see the global variable pInfo->lcflag); and EXTRA_FIELD, wherein the
1681 `string' is assumed to be an extra field and is copied to the (freshly
1682 malloced) buffer G.extra_field. The third option should be OK since
1683 filename is dimensioned at 1025, but we check anyway.
1684
1685 The string, by the way, is assumed to start at the current file-pointer
1686 position; its length is given by len. So start off by checking length
1687 of string: if zero, we're already done.
1688 ---------------------------------------------------------------------------*/
1689
1690 if (!len)
1691 return PK_COOL;
1692
1693 switch (option) {
1694
1695 /*
1696 * First case: print string on standard output. First set loop vari-
1697 * ables, then loop through the comment in chunks of OUTBUFSIZ bytes,
1698 * converting formats and printing as we go. The second half of the
1699 * loop conditional was added because the file might be truncated, in
1700 * which case comment_bytes_left will remain at some non-zero value for
1701 * all time. outbuf and slide are used as scratch buffers because they
1702 * are available (we should be either before or in between any file pro-
1703 * cessing).
1704 */
1705
1706 case DISPLAY:
1707 case DISPL_8:
1708 comment_bytes_left = len;
1709 block_length = OUTBUFSIZ; /* for the while statement, first time */
1710 while (comment_bytes_left > 0 && block_length > 0) {
1711 register uch *p = G.outbuf;
1712 register uch *q = G.outbuf;
1713
1714 if ((block_length = readbuf(__G__ (char *)G.outbuf,
1715 (unsigned) MIN((long)OUTBUFSIZ, comment_bytes_left))) == 0)
1716 return PK_EOF;
1717 comment_bytes_left -= block_length;
1718
1719 /* this is why we allocated an extra byte for outbuf: terminate
1720 * with zero (ASCIIZ) */
1721 G.outbuf[(unsigned)block_length] = '\0';
1722
1723 /* remove all ASCII carriage returns from comment before printing
1724 * (since used before A_TO_N(), check for CR instead of '\r')
1725 */
1726 while (*p) {
1727 while (*p == CR)
1728 ++p;
1729 *q++ = *p++;
1730 }
1731 /* could check whether (p - outbuf) == block_length here */
1732 *q = '\0';
1733
1734 if (option == DISPL_8) {
1735 /* translate the text coded in the entry's host-dependent
1736 "extended ASCII" charset into the compiler's (system's)
1737 internal text code page */
1738 Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,
1739 G.crec.version_made_by[0]);
1740 #ifdef WINDLL
1741 /* translate to ANSI (RTL internal codepage may be OEM) */
1742 INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
1743 #else /* !WINDLL */
1744 #ifdef WIN32
1745 /* Win9x console always uses OEM character coding, and
1746 WinNT console is set to OEM charset by default, too */
1747 INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);
1748 #endif /* WIN32 */
1749 #endif /* ?WINDLL */
1750 } else {
1751 A_TO_N(G.outbuf); /* translate string to native */
1752 }
1753
1754 #ifdef WINDLL
1755 /* ran out of local mem -- had to cheat */
1756 win_fprintf((zvoid *)&G, stdout, len, (char *)G.outbuf);
1757 win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
1758 #else /* !WINDLL */
1759 #ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
1760 (*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
1761 #else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
1762 p = G.outbuf - 1;
1763 q = slide;
1764 while (*++p) {
1765 int pause = FALSE;
1766
1767 if (*p == 0x1B) { /* ASCII escape char */
1768 *q++ = '^';
1769 *q++ = '[';
1770 } else if (*p == 0x13) { /* ASCII ^S (pause) */
1771 pause = TRUE;
1772 if (p[1] == LF) /* ASCII LF */
1773 *q++ = *++p;
1774 else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */
1775 *q++ = *++p;
1776 *q++ = *++p;
1777 }
1778 } else
1779 *q++ = *p;
1780 if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */
1781 (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
1782 q = slide;
1783 if (pause && G.extract_flag) /* don't pause for list/test */
1784 (*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
1785 }
1786 }
1787 (*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
1788 #endif /* ?NOANSIFILT */
1789 #endif /* ?WINDLL */
1790 }
1791 /* add '\n' if not at start of line */
1792 (*G.message)((zvoid *)&G, slide, 0L, 0x40);
1793 break;
1794
1795 /*
1796 * Second case: read string into filename[] array. The filename should
1797 * never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
1798 * just to be sure.
1799 */
1800
1801 case DS_FN:
1802 extra_len = 0;
1803 if (len >= FILNAMSIZ) {
1804 Info(slide, 0x401, ((char *)slide,
1805 LoadFarString(FilenameTooLongTrunc)));
1806 error = PK_WARN;
1807 extra_len = (ush)(len - FILNAMSIZ + 1);
1808 len = FILNAMSIZ - 1;
1809 }
1810 if (readbuf(__G__ G.filename, len) == 0)
1811 return PK_EOF;
1812 G.filename[len] = '\0'; /* terminate w/zero: ASCIIZ */
1813
1814 /* translate the Zip entry filename coded in host-dependent "extended
1815 ASCII" into the compiler's (system's) internal text code page */
1816 Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum,
1817 G.crec.version_made_by[0]);
1818
1819 if (G.pInfo->lcflag) /* replace with lowercase filename */
1820 TOLOWER(G.filename, G.filename);
1821
1822 if (G.pInfo->vollabel && len > 8 && G.filename[8] == '.') {
1823 char *p = G.filename+8;
1824 while (*p++)
1825 p[-1] = *p; /* disk label, and 8th char is dot: remove dot */
1826 }
1827
1828 if (!extra_len) /* we're done here */
1829 break;
1830
1831 /*
1832 * We truncated the filename, so print what's left and then fall
1833 * through to the SKIP routine.
1834 */
1835 Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
1836 len = extra_len;
1837 /* FALL THROUGH... */
1838
1839 /*
1840 * Third case: skip string, adjusting readbuf's internal variables
1841 * as necessary (and possibly skipping to and reading a new block of
1842 * data).
1843 */
1844
1845 case SKIP:
1846 /* cur_zipfile_bufstart already takes account of extra_bytes, so don't
1847 * correct for it twice: */
1848 ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
1849 (G.inptr-G.inbuf) + len)
1850 break;
1851
1852 /*
1853 * Fourth case: assume we're at the start of an "extra field"; malloc
1854 * storage for it and read data into the allocated space.
1855 */
1856
1857 case EXTRA_FIELD:
1858 if (G.extra_field != (uch *)NULL)
1859 free(G.extra_field);
1860 if ((G.extra_field = (uch *)malloc(len)) == (uch *)NULL) {
1861 Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
1862 len));
1863 /* cur_zipfile_bufstart already takes account of extra_bytes,
1864 * so don't correct for it twice: */
1865 ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes +
1866 (G.inptr-G.inbuf) + len)
1867 } else
1868 if (readbuf(__G__ (char *)G.extra_field, len) == 0)
1869 return PK_EOF;
1870 break;
1871
1872 #ifdef AMIGA
1873 /*
1874 * Fifth case, for the Amiga only: take the comment that would ordinarily
1875 * be skipped over, and turn it into a 79 character string that will be
1876 * attached to the file as a "filenote" after it is extracted.
1877 */
1878
1879 case FILENOTE:
1880 if ((extra_len = readbuf(__G__ tmp_fnote, (unsigned)
1881 MIN(len, 2 * AMIGA_FILENOTELEN - 1))) == 0)
1882 return PK_EOF;
1883 if ((len -= extra_len) > 0) /* treat remainder as in case SKIP: */
1884 ZLSEEK(G.cur_zipfile_bufstart - G.extra_bytes
1885 + (G.inptr - G.inbuf) + len)
1886 /* convert multi-line text into single line with no ctl-chars: */
1887 tmp_fnote[extra_len] = '\0';
1888 while ((short int) --extra_len >= 0)
1889 if ((unsigned) tmp_fnote[extra_len] < ' ')
1890 if (tmp_fnote[extra_len+1] == ' ') /* no excess */
1891 strcpy(tmp_fnote+extra_len, tmp_fnote+extra_len+1);
1892 else
1893 tmp_fnote[extra_len] = ' ';
1894 tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0';
1895 if (G.filenotes[G.filenote_slot])
1896 free(G.filenotes[G.filenote_slot]); /* should not happen */
1897 G.filenotes[G.filenote_slot] = NULL;
1898 if (tmp_fnote[0]) {
1899 if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
1900 return PK_MEM;
1901 strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
1902 }
1903 break;
1904 #endif /* AMIGA */
1905
1906 } /* end switch (option) */
1907
1908 return error;
1909
1910 } /* end function do_string() */
1911
1912
1913
1914
1915
1916 /***********************/
1917 /* Function makeword() */
1918 /***********************/
1919
1920 ush makeword(b)
1921 ZCONST uch *b;
1922 {
1923 /*
1924 * Convert Intel style 'short' integer to non-Intel non-16-bit
1925 * host format. This routine also takes care of byte-ordering.
1926 */
1927 return (ush)((b[1] << 8) | b[0]);
1928 }
1929
1930
1931
1932
1933
1934 /***********************/
1935 /* Function makelong() */
1936 /***********************/
1937
1938 ulg makelong(sig)
1939 ZCONST uch *sig;
1940 {
1941 /*
1942 * Convert intel style 'long' variable to non-Intel non-16-bit
1943 * host format. This routine also takes care of byte-ordering.
1944 */
1945 return (((ulg)sig[3]) << 24)
1946 + (((ulg)sig[2]) << 16)
1947 + (((ulg)sig[1]) << 8)
1948 + ((ulg)sig[0]);
1949 }
1950
1951
1952
1953 #if CRYPT
1954
1955 #ifdef NEED_STR2ISO
1956 /**********************/
1957 /* Function str2iso() */
1958 /**********************/
1959
1960 char *str2iso(dst, src)
1961 char *dst; /* destination buffer */
1962 register ZCONST char *src; /* source string */
1963 {
1964 #ifdef INTERN_TO_ISO
1965 INTERN_TO_ISO(src, dst);
1966 #else
1967 register uch c;
1968 register char *dstp = dst;
1969
1970 do {
1971 c = (uch)foreign(*src++);
1972 *dstp++ = (char)ASCII2ISO(c);
1973 } while (c != '\0');
1974 #endif
1975
1976 return dst;
1977 }
1978 #endif /* NEED_STR2ISO */
1979
1980
1981 #ifdef NEED_STR2OEM
1982 /**********************/
1983 /* Function str2oem() */
1984 /**********************/
1985
1986 char *str2oem(dst, src)
1987 char *dst; /* destination buffer */
1988 register ZCONST char *src; /* source string */
1989 {
1990 #ifdef INTERN_TO_OEM
1991 INTERN_TO_OEM(src, dst);
1992 #else
1993 register uch c;
1994 register char *dstp = dst;
1995
1996 do {
1997 c = (uch)foreign(*src++);
1998 *dstp++ = (char)ASCII2OEM(c);
1999 } while (c != '\0');
2000 #endif
2001
2002 return dst;
2003 }
2004 #endif /* NEED_STR2OEM */
2005
2006 #endif /* CRYPT */
2007
2008
2009 #ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
2010 /* bzero/bcmp/bcopy */
2011 /* (no known systems as of 960211) */
2012
2013 /*********************/
2014 /* Function memset() */
2015 /*********************/
2016
2017 zvoid *memset(buf, init, len)
2018 register zvoid *buf; /* buffer location */
2019 register int init; /* initializer character */
2020 register unsigned int len; /* length of the buffer */
2021 {
2022 zvoid *start;
2023
2024 start = buf;
2025 while (len--)
2026 *((char *)buf++) = (char)init;
2027 return start;
2028 }
2029
2030
2031
2032 /*********************/
2033 /* Function memcmp() */
2034 /*********************/
2035
2036 int memcmp(b1, b2, len)
2037 register ZCONST zvoid *b1;
2038 register ZCONST zvoid *b2;
2039 register unsigned int len;
2040 {
2041 register int c;
2042
2043 if (len > 0) do {
2044 if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
2045 (int)(*((ZCONST unsigned char *)b2)++)) != 0)
2046 return c;
2047 } while (--len > 0)
2048 return 0;
2049 }
2050
2051
2052
2053 /*********************/
2054 /* Function memcpy() */
2055 /*********************/
2056
2057 zvoid *memcpy(dst, src, len)
2058 register zvoid *dst;
2059 register ZCONST zvoid *src;
2060 register unsigned int len;
2061 {
2062 zvoid *start;
2063
2064 start = dst;
2065 while (len-- > 0)
2066 *((char *)dst)++ = *((ZCONST char *)src)++;
2067 return start;
2068 }
2069
2070 #endif /* ZMEM */
2071
2072
2073
2074
2075
2076 /************************/
2077 /* Function zstrnicmp() */
2078 /************************/
2079
2080 int zstrnicmp(s1, s2, n)
2081 register ZCONST char *s1, *s2;
2082 register unsigned n;
2083 {
2084 for (; n > 0; --n, ++s1, ++s2) {
2085
2086 if (ToLower(*s1) != ToLower(*s2))
2087 /* test includes early termination of one string */
2088 return (ToLower(*s1) < ToLower(*s2))? -1 : 1;
2089
2090 if (*s1 == '\0') /* both strings terminate early */
2091 return 0;
2092 }
2093 return 0;
2094 }
2095
2096
2097
2098
2099
2100 #ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
2101 # undef stat
2102
2103 /********************/
2104 /* Function zstat() */
2105 /********************/
2106
2107 int zstat(p, s)
2108 char *p;
2109 struct stat *s;
2110 {
2111 return (stat(p,s) >= 0? 0 : (-1));
2112 }
2113
2114 #endif /* REGULUS */
2115
2116
2117
2118
2119
2120 #ifdef SMALL_MEM
2121
2122 /*******************************/
2123 /* Function fLoadFarString() */ /* (and friends...) */
2124 /*******************************/
2125
2126 char *fLoadFarString(__GPRO__ const char Far *sz)
2127 {
2128 (void)zfstrcpy(G.rgchBigBuffer, sz);
2129 return G.rgchBigBuffer;
2130 }
2131
2132 char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
2133 {
2134 (void)zfstrcpy(G.rgchSmallBuffer, sz);
2135 return G.rgchSmallBuffer;
2136 }
2137
2138 char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
2139 {
2140 (void)zfstrcpy(G.rgchSmallBuffer2, sz);
2141 return G.rgchSmallBuffer2;
2142 }
2143
2144
2145
2146
2147 #if (!defined(_MSC_VER) || (_MSC_VER < 600))
2148 /*************************/
2149 /* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
2150 /*************************/
2151
2152 char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
2153 {
2154 char Far *p = s1;
2155
2156 while ((*s1++ = *s2++) != '\0');
2157 return p;
2158 }
2159 #endif /* !_MSC_VER || (_MSC_VER < 600) */
2160
2161 #endif /* SMALL_MEM */