2
Copyright (c) 1990-2004 Info-ZIP. All rights reserved.
4
See the accompanying file LICENSE, version 2000-Apr-09 or later
5
(the contents of which are also included in unzip.h) for terms of use.
6
If, for some reason, all these files are missing, the Info-ZIP license
7
also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
9
/*---------------------------------------------------------------------------
13
This file contains routines for doing direct but relatively generic input/
14
output, file-related sorts of things, plus some miscellaneous stuff. Most
15
of the stuff has to do with opening, closing, reading and/or writing files.
17
Contains: open_input_file()
18
open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM)
20
defer_leftover_input()
26
is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only)
27
disk_error() (non-VMS)
29
UzpMessageNull() (DLL only)
32
UzpPassword() (non-WINDLL)
34
dos_to_unix_time() (non-VMS, non-VM/CMS, non-MVS)
35
check_for_newer() (non-VMS, non-OS/2, non-VM/CMS, non-MVS)
39
str2iso() (CRYPT && NEED_STR2ISO, only)
40
str2oem() (CRYPT && NEED_STR2OEM, only)
43
zstrnicmp() (NO_STRNICMP only)
44
zstat() (REGULUS only)
45
plastchar() (_MBCS only)
46
uzmbschr() (_MBCS && NEED_UZMBSCHR, only)
47
uzmbsrchr() (_MBCS && NEED_UZMBSRCHR, only)
48
fLoadFarString() (SMALL_MEM only)
49
fLoadFarStringSmall() (SMALL_MEM only)
50
fLoadFarStringSmall2() (SMALL_MEM only)
51
zfstrcpy() (SMALL_MEM only)
52
zfstrcmp() (SMALL_MEM && !(SFX || FUNZIP) only)
54
---------------------------------------------------------------------------*/
57
#define __FILEIO_C /* identifies this source module */
58
#define UNZIP_INTERNAL
62
# include "wince/intrface.h"
64
# include "windll/windll.h"
71
/* setup of codepage conversion for decryption passwords */
73
# if (defined(CRYP_USES_ISO2OEM) && !defined(IZ_ISO2OEM_ARRAY))
74
# define IZ_ISO2OEM_ARRAY /* pull in iso2oem[] table */
76
# if (defined(CRYP_USES_OEM2ISO) && !defined(IZ_OEM2ISO_ARRAY))
77
# define IZ_OEM2ISO_ARRAY /* pull in oem2iso[] table */
80
#include "ebcdic.h" /* definition/initialization of ebcdic[] */
84
Note: Under Windows, the maximum size of the buffer that can be used
85
with any of the *printf calls is 16,384, so win_fprintf was used to
86
feed the fprintf clone no more than 16K chunks at a time. This should
87
be valid for anything up to 64K (and probably beyond, assuming your
88
buffers are that big).
91
# define WriteError(buf,len,strm) \
92
(win_fprintf(pG, strm, (extent)len, (char far *)buf) != (int)(len))
95
# define WriteError(buf,len,strm) \
96
((extent)fwrite((char *)(buf),1,(extent)(len),strm) != (extent)(len))
98
# define WriteError(buf,len,strm) \
99
((extent)write(fileno(strm),(char *)(buf),(extent)(len)) != (extent)(len))
103
#if (defined(USE_DEFLATE64) && defined(__16BIT__))
104
static int partflush OF((__GPRO__ uch *rawbuf, ulg size, int unshrink));
107
static int is_vms_varlen_txt OF((__GPRO__ uch *ef_buf, unsigned ef_len));
109
static int disk_error OF((__GPRO));
112
/****************************/
113
/* Strings used in fileio.c */
114
/****************************/
116
static ZCONST char Far CannotOpenZipfile[] =
117
"error: cannot open zipfile [ %s ]\n %s";
119
#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
120
#if (!defined(TANDEM))
121
#if (defined(BEO_THS_UNX) || defined(DOS_FLX_NLM_OS2_W32))
122
static ZCONST char Far CannotDeleteOldFile[] =
123
"error: cannot delete old %s\n";
125
static ZCONST char Far CannotRenameOldFile[] =
126
"error: cannot rename old %s\n";
127
static ZCONST char Far BackupSuffix[] = "~";
129
#endif /* BEO_THS_UNX || DOS_FLX_NLM_OS2_W32 */
130
#ifdef NOVELL_BUG_FAILSAFE
131
static ZCONST char Far NovellBug[] =
132
"error: %s: stat() says does not exist, but fopen() found anyway\n";
134
static ZCONST char Far CannotCreateFile[] = "error: cannot create %s\n";
136
#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
138
static ZCONST char Far ReadError[] = "error: zipfile read error\n";
139
static ZCONST char Far FilenameTooLongTrunc[] =
140
"warning: filename too long--truncating.\n";
141
static ZCONST char Far ExtraFieldTooLong[] =
142
"warning: extra field too long (%d). Ignoring...\n";
145
static ZCONST char Far DiskFullQuery[] =
146
"%s: write error (disk full?).\n";
148
static ZCONST char Far DiskFullQuery[] =
149
"%s: write error (disk full?). Continue? (y/n/^C) ";
150
static ZCONST char Far ZipfileCorrupt[] =
151
"error: zipfile probably corrupt (%s)\n";
153
static ZCONST char Far FileIsSymLink[] =
154
"%s exists and is a symbolic link%s.\n";
157
static ZCONST char Far MorePrompt[] = "--More--(%lu)";
159
static ZCONST char Far QuitPrompt[] =
160
"--- Press `Q' to quit, or any other key to continue ---";
161
static ZCONST char Far HidePrompt[] = /* "\r \r"; */
165
/* SPC: are names on MacOS REALLY so much longer than elsewhere ??? */
166
static ZCONST char Far PasswPrompt[] = "[%s]\n %s password: ";
168
static ZCONST char Far PasswPrompt[] = "[%s] %s password: ";
170
static ZCONST char Far PasswPrompt2[] = "Enter password: ";
171
static ZCONST char Far PasswRetry[] = "password incorrect--reenter: ";
179
/******************************/
180
/* Function open_input_file() */
181
/******************************/
183
int open_input_file(__G) /* return 1 if open failed */
187
* open the zipfile for reading and in BINARY mode to prevent cr/lf
188
* translation, which would corrupt the bitstreams
192
G.zipfd = open(G.zipfn, O_RDONLY, 0, "ctx=stm");
195
G.zipfd = open(G.zipfn, 0);
198
G.zipfd = vmmvs_open_infile(__G);
200
#ifdef USE_STRM_INPUT
201
G.zipfd = fopen(G.zipfn, FOPR);
202
#else /* !USE_STRM_INPUT */
204
G.zipfd = open(G.zipfn, O_RDONLY | O_BINARY);
206
G.zipfd = open(G.zipfn, O_RDONLY);
208
#endif /* ?USE_STRM_INPUT */
209
#endif /* ?CMS_MVS */
213
#ifdef USE_STRM_INPUT
216
/* if (G.zipfd < 0) */ /* no good for Windows CE port */
220
Info(slide, 0x401, ((char *)slide, LoadFarString(CannotOpenZipfile),
221
G.zipfn, strerror(errno)));
226
} /* end function open_input_file() */
231
#if (!defined(VMS) && !defined(AOS_VS) && !defined(CMS_MVS) && !defined(MACOS))
232
#if (!defined(TANDEM))
234
/***************************/
235
/* Function open_outfile() */
236
/***************************/
238
int open_outfile(__G) /* return 1 if fail */
243
return (redirect_outfile(__G) == FALSE);
246
QFilename(__G__ G.filename);
248
#if (defined(DOS_FLX_NLM_OS2_W32) || defined(BEO_THS_UNX))
249
#ifdef BORLAND_STAT_BUG
250
/* Borland 5.0's stat() barfs if the filename has no extension and the
251
* file doesn't exist. */
252
if (access(G.filename, 0) == -1) {
253
FILE *tmp = fopen(G.filename, "wb+");
255
/* file doesn't exist, so create a dummy file to keep stat() from
256
* failing (will be over-written anyway) */
257
fputc('0', tmp); /* just to have something in the file */
260
#endif /* BORLAND_STAT_BUG */
262
if (SSTAT(G.filename, &G.statbuf) == 0 || lstat(G.filename,&G.statbuf) == 0)
264
if (SSTAT(G.filename, &G.statbuf) == 0)
265
#endif /* ?SYMLINKS */
267
Trace((stderr, "open_outfile: stat(%s) returns 0: file exists\n",
268
FnFilter1(G.filename)));
270
if (uO.B_flag) { /* do backup */
273
int blen, flen, tlen;
275
blen = strlen(BackupSuffix);
276
flen = strlen(G.filename);
277
tlen = flen + blen + 6; /* includes space for 5 digits */
278
if (tlen >= FILNAMSIZ) { /* in case name is too long, truncate */
279
tname = (char *)malloc(FILNAMSIZ);
281
return 1; /* in case we run out of space */
282
tlen = FILNAMSIZ - 1 - blen;
283
strcpy(tname, G.filename); /* make backup name */
285
if (flen > tlen) flen = tlen;
288
tname = (char *)malloc(tlen);
290
return 1; /* in case we run out of space */
291
strcpy(tname, G.filename); /* make backup name */
293
strcpy(tname+flen, BackupSuffix);
295
if (IS_OVERWRT_ALL) {
296
/* If there is a previous backup file, delete it,
297
* otherwise the following rename operation may fail.
299
if (SSTAT(tname, &tmpstat) == 0)
302
/* Check if backupname exists, and, if it's true, try
303
* appending numbers of up to 5 digits to the BackupSuffix,
304
* until an unused name is found.
307
char *numtail = tname + flen + blen;
310
switch (tlen - flen - blen - 1) {
311
case 4: maxtail = 9999; break;
312
case 3: maxtail = 999; break;
313
case 2: maxtail = 99; break;
314
case 1: maxtail = 9; break;
315
case 0: maxtail = 0; break;
317
/* while filename exists */
318
for (i = 0; (i <= maxtail) && (SSTAT(tname, &tmpstat) == 0);)
319
sprintf(numtail,"%u", ++i);
322
if (rename(G.filename, tname) != 0) { /* move file */
323
Info(slide, 0x401, ((char *)slide,
324
LoadFarString(CannotRenameOldFile), FnFilter1(G.filename)));
328
Trace((stderr, "open_outfile: %s now renamed into %s\n",
329
FnFilter1(G.filename), FnFilter2(tname)));
332
#endif /* UNIXBACKUP */
334
#ifdef DOS_FLX_OS2_W32
335
if (!(G.statbuf.st_mode & S_IWRITE)) {
337
"open_outfile: existing file %s is read-only\n",
338
FnFilter1(G.filename)));
339
chmod(G.filename, S_IREAD | S_IWRITE);
340
Trace((stderr, "open_outfile: %s now writable\n",
341
FnFilter1(G.filename)));
343
#endif /* DOS_FLX_OS2_W32 */
345
/* Give the file read/write permission (non-POSIX shortcut) */
346
chmod(G.filename, 0);
348
if (unlink(G.filename) != 0) {
349
Info(slide, 0x401, ((char *)slide,
350
LoadFarString(CannotDeleteOldFile), FnFilter1(G.filename)));
353
Trace((stderr, "open_outfile: %s now deleted\n",
354
FnFilter1(G.filename)));
357
#endif /* DOS_FLX_NLM_OS2_W32 || BEO_THS_UNX */
359
if (SWI_OS_File_7(G.filename,0xDEADDEAD,0xDEADDEAD,G.lrec.ucsize)!=NULL) {
360
Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
361
FnFilter1(G.filename)));
368
if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL)
370
strcpy(tfilnam, G.filename);
373
if ((G.outfile = fopen(tfilnam, FOPW)) == (FILE *)NULL) {
374
Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
383
G.outfile = fopen(G.filename, FOPWT);
385
G.outfile = fopen(G.filename, FOPW);
386
if (G.outfile == (FILE *)NULL) {
387
Info(slide, 1, ((char *)slide, LoadFarString(CannotCreateFile),
388
FnFilter1(G.filename)));
393
Info(slide, 1, ((char *)slide,
394
"open_outfile: doing fopen(%s) for reading\n", FnFilter1(G.filename)));
395
if ((G.outfile = fopen(G.filename, FOPR)) == (FILE *)NULL)
396
Info(slide, 1, ((char *)slide,
397
"open_outfile: fopen(%s) for reading failed: does not exist\n",
398
FnFilter1(G.filename)));
400
Info(slide, 1, ((char *)slide,
401
"open_outfile: fopen(%s) for reading succeeded: file exists\n",
402
FnFilter1(G.filename)));
406
#ifdef NOVELL_BUG_FAILSAFE
407
if (G.dne && ((G.outfile = fopen(G.filename, FOPR)) != (FILE *)NULL)) {
408
Info(slide, 0x401, ((char *)slide, LoadFarString(NovellBug),
409
FnFilter1(G.filename)));
411
return 1; /* with "./" fix in checkdir(), should never reach here */
413
#endif /* NOVELL_BUG_FAILSAFE */
414
Trace((stderr, "open_outfile: doing fopen(%s) for writing\n",
415
FnFilter1(G.filename)));
416
if ((G.outfile = fopen(G.filename, FOPW)) == (FILE *)NULL) {
417
Info(slide, 0x401, ((char *)slide, LoadFarString(CannotCreateFile),
418
FnFilter1(G.filename)));
421
Trace((stderr, "open_outfile: fopen(%s) for writing succeeded\n",
422
FnFilter1(G.filename)));
427
#ifdef DOS_NLM_OS2_W32
428
/* 16-bit MSC: buffer size must be strictly LESS than 32K (WSIZE): bogus */
429
setbuf(G.outfile, (char *)NULL); /* make output unbuffered */
430
#else /* !DOS_NLM_OS2_W32 */
432
#ifdef _IOFBF /* make output fully buffered (works just about like write()) */
433
setvbuf(G.outfile, (char *)slide, _IOFBF, WSIZE);
435
setbuf(G.outfile, (char *)slide);
438
#endif /* ?DOS_NLM_OS2_W32 */
439
#endif /* USE_FWRITE */
441
/* preallocate the final file size to prevent file fragmentation */
442
SetFileSize(G.outfile, G.lrec.ucsize);
446
} /* end function open_outfile() */
449
#endif /* !VMS && !AOS_VS && !CMS_MVS && !MACOS */
456
* These functions allow NEXTBYTE to function without needing two bounds
457
* checks. Call defer_leftover_input() if you ever have filled G.inbuf
458
* by some means other than readbyte(), and you then want to start using
459
* NEXTBYTE. When going back to processing bytes without NEXTBYTE, call
460
* undefer_input(). For example, extract_or_test_member brackets its
461
* central section that does the decompression with these two functions.
462
* If you need to check the number of bytes remaining in the current
463
* file while using NEXTBYTE, check (G.csize + G.incnt), not G.csize.
466
/****************************/
467
/* function undefer_input() */
468
/****************************/
470
void undefer_input(__G)
475
if (G.incnt_leftover > 0) {
476
/* We know that "(G.csize < MAXINT)" so we can cast G.csize to int:
477
* This condition was checked when G.incnt_leftover was set > 0 in
478
* defer_leftover_input(), and it is NOT allowed to touch G.csize
479
* before calling undefer_input() when (G.incnt_leftover > 0)
480
* (single exception: see read_byte()'s "G.csize <= 0" handling) !!
482
G.incnt = G.incnt_leftover + (int)G.csize;
483
G.inptr = G.inptr_leftover - (int)G.csize;
484
G.incnt_leftover = 0;
485
} else if (G.incnt < 0)
487
} /* end function undefer_input() */
493
/***********************************/
494
/* function defer_leftover_input() */
495
/***********************************/
497
void defer_leftover_input(__G)
500
if ((long)G.incnt > G.csize) {
501
/* (G.csize < MAXINT), we can safely cast it to int !! */
504
G.inptr_leftover = G.inptr + (int)G.csize;
505
G.incnt_leftover = G.incnt - (int)G.csize;
506
G.incnt = (int)G.csize;
508
G.incnt_leftover = 0;
510
} /* end function defer_leftover_input() */
516
/**********************/
517
/* Function readbuf() */
518
/**********************/
520
unsigned readbuf(__G__ buf, size) /* return number of bytes read into buf */
523
register unsigned size;
525
register unsigned count;
531
if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0)
533
else if (G.incnt < 0) {
534
/* another hack, but no real harm copying same thing twice */
535
(*G.message)((zvoid *)&G,
536
(uch *)LoadFarString(ReadError), /* CANNOT use slide */
537
(ulg)strlen(LoadFarString(ReadError)), 0x401);
538
return 0; /* discarding some data; better than lock-up */
540
/* buffer ALWAYS starts on a block boundary: */
541
G.cur_zipfile_bufstart += INBUFSIZ;
544
count = MIN(size, (unsigned)G.incnt);
545
memcpy(buf, G.inptr, count);
553
} /* end function readbuf() */
559
/***********************/
560
/* Function readbyte() */
561
/***********************/
563
int readbyte(__G) /* refill inbuf and return a byte if available, else EOF */
569
G.csize--; /* for tests done after exploding */
574
if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) == 0) {
575
G.incnt = 0; /* do not allow negative value to affect stuff */
577
} else if (G.incnt < 0) { /* "fail" (abort, retry, ...) returns this */
578
/* another hack, but no real harm copying same thing twice */
579
(*G.message)((zvoid *)&G,
580
(uch *)LoadFarString(ReadError),
581
(ulg)strlen(LoadFarString(ReadError)), 0x401);
584
longjmp(dll_error_return, 1);
587
EXIT(PK_BADERR); /* totally bailing; better than lock-up */
590
G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on block bndry */
592
defer_leftover_input(__G); /* decrements G.csize */
596
if (G.pInfo->encrypted) {
600
/* This was previously set to decrypt one byte beyond G.csize, when
601
* incnt reached that far. GRR said, "but it's required: why?" This
602
* was a bug in fillinbuf() -- was it also a bug here?
604
for (n = G.incnt, p = G.inptr; n--; p++)
612
} /* end function readbyte() */
620
/************************/
621
/* Function fillinbuf() */
622
/************************/
624
int fillinbuf(__G) /* like readbyte() except returns number of bytes in inbuf */
628
(G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
630
G.cur_zipfile_bufstart += INBUFSIZ; /* always starts on a block boundary */
632
defer_leftover_input(__G); /* decrements G.csize */
635
if (G.pInfo->encrypted) {
639
for (n = G.incnt, p = G.inptr; n--; p++)
646
} /* end function fillinbuf() */
648
#endif /* USE_ZLIB */
654
/************************/
655
/* Function seek_zipf() */
656
/************************/
658
int seek_zipf(__G__ abs_offset)
663
* Seek to the block boundary of the block which includes abs_offset,
664
* then read block into input buffer and set pointers appropriately.
665
* If block is already in the buffer, just set the pointers. This function
666
* is used by do_seekable (process.c), extract_or_test_entrylist (extract.c)
667
* and do_string (fileio.c). Also, a slightly modified version is embedded
668
* within extract_or_test_entrylist (extract.c). readbyte() and readbuf()
669
* (fileio.c) are compatible. NOTE THAT abs_offset is intended to be the
670
* "proper offset" (i.e., if there were no extra bytes prepended);
671
* cur_zipfile_bufstart contains the corrected offset.
673
* Since seek_zipf() is never used during decompression, it is safe to
674
* use the slide[] buffer for the error message.
676
* returns PK error codes:
677
* PK_BADERR if effective offset in zipfile is negative
678
* PK_EOF if seeking past end of zipfile
679
* PK_OK when seek was successful
681
LONGINT request = abs_offset + G.extra_bytes;
682
LONGINT inbuf_offset = request % INBUFSIZ;
683
LONGINT bufstart = request - inbuf_offset;
686
Info(slide, 1, ((char *)slide, LoadFarStringSmall(SeekMsg),
687
G.zipfn, LoadFarString(ReportMsg)));
689
} else if (bufstart != G.cur_zipfile_bufstart) {
691
"fpos_zip: abs_offset = %ld, G.extra_bytes = %ld\n",
692
abs_offset, G.extra_bytes));
693
#ifdef USE_STRM_INPUT
694
fseek(G.zipfd, (LONGINT)bufstart, SEEK_SET);
695
G.cur_zipfile_bufstart = ftell(G.zipfd);
696
#else /* !USE_STRM_INPUT */
697
G.cur_zipfile_bufstart = lseek(G.zipfd, (LONGINT)bufstart, SEEK_SET);
698
#endif /* ?USE_STRM_INPUT */
700
" request = %ld, (abs+extra) = %ld, inbuf_offset = %ld\n",
701
request, (abs_offset+G.extra_bytes), inbuf_offset));
702
Trace((stderr, " bufstart = %ld, cur_zipfile_bufstart = %ld\n",
703
bufstart, G.cur_zipfile_bufstart));
704
if ((G.incnt = read(G.zipfd, (char *)G.inbuf, INBUFSIZ)) <= 0)
706
G.incnt -= (int)inbuf_offset;
707
G.inptr = G.inbuf + (int)inbuf_offset;
709
G.incnt += (G.inptr-G.inbuf) - (int)inbuf_offset;
710
G.inptr = G.inbuf + (int)inbuf_offset;
713
} /* end function seek_zipf() */
719
#ifndef VMS /* for VMS use code in vms.c */
721
/********************/
722
/* Function flush() */ /* returns PK error codes: */
723
/********************/ /* if cflag => always 0; PK_DISK if write error */
725
int flush(__G__ rawbuf, size, unshrink)
730
#if (defined(USE_DEFLATE64) && defined(__16BIT__))
734
/* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions
735
* cannot handle writes of 64k blocks at once. For these systems, the
736
* blocks to flush are split into pieces of 32k or less.
738
while (size > 0x8000L) {
739
ret = partflush(__G__ rawbuf, 0x8000L, unshrink);
743
rawbuf += (extent)0x8000;
745
return partflush(__G__ rawbuf, size, unshrink);
746
} /* end function flush() */
749
/************************/
750
/* Function partflush() */ /* returns PK error codes: */
751
/************************/ /* if cflag => always 0; PK_DISK if write error */
753
static int partflush(__G__ rawbuf, size, unshrink)
755
uch *rawbuf; /* cannot be ZCONST, gets passed to (*G.message)() */
758
#endif /* USE_DEFLATE64 && __16BIT__ */
763
#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
766
/* static int didCRlast = FALSE; moved to globals.h */
769
/*---------------------------------------------------------------------------
770
Compute the CRC first; if testing or if disk is full, that's it.
771
---------------------------------------------------------------------------*/
773
G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
776
if ((G.statreportcb != NULL) &&
777
(*G.statreportcb)(__G__ UZ_ST_IN_PROGRESS, G.zipfn, G.filename, NULL))
778
return IZ_CTRLC; /* cancel operation by user request */
781
if (uO.tflag || size == 0L) /* testing or nothing to write: all done */
785
return PK_DISK; /* disk already full: ignore rest of file */
787
/*---------------------------------------------------------------------------
788
Write the bytes rawbuf[0..size-1] to the output device, first converting
789
end-of-lines and ASCII/EBCDIC as needed. If SMALL_MEM or MED_MEM are NOT
790
defined, outbuf is assumed to be at least as large as rawbuf and is not
791
necessarily checked for overflow.
792
---------------------------------------------------------------------------*/
794
if (!G.pInfo->textmode) { /* write raw binary data */
795
/* GRR: note that for standard MS-DOS compilers, size argument to
796
* fwrite() can never be more than 65534, so WriteError macro will
797
* have to be rewritten if size can ever be that large. For now,
798
* never more than 32K. Also note that write() returns an int, which
799
* doesn't necessarily limit size to 32767 bytes if write() is used
800
* on 16-bit systems but does make it more of a pain; however, because
801
* at least MSC 5.1 has a lousy implementation of fwrite() (as does
802
* DEC Ultrix cc), write() is used anyway.
805
if (G.redirect_data) {
806
#ifdef NO_SLIDE_REDIR
807
if (writeToMemory(__G__ rawbuf, (extent)size)) return PK_ERR;
809
writeToMemory(__G__ rawbuf, (extent)size);
813
if (!uO.cflag && WriteError(rawbuf, size, G.outfile))
814
return disk_error(__G);
815
else if (uO.cflag && (*G.message)((zvoid *)&G, rawbuf, size, 0))
817
} else { /* textmode: aflag is true */
819
/* rawbuf = outbuf */
820
transbuf = G.outbuf2;
821
#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
822
transbufsiz = TRANSBUFSIZ;
827
#if (defined(SMALL_MEM) || defined(MED_MEM) || defined(VMS_TEXT_CONV))
828
transbufsiz = OUTBUFSIZ;
829
Trace((stderr, "\ntransbufsiz = OUTBUFSIZ = %u\n",
830
(unsigned)OUTBUFSIZ));
835
if (G.pInfo->hostnum == VMS_ && G.extra_field &&
836
is_vms_varlen_txt(__G__ G.extra_field,
837
G.lrec.extra_field_length))
838
G.VMS_line_state = 0; /* 0: ready to read line length */
840
G.VMS_line_state = -1; /* -1: don't treat as VMS text */
842
G.didCRlast = FALSE; /* no previous buffers written */
847
if (G.VMS_line_state >= 0)
851
while ((extent)(p-rawbuf) < (extent)size) {
852
switch (G.VMS_line_state) {
854
/* 0: ready to read line length */
856
G.VMS_line_length = 0;
857
if ((extent)(p-rawbuf) == (extent)size-1) {
859
G.VMS_line_length = (unsigned)(*p++);
860
G.VMS_line_state = 1;
862
G.VMS_line_length = makeword(p);
864
G.VMS_line_state = 2;
867
((G.VMS_line_length & 1) != 0); /* odd */
870
/* 1: read one byte of length, need second */
872
G.VMS_line_length += ((unsigned)(*p++) << 8);
873
G.VMS_line_state = 2;
876
/* 2: ready to read VMS_line_length chars */
879
extent remaining = (extent)size+(rawbuf-p);
882
if (G.VMS_line_length < remaining) {
883
remaining = G.VMS_line_length;
884
G.VMS_line_state = 3;
887
outroom = transbuf+(extent)transbufsiz-q;
888
if (remaining >= outroom) {
889
remaining -= outroom;
890
for (;outroom > 0; p++, outroom--)
893
if (G.redirect_data) {
894
if (writeToMemory(__G__ transbuf,
895
(extent)(q-transbuf))) return PK_ERR;
898
if (!uO.cflag && WriteError(transbuf,
899
(extent)(q-transbuf), G.outfile))
900
return disk_error(__G);
901
else if (uO.cflag && (*G.message)((zvoid *)&G,
902
transbuf, (ulg)(q-transbuf), 0))
905
/* fall through to normal case */
907
G.VMS_line_length -= remaining;
908
for (;remaining > 0; p++, remaining--)
913
/* 3: ready to PutNativeEOL */
915
if (q > transbuf+(extent)transbufsiz-lenEOL) {
917
if (G.redirect_data) {
918
if (writeToMemory(__G__ transbuf,
919
(extent)(q-transbuf))) return PK_ERR;
923
WriteError(transbuf, (extent)(q-transbuf),
925
return disk_error(__G);
926
else if (uO.cflag && (*G.message)((zvoid *)&G,
927
transbuf, (ulg)(q-transbuf), 0))
932
G.VMS_line_state = G.VMS_line_pad ? 4 : 0;
935
/* 4: ready to read pad byte */
938
G.VMS_line_state = 0;
944
#endif /* VMS_TEXT_CONV */
946
/*-----------------------------------------------------------------------
947
Algorithm: CR/LF => native; lone CR => native; lone LF => native.
948
This routine is only for non-raw-VMS, non-raw-VM/CMS files (i.e.,
949
stream-oriented files, not record-oriented).
950
-----------------------------------------------------------------------*/
952
/* else not VMS text */ {
954
if (*p == LF && G.didCRlast)
957
for (q = transbuf; (extent)(p-rawbuf) < (extent)size; ++p) {
958
if (*p == CR) { /* lone CR or CR/LF: treat as EOL */
960
if ((extent)(p-rawbuf) == (extent)size-1)
961
/* last char in buffer */
963
else if (p[1] == LF) /* get rid of accompanying LF */
965
} else if (*p == LF) /* lone LF */
968
#ifndef DOS_FLX_OS2_W32
969
if (*p != CTRLZ) /* lose all ^Z's */
973
#if (defined(SMALL_MEM) || defined(MED_MEM))
974
# if (lenEOL == 1) /* don't check unshrink: both buffers small but equal */
977
/* check for danger of buffer overflow and flush */
978
if (q > transbuf+(extent)transbufsiz-lenEOL) {
980
"p - rawbuf = %u q-transbuf = %u size = %lu\n",
981
(unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
982
if (!uO.cflag && WriteError(transbuf,
983
(extent)(q-transbuf), G.outfile))
984
return disk_error(__G);
985
else if (uO.cflag && (*G.message)((zvoid *)&G,
986
transbuf, (ulg)(q-transbuf), 0))
991
#endif /* SMALL_MEM || MED_MEM */
995
/*-----------------------------------------------------------------------
996
Done translating: write whatever we've got to file (or screen).
997
-----------------------------------------------------------------------*/
999
Trace((stderr, "p - rawbuf = %u q-transbuf = %u size = %lu\n",
1000
(unsigned)(p-rawbuf), (unsigned)(q-transbuf), size));
1003
if (G.redirect_data) {
1004
if (writeToMemory(__G__ transbuf, (extent)(q-transbuf)))
1008
if (!uO.cflag && WriteError(transbuf, (extent)(q-transbuf),
1010
return disk_error(__G);
1011
else if (uO.cflag && (*G.message)((zvoid *)&G, transbuf,
1012
(ulg)(q-transbuf), 0))
1019
} /* end function flush() [resp. partflush() for 16-bit Deflate64 support] */
1025
#ifdef VMS_TEXT_CONV
1027
/********************************/
1028
/* Function is_vms_varlen_txt() */
1029
/********************************/
1031
static int is_vms_varlen_txt(__G__ ef_buf, ef_len)
1033
uch *ef_buf; /* buffer containing extra field */
1034
unsigned ef_len; /* total length of extra field */
1040
#define VMSREC_C_UNDEF 0
1041
#define VMSREC_C_VAR 2
1042
uch vms_rectype = VMSREC_C_UNDEF;
1043
uch vms_fileorg = 0;
1045
#define VMSPK_ITEMID 0
1046
#define VMSPK_ITEMLEN 2
1047
#define VMSPK_ITEMHEADSZ 4
1049
#define VMSATR_C_RECATTR 4
1050
#define VMS_FABSIG 0x42414656 /* "VFAB" */
1051
/* offsets of interesting fields in VMS fabdef structure */
1052
#define VMSFAB_B_RFM 31 /* record format byte */
1053
#define VMSFAB_B_ORG 29 /* file organization byte */
1055
if (ef_len == 0 || ef_buf == NULL)
1058
while (ef_len >= EB_HEADSIZE) {
1059
eb_id = makeword(EB_ID + ef_buf);
1060
eb_len = makeword(EB_LEN + ef_buf);
1062
if (eb_len > (ef_len - EB_HEADSIZE)) {
1063
/* discovered some extra field inconsistency! */
1065
"is_vms_varlen_txt: block length %u > rest ef_size %u\n", eb_len,
1066
ef_len - EB_HEADSIZE));
1072
/* The PKVMS e.f. raw data part consists of:
1073
* a) 4 bytes CRC checksum
1074
* b) list of uncompressed variable-length data items
1075
* Each data item is introduced by a fixed header
1076
* - 2 bytes data type ID
1077
* - 2 bytes <size> of data
1078
* - <size> bytes of actual attribute data
1081
/* get pointer to start of data and its total length */
1082
eb_data = ef_buf+(EB_HEADSIZE+4);
1083
eb_datlen = eb_len-4;
1085
/* test the CRC checksum */
1086
if (makelong(ef_buf+EB_HEADSIZE) !=
1087
crc32(CRCVAL_INITIAL, eb_data, (extent)eb_datlen))
1089
Info(slide, 1, ((char *)slide,
1090
"[Warning: CRC error, discarding PKWARE extra field]\n"));
1091
/* skip over the data analysis code */
1095
/* scan through the attribute data items */
1096
while (eb_datlen > 4)
1098
unsigned fldsize = makeword(&eb_data[VMSPK_ITEMLEN]);
1100
/* check the item type word */
1101
switch (makeword(&eb_data[VMSPK_ITEMID])) {
1102
case VMSATR_C_RECATTR:
1103
/* we have found the (currently only) interesting
1106
vms_rectype = eb_data[VMSPK_ITEMHEADSZ] & 15;
1107
vms_fileorg = eb_data[VMSPK_ITEMHEADSZ] >> 4;
1113
/* skip to next data item */
1114
eb_datlen -= fldsize + VMSPK_ITEMHEADSZ;
1115
eb_data += fldsize + VMSPK_ITEMHEADSZ;
1120
if (makelong(ef_buf+EB_HEADSIZE) == VMS_FABSIG) {
1121
if ((eb_data = extract_izvms_block(__G__
1122
ef_buf+EB_HEADSIZE, eb_len,
1123
&eb_datlen, NULL, 0))
1126
if (eb_datlen >= VMSFAB_B_RFM+1) {
1127
vms_rectype = eb_data[VMSFAB_B_RFM] & 15;
1128
vms_fileorg = eb_data[VMSFAB_B_ORG] >> 4;
1139
/* Skip this extra field block */
1140
ef_buf += (eb_len + EB_HEADSIZE);
1141
ef_len -= (eb_len + EB_HEADSIZE);
1144
return (vms_rectype == VMSREC_C_VAR);
1146
} /* end function is_vms_varlen_txtfile() */
1148
#endif /* VMS_TEXT_CONV */
1153
/*************************/
1154
/* Function disk_error() */
1155
/*************************/
1157
static int disk_error(__G)
1160
/* OK to use slide[] here because this file is finished regardless */
1161
Info(slide, 0x4a1, ((char *)slide, LoadFarString(DiskFullQuery),
1162
FnFilter1(G.filename)));
1165
fgets(G.answerbuf, 9, stdin);
1166
if (*G.answerbuf == 'y') /* stop writing to this file */
1167
G.disk_full = 1; /* (outfile bad?), but new OK */
1170
G.disk_full = 2; /* no: exit program */
1174
} /* end function disk_error() */
1182
/*****************************/
1183
/* Function UzpMessagePrnt() */
1184
/*****************************/
1186
int UZ_EXP UzpMessagePrnt(pG, buf, size, flag)
1187
zvoid *pG; /* globals struct: always passed */
1188
uch *buf; /* preformatted string to be printed */
1189
ulg size; /* length of string (may include nulls) */
1190
int flag; /* flag bits */
1193
* The name of the first parameter of UzpMessagePrnt(), which passes
1194
* the "Uz_Globs" address, >>> MUST <<< be identical to the string
1195
* expansion of the __G__ macro in the REENTRANT case (see globals.h).
1196
* This name identity is mandatory for the LoadFarString() macro
1197
* (in the SMALL_MEM case) !!!
1200
uch *q=buf, *endbuf=buf+(unsigned)size;
1203
#if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1204
int islinefeed = FALSE;
1210
/*---------------------------------------------------------------------------
1211
These tests are here to allow fine-tuning of UnZip's output messages,
1212
but none of them will do anything without setting the appropriate bit
1213
in the flag argument of every Info() statement which is to be turned
1214
*off*. That is, all messages are currently turned on for all ports.
1215
To turn off *all* messages, use the UzpMessageNull() function instead
1217
---------------------------------------------------------------------------*/
1219
#if (defined(OS2) && defined(DLL))
1220
if (MSG_NO_DLL2(flag)) /* if OS/2 DLL bit is set, do NOT print this msg */
1224
if (MSG_NO_WDLL(flag))
1228
if (MSG_NO_WGUI(flag))
1233
if (MSG_NO_AGUI(flag))
1237
#ifdef DLL /* don't display message if data is redirected */
1238
if (((Uz_Globs *)pG)->redirect_data &&
1239
!((Uz_Globs *)pG)->redirect_text)
1243
if (MSG_STDERR(flag) && !((Uz_Globs *)pG)->UzO.tflag)
1244
outfp = (FILE *)stderr;
1246
outfp = (FILE *)stdout;
1248
#ifdef QUERY_TRNEWLN
1249
/* some systems require termination of query prompts with '\n' to force
1250
* immediate display */
1251
if (MSG_MNEWLN(flag)) { /* assumes writable buffer (e.g., slide[]) */
1252
*endbuf++ = '\n'; /* with room for one more char at end of buf */
1253
++size; /* (safe assumption: only used for four */
1254
} /* short queries in extract.c and fileio.c) */
1257
if (MSG_TNEWLN(flag)) { /* again assumes writable buffer: fragile... */
1258
if ((!size && !((Uz_Globs *)pG)->sol) ||
1259
(size && (endbuf[-1] != '\n')))
1268
/* room for --More-- and one line of overlap: */
1269
# if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1270
SCREENSIZE(&((Uz_Globs *)pG)->height, &((Uz_Globs *)pG)->width);
1272
SCREENSIZE(&((Uz_Globs *)pG)->height, (int *)NULL);
1274
((Uz_Globs *)pG)->height -= 2;
1276
/* room for --More-- and one line of overlap: */
1277
((Uz_Globs *)pG)->height = SCREENLINES - 2;
1278
# if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1279
((Uz_Globs *)pG)->width = SCREENWIDTH;
1284
if (MSG_LNEWLN(flag) && !((Uz_Globs *)pG)->sol) {
1285
/* not at start of line: want newline */
1287
if (!((Uz_Globs *)pG)->redirect_text) {
1292
if (((Uz_Globs *)pG)->M_flag)
1294
#if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1295
((Uz_Globs *)pG)->chars = 0;
1297
++((Uz_Globs *)pG)->numlines;
1298
++((Uz_Globs *)pG)->lines;
1299
if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height)
1300
(*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
1301
LoadFarString(MorePrompt), 1);
1304
if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1305
!isatty(1) && isatty(2))
1307
/* error output from testing redirected: also send to stderr */
1315
((Uz_Globs *)pG)->sol = TRUE;
1318
/* put zipfile name, filename and/or error/warning keywords here */
1321
if (((Uz_Globs *)pG)->M_flag
1323
&& !((Uz_Globs *)pG)->redirect_text
1327
while (p < endbuf) {
1329
#if (defined(SCREENWIDTH) && defined(SCREENLWRAP))
1331
} else if (SCREENLWRAP) {
1333
((Uz_Globs *)pG)->chars = 0;
1337
((Uz_Globs *)pG)->chars +=
1338
(TABSIZE - (((Uz_Globs *)pG)->chars % TABSIZE));
1341
++((Uz_Globs *)pG)->chars;
1343
if (((Uz_Globs *)pG)->chars >= ((Uz_Globs *)pG)->width)
1349
((Uz_Globs *)pG)->chars = 0;
1350
#endif /* (SCREENWIDTH && SCREEN_LWRAP) */
1351
++((Uz_Globs *)pG)->numlines;
1352
++((Uz_Globs *)pG)->lines;
1353
if (((Uz_Globs *)pG)->lines >= ((Uz_Globs *)pG)->height)
1355
if ((error = WriteError(q, p-q+1, outfp)) != 0)
1358
((Uz_Globs *)pG)->sol = TRUE;
1360
(*((Uz_Globs *)pG)->mpause)((zvoid *)pG,
1361
LoadFarString(MorePrompt), 1);
1366
size = (ulg)(p - q); /* remaining text */
1372
if (!((Uz_Globs *)pG)->redirect_text) {
1374
if ((error = WriteError(q, size, outfp)) != 0)
1377
if (MSG_STDERR(flag) && ((Uz_Globs *)pG)->UzO.tflag &&
1378
!isatty(1) && isatty(2))
1380
/* error output from testing redirected: also send to stderr */
1381
if ((error = WriteError(q, size, stderr)) != 0)
1386
} else { /* GRR: this is ugly: hide with macro */
1387
if ((error = REDIRECTPRINT(q, size)) != 0)
1391
((Uz_Globs *)pG)->sol = (endbuf[-1] == '\n');
1395
} /* end function UzpMessagePrnt() */
1403
/*****************************/
1404
/* Function UzpMessageNull() */ /* convenience routine for no output at all */
1405
/*****************************/
1407
int UZ_EXP UzpMessageNull(pG, buf, size, flag)
1408
zvoid *pG; /* globals struct: always passed */
1409
uch *buf; /* preformatted string to be printed */
1410
ulg size; /* length of string (may include nulls) */
1411
int flag; /* flag bits */
1415
} /* end function UzpMessageNull() */
1423
/***********************/
1424
/* Function UzpInput() */ /* GRR: this is a placeholder for now */
1425
/***********************/
1427
int UZ_EXP UzpInput(pG, buf, size, flag)
1428
zvoid *pG; /* globals struct: always passed */
1429
uch *buf; /* preformatted string to be printed */
1430
int *size; /* (address of) size of buf and of returned string */
1431
int flag; /* flag bits (bit 0: no echo) */
1433
/* tell picky compilers to shut up about "unused variable" warnings */
1434
pG = pG; buf = buf; flag = flag;
1439
} /* end function UzpInput() */
1445
#if (!defined(WINDLL) && !defined(MACOS))
1447
/***************************/
1448
/* Function UzpMorePause() */
1449
/***************************/
1451
void UZ_EXP UzpMorePause(pG, prompt, flag)
1452
zvoid *pG; /* globals struct: always passed */
1453
ZCONST char *prompt; /* "--More--" prompt */
1454
int flag; /* 0 = any char OK; 1 = accept only '\n', ' ', q */
1458
/*---------------------------------------------------------------------------
1459
Print a prompt and wait for the user to press a key, then erase prompt
1461
---------------------------------------------------------------------------*/
1463
if (!((Uz_Globs *)pG)->sol)
1464
fprintf(stderr, "\n");
1465
/* numlines may or may not be used: */
1466
fprintf(stderr, prompt, ((Uz_Globs *)pG)->numlines);
1473
c != 17 && /* standard QUIT key */
1475
c != '\r' && c != '\n' && c != ' ' && c != 'q' && c != 'Q');
1479
/* newline was not echoed, so cover up prompt line */
1480
fprintf(stderr, LoadFarString(HidePrompt));
1485
(c == 17) || /* standard QUIT key */
1487
(ToLower(c) == 'q')) {
1492
((Uz_Globs *)pG)->sol = TRUE;
1495
/* space for another screen, enter for another line. */
1496
if ((flag & 1) && c == ' ')
1497
((Uz_Globs *)pG)->lines = 0;
1500
} /* end function UzpMorePause() */
1502
#endif /* !WINDLL && !MACOS */
1509
/**************************/
1510
/* Function UzpPassword() */
1511
/**************************/
1513
int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn)
1514
zvoid *pG; /* pointer to UnZip's internal global vars */
1515
int *rcnt; /* retry counter */
1516
char *pwbuf; /* buffer for password */
1517
int size; /* size of password buffer */
1518
ZCONST char *zfn; /* name of zip archive */
1519
ZCONST char *efn; /* name of archive entry being processed */
1522
int r = IZ_PW_ENTERED;
1527
/* tell picky compilers to shut up about "unused variable" warnings */
1531
if (*rcnt == 0) { /* First call for current entry */
1533
if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
1534
sprintf(prompt, LoadFarString(PasswPrompt),
1535
FnFilter1(zfn), FnFilter2(efn));
1538
m = (char *)LoadFarString(PasswPrompt2);
1539
} else { /* Retry call, previous password was wrong */
1542
m = (char *)LoadFarString(PasswRetry);
1545
m = getp(__G__ m, pwbuf, size);
1546
if (prompt != (char *)NULL) {
1549
if (m == (char *)NULL) {
1552
else if (*pwbuf == '\0') {
1553
r = IZ_PW_CANCELALL;
1558
/* tell picky compilers to shut up about "unused variable" warnings */
1559
pG = pG; rcnt = rcnt; pwbuf = pwbuf; size = size; zfn = zfn; efn = efn;
1561
return IZ_PW_ERROR; /* internal error; function should never get called */
1564
} /* end function UzpPassword() */
1570
/**********************/
1571
/* Function handler() */
1572
/**********************/
1574
void handler(signal) /* upon interrupt, turn on echo and exit cleanly */
1579
#if !(defined(SIGBUS) || defined(SIGSEGV)) /* add a newline if not at */
1580
(*G.message)((zvoid *)&G, slide, 0L, 0x41); /* start of line (to stderr; */
1581
#endif /* slide[] should be safe) */
1586
if (signal == SIGBUS) {
1587
Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1595
if (signal == SIGSEGV) {
1596
Info(slide, 0x421, ((char *)slide, LoadFarString(ZipfileCorrupt),
1597
"segmentation violation"));
1601
#endif /* SIGSEGV */
1603
/* probably ctrl-C */
1605
#if defined(AMIGA) && defined(__SASC)
1608
EXIT(IZ_CTRLC); /* was EXIT(0), then EXIT(PK_ERR) */
1611
#endif /* !WINDLL */
1616
#if (!defined(VMS) && !defined(CMS_MVS))
1617
#if (!defined(OS2) || defined(TIMESTAMP))
1619
#if (!defined(HAVE_MKTIME) || defined(WIN32))
1620
/* also used in amiga/filedate.c and win32/win32.c */
1621
ZCONST ush ydays[] =
1622
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
1625
/*******************************/
1626
/* Function dos_to_unix_time() */ /* used for freshening/updating/timestamps */
1627
/*******************************/
1629
time_t dos_to_unix_time(dosdatetime)
1636
ZCONST time_t now = time(NULL);
1638
# define YRBASE 1900
1640
tm = localtime(&now);
1641
tm->tm_isdst = -1; /* let mktime determine if DST is in effect */
1644
tm->tm_year = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
1645
tm->tm_mon = ((int)(dosdatetime >> 21) & 0x0f) - 1;
1646
tm->tm_mday = ((int)(dosdatetime >> 16) & 0x1f);
1649
tm->tm_hour = (int)((unsigned)dosdatetime >> 11) & 0x1f;
1650
tm->tm_min = (int)((unsigned)dosdatetime >> 5) & 0x3f;
1651
tm->tm_sec = (int)((unsigned)dosdatetime << 1) & 0x3e;
1653
m_time = mktime(tm);
1654
NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
1655
TTrace((stderr, " final m_time = %lu\n", (ulg)m_time));
1657
#else /* !HAVE_MKTIME */
1659
int yr, mo, dy, hh, mm, ss;
1661
# define YRBASE 1900
1665
# define YRBASE 1970
1669
#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1671
TIME_ZONE_INFORMATION tzinfo;
1674
#ifndef BSD4_4 /* GRR: change to !defined(MODERN) ? */
1675
#if (defined(BSD) || defined(MTS) || defined(__GO32__))
1677
#else /* !(BSD || MTS || __GO32__) */
1678
#ifdef DECLARE_TIMEZONE
1679
extern time_t timezone;
1681
#endif /* ?(BSD || MTS || __GO32__) */
1682
#endif /* !BSD4_4 */
1684
#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1685
#endif /* ?TOPS20 */
1689
yr = ((int)(dosdatetime >> 25) & 0x7f) + (1980 - YRBASE);
1690
mo = ((int)(dosdatetime >> 21) & 0x0f) - 1;
1691
dy = ((int)(dosdatetime >> 16) & 0x1f) - 1;
1694
hh = (int)((unsigned)dosdatetime >> 11) & 0x1f;
1695
mm = (int)((unsigned)dosdatetime >> 5) & 0x3f;
1696
ss = (int)((unsigned)dosdatetime & 0x1f) * 2;
1699
tmx = (struct tmx *)malloc(sizeof(struct tmx));
1700
sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss);
1701
time_parse(temp, tmx, (char *)0);
1702
m_time = time_make(tmx);
1707
/*---------------------------------------------------------------------------
1708
Calculate the number of seconds since the epoch, usually 1 January 1970.
1709
---------------------------------------------------------------------------*/
1711
/* leap = # of leap yrs from YRBASE up to but not including current year */
1712
leap = ((yr + YRBASE - 1) / 4); /* leap year base factor */
1714
/* calculate days from BASE to this year and add expired days this year */
1715
days = (yr * 365) + (leap - 492) + ydays[mo];
1717
/* if year is a leap year and month is after February, add another day */
1718
if ((mo > 1) && ((yr+YRBASE)%4 == 0) && ((yr+YRBASE) != 2100))
1719
++days; /* OK through 2199 */
1721
/* convert date & time to seconds relative to 00:00:00, 01/01/YRBASE */
1722
m_time = (time_t)((unsigned long)(days + dy) * 86400L +
1723
(unsigned long)hh * 3600L +
1724
(unsigned long)(mm * 60 + ss));
1725
/* - 1; MS-DOS times always rounded up to nearest even second */
1726
TTrace((stderr, "dos_to_unix_time:\n"));
1727
TTrace((stderr, " m_time before timezone = %lu\n", (ulg)m_time));
1729
/*---------------------------------------------------------------------------
1730
Adjust for local standard timezone offset.
1731
---------------------------------------------------------------------------*/
1733
#if (!defined(MACOS) && !defined(RISCOS) && !defined(QDOS) && !defined(TANDEM))
1735
/* account for timezone differences */
1736
res = GetTimeZoneInformation(&tzinfo);
1737
if (res != TIME_ZONE_ID_INVALID)
1739
m_time += 60*(tzinfo.Bias);
1741
#if (defined(BSD) || defined(MTS) || defined(__GO32__))
1743
if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1744
(m_time < (time_t)0x70000000L) )
1745
m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1746
if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1747
m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1748
if ((tm = localtime(&m_time)) != (struct tm *)NULL)
1749
m_time -= tm->tm_gmtoff; /* sec. EAST of GMT: subtr. */
1750
#else /* !(BSD4_4 */
1751
ftime(&tbp); /* get `timezone' */
1752
m_time += tbp.timezone * 60L; /* seconds WEST of GMT: add */
1753
#endif /* ?(BSD4_4 || __EMX__) */
1754
#else /* !(BSD || MTS || __GO32__) */
1755
/* tzset was already called at start of process_zipfiles() */
1756
/* tzset(); */ /* set `timezone' variable */
1757
#ifndef __BEOS__ /* BeOS DR8 has no timezones... */
1758
m_time += timezone; /* seconds WEST of GMT: add */
1760
#endif /* ?(BSD || MTS || __GO32__) */
1762
TTrace((stderr, " m_time after timezone = %lu\n", (ulg)m_time));
1764
/*---------------------------------------------------------------------------
1765
Adjust for local daylight savings (summer) time.
1766
---------------------------------------------------------------------------*/
1768
#ifndef BSD4_4 /* (DST already added to tm_gmtoff, so skip tm_isdst) */
1769
if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1770
(m_time < (time_t)0x70000000L) )
1771
m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1772
if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1773
m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1774
TIMET_TO_NATIVE(m_time) /* NOP unless MSC 7.0 or Macintosh */
1775
if (((tm = localtime((time_t *)&m_time)) != NULL) && tm->tm_isdst)
1777
m_time += 60L * tzinfo.DaylightBias; /* adjust with DST bias */
1779
m_time += 60L * tzinfo.StandardBias; /* add StdBias (normally 0) */
1781
m_time -= 60L * 60L; /* adjust for daylight savings time */
1783
NATIVE_TO_TIMET(m_time) /* NOP unless MSC 7.0 or Macintosh */
1784
TTrace((stderr, " m_time after DST = %lu\n", (ulg)m_time));
1785
#endif /* !BSD4_4 */
1789
#endif /* !MACOS && !RISCOS && !QDOS && !TANDEM */
1790
#endif /* ?TOPS20 */
1792
#endif /* ?HAVE_MKTIME */
1794
if ( (dosdatetime >= DOSTIME_2038_01_18) &&
1795
(m_time < (time_t)0x70000000L) )
1796
m_time = U_TIME_T_MAX; /* saturate in case of (unsigned) overflow */
1797
if (m_time < (time_t)0L) /* a converted DOS time cannot be negative */
1798
m_time = S_TIME_T_MAX; /* -> saturate at max signed time_t value */
1802
} /* end function dos_to_unix_time() */
1804
#endif /* !OS2 || TIMESTAMP */
1805
#endif /* !VMS && !CMS_MVS */
1809
#if (!defined(VMS) && !defined(OS2) && !defined(CMS_MVS))
1811
/******************************/
1812
/* Function check_for_newer() */ /* used for overwriting/freshening/updating */
1813
/******************************/
1815
int check_for_newer(__G__ filename) /* return 1 if existing file is newer */
1816
__GDEF /* or equal; 0 if older; -1 if doesn't */
1817
char *filename; /* exist yet */
1819
time_t existing, archive;
1820
#ifdef USE_EF_UT_TIME
1824
long dyy, dmm, ddd, dhh, dmin, dss;
1827
dyy = (lrec.last_mod_dos_datetime >> 25) + 1980;
1828
dmm = (lrec.last_mod_dos_datetime >> 21) & 0x0f;
1829
ddd = (lrec.last_mod_dos_datetime >> 16) & 0x1f;
1830
dhh = (lrec.last_mod_dos_datetime >> 11) & 0x1f;
1831
dmin = (lrec.last_mod_dos_datetime >> 5) & 0x3f;
1832
dss = (lrec.last_mod_dos_datetime & 0x1f) * 2;
1834
/* under AOS/VS, file times can only be set at creation time,
1835
* with the info in a special DG format. Make sure we can create
1836
* it here - we delete it later & re-create it, whether or not
1839
if (!zvs_create(filename, (((ulg)dgdate(dmm, ddd, dyy)) << 16) |
1840
(dhh*1800L + dmin*30L + dss/2L), -1L, -1L, (char *) -1, -1, -1, -1))
1841
return DOES_NOT_EXIST;
1844
Trace((stderr, "check_for_newer: doing stat(%s)\n", FnFilter1(filename)));
1845
if (SSTAT(filename, &G.statbuf)) {
1847
"check_for_newer: stat(%s) returns %d: file does not exist\n",
1848
FnFilter1(filename), SSTAT(filename, &G.statbuf)));
1850
Trace((stderr, "check_for_newer: doing lstat(%s)\n",
1851
FnFilter1(filename)));
1852
/* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1853
if (lstat(filename, &G.statbuf) == 0) {
1855
"check_for_newer: lstat(%s) returns 0: symlink does exist\n",
1856
FnFilter1(filename)));
1857
if (QCOND2 && !IS_OVERWRT_ALL)
1858
Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
1859
FnFilter1(filename), " with no real file"));
1860
return EXISTS_AND_OLDER; /* symlink dates are meaningless */
1862
#endif /* SYMLINKS */
1863
return DOES_NOT_EXIST;
1865
Trace((stderr, "check_for_newer: stat(%s) returns 0: file exists\n",
1866
FnFilter1(filename)));
1869
/* GRR OPTION: could instead do this test ONLY if G.symlnk is true */
1870
if (lstat(filename, &G.statbuf) == 0 && S_ISLNK(G.statbuf.st_mode)) {
1871
Trace((stderr, "check_for_newer: %s is a symbolic link\n",
1872
FnFilter1(filename)));
1873
if (QCOND2 && !IS_OVERWRT_ALL)
1874
Info(slide, 0, ((char *)slide, LoadFarString(FileIsSymLink),
1875
FnFilter1(filename), ""));
1876
return EXISTS_AND_OLDER; /* symlink dates are meaningless */
1878
#endif /* SYMLINKS */
1880
NATIVE_TO_TIMET(G.statbuf.st_mtime) /* NOP unless MSC 7.0 or Macintosh */
1882
#ifdef USE_EF_UT_TIME
1883
/* The `Unix extra field mtime' should be used for comparison with the
1884
* time stamp of the existing file >>>ONLY<<< when the EF info is also
1885
* used to set the modification time of the extracted file.
1887
if (G.extra_field &&
1891
(ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
1892
G.lrec.last_mod_dos_datetime, &z_utime, NULL)
1895
TTrace((stderr, "check_for_newer: using Unix extra field mtime\n"));
1896
existing = G.statbuf.st_mtime;
1897
archive = z_utime.mtime;
1899
/* round up existing filetime to nearest 2 seconds for comparison,
1900
* but saturate in case of arithmetic overflow
1902
existing = ((G.statbuf.st_mtime & 1) &&
1903
(G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
1904
G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
1905
archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
1907
#else /* !USE_EF_UT_TIME */
1908
/* round up existing filetime to nearest 2 seconds for comparison,
1909
* but saturate in case of arithmetic overflow
1911
existing = ((G.statbuf.st_mtime & 1) &&
1912
(G.statbuf.st_mtime + 1 > G.statbuf.st_mtime)) ?
1913
G.statbuf.st_mtime + 1 : G.statbuf.st_mtime;
1914
archive = dos_to_unix_time(G.lrec.last_mod_dos_datetime);
1915
#endif /* ?USE_EF_UT_TIME */
1917
TTrace((stderr, "check_for_newer: existing %lu, archive %lu, e-a %ld\n",
1918
(ulg)existing, (ulg)archive, (long)(existing-archive)));
1920
return (existing >= archive);
1922
} /* end function check_for_newer() */
1924
#endif /* !VMS && !OS2 && !CMS_MVS */
1930
/************************/
1931
/* Function do_string() */
1932
/************************/
1934
int do_string(__G__ length, option) /* return PK-type error code */
1936
unsigned int length; /* without prototype, ush converted to this */
1939
unsigned comment_bytes_left;
1940
unsigned int block_len;
1943
char tmp_fnote[2 * AMIGA_FILENOTELEN]; /* extra room for squozen chars */
1947
/*---------------------------------------------------------------------------
1948
This function processes arbitrary-length (well, usually) strings. Four
1949
major options are allowed: SKIP, wherein the string is skipped (pretty
1950
logical, eh?); DISPLAY, wherein the string is printed to standard output
1951
after undergoing any necessary or unnecessary character conversions;
1952
DS_FN, wherein the string is put into the filename[] array after under-
1953
going appropriate conversions (including case-conversion, if that is
1954
indicated: see the global variable pInfo->lcflag); and EXTRA_FIELD,
1955
wherein the `string' is assumed to be an extra field and is copied to
1956
the (freshly malloced) buffer G.extra_field. The third option should
1957
be OK since filename is dimensioned at 1025, but we check anyway.
1959
The string, by the way, is assumed to start at the current file-pointer
1960
position; its length is given by 'length'. So start off by checking the
1961
length of the string: if zero, we're already done.
1962
---------------------------------------------------------------------------*/
1969
#if (defined(SFX) && defined(CHEAP_SFX_AUTORUN))
1971
* Special case: See if the comment begins with an autorun command line.
1972
* Save that and display (or skip) the remainder.
1976
case CHECK_AUTORUN_Q:
1977
comment_bytes_left = length;
1980
block_len = readbuf(__G__ (char *)G.outbuf, 10);
1983
comment_bytes_left -= block_len;
1984
G.outbuf[block_len] = '\0';
1985
if (!strcmp((char *)G.outbuf, "$AUTORUN$>")) {
1988
block_len = readbuf(__G__ G.autorun_command,
1989
MIN(length, sizeof(G.autorun_command)-1));
1992
comment_bytes_left -= block_len;
1993
G.autorun_command[block_len] = '\0';
1994
A_TO_N(G.autorun_command);
1995
eol = strchr(G.autorun_command, '\n');
1997
eol = G.autorun_command + strlen(G.autorun_command) - 1;
1998
length -= eol + 1 - G.autorun_command;
1999
while (eol >= G.autorun_command && isspace(*eol))
2001
#if (defined(WIN32) && !defined(_WIN32_WCE))
2002
/* Win9x console always uses OEM character coding, and
2003
WinNT console is set to OEM charset by default, too */
2004
INTERN_TO_OEM(G.autorun_command, G.autorun_command);
2005
#endif /* (WIN32 && !_WIN32_WCE) */
2008
if (option == CHECK_AUTORUN_Q) /* don't display the remainder */
2010
/* seek to beginning of remaining part of comment -- rewind if */
2011
/* displaying entire comment, or skip to end if discarding it */
2012
seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
2013
(G.inptr - G.inbuf) + comment_bytes_left - length);
2016
/* FALL THROUGH... */
2017
#endif /* SFX && CHEAP_SFX_AUTORUN */
2020
* First normal case: print string on standard output. First set loop
2021
* variables, then loop through the comment in chunks of OUTBUFSIZ bytes,
2022
* converting formats and printing as we go. The second half of the
2023
* loop conditional was added because the file might be truncated, in
2024
* which case comment_bytes_left will remain at some non-zero value for
2025
* all time. outbuf and slide are used as scratch buffers because they
2026
* are available (we should be either before or in between any file pro-
2032
comment_bytes_left = length;
2033
block_len = OUTBUFSIZ; /* for the while statement, first time */
2034
while (comment_bytes_left > 0 && block_len > 0) {
2035
register uch *p = G.outbuf;
2036
register uch *q = G.outbuf;
2038
if ((block_len = readbuf(__G__ (char *)G.outbuf,
2039
MIN((unsigned)OUTBUFSIZ, comment_bytes_left))) == 0)
2041
comment_bytes_left -= block_len;
2043
/* this is why we allocated an extra byte for outbuf: terminate
2044
* with zero (ASCIIZ) */
2045
G.outbuf[block_len] = '\0';
2047
/* remove all ASCII carriage returns from comment before printing
2048
* (since used before A_TO_N(), check for CR instead of '\r')
2055
/* could check whether (p - outbuf) == block_len here */
2058
if (option == DISPL_8) {
2059
/* translate the text coded in the entry's host-dependent
2060
"extended ASCII" charset into the compiler's (system's)
2061
internal text code page */
2062
Ext_ASCII_TO_Native((char *)G.outbuf, G.pInfo->hostnum,
2063
G.pInfo->hostver, G.pInfo->HasUxAtt,
2066
/* translate to ANSI (RTL internal codepage may be OEM) */
2067
INTERN_TO_ISO((char *)G.outbuf, (char *)G.outbuf);
2069
#if (defined(WIN32) && !defined(_WIN32_WCE))
2070
/* Win9x console always uses OEM character coding, and
2071
WinNT console is set to OEM charset by default, too */
2072
INTERN_TO_OEM((char *)G.outbuf, (char *)G.outbuf);
2073
#endif /* (WIN32 && !_WIN32_WCE) */
2074
#endif /* ?WINDLL */
2076
A_TO_N(G.outbuf); /* translate string to native */
2080
/* ran out of local mem -- had to cheat */
2081
win_fprintf((zvoid *)&G, stdout, length, (char *)G.outbuf);
2082
win_fprintf((zvoid *)&G, stdout, 2, (char *)"\n\n");
2084
#ifdef NOANSIFILT /* GRR: can ANSI be used with EBCDIC? */
2085
(*G.message)((zvoid *)&G, G.outbuf, (ulg)(q-G.outbuf), 0);
2086
#else /* ASCII, filter out ANSI escape sequences and handle ^S (pause) */
2092
if (*p == 0x1B) { /* ASCII escape char */
2095
} else if (*p == 0x13) { /* ASCII ^S (pause) */
2097
if (p[1] == LF) /* ASCII LF */
2099
else if (p[1] == CR && p[2] == LF) { /* ASCII CR LF */
2105
if ((unsigned)(q-slide) > WSIZE-3 || pause) { /* flush */
2106
(*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
2108
if (pause && G.extract_flag) /* don't pause for list/test */
2109
(*G.mpause)((zvoid *)&G, LoadFarString(QuitPrompt), 0);
2112
(*G.message)((zvoid *)&G, slide, (ulg)(q-slide), 0);
2113
#endif /* ?NOANSIFILT */
2114
#endif /* ?WINDLL */
2116
/* add '\n' if not at start of line */
2117
(*G.message)((zvoid *)&G, slide, 0L, 0x40);
2121
* Second case: read string into filename[] array. The filename should
2122
* never ever be longer than FILNAMSIZ-1 (1024), but for now we'll check,
2128
if (length >= FILNAMSIZ) {
2129
Info(slide, 0x401, ((char *)slide,
2130
LoadFarString(FilenameTooLongTrunc)));
2132
/* remember excess length in block_len */
2133
block_len = length - (FILNAMSIZ - 1);
2134
length = FILNAMSIZ - 1;
2136
/* no excess size */
2138
if (readbuf(__G__ G.filename, length) == 0)
2140
G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */
2142
/* translate the Zip entry filename coded in host-dependent "extended
2143
ASCII" into the compiler's (system's) internal text code page */
2144
Ext_ASCII_TO_Native(G.filename, G.pInfo->hostnum, G.pInfo->hostver,
2145
G.pInfo->HasUxAtt, (option == DS_FN_L));
2147
if (G.pInfo->lcflag) /* replace with lowercase filename */
2148
STRLOWER(G.filename, G.filename);
2150
if (G.pInfo->vollabel && length > 8 && G.filename[8] == '.') {
2151
char *p = G.filename+8;
2153
p[-1] = *p; /* disk label, and 8th char is dot: remove dot */
2156
if (!block_len) /* no overflow, we're done here */
2160
* We truncated the filename, so print what's left and then fall
2161
* through to the SKIP routine.
2163
Info(slide, 0x401, ((char *)slide, "[ %s ]\n", FnFilter1(G.filename)));
2164
length = block_len; /* SKIP the excess bytes... */
2165
/* FALL THROUGH... */
2168
* Third case: skip string, adjusting readbuf's internal variables
2169
* as necessary (and possibly skipping to and reading a new block of
2174
/* cur_zipfile_bufstart already takes account of extra_bytes, so don't
2175
* correct for it twice: */
2176
seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
2177
(G.inptr-G.inbuf) + length);
2181
* Fourth case: assume we're at the start of an "extra field"; malloc
2182
* storage for it and read data into the allocated space.
2186
if (G.extra_field != (uch *)NULL)
2187
free(G.extra_field);
2188
if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) {
2189
Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong),
2191
/* cur_zipfile_bufstart already takes account of extra_bytes,
2192
* so don't correct for it twice: */
2193
seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
2194
(G.inptr-G.inbuf) + length);
2196
if (readbuf(__G__ (char *)G.extra_field, length) == 0)
2202
* Fifth case, for the Amiga only: take the comment that would ordinarily
2203
* be skipped over, and turn it into a 79 character string that will be
2204
* attached to the file as a "filenote" after it is extracted.
2208
if ((block_len = readbuf(__G__ tmp_fnote, (unsigned)
2209
MIN(length, 2 * AMIGA_FILENOTELEN - 1))) == 0)
2211
if ((length -= block_len) > 0) /* treat remainder as in case SKIP: */
2212
seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes
2213
+ (G.inptr - G.inbuf) + length);
2214
/* convert multi-line text into single line with no ctl-chars: */
2215
tmp_fnote[block_len] = '\0';
2216
while ((short int) --block_len >= 0)
2217
if ((unsigned) tmp_fnote[block_len] < ' ')
2218
if (tmp_fnote[block_len+1] == ' ') /* no excess */
2219
strcpy(tmp_fnote+block_len, tmp_fnote+block_len+1);
2221
tmp_fnote[block_len] = ' ';
2222
tmp_fnote[AMIGA_FILENOTELEN - 1] = '\0';
2223
if (G.filenotes[G.filenote_slot])
2224
free(G.filenotes[G.filenote_slot]); /* should not happen */
2225
G.filenotes[G.filenote_slot] = NULL;
2227
if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1)))
2229
strcpy(G.filenotes[G.filenote_slot], tmp_fnote);
2234
} /* end switch (option) */
2238
} /* end function do_string() */
2244
/***********************/
2245
/* Function makeword() */
2246
/***********************/
2252
* Convert Intel style 'short' integer to non-Intel non-16-bit
2253
* host format. This routine also takes care of byte-ordering.
2255
return (ush)((b[1] << 8) | b[0]);
2262
/***********************/
2263
/* Function makelong() */
2264
/***********************/
2270
* Convert intel style 'long' variable to non-Intel non-16-bit
2271
* host format. This routine also takes care of byte-ordering.
2273
return (((ulg)sig[3]) << 24)
2274
+ (((ulg)sig[2]) << 16)
2275
+ (((ulg)sig[1]) << 8)
2284
/**********************/
2285
/* Function str2iso() */
2286
/**********************/
2288
char *str2iso(dst, src)
2289
char *dst; /* destination buffer */
2290
register ZCONST char *src; /* source string */
2292
#ifdef INTERN_TO_ISO
2293
INTERN_TO_ISO(src, dst);
2296
register char *dstp = dst;
2299
c = (uch)foreign(*src++);
2300
*dstp++ = (char)ASCII2ISO(c);
2301
} while (c != '\0');
2306
#endif /* NEED_STR2ISO */
2310
/**********************/
2311
/* Function str2oem() */
2312
/**********************/
2314
char *str2oem(dst, src)
2315
char *dst; /* destination buffer */
2316
register ZCONST char *src; /* source string */
2318
#ifdef INTERN_TO_OEM
2319
INTERN_TO_OEM(src, dst);
2322
register char *dstp = dst;
2325
c = (uch)foreign(*src++);
2326
*dstp++ = (char)ASCII2OEM(c);
2327
} while (c != '\0');
2332
#endif /* NEED_STR2OEM */
2337
#ifdef ZMEM /* memset/memcmp/memcpy for systems without either them or */
2338
/* bzero/bcmp/bcopy */
2339
/* (no known systems as of 960211) */
2341
/*********************/
2342
/* Function memset() */
2343
/*********************/
2345
zvoid *memset(buf, init, len)
2346
register zvoid *buf; /* buffer location */
2347
register int init; /* initializer character */
2348
register unsigned int len; /* length of the buffer */
2354
*((char *)buf++) = (char)init;
2360
/*********************/
2361
/* Function memcmp() */
2362
/*********************/
2364
int memcmp(b1, b2, len)
2365
register ZCONST zvoid *b1;
2366
register ZCONST zvoid *b2;
2367
register unsigned int len;
2372
if ((c = (int)(*((ZCONST unsigned char *)b1)++) -
2373
(int)(*((ZCONST unsigned char *)b2)++)) != 0)
2381
/*********************/
2382
/* Function memcpy() */
2383
/*********************/
2385
zvoid *memcpy(dst, src, len)
2386
register zvoid *dst;
2387
register ZCONST zvoid *src;
2388
register unsigned int len;
2394
*((char *)dst)++ = *((ZCONST char *)src)++;
2405
/************************/
2406
/* Function zstrnicmp() */
2407
/************************/
2409
int zstrnicmp(s1, s2, n)
2410
register ZCONST char *s1, *s2;
2411
register unsigned n;
2413
for (; n > 0; --n, ++s1, ++s2) {
2415
if (ToLower(*s1) != ToLower(*s2))
2416
/* test includes early termination of one string */
2417
return (ToLower(*s1) < ToLower(*s2))? -1 : 1;
2419
if (*s1 == '\0') /* both strings terminate early */
2425
#endif /* NO_STRNICMP */
2430
#ifdef REGULUS /* returns the inode number on success(!)...argh argh argh */
2433
/********************/
2434
/* Function zstat() */
2435
/********************/
2441
return (stat((char *)p,s) >= 0? 0 : (-1));
2444
#endif /* REGULUS */
2451
/* DBCS support for Info-ZIP's zip (mainly for japanese (-: )
2452
* by Yoshioka Tsuneo (QWF00133@nifty.ne.jp,tsuneo-y@is.aist-nara.ac.jp)
2453
* This code is public domain! Date: 1998/12/20
2456
/************************/
2457
/* Function plastchar() */
2458
/************************/
2460
char *plastchar(ptr, len)
2465
ZCONST char *oldptr = ptr;
2466
while(*ptr != '\0' && len > 0){
2472
return (char *)oldptr;
2476
#ifdef NEED_UZMBSCHR
2477
/***********************/
2478
/* Function uzmbschr() */
2479
/***********************/
2481
unsigned char *uzmbschr(str, c)
2482
ZCONST unsigned char *str;
2485
while(*str != '\0'){
2486
if (*str == c) {return (unsigned char *)str;}
2491
#endif /* NEED_UZMBSCHR */
2494
#ifdef NEED_UZMBSRCHR
2495
/************************/
2496
/* Function uzmbsrchr() */
2497
/************************/
2499
unsigned char *uzmbsrchr(str, c)
2500
ZCONST unsigned char *str;
2503
unsigned char *match = NULL;
2504
while(*str != '\0'){
2505
if (*str == c) {match = (unsigned char *)str;}
2510
#endif /* NEED_UZMBSRCHR */
2519
/*******************************/
2520
/* Function fLoadFarString() */ /* (and friends...) */
2521
/*******************************/
2523
char *fLoadFarString(__GPRO__ const char Far *sz)
2525
(void)zfstrcpy(G.rgchBigBuffer, sz);
2526
return G.rgchBigBuffer;
2529
char *fLoadFarStringSmall(__GPRO__ const char Far *sz)
2531
(void)zfstrcpy(G.rgchSmallBuffer, sz);
2532
return G.rgchSmallBuffer;
2535
char *fLoadFarStringSmall2(__GPRO__ const char Far *sz)
2537
(void)zfstrcpy(G.rgchSmallBuffer2, sz);
2538
return G.rgchSmallBuffer2;
2544
#if (!defined(_MSC_VER) || (_MSC_VER < 600))
2545
/*************************/
2546
/* Function zfstrcpy() */ /* portable clone of _fstrcpy() */
2547
/*************************/
2549
char Far * Far zfstrcpy(char Far *s1, const char Far *s2)
2553
while ((*s1++ = *s2++) != '\0');
2557
#if (!(defined(SFX) || defined(FUNZIP)))
2558
/*************************/
2559
/* Function zfstrcmp() */ /* portable clone of _fstrcmp() */
2560
/*************************/
2562
int Far zfstrcmp(const char Far *s1, const char Far *s2)
2566
while ((ret = (int)(uch)*s1 - (int)(uch)*s2) == 0
2572
#endif /* !(SFX || FUNZIP) */
2573
#endif /* !_MSC_VER || (_MSC_VER < 600) */
2575
#endif /* SMALL_MEM */