~ubuntu-branches/ubuntu/precise/unzip/precise-proposed

« back to all changes in this revision

Viewing changes to fileio.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2004-06-06 17:57:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040606175746-nl7p2dgp3aobyc2c
Tags: upstream-5.51
ImportĀ upstreamĀ versionĀ 5.51

Show diffs side-by-side

added added

removed removed

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