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