Subversion Repositories Kolibri OS

Rev

Rev 6725 | Details | Compare with Previous | Last modification | View Log | RSS feed

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