Annotation of coherent/b/bin/unzip/unzip.c, revision 1.1

1.1     ! root        1: /*---------------------------------------------------------------------------
        !             2: 
        !             3:   unzip.c
        !             4: 
        !             5:   UnZip - a zipfile extraction utility.  See below for make instructions, or
        !             6:   read the comments in Makefile and the various Contents files for more de-
        !             7:   tailed explanations.  To report a bug, send a *complete* description to
        !             8:   [email protected]; include machine type, operating system and version,
        !             9:   compiler and version, and reasonably detailed error messages or problem
        !            10:   report.  To join Info-ZIP, send a message to [email protected].
        !            11: 
        !            12:   UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
        !            13:   which in turn was almost a complete rewrite of version 3.x.  For a detailed
        !            14:   revision history, see UnzpHist.zip at Info-ZIP headquarters (below).  For a 
        !            15:   (partial) list of the many (near infinite) contributors, see "CONTRIBS" in
        !            16:   the UnZip source distribution.
        !            17: 
        !            18:   ---------------------------------------------------------------------------
        !            19: 
        !            20:   To compile (partial instructions):
        !            21: 
        !            22:      under Unix (cc):  make <system name>
        !            23:        (type "make list" for a list of valid names, or read Makefile for 
        !            24:        details.  "make unzip" works for most systems.  If you have a NEW
        !            25:        system, not covered by any of the existing targets, send FULL infor-
        !            26:        mation--hardware, OS, versions, etc.--to [email protected])
        !            27: 
        !            28:      under MS-DOS (MSC, Turbo C, or Borland C++):  use the makefiles or
        !            29:        project files in the MSDOS sub-archive; edit or otherwise modify
        !            30:        as appropriate.  For MSC, use NMAKE.
        !            31: 
        !            32:      under MS Windows 3.x:  get wunz12sr.{zip | zoo | whatever} and use
        !            33:        the included makefile
        !            34: 
        !            35:      under OS/2 (MSC, gcc, IBM C Set/2, Watcom C):  make -f makefile.os2
        !            36:        (from OS2 sub-archive; for MSC, use NMAKE)
        !            37: 
        !            38:      under VMS (VAX C or GNU C):  @make_unzip_vaxc  or  @make_unzip_gcc
        !            39:        (from VMS sub-archive; can also use MMS or MAKE/VMS; see VMS.notes)
        !            40: 
        !            41:      under Macintosh OS:  Double click on unzip.make.  Press <Command>-M.
        !            42:        (from MAC sub-archive)
        !            43: 
        !            44:      under Windows NT:  use makefile.nt (from NT sub-archive)
        !            45: 
        !            46:      under AmigaDOS:  try one of the makefiles in the AMIGA sub-archive;
        !            47:        may need some work yet...
        !            48: 
        !            49:      under Atari TOS:  needs considerable work yet...
        !            50: 
        !            51:   ---------------------------------------------------------------------------
        !            52: 
        !            53:   Version:  unz50p1.{tar.Z | zip | zoo} for Unix, VMS, OS/2, MS-DOS, Windows,
        !            54:               Windows NT, Macintosh and Amiga.  Decryption requires sources
        !            55:               in zcrypt19.zip, and Windows (not NT) support requires sources
        !            56:               in wunz12sr.zip.  See accompanying file "Where" in the main
        !            57:               source distribution for ftp, uucp and mail-server sites.
        !            58:   Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
        !            59: 
        !            60:   ---------------------------------------------------------------------------*/
        !            61: 
        !            62: 
        !            63: 
        !            64: 
        !            65: 
        !            66: #include "unzip.h"               /* includes, defines, and macros */
        !            67: #ifdef MSWIN
        !            68: #  include "wizunzip.h"          /* see History.500 for version history */
        !            69: #endif
        !            70: 
        !            71: #define VERSION  "5.0p1 of 12 January 1993"
        !            72: /* #define VERSION  "v5.0p BETA of 8-21-92" */   /* internal beta level */
        !            73: #define PAKFIX   /* temporary(?) solution to PAK-created zipfiles */
        !            74: 
        !            75: 
        !            76: 
        !            77: 
        !            78: 
        !            79: /**********************/
        !            80: /*  Global Variables  */
        !            81: /**********************/
        !            82: 
        !            83: int aflag=0;          /* -a: do ASCII to EBCDIC translation, or CR-LF  */
        !            84:                       /*     to CR or LF conversion of extracted files */
        !            85: /* int bflag=0; RESERVED for -b: extract as binary */
        !            86: int cflag=0;          /* -c: output to stdout */
        !            87: int fflag=0;          /* -f: "freshen" (extract only newer files) */
        !            88: int jflag=0;          /* -j: junk pathnames */
        !            89: int overwrite_none=0; /* -n: never overwrite files (no prompting) */
        !            90: int overwrite_all=0;  /* -o: OK to overwrite files without prompting */
        !            91: int force_flag=0;     /* (shares -o for now): force to override errors, etc. */
        !            92: int quietflg=0;       /* -q: produce a lot less output */
        !            93: #ifdef DOS_OS2
        !            94:    int sflag=1;       /* -s: allow spaces (blanks) in filenames */
        !            95: #endif /* DOS_OS2 */
        !            96: int tflag=0;          /* -t: test */
        !            97: int uflag=0;          /* -u: "update" (extract only newer & brand-new files) */
        !            98: static int U_flag=0;  /* -U: leave filenames in upper or mixed case */
        !            99: static int vflag=0;   /* -v: view directory (only used in unzip.c) */
        !           100: int V_flag=0;         /* -V: don't strip VMS version numbers */
        !           101: #ifdef VMS
        !           102:    int secinf=0;      /* -X: keep owner/protection */
        !           103: #endif /* VMS */
        !           104: int zflag=0;          /* -z: display only the archive comment */
        !           105: int process_all_files=0;
        !           106: 
        !           107: longint csize;        /* used by list_files(), ReadByte(): must be signed */
        !           108: longint ucsize;       /* used by list_files(), unReduce(), explode() */
        !           109: 
        !           110: char *fnames[2] = {"*", NULL};   /* default filenames vector */
        !           111: char **fnv = fnames;
        !           112: char sig[5];
        !           113: char answerbuf[10];
        !           114: 
        !           115: min_info info[DIR_BLKSIZ], *pInfo=info;
        !           116: 
        !           117: #ifdef OS2
        !           118:    int longname;              /* used in extract.c, mapname.c and file_io.c */
        !           119:    char longfilename[FILNAMSIZ];
        !           120: #endif /* OS2 */
        !           121: 
        !           122: #ifdef CRYPT
        !           123:    char *key = (char *)NULL;  /* password with which to decrypt data, or NULL */
        !           124: #endif /* CRYPT */
        !           125: 
        !           126: /*---------------------------------------------------------------------------
        !           127:     unShrink/unReduce/explode/inflate working storage and globals:
        !           128:   ---------------------------------------------------------------------------*/
        !           129: 
        !           130: union work area;              /* see unzip.h for the definition of work */
        !           131: ULONG crc32val;
        !           132: 
        !           133: UWORD mask_bits[] = {
        !           134:     0x0000,
        !           135:     0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
        !           136:     0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
        !           137: };
        !           138: 
        !           139: /*---------------------------------------------------------------------------
        !           140:     Input file variables:
        !           141:   ---------------------------------------------------------------------------*/
        !           142: 
        !           143: byte *inbuf, *inptr;     /* input buffer (any size is legal) and pointer */
        !           144: int incnt;
        !           145: 
        !           146: ULONG bitbuf;
        !           147: int bits_left;
        !           148: boolean zipeof;
        !           149: 
        !           150: int zipfd;               /* zipfile file handle */
        !           151: #ifdef MSWIN
        !           152:    char *zipfn;
        !           153: #else
        !           154:    char zipfn[FILNAMSIZ];
        !           155: #endif
        !           156: 
        !           157: char local_hdr_sig[5] = "\120";    /* remaining signature bytes come later   */
        !           158: char central_hdr_sig[5] = "\120";  /*  (must initialize at runtime so unzip  */
        !           159: char end_central_sig[5] = "\120";  /*  executable won't look like a zipfile) */
        !           160: /* char extd_local_sig[5] = "\120";  NOT USED YET */
        !           161: 
        !           162: cdir_file_hdr crec;      /* used in unzip.c, extract.c, misc.c */
        !           163: local_file_hdr lrec;     /* used in unzip.c, extract.c */
        !           164: ecdir_rec ecrec;         /* used in unzip.c, extract.c */
        !           165: struct stat statbuf;     /* used by main(), mapped_name(), check_for_newer() */
        !           166: 
        !           167: longint extra_bytes = 0;        /* used in unzip.c, misc.c */
        !           168: longint cur_zipfile_bufstart;   /* extract_or_test_files, readbuf, ReadByte */
        !           169:   
        !           170: #ifdef MACOS
        !           171:    short  gnVRefNum;
        !           172:    long  glDirID;
        !           173:    OSType  gostCreator;
        !           174:    OSType  gostType;
        !           175:    boolean  fMacZipped;
        !           176:    boolean  macflag;
        !           177:    CursHandle  rghCursor[4];    /* status cursors */
        !           178:    short  giCursor = 0;
        !           179: #endif
        !           180: 
        !           181: /*---------------------------------------------------------------------------
        !           182:     Output stream variables:
        !           183:   ---------------------------------------------------------------------------*/
        !           184: 
        !           185: byte *outbuf;                   /* buffer for rle look-back */
        !           186: byte *outptr;
        !           187: #ifdef MSWIN
        !           188:    byte __far *outout;
        !           189:    char *filename;
        !           190: #else /* !MSWIN */
        !           191:    byte *outout;                /* scratch pad for ASCII-native trans */
        !           192:    char filename[FILNAMSIZ];
        !           193: #endif /* ?MSWIN */
        !           194: byte *extra_field = (byte *)NULL;  /* used by VMS, Mac and OS/2 versions */
        !           195: longint outpos;                 /* absolute position in outfile */
        !           196: int outcnt;                     /* current position in outbuf */
        !           197: int outfd;
        !           198: int mem_mode = 0;
        !           199: int disk_full;
        !           200: 
        !           201: /*---------------------------------------------------------------------------
        !           202:     unzip.c static global variables (visible only within this file):
        !           203:   ---------------------------------------------------------------------------*/
        !           204: 
        !           205: static byte *hold;
        !           206: static char unkn[10];
        !           207: static longint ziplen;
        !           208: static UWORD methnum;
        !           209: 
        !           210: /*---------------------------------------------------------------------------
        !           211:     unzip.c repeated error messages (we use all of these at least twice)
        !           212:   ---------------------------------------------------------------------------*/
        !           213: 
        !           214: char *EndSigMsg = "\nwarning:\
        !           215:   didn't find end-of-central-dir signature at end of central dir.\n";
        !           216: char *CentSigMsg =
        !           217:   "error:  expected central file header signature not found (file #%u).\n";
        !           218: char *SeekMsg =
        !           219:   "error:  attempt to seek before beginning of zipfile\n%s";
        !           220: 
        !           221: #ifdef VMS
        !           222: char *ReportMsg = "\
        !           223:   (please check that you have transferred or created the zipfile in the\n\
        !           224:   appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n";
        !           225: #else /* !VMS */
        !           226: char *ReportMsg = "\
        !           227:   (please check that you have transferred or created the zipfile in the\n\
        !           228:   appropriate BINARY mode and that you have compiled unzip properly)\n";
        !           229: #endif /* ?VMS */
        !           230: 
        !           231: 
        !           232: #ifdef MSWIN
        !           233: /* MS Windows Setup  and Take-Down functions bracket calls to 
        !           234:  * process_zipfile().
        !           235:  * These functions allocate and free the necessary buffers, set and clear
        !           236:  * any global variables so that  process_zipfile()  can be called multiple
        !           237:  * times in the same session of WizUnzip. You'll recognize some of the 
        !           238:  * code from main() in SetUpToProcessZipFile().
        !           239:  */
        !           240: HANDLE hOutBuf;
        !           241: HANDLE hOutOut;   /* added 04/03/92 for version 1.1 */
        !           242: HANDLE hInBuf;
        !           243: HANDLE hZipFN;
        !           244: HANDLE hFileName;
        !           245: 
        !           246: BOOL FSetUpToProcessZipFile(int ncflag, int ntflag, int nvflag, int nUflag, 
        !           247:        int nzflag, int ndflag, int noflag, int naflag, int argc,
        !           248:        LPSTR lpszZipFN, PSTR *FNV)
        !           249: {
        !           250:     /* clear all global flags -- need to or not. */
        !           251: 
        !           252:     tflag = vflag=cflag=aflag=U_flag=quietflg=zflag = 0;
        !           253:     overwrite_all=overwrite_none=0;
        !           254:     fnv = &fnames[0];       /* assign default file name vector */
        !           255: 
        !           256:     cflag = ncflag ; overwrite_all = noflag;
        !           257:     tflag = ntflag ; vflag = nvflag; zflag = nzflag; U_flag = nUflag;
        !           258:     aflag = naflag;
        !           259:     sflag = 1;
        !           260: 
        !           261:     local_hdr_sig[0] = central_hdr_sig[0] = end_central_sig[0] = '\120';
        !           262:     local_hdr_sig[1] = central_hdr_sig[1] = end_central_sig[1] = '\0';
        !           263: 
        !           264:     if (!(hZipFN = LocalAlloc(LMEM_MOVEABLE, FILNAMSIZ)))
        !           265:         return FALSE;
        !           266: 
        !           267:     zipfn = (char *)LocalLock(hZipFN);
        !           268:     lstrcpy(zipfn, lpszZipFN);
        !           269:     if (stat(zipfn, &statbuf) || (statbuf.st_mode & S_IFMT) == S_IFDIR)
        !           270:         strcat(zipfn, ZSUFX);
        !           271: 
        !           272:     if (stat(zipfn, &statbuf)) {  /* try again */
        !           273:         fprintf(stderr, "error:  can't find zipfile [ %s ]\n", zipfn);
        !           274:         return TRUE;              /* 9:  file not found */
        !           275:     } else
        !           276:         ziplen = statbuf.st_size;
        !           277: 
        !           278:     if (argc != 0) {
        !           279:         fnv = FNV;
        !           280:         process_all_files = FALSE;
        !           281:     } else
        !           282:         process_all_files = TRUE;       /* for speed */
        !           283: 
        !           284: /*---------------------------------------------------------------------------
        !           285:     Okey dokey, we have everything we need to get started.  Let's roll.
        !           286:   ---------------------------------------------------------------------------*/
        !           287: 
        !           288:     if (hInBuf = LocalAlloc(LMEM_MOVEABLE, INBUFSIZ+4)) {  /* 4 extra: hold[] */
        !           289:         inbuf = (byte *) LocalLock(hInBuf);
        !           290:         WinAssert(inbuf);
        !           291:     }
        !           292:     if (hOutBuf = LocalAlloc(LMEM_MOVEABLE, OUTBUFSIZ+1)) {  /* extra: ASCIIZ */
        !           293:         outbuf = (byte *)LocalLock(hOutBuf);
        !           294:         WinAssert(outbuf);
        !           295:         if (aflag) {   /* if LF => CR,LF translation */
        !           296:             if (hOutOut = GlobalAlloc(GMEM_MOVEABLE,OUTBUFSIZ)) {
        !           297:                 outout = (byte _far *)GlobalLock(hOutOut);
        !           298:                 WinAssert(outout);
        !           299:             }
        !           300:         } else    /* no translation; just re-use output buffer */
        !           301:             outout = (byte _far *)outbuf;  /*  point to outbuf */
        !           302:     }
        !           303:     if ( hFileName = LocalAlloc(LMEM_MOVEABLE, FILNAMSIZ)) {
        !           304:         filename = (char *)LocalLock(hFileName);
        !           305:         WinAssert(filename);
        !           306:     }
        !           307: 
        !           308:     if ((inbuf == NULL) || (outbuf == NULL) || (outout == NULL) ||
        !           309:         (zipfn == NULL) || (filename == NULL))
        !           310:         return FALSE;
        !           311: 
        !           312:     hold = &inbuf[INBUFSIZ];   /* to check for boundary-spanning signatures */
        !           313: 
        !           314:     return TRUE;    /* set up was OK */
        !           315: }
        !           316: 
        !           317: void TakeDownFromProcessZipFile(void)
        !           318: {
        !           319:     if (inbuf) {
        !           320:         LocalUnlock(hInBuf);
        !           321:         inbuf = NULL;
        !           322:     }
        !           323:     if (hInBuf)
        !           324:         hInBuf = LocalFree(hInBuf);
        !           325: 
        !           326:     if (outbuf) {
        !           327:         LocalUnlock(hOutBuf);
        !           328:         outbuf = NULL;
        !           329:     }
        !           330:     if (hOutBuf)
        !           331:         hOutBuf = LocalFree(hOutBuf);
        !           332: 
        !           333:     if (aflag && outout)    /* if doing LF => CR,LF translation */
        !           334:         GlobalUnlock(hOutOut);
        !           335:     outout = NULL;          /* free now, translation or not     */
        !           336:     if (hOutOut)
        !           337:         hOutOut = GlobalFree(hOutOut);  /* mark buffer as freed */
        !           338: 
        !           339:     if (zipfn) {
        !           340:         LocalUnlock(hZipFN);
        !           341:         zipfn = NULL;
        !           342:     }
        !           343:     if (hZipFN)
        !           344:         hZipFN = LocalFree(hZipFN);
        !           345: 
        !           346:     if (filename) {
        !           347:         LocalUnlock(hFileName);
        !           348:         filename = NULL;
        !           349:     }
        !           350:     if (hFileName)
        !           351:         hFileName = LocalFree(hFileName);
        !           352: }
        !           353: 
        !           354: #else /* !MSWIN */
        !           355: 
        !           356: /******************/
        !           357: /*  Main program  */
        !           358: /******************/
        !           359: 
        !           360: int main(argc, argv)   /* return PK-type error code (except under VMS) */
        !           361:     int argc;
        !           362:     char *argv[];
        !           363: {
        !           364:     char *s;
        !           365:     int c, error=FALSE, negative=0;
        !           366: 
        !           367: 
        !           368: /*---------------------------------------------------------------------------
        !           369:     Macintosh initialization code.
        !           370:   ---------------------------------------------------------------------------*/
        !           371: 
        !           372: #ifdef MACOS
        !           373: #ifdef THINK_C
        !           374: #   include <console.h>
        !           375:     static char *argstr[30], args[30*64];
        !           376:     Point p;
        !           377:     SFTypeList sfT;
        !           378:     EventRecord theEvent;
        !           379:     short eMask;
        !           380:     SFReply fileRep;
        !           381: #endif /* THINK_C */
        !           382:     int a;
        !           383: 
        !           384:     for (a = 0;  a < 4;  ++a)
        !           385:         rghCursor[a] = GetCursor(a+128);
        !           386:     giCursor = 0;
        !           387: 
        !           388:     area.Slide = (byte *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char));
        !           389:     area.shrink.Prefix_of = (short *)area.Slide;
        !           390:     area.shrink.Suffix_of = area.Slide + (sizeof(short)*(HSIZE+1));
        !           391:     area.shrink.Stack = area.Slide + (sizeof(short) + sizeof(char))*(HSIZE+1);
        !           392: 
        !           393: #ifdef THINK_C   
        !           394:     for (a = 0;  a < 30;  ++a)
        !           395:         argstr[a] = &args[a*64];
        !           396: start:
        !           397:     tflag=vflag=cflag=aflag=jflag=U_flag=quietflg=fflag=uflag=zflag = 0;
        !           398:     local_hdr_sig[1] = central_hdr_sig[1] = end_central_sig[1] = '\0';
        !           399: /*  extd_local_sig[1] = '\0';  */
        !           400:     error = FALSE;
        !           401: 
        !           402:     argc = ccommand(&argv);
        !           403:     SetPt(&p, 40, 40);
        !           404: 
        !           405:     SFGetFile(p, "\pSpecify ZIP file:", 0L, -1, sfT, 0L, &fileRep);
        !           406:     if (fileRep.good) {
        !           407:         macfstest(fileRep.vRefNum);
        !           408:         ResolveMacVol(fileRep.vRefNum, &gnVRefNum, &glDirID, NULL);
        !           409:         for (a = 1;  a < argc;  ++a)
        !           410:             if (argv[a][0] == '-')
        !           411:                 BlockMove(argv[a], argstr[a], (strlen(argv[a]) > 63) ? 64 :
        !           412:                    strlen(argv[a])+1);
        !           413:             else
        !           414:                 break;
        !           415:         PtoCstr((char *)fileRep.fName);
        !           416:         strcpy(argstr[a], (char *)fileRep.fName);
        !           417:         for (;  a < argc;  ++a)
        !           418:             BlockMove(argv[a], argstr[a+1], (strlen(argv[a]) > 63) ? 64 :
        !           419:                strlen(argv[a])+1);
        !           420:         ++argc;
        !           421:         argv = argstr;
        !           422: 
        !           423:         if (hfsflag == FALSE)  /* can't support directories:  junk pathnames */
        !           424:             jflag = 1;
        !           425:     }
        !           426: #endif /* THINK_C */
        !           427: #endif /* MACOS */
        !           428: 
        !           429: /*---------------------------------------------------------------------------
        !           430:     Set signal handler for restoring echo, warn of zipfile corruption, etc.
        !           431:   ---------------------------------------------------------------------------*/
        !           432: 
        !           433:     signal(SIGINT, handler);
        !           434:     signal(SIGTERM, handler);
        !           435: #ifdef SIGBUS
        !           436:     signal(SIGBUS, handler);
        !           437: #endif
        !           438: #ifdef SIGSEGV
        !           439:     signal(SIGSEGV, handler);
        !           440: #endif
        !           441: 
        !           442: /*---------------------------------------------------------------------------
        !           443:     Debugging info for checking on structure padding:
        !           444:   ---------------------------------------------------------------------------*/
        !           445: 
        !           446: #ifdef DEBUG_STRUC
        !           447:     printf("local_file_hdr size: %X\n",
        !           448:            sizeof(local_file_hdr));
        !           449:     printf("local_byte_hdr size: %X\n",
        !           450:            sizeof(local_byte_hdr));
        !           451:     printf("actual size of local headers: %X\n", LREC_SIZE);
        !           452: 
        !           453:     printf("central directory header size: %X\n",
        !           454:            sizeof(cdir_file_hdr));
        !           455:     printf("central directory byte header size: %X\n",
        !           456:            sizeof(cdir_byte_hdr));
        !           457:     printf("actual size of central dir headers: %X\n", CREC_SIZE);
        !           458: 
        !           459:     printf("end central dir record size: %X\n",
        !           460:            sizeof(ecdir_rec));
        !           461:     printf("end central dir byte record size: %X\n",
        !           462:            sizeof(ec_byte_rec));
        !           463:     printf("actual size of end-central-dir record: %X\n", ECREC_SIZE);
        !           464: #endif /* DEBUG_STRUC */
        !           465: 
        !           466: /*---------------------------------------------------------------------------
        !           467:     Put environment-variable options into the queue, then rip through any
        !           468:     command-line options lurking about...
        !           469:   ---------------------------------------------------------------------------*/
        !           470: 
        !           471:     envargs(&argc, &argv, ENV_UNZIP);
        !           472: 
        !           473:     while (--argc > 0 && (*++argv)[0] == '-') {
        !           474:         s = argv[0] + 1;
        !           475:         while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
        !           476:             switch (c) {
        !           477:                 case ('-'):
        !           478:                     ++negative;
        !           479:                     break;
        !           480:                 case ('a'):
        !           481:                     if (negative)
        !           482:                         aflag = FALSE, negative = 0;
        !           483:                     else
        !           484:                         aflag = TRUE;
        !           485:                     break;
        !           486: #if 0
        !           487:                 case ('b'):    /* force binary mode */
        !           488:                     if (negative)
        !           489:                         bflag = FALSE, negative = 0;
        !           490:                     else
        !           491:                         bflag = TRUE;
        !           492:                     break;
        !           493: #endif
        !           494:                 case ('c'):
        !           495:                     if (negative) {
        !           496:                         cflag = FALSE, negative = 0;
        !           497: #ifdef NATIVE
        !           498:                         aflag = FALSE;
        !           499: #endif
        !           500:                     } else {
        !           501:                         cflag = TRUE;
        !           502: #ifdef NATIVE
        !           503:                         aflag = TRUE;  /* so you can read it on the screen */
        !           504: #endif
        !           505:                     }
        !           506:                     break;
        !           507:                 case ('d'):    /* re-create directory structure (default) */
        !           508:                     if (negative)
        !           509:                         jflag = TRUE, negative = 0;
        !           510:                     break;
        !           511:                 case ('e'):    /* just ignore -e, -x options (extract) */
        !           512:                     break;
        !           513:                 case ('f'):    /* "freshen" (extract only newer files) */
        !           514:                     if (negative)
        !           515:                         fflag = uflag = FALSE, negative = 0;
        !           516:                     else
        !           517:                         fflag = uflag = TRUE;
        !           518:                     break;
        !           519:                 case ('j'):    /* junk pathnames/directory structure */
        !           520:                     if (negative)
        !           521:                         jflag = FALSE, negative = 0;
        !           522:                     else
        !           523:                         jflag = TRUE;
        !           524:                     break;
        !           525:                 case ('l'):
        !           526:                     if (negative) {
        !           527:                         vflag = MAX(vflag-negative,0);
        !           528:                         negative = 0;
        !           529:                     } else
        !           530:                         ++vflag;
        !           531:                     break;
        !           532:                 case ('n'):    /* don't overwrite any files */
        !           533:                     if (negative)
        !           534:                         overwrite_none = FALSE, negative = 0;
        !           535:                     else
        !           536:                         overwrite_none = TRUE;
        !           537:                     break;
        !           538:                 case ('o'):    /* OK to overwrite files without prompting */
        !           539:                     if (negative) {
        !           540:                         overwrite_all = MAX(overwrite_all-negative,0);
        !           541:                         force_flag = MAX(force_flag-negative,0);
        !           542:                         negative = 0;
        !           543:                     } else {
        !           544:                         ++overwrite_all;
        !           545:                         ++force_flag;  /* (share -o for now) force to cont. */
        !           546:                     }
        !           547:                     break;
        !           548:                 case ('p'):    /* pipes:  stdout, no tranlation, no messages */
        !           549:                     if (negative) {
        !           550:                         cflag = FALSE;
        !           551:                         quietflg = MAX(quietflg-999,0);
        !           552:                         negative = 0;
        !           553:                     } else {
        !           554:                         cflag = TRUE;
        !           555:                         quietflg += 999;
        !           556:                     }
        !           557:                     break;
        !           558:                 case ('q'):    /* quiet:  fewer comments/messages */
        !           559:                     if (negative) {
        !           560:                         quietflg = MAX(quietflg-negative,0);
        !           561:                         negative = 0;
        !           562:                     } else
        !           563:                         ++quietflg;
        !           564:                     break;
        !           565: #ifdef DOS_OS2
        !           566:                 case ('s'):    /* spaces in filenames:  allow by default */
        !           567:                     if (negative)
        !           568:                         sflag = TRUE, negative = 0;
        !           569:                     else
        !           570:                         sflag = FALSE;
        !           571:                     break;
        !           572: #endif
        !           573:                 case ('t'):
        !           574:                     if (negative)
        !           575:                         tflag = FALSE, negative = 0;
        !           576:                     else
        !           577:                         tflag = TRUE;
        !           578:                     break;
        !           579:                 case ('U'):    /* Uppercase (don't convert to all-lower) */
        !           580:                     if (negative)
        !           581:                         U_flag = FALSE, negative = 0;
        !           582:                     else
        !           583:                         U_flag = TRUE;
        !           584:                     break;
        !           585:                 case ('u'):    /* update (extract only new and newer files) */
        !           586:                     if (negative)
        !           587:                         uflag = FALSE, negative = 0;
        !           588:                     else
        !           589:                         uflag = TRUE;
        !           590:                     break;
        !           591:                 case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
        !           592:                     if (negative)
        !           593:                         V_flag = FALSE, negative = 0;
        !           594:                     else
        !           595:                         V_flag = TRUE;
        !           596:                     break;
        !           597:                 case ('v'):    /* verbose */
        !           598:                     if (negative) {
        !           599:                         vflag = MAX(vflag-negative,0);
        !           600:                         negative = 0;
        !           601:                     } else if (vflag)
        !           602:                         ++vflag;
        !           603:                     else
        !           604:                         vflag = 2;
        !           605:                     break;
        !           606: #ifdef VMS
        !           607:                 case ('X'):   /* restore owner/protection info (need privs?) */
        !           608:                     if (negative)
        !           609:                         secinf = FALSE, negative = 0;
        !           610:                     else
        !           611:                         secinf = TRUE;
        !           612:                     break;
        !           613: #endif /* VMS */
        !           614:                 case ('x'):    /* extract:  default */
        !           615:                     break;
        !           616:                 case ('z'):    /* display only the archive comment */
        !           617:                     if (negative) {
        !           618:                         zflag = MAX(zflag-negative,0);
        !           619:                         negative = 0;
        !           620:                     } else
        !           621:                         ++zflag;
        !           622:                     break;
        !           623:                 default:
        !           624:                     error = TRUE;
        !           625:                     break;
        !           626: 
        !           627:             } /* end switch */
        !           628:         } /* end while (not end of argument string) */
        !           629:     } /* end while (not done with switches) */
        !           630: 
        !           631: /*---------------------------------------------------------------------------
        !           632:     Make sure we aren't trying to do too many things here.  [This seems like
        !           633:     kind of a brute-force way to do things; but aside from that, isn't the
        !           634:     -a option useful when listing the directory (i.e., for reading zipfile
        !           635:     comments)?  It's a modifier, not an action in and of itself, so perhaps
        !           636:     it should not be included in the test--certainly, in the case of zipfile
        !           637:     testing, it can just be ignored.]
        !           638:   ---------------------------------------------------------------------------*/
        !           639: 
        !           640:     if ((aflag && tflag) || (aflag && vflag) || (cflag && tflag) ||
        !           641:         (cflag && uflag) || (cflag && vflag) || (tflag && uflag) ||
        !           642:         (tflag && vflag) || (uflag && vflag) || (fflag && overwrite_none)) {
        !           643:         fprintf(stderr, "error:\
        !           644:   -at, -av, -ct, -cu, -cv, -fn, -tu, -tv, -uv combinations not allowed\n");
        !           645:         error = TRUE;
        !           646:     }
        !           647:     if (quietflg && zflag)
        !           648:         quietflg = 0;
        !           649:     if (overwrite_all && overwrite_none) {
        !           650:         fprintf(stderr, "caution:  both -n and -o specified; ignoring -o\n");
        !           651:         overwrite_all = FALSE;
        !           652:     }
        !           653:     if ((argc-- == 0) || error)
        !           654:         RETURN(usage(error));
        !           655: 
        !           656: /*---------------------------------------------------------------------------
        !           657:     Now get the zipfile name from the command line and see if it exists as a
        !           658:     regular (non-directory) file.  If not, append the ".zip" suffix.  We don't
        !           659:     immediately check to see if this results in a good name, but we will do so
        !           660:     later.  In the meantime, see if there are any member filespecs on the com-
        !           661:     mand line, and if so, set the filename pointer to point at them.
        !           662:   ---------------------------------------------------------------------------*/
        !           663: 
        !           664:     strcpy(zipfn, *argv++);
        !           665:     if (stat(zipfn, &statbuf) || (statbuf.st_mode & S_IFMT) == S_IFDIR)
        !           666:         strcat(zipfn, ZSUFX);
        !           667: #if (defined(UNIX) && !defined(VMS)) /* Unix executables have no extension-- */
        !           668:     else if (statbuf.st_mode & S_IXUSR)  /* might find zip, not zip.zip; etc */
        !           669:         fprintf(stderr, "\nnote:  file [ %s ] may be an executable\n\n", zipfn);
        !           670: #endif /* UNIX && !VMS */
        !           671: 
        !           672:     if (stat(zipfn, &statbuf)) {/* try again */
        !           673:         fprintf(stderr, "error:  can't find zipfile [ %s ]\n", zipfn);
        !           674:         RETURN(9);              /* 9:  file not found */
        !           675:     } else
        !           676:         ziplen = statbuf.st_size;
        !           677: 
        !           678:     if (argc != 0) {
        !           679:         fnv = argv;
        !           680:         process_all_files = FALSE;
        !           681:     } else
        !           682:         process_all_files = TRUE;       /* for speed */
        !           683: 
        !           684: /*---------------------------------------------------------------------------
        !           685:     Okey dokey, we have everything we need to get started.  Let's roll.
        !           686:   ---------------------------------------------------------------------------*/
        !           687: 
        !           688:     inbuf = (byte *) malloc(INBUFSIZ + 4);     /* 4 extra for hold[] (below) */
        !           689:     outbuf = (byte *) malloc(OUTBUFSIZ + 1);   /* 1 extra for string termin. */
        !           690: #ifndef DOS_OS2
        !           691:     if (aflag)                  /* if need an ascebc scratch, */
        !           692:         outout = (byte *) malloc(OUTBUFSIZ);
        !           693:     else                        /*  allocate it... */
        !           694: #endif /* !DOS_OS2 */
        !           695:         outout = outbuf;        /*  else just point to outbuf */
        !           696: 
        !           697:     if ((inbuf == (byte *)NULL) || (outbuf == (byte *)NULL) ||
        !           698:         (outout == (byte *)NULL)) {
        !           699:         fprintf(stderr, "error:  can't allocate unzip buffers\n");
        !           700:         RETURN(4);              /* 4-8:  insufficient memory */
        !           701:     }
        !           702:     hold = &inbuf[INBUFSIZ];    /* to check for boundary-spanning signatures */
        !           703: 
        !           704:     RETURN(process_zipfile());  /* keep passing errors back... */
        !           705: 
        !           706: } /* end main() */
        !           707: 
        !           708: 
        !           709: 
        !           710: 
        !           711: 
        !           712: /**********************/
        !           713: /*  Function usage()  */
        !           714: /**********************/
        !           715: 
        !           716: int usage(error)   /* return PK-type error code */
        !           717:     int error;
        !           718: {
        !           719: #ifdef NATIVE
        !           720: #ifdef EBCDIC
        !           721:     char *astring = "-a  convert ASCII to EBCDIC";
        !           722: #else /* !EBCDIC */
        !           723:     char *astring = "-a  convert ASCII to native chars";
        !           724: #endif /* ?EBCDIC */
        !           725: /*  char *astring = "-a  convert ASCII to " NATIVE;  (ANSI C concatenation)  */
        !           726:     char *loc_str = "";
        !           727: #else /* !NATIVE */
        !           728: #ifdef DOS_OS2
        !           729:     char *astring = "-a  convert text (LF => CR LF)";
        !           730:     char *loc_str = "-s  spaces in filenames => _";
        !           731: #else /* !DOS_OS2 */
        !           732: #ifdef MACOS
        !           733:     char *astring = "-a  convert text (CR LF => CR)";
        !           734:     char *loc_str = "";
        !           735: #else /* !MACOS:  UNIX, VMS */
        !           736:     char *astring = "-a  convert text (CR LF => LF)";
        !           737: #ifdef VMS
        !           738:     char *loc_str = "-X  restore owner/protection info";
        !           739: #else /* !VMS */
        !           740:     char *loc_str = "";
        !           741: #endif /* ?VMS */
        !           742: #endif /* ?MACOS */
        !           743: #endif /* ?DOS_OS2 */
        !           744: #endif /* ?NATIVE */
        !           745:     FILE *usagefp;
        !           746: 
        !           747: 
        !           748: /*---------------------------------------------------------------------------
        !           749:     If user requested usage, send it to stdout; else send to stderr.
        !           750:   ---------------------------------------------------------------------------*/
        !           751: 
        !           752:     if (error)
        !           753:         usagefp = (FILE *) stderr;
        !           754:     else
        !           755:         usagefp = (FILE *) stdout;
        !           756: 
        !           757:     fprintf(usagefp, "\
        !           758: UnZip %s, by Info-ZIP.  Portions (c) 1989 by S. H. Smith.\n\
        !           759: Bug reports ONLY to zip-bugs%%[email protected]; see README for detail\
        !           760: s\n\n", VERSION);
        !           761: 
        !           762:     fprintf(usagefp, "\
        !           763: Usage: unzip [ -options[modifiers] ] file[.zip] [filespec...]\n\
        !           764:   -x  extract files (default)                -l  list files (short format)\n\
        !           765:   -c  extract files to stdout/screen (CRT)   -v  list files (verbose format)\n\
        !           766:   -f  freshen existing files, create none    -p  extract to pipe, no messages\n\
        !           767:   -u  update files, create if necessary      -t  test archive integrity\n\
        !           768:                                              -z  display archive comment\n\
        !           769: modifiers:\n\
        !           770:   -n  never overwrite existing files         %s\n", loc_str);
        !           771:     fprintf(usagefp, "\
        !           772:   -o  overwrite files WITHOUT prompting      %s\n\
        !           773:   -j  junk paths (don't make directories)    -U  don't make names lowercase\n\
        !           774:   -q  quiet mode (-qq => quieter)            -V  retain VMS version numbers\
        !           775: \n\n\
        !           776: Examples: (See manual for more information)\n\
        !           777:   unzip data1 ReadMe   => extracts file ReadMe from zipfile data1.zip\n\
        !           778:   unzip -p foo | more  => send contents of foo.zip via pipe into program more\n\
        !           779:   unzip -fo foo        => quietly replace existing files if archive files newer\
        !           780: \n", astring);
        !           781: 
        !           782: #ifdef VMS
        !           783:     fprintf(usagefp, "\
        !           784:   unzip \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\
        !           785: \n");
        !           786: #endif
        !           787: 
        !           788:     if (error)
        !           789:         return 10;    /* 10:  bad or illegal parameters specified */
        !           790:     else
        !           791:         return 0;     /* just wanted usage screen: no error */
        !           792: 
        !           793: } /* end function usage() */
        !           794: 
        !           795: #endif /* ?MSWIN */
        !           796: 
        !           797: 
        !           798: 
        !           799: 
        !           800: /********************************/
        !           801: /*  Function process_zipfile()  */
        !           802: /********************************/
        !           803: 
        !           804: int process_zipfile()    /* return PK-type error code */
        !           805: {
        !           806:     int error=0, error_in_archive;
        !           807:     longint real_ecrec_offset, expect_ecrec_offset;
        !           808: 
        !           809: 
        !           810: /*---------------------------------------------------------------------------
        !           811:     Open the zipfile for reading and in BINARY mode to prevent CR/LF trans-
        !           812:     lation, which would corrupt the bitstreams.
        !           813:   ---------------------------------------------------------------------------*/
        !           814: 
        !           815: #ifdef VMS
        !           816:     if (check_format())         /* check for variable-length format */
        !           817:         return 2;               /* 2:  error in zipfile */
        !           818: #endif /* VMS */
        !           819: 
        !           820:     if (open_input_file())      /* this should never happen, given the */
        !           821:         return 9;               /*   stat() test in main(), but... */
        !           822: 
        !           823: /*---------------------------------------------------------------------------
        !           824:     Reconstruct the various PK signature strings, and find and process the
        !           825:     end-of-central-directory header.
        !           826:   ---------------------------------------------------------------------------*/
        !           827: 
        !           828:     strcat(local_hdr_sig, LOCAL_HDR_SIG);
        !           829:     strcat(central_hdr_sig, CENTRAL_HDR_SIG);
        !           830:     strcat(end_central_sig, END_CENTRAL_SIG);
        !           831: /*  strcat(extd_local_sig, EXTD_LOCAL_SIG);  */
        !           832: 
        !           833:     if (find_end_central_dir()) {   /* not found; nothing to do */
        !           834:         close(zipfd);
        !           835:         return 2;                   /* 2:  error in zipfile */
        !           836:     }
        !           837: 
        !           838:     real_ecrec_offset = cur_zipfile_bufstart+(inptr-inbuf);
        !           839: #ifdef TEST
        !           840:     printf("\n  found end-of-central-dir signature at offset %ld (%.8lXh)\n",
        !           841:       real_ecrec_offset, real_ecrec_offset);
        !           842:     printf("    from beginning of file; offset %d (%.4Xh) within block\n",
        !           843:       inptr-inbuf, inptr-inbuf);
        !           844: #endif
        !           845: 
        !           846:     if ((error_in_archive = process_end_central_dir()) > 1) {
        !           847:         close(zipfd);
        !           848:         return error_in_archive;
        !           849:     }
        !           850: 
        !           851:     if (zflag) {
        !           852:         close(zipfd);
        !           853:         return 0;
        !           854:     }
        !           855: 
        !           856: /*---------------------------------------------------------------------------
        !           857:     Test the end-of-central-directory info for incompatibilities and incon-
        !           858:     sistencies.
        !           859:   ---------------------------------------------------------------------------*/
        !           860: 
        !           861: #ifndef PAKFIX
        !           862:     if (ecrec.number_this_disk == 0) {
        !           863: #else /* PAKFIX */
        !           864:     error = ((ecrec.number_this_disk == 1) &&
        !           865:              (ecrec.num_disk_with_start_central_dir == 1));
        !           866:     if ((ecrec.number_this_disk == 0) || error) {
        !           867:         if (error) {
        !           868:             fprintf(stderr,
        !           869:      "\n     Warning:  zipfile claims to be disk 2 of a two-part archive;\n\
        !           870:      attempting to process anyway.  If no further errors occur, this\n\
        !           871:      archive was probably created by PAK v2.51 or earlier.  This bug\n\
        !           872:      was reported to NoGate in March 1991 and was supposed to have been\n\
        !           873:      fixed by mid-1991; as of mid-1992 it still hadn't been.\n\n");
        !           874:             error_in_archive = 1;  /* 1:  warning */
        !           875:         }
        !           876: #endif /* ?PAKFIX */
        !           877:         expect_ecrec_offset = ecrec.offset_start_central_directory +
        !           878:                               ecrec.size_central_directory;
        !           879:         if ((extra_bytes = real_ecrec_offset - expect_ecrec_offset) < 0) {
        !           880:             fprintf(stderr, "\nerror:  missing %ld bytes in zipfile (\
        !           881: attempting to process anyway)\n\n", -extra_bytes);
        !           882:             error_in_archive = 2;       /* 2:  (weak) error in zipfile */
        !           883:         } else if (extra_bytes > 0) {
        !           884:             if ((ecrec.offset_start_central_directory == 0) &&
        !           885:                 (ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
        !           886:             {
        !           887:                 fprintf(stderr, "\nerror:  NULL central directory offset (\
        !           888: attempting to process anyway)\n\n");
        !           889:                 ecrec.offset_start_central_directory = extra_bytes;
        !           890:                 extra_bytes = 0;
        !           891:                 error_in_archive = 2;   /* 2:  (weak) error in zipfile */
        !           892:             } else {
        !           893:                 fprintf(stderr, "\nwarning:  extra %ld bytes at beginning or\
        !           894:  within zipfile\n          (attempting to process anyway)\n\n", extra_bytes);
        !           895:                 error_in_archive = 1;   /* 1:  warning error */
        !           896:             }
        !           897:         }
        !           898: 
        !           899:     /*-----------------------------------------------------------------------
        !           900:         Check for empty zipfile and exit now if so.
        !           901:       -----------------------------------------------------------------------*/
        !           902: 
        !           903:         if (expect_ecrec_offset == 0L  &&  ecrec.size_central_directory == 0) {
        !           904:             fprintf(stderr, "warning:  zipfile is empty\n");
        !           905:             close(zipfd);
        !           906:             return (error_in_archive > 1)? error_in_archive : 1;
        !           907:         }
        !           908: 
        !           909:     /*-----------------------------------------------------------------------
        !           910:         Compensate for missing or extra bytes, and seek to where the start
        !           911:         of central directory should be.  If header not found, uncompensate
        !           912:         and try again (necessary for at least some Atari archives created
        !           913:         with STZIP, as well as archives created by J.H. Holm's ZIPSPLIT).
        !           914:       -----------------------------------------------------------------------*/
        !           915: 
        !           916:         LSEEK( ecrec.offset_start_central_directory )
        !           917:         if ((readbuf(sig, 4) <= 0) || strncmp(sig, central_hdr_sig, 4)) {
        !           918:             longint tmp = extra_bytes;
        !           919: 
        !           920:             extra_bytes = 0;
        !           921:             LSEEK( ecrec.offset_start_central_directory )
        !           922:             if ((readbuf(sig, 4) <= 0) || strncmp(sig, central_hdr_sig, 4)) {
        !           923:                 fprintf(stderr,
        !           924:             "error:  start of central directory not found; zipfile corrupt.\n");
        !           925:                 fprintf(stderr, ReportMsg);
        !           926:                 close(zipfd);
        !           927:                 return 3;           /* 3:  severe error in zipfile */
        !           928:             }
        !           929:             fprintf(stderr, "error:  reported length of central directory is \
        !           930: %d bytes too\n        long (Atari STZIP zipfile?  J.H. Holm ZIPSPLIT zipfile?)\
        !           931: .\n        Compensating...\n\n", -tmp);
        !           932:             error_in_archive = 2;   /* 2:  (weak) error in zipfile */
        !           933:         }
        !           934: 
        !           935:     /*-----------------------------------------------------------------------
        !           936:         Seek to the start of the central directory one last time, since we
        !           937:         have just read the first entry's signature bytes; then list, extract
        !           938:         or test member files as instructed, and close the zipfile.
        !           939:       -----------------------------------------------------------------------*/
        !           940: 
        !           941:         LSEEK( ecrec.offset_start_central_directory )
        !           942:         if (vflag)
        !           943:             error = list_files();               /* LIST 'EM */
        !           944:         else
        !           945:             error = extract_or_test_files();    /* EXTRACT OR TEST 'EM */
        !           946:         if (error > error_in_archive)   /* don't overwrite stronger error */
        !           947:             error_in_archive = error;   /*  with (for example) a warning */
        !           948:     } else {
        !           949:         fprintf(stderr, "\nerror:  zipfile is part of multi-disk archive \
        !           950: (sorry, not supported).\n");
        !           951:     /*  fprintf(stderr, "Please report to [email protected]\n");  */
        !           952:         error_in_archive = 11;  /* 11:  no files found */
        !           953:     }
        !           954: 
        !           955:     close(zipfd);
        !           956:     return error_in_archive;
        !           957: 
        !           958: } /* end function process_zipfile() */
        !           959: 
        !           960: 
        !           961: 
        !           962: 
        !           963: 
        !           964: /************************************/
        !           965: /*  Function find_end_central_dir() */
        !           966: /************************************/
        !           967: 
        !           968: int find_end_central_dir()   /* return 0 if found, 1 otherwise */
        !           969: {
        !           970:     int i, numblks;
        !           971:     longint tail_len;
        !           972: 
        !           973: 
        !           974: 
        !           975: /*---------------------------------------------------------------------------
        !           976:     Treat case of short zipfile separately.
        !           977:   ---------------------------------------------------------------------------*/
        !           978: 
        !           979:     if (ziplen <= INBUFSIZ) {
        !           980:         lseek(zipfd, 0L, SEEK_SET);
        !           981:         if ((incnt = read(zipfd,(char *)inbuf,(unsigned int)ziplen)) ==
        !           982:              (int)ziplen)
        !           983: 
        !           984:             /* 'P' must be at least 22 bytes from end of zipfile */
        !           985:             for (inptr = inbuf+(int)ziplen-22;  inptr >= inbuf;  --inptr)
        !           986:                 if ((ascii_to_native(*inptr) == 'P')  &&
        !           987:                      !strncmp((char *)inptr, end_central_sig, 4)) {
        !           988:                     incnt -= inptr - inbuf;
        !           989:                     return 0;   /* found it! */
        !           990:                 }               /* ...otherwise fall through & fail */
        !           991: 
        !           992: /*---------------------------------------------------------------------------
        !           993:     Zipfile is longer than INBUFSIZ:  may need to loop.  Start with short
        !           994:     block at end of zipfile (if not TOO short).
        !           995:   ---------------------------------------------------------------------------*/
        !           996: 
        !           997:     } else {
        !           998:         if ((tail_len = ziplen % INBUFSIZ) > ECREC_SIZE) {
        !           999:             cur_zipfile_bufstart = lseek(zipfd, ziplen-tail_len, SEEK_SET);
        !          1000:             if ((incnt = read(zipfd,(char *)inbuf,(unsigned int)tail_len)) !=
        !          1001:                  (int)tail_len)
        !          1002:                 goto fail;      /* shut up; it's expedient. */
        !          1003: 
        !          1004:             /* 'P' must be at least 22 bytes from end of zipfile */
        !          1005:             for (inptr = inbuf+(int)tail_len-22;  inptr >= inbuf;  --inptr)
        !          1006:                 if ((ascii_to_native(*inptr) == 'P')  &&
        !          1007:                      !strncmp((char *)inptr, end_central_sig, 4)) {
        !          1008:                     incnt -= inptr - inbuf;
        !          1009:                     return 0;   /* found it */
        !          1010:                 }               /* ...otherwise search next block */
        !          1011:             strncpy((char *)hold, (char *)inbuf, 3);    /* sig may span block
        !          1012:                                                            boundary */
        !          1013:         } else {
        !          1014:             cur_zipfile_bufstart = ziplen - tail_len;
        !          1015:         }
        !          1016: 
        !          1017:     /*-----------------------------------------------------------------------
        !          1018:         Loop through blocks of zipfile data, starting at the end and going
        !          1019:         toward the beginning.  Need only check last 65557 bytes of zipfile:
        !          1020:         comment may be up to 65535 bytes long, end-of-central-directory rec-
        !          1021:         ord is 18 bytes (shouldn't hardcode this number, but what the hell:
        !          1022:         already did so above (22=18+4)), and sig itself is 4 bytes.
        !          1023:       -----------------------------------------------------------------------*/
        !          1024: 
        !          1025:         numblks = (int)
        !          1026:                   ((MIN(ziplen,65557L) - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
        !          1027:         /*          =amount to search=   ==done==   ==rounding==    =blksiz= */
        !          1028: 
        !          1029:         for (i = 1;  i <= numblks;  ++i) {
        !          1030:             cur_zipfile_bufstart -= INBUFSIZ;
        !          1031:             lseek(zipfd, cur_zipfile_bufstart, SEEK_SET);
        !          1032:             if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) != INBUFSIZ)
        !          1033:                 break;          /* fall through and fail */
        !          1034: 
        !          1035:             for (inptr = inbuf+INBUFSIZ-1;  inptr >= inbuf;  --inptr)
        !          1036:                 if ((ascii_to_native(*inptr) == 'P')  &&
        !          1037:                      !strncmp((char *)inptr, end_central_sig, 4)) {
        !          1038:                     incnt -= inptr - inbuf;
        !          1039:                     return 0;   /* found it */
        !          1040:                 }
        !          1041:             strncpy((char *)hold, (char *)inbuf, 3);    /* sig may span block
        !          1042:                                                            boundary */
        !          1043:         }
        !          1044: 
        !          1045:     } /* end if (ziplen > INBUFSIZ) */
        !          1046: 
        !          1047: /*---------------------------------------------------------------------------
        !          1048:     Searched through whole region where signature should be without finding
        !          1049:     it.  Print informational message and die a horrible death.
        !          1050:   ---------------------------------------------------------------------------*/
        !          1051: 
        !          1052: fail:
        !          1053: #ifdef MSWIN
        !          1054:     MessageBeep(1);
        !          1055: #endif
        !          1056: 
        !          1057:     fprintf(stderr, "\nFile:  %s\n\n\
        !          1058:      End-of-central-directory signature not found.  Either this file is not\n\
        !          1059:      a zipfile, or it constitutes one disk of a multi-part archive.  In the\n\
        !          1060:      latter case the central directory and zipfile comment will be found on\n\
        !          1061:      the last disk(s) of this archive.\n", zipfn);
        !          1062:     return 1;
        !          1063: 
        !          1064: } /* end function find_end_central_dir() */
        !          1065: 
        !          1066: 
        !          1067: 
        !          1068: 
        !          1069: 
        !          1070: /***************************************/
        !          1071: /*  Function process_end_central_dir() */
        !          1072: /***************************************/
        !          1073: 
        !          1074: int process_end_central_dir()    /* return PK-type error code */
        !          1075: {
        !          1076:     ec_byte_rec byterec;
        !          1077:     int error=0;
        !          1078: 
        !          1079: 
        !          1080: /*---------------------------------------------------------------------------
        !          1081:     Read the end-of-central-directory record and do any necessary machine-
        !          1082:     type conversions (byte ordering, structure padding compensation) by
        !          1083:     reading data into character array, then copying to struct.
        !          1084:   ---------------------------------------------------------------------------*/
        !          1085: 
        !          1086:     if (readbuf((char *) byterec, ECREC_SIZE+4) <= 0)
        !          1087:         return 51;
        !          1088: 
        !          1089:     ecrec.number_this_disk =
        !          1090:         makeword(&byterec[NUMBER_THIS_DISK]);
        !          1091:     ecrec.num_disk_with_start_central_dir =
        !          1092:         makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
        !          1093:     ecrec.num_entries_centrl_dir_ths_disk =
        !          1094:         makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
        !          1095:     ecrec.total_entries_central_dir =
        !          1096:         makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
        !          1097:     ecrec.size_central_directory =
        !          1098:         makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
        !          1099:     ecrec.offset_start_central_directory =
        !          1100:         makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
        !          1101:     ecrec.zipfile_comment_length =
        !          1102:         makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
        !          1103: 
        !          1104: /*---------------------------------------------------------------------------
        !          1105:     Get the zipfile comment, if any, and print it out.  (Comment may be up
        !          1106:     to 64KB long.  May the fleas of a thousand camels infest the armpits of
        !          1107:     anyone who actually takes advantage of this fact.)  Then position the
        !          1108:     file pointer to the beginning of the central directory and fill buffer.
        !          1109:   ---------------------------------------------------------------------------*/
        !          1110: 
        !          1111: #ifdef MSWIN
        !          1112:     cchComment = ecrec.zipfile_comment_length; /* save for comment button */
        !          1113:     if (ecrec.zipfile_comment_length && zflag) {
        !          1114: #else /* !MSWIN */
        !          1115:     if (ecrec.zipfile_comment_length && !quietflg) {
        !          1116:         if (!zflag)
        !          1117:           printf("[%s] comment:\n", zipfn);
        !          1118: #endif /* ?MSWIN */
        !          1119:         if (do_string(ecrec.zipfile_comment_length,DISPLAY)) {
        !          1120:             fprintf(stderr, "\ncaution:  zipfile comment truncated\n");
        !          1121:             error = 1;          /* 1:  warning error */
        !          1122:         }
        !          1123:     }
        !          1124: 
        !          1125:     return error;
        !          1126: 
        !          1127: } /* end function process_end_central_dir() */
        !          1128: 
        !          1129: 
        !          1130: 
        !          1131: 
        !          1132: 
        !          1133: /* also referenced in UpdateListBox() in updatelb.c (Windows version) */
        !          1134: char *Headers[][2] = {
        !          1135:     {" Length    Date    Time    Name",
        !          1136:      " ------    ----    ----    ----"},
        !          1137:     {" Length  Method   Size  Ratio   Date    Time   CRC-32     Name",
        !          1138:      " ------  ------   ----  -----   ----    ----   ------     ----"}
        !          1139: };
        !          1140: 
        !          1141: /*************************/
        !          1142: /* Function list_files() */
        !          1143: /*************************/
        !          1144: 
        !          1145: int list_files()    /* return PK-type error code */
        !          1146: {
        !          1147:     char **fnamev;
        !          1148:     int do_this_file=FALSE, ratio, error, error_in_archive=0;
        !          1149:     int which_hdr=(vflag>1), date_format;
        !          1150:     UWORD j, yr, mo, dy, hh, mm, members=0;
        !          1151:     ULONG tot_csize=0L, tot_ucsize=0L;
        !          1152: #ifdef OS2
        !          1153:     ULONG tot_easize=0L, tot_eafiles=0L, ea_size;
        !          1154: #endif
        !          1155: #ifdef MSWIN
        !          1156:     PSTR psLBEntry;  /* list box entry */
        !          1157: #endif
        !          1158:     min_info info;
        !          1159:     static char *method[NUM_METHODS+1] =
        !          1160:         {"Stored", "Shrunk", "Reduce1", "Reduce2", "Reduce3", "Reduce4",
        !          1161:          "Implode", "Token", "Deflate", unkn};
        !          1162: 
        !          1163: 
        !          1164: 
        !          1165: /*---------------------------------------------------------------------------
        !          1166:     Unlike extract_or_test_files(), this routine confines itself to the cen-
        !          1167:     tral directory.  Thus its structure is somewhat simpler, since we can do
        !          1168:     just a single loop through the entire directory, listing files as we go.
        !          1169: 
        !          1170:     So to start off, print the heading line and then begin main loop through
        !          1171:     the central directory.  The results will look vaguely like the following:
        !          1172: 
        !          1173:   Length  Method   Size  Ratio   Date    Time   CRC-32     Name ("^" ==> case
        !          1174:   ------  ------   ----  -----   ----    ----   ------     ----   conversion)
        !          1175:    44004  Implode  13041  71%  11-02-89  19:34  8b4207f7   Makefile.UNIX
        !          1176:     3438  Shrunk    2209  36%  09-15-90  14:07  a2394fd8  ^dos-file.ext
        !          1177:   ---------------------------------------------------------------------------*/
        !          1178: 
        !          1179:     pInfo = &info;
        !          1180:     date_format = dateformat();
        !          1181: 
        !          1182: #ifndef MSWIN
        !          1183:     if (quietflg < 2)
        !          1184:         if (U_flag)
        !          1185:             printf("%s\n%s\n", Headers[which_hdr][0], Headers[which_hdr][1]);
        !          1186:         else
        !          1187:             printf("%s (\"^\" ==> case\n%s   conversion)\n", 
        !          1188:               Headers[which_hdr][0], Headers[which_hdr][1]);
        !          1189: #endif /* !MSWIN */
        !          1190: 
        !          1191:     for (j = 0; j < ecrec.total_entries_central_dir; ++j) {
        !          1192: 
        !          1193:         if (readbuf(sig, 4) <= 0)
        !          1194:             return 51;          /* 51:  unexpected EOF */
        !          1195:         if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
        !          1196:             fprintf(stderr, CentSigMsg, j);  /* sig not found */
        !          1197:             fprintf(stderr, ReportMsg);   /* check binary transfers */
        !          1198:             return 3;           /* 3:  error in zipfile */
        !          1199:         }
        !          1200:         if ((error = process_cdir_file_hdr()) != 0)  /* (sets pInfo->lcflag) */
        !          1201:             return error;       /* only 51 (EOF) defined */
        !          1202: 
        !          1203:         /*
        !          1204:          * We could DISPLAY the filename instead of storing (and possibly trun-
        !          1205:          * cating, in the case of a very long name) and printing it, but that
        !          1206:          * has the disadvantage of not allowing case conversion--and it's nice
        !          1207:          * to be able to see in the listing precisely how you have to type each
        !          1208:          * filename in order for unzip to consider it a match.  Speaking of
        !          1209:          * which, if member names were specified on the command line, check in
        !          1210:          * with match() to see if the current file is one of them, and make a
        !          1211:          * note of it if it is.
        !          1212:          */
        !          1213: 
        !          1214:         if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
        !          1215:             error_in_archive = error;  /*             ^--(uses pInfo->lcflag) */
        !          1216:             if (error > 1)      /* fatal:  can't continue */
        !          1217:                 return error;
        !          1218:         }
        !          1219:         if (extra_field != (byte *)NULL)
        !          1220:             free(extra_field);
        !          1221:         extra_field = (byte *)NULL;
        !          1222:         if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0) {
        !          1223:             error_in_archive = error;  
        !          1224:             if (error > 1)      /* fatal:  can't continue */
        !          1225:                 return error;
        !          1226:         }
        !          1227:         if (!process_all_files) {   /* check if specified on command line */
        !          1228:             do_this_file = FALSE;
        !          1229:             fnamev = fnv;       /* don't destroy permanent filename ptr */
        !          1230:             for (--fnamev; *++fnamev;)
        !          1231:                 if (match(filename, *fnamev)) {
        !          1232:                     do_this_file = TRUE;
        !          1233:                     break;      /* found match, so stop looping */
        !          1234:                 }
        !          1235:         }
        !          1236:         /*
        !          1237:          * If current file was specified on command line, or if no names were
        !          1238:          * specified, do the listing for this file.  Otherwise, get rid of the
        !          1239:          * file comment and go back for the next file.
        !          1240:          */
        !          1241: 
        !          1242:         if (process_all_files || do_this_file) {
        !          1243: 
        !          1244:             yr = (((crec.last_mod_file_date >> 9) & 0x7f) + 80) % (unsigned)100;
        !          1245:             mo = (crec.last_mod_file_date >> 5) & 0x0f;
        !          1246:             dy = crec.last_mod_file_date & 0x1f;
        !          1247: 
        !          1248:             /* twist date so it displays according to national convention */
        !          1249:             switch (date_format) {
        !          1250:                 case DF_YMD:
        !          1251:                     hh = mo; mo = yr; yr = dy; dy = hh; break;
        !          1252:                 case DF_DMY:
        !          1253:                     hh = mo; mo = dy; dy = hh;
        !          1254:             }
        !          1255:             hh = (crec.last_mod_file_time >> 11) & 0x1f;
        !          1256:             mm = (crec.last_mod_file_time >> 5) & 0x3f;
        !          1257: 
        !          1258:             csize = (longint) crec.compressed_size;
        !          1259:             ucsize = (longint) crec.uncompressed_size;
        !          1260:             if (crec.general_purpose_bit_flag & 1)
        !          1261:                 csize -= 12;    /* if encrypted, don't count encrypt hdr */
        !          1262: 
        !          1263:             ratio = (ucsize == 0) ? 0 :   /* .zip can have 0-length members */
        !          1264:                 ((ucsize > 2000000L) ?    /* risk signed overflow if mult. */
        !          1265:                 (int) ((ucsize-csize) / (ucsize/1000L)) + 5 :   /* big */
        !          1266:                 (int) ((1000L*(ucsize-csize)) / ucsize) + 5);   /* small */
        !          1267: 
        !          1268: #if 0       /* GRR/Euro:  add this?  define p above */
        !          1269: #if (defined(DOS_OS2) || (defined(UNIX) && !defined(VMS)))
        !          1270:             for (p = filename;  *p;  ++p)
        !          1271:                 if (!isprint(*p))
        !          1272:                     *p = '?';  /* change non-printable chars to '?' */
        !          1273: #endif /* DOS_OS2 || UNIX */
        !          1274: #endif /* 0 */
        !          1275: 
        !          1276: #ifdef MSWIN
        !          1277: #ifdef NEED_EARLY_REDRAW
        !          1278:             /* turn on listbox redrawing just before adding last line */
        !          1279:             if (j == (ecrec.total_entries_central_dir-1))
        !          1280:                 (void)SendMessage(hWndList, WM_SETREDRAW, TRUE, 0L);
        !          1281: #endif /* NEED_EARLY_REDRAW */
        !          1282:             psLBEntry =
        !          1283:               (PSTR)LocalAlloc(LMEM_FIXED, FILNAMSIZ+LONG_FORM_FNAME_INX);
        !          1284:             switch (which_hdr) {
        !          1285:                 case 0:   /* short form */
        !          1286:                     OemToAnsi(filename, filename);  /* translate to ANSI */
        !          1287:                     wsprintf(psLBEntry, "%7ld  %02u-%02u-%02u  %02u:%02u  %c%s",
        !          1288:                       (long)ucsize, mo, dy, yr, hh, mm, (pInfo->lcflag?'^':' '),
        !          1289:                       (LPSTR)filename);
        !          1290:                     SendMessage(hWndList, LB_ADDSTRING, 0,
        !          1291:                       (LONG)(LPSTR)psLBEntry);
        !          1292:                     break;
        !          1293:                 case 1:   /* verbose */
        !          1294:                     OemToAnsi(filename, filename);  /* translate to ANSI */
        !          1295:                     wsprintf(psLBEntry, 
        !          1296:                  "%7ld  %-7s%7ld %3d%%  %02u-%02u-%02u  %02u:%02u  %08lx  %c%s",
        !          1297:                       (long)ucsize, (LPSTR)method[methnum], (long)csize,
        !          1298:                       ratio/10, mo, dy, yr, hh, mm, (unsigned long)crec.crc32,
        !          1299:                       (pInfo->lcflag?'^':' '), (LPSTR)filename);
        !          1300:                     SendMessage(hWndList, LB_ADDSTRING, 0,
        !          1301:                       (LONG)(LPSTR)psLBEntry);
        !          1302:             }
        !          1303:             LocalFree((HANDLE)psLBEntry);
        !          1304: #else /* !MSWIN */
        !          1305:             switch (which_hdr) {
        !          1306:                 case 0:   /* short form */
        !          1307:                     printf("%7ld  %02u-%02u-%02u  %02u:%02u  %c%s\n",
        !          1308:                       ucsize, mo, dy, yr, hh, mm, (pInfo->lcflag?'^':' '),
        !          1309:                       filename);
        !          1310:                     break;
        !          1311:                 case 1:   /* verbose */
        !          1312:                     printf(
        !          1313:               "%7ld  %-7s%7ld %3d%%  %02u-%02u-%02u  %02u:%02u  %08lx  %c%s\n",
        !          1314:                       ucsize, method[methnum], csize, ratio/10, mo, dy, yr,
        !          1315:                       hh, mm, crec.crc32, (pInfo->lcflag?'^':' '), filename);
        !          1316:             }
        !          1317: #endif /* ?MSWIN */
        !          1318: 
        !          1319:             error = do_string(crec.file_comment_length, (QCOND? DISPLAY:SKIP));
        !          1320:             if (error) {
        !          1321:                 error_in_archive = error;  /* might be just warning */
        !          1322:                 if (error > 1)  /* fatal */
        !          1323:                     return error;
        !          1324:             }
        !          1325:             tot_ucsize += (ULONG) ucsize;
        !          1326:             tot_csize += (ULONG) csize;
        !          1327:             ++members;
        !          1328: #ifdef OS2
        !          1329:             if ((ea_size = SizeOfEAs(extra_field)) != 0) {
        !          1330:                 tot_easize += ea_size;
        !          1331:                 tot_eafiles++;
        !          1332:             }
        !          1333: #endif
        !          1334:         } else {        /* not listing this file */
        !          1335:             SKIP_(crec.file_comment_length)
        !          1336:         }
        !          1337:     }                   /* end for-loop (j: files in central directory) */
        !          1338: 
        !          1339: /*---------------------------------------------------------------------------
        !          1340:     Print footer line and totals (compressed size, uncompressed size, number
        !          1341:     of members in zipfile).
        !          1342:   ---------------------------------------------------------------------------*/
        !          1343: 
        !          1344:     ratio = (tot_ucsize == 0) ? 
        !          1345:         0 : ((tot_ucsize > 4000000L) ?   /* risk unsigned overflow if mult. */
        !          1346:         (int) ((tot_ucsize - tot_csize) / (tot_ucsize/1000L)) + 5 :
        !          1347:         (int) ((tot_ucsize - tot_csize) * 1000L / tot_ucsize) + 5);
        !          1348: 
        !          1349:     if (quietflg < 2) {
        !          1350: #ifdef MSWIN
        !          1351:         /* Display just the totals since the dashed lines get displayed
        !          1352:          * in UpdateListBox(). Get just enough space to display total.
        !          1353:          */
        !          1354:         switch (which_hdr) {
        !          1355:             case 0:         /* short */
        !          1356:                 wsprintf(lpumb->szTotalsLine, "%7lu                    %-7u", 
        !          1357:                   (ULONG)tot_ucsize, members);
        !          1358:                 break;
        !          1359:             case 1:         /* verbose */
        !          1360:                 wsprintf(lpumb->szTotalsLine, 
        !          1361:                   "%7lu         %7lu %3d%%                              %-7u", 
        !          1362:                   (ULONG)tot_ucsize, (ULONG)tot_csize, ratio / 10, members);
        !          1363:                 break;
        !          1364:         }
        !          1365: #else /* !MSWIN */
        !          1366:         switch (which_hdr) {
        !          1367:         case 0:         /* short */
        !          1368:             printf("%s\n%7lu                    %-7u\n",
        !          1369:                    " ------                    -------",
        !          1370:                    tot_ucsize, members);
        !          1371:             break;
        !          1372:         case 1:         /* verbose */
        !          1373:             printf(
        !          1374:               "%s\n%7lu         %7lu %3d%%                              %-7u\n",
        !          1375:               " ------          ------  ---                              -------",
        !          1376:               tot_ucsize, tot_csize, ratio / 10, members);
        !          1377:         }
        !          1378: #endif /* ?MSWIN */
        !          1379: #ifdef OS2
        !          1380:         if (tot_eafiles && tot_easize)
        !          1381:             printf("\n%ld file%s %ld bytes of EA's attached.\n", tot_eafiles, 
        !          1382:               tot_eafiles == 1 ? " has" : "s have a total of", tot_easize);
        !          1383: #endif
        !          1384:     }
        !          1385: /*---------------------------------------------------------------------------
        !          1386:     Double check that we're back at the end-of-central-directory record.
        !          1387:   ---------------------------------------------------------------------------*/
        !          1388: 
        !          1389:     readbuf(sig, 4);
        !          1390:     if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
        !          1391:         fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
        !          1392: /*      fprintf(stderr, ReportMsg);   */
        !          1393:         error_in_archive = 1;        /* 1:  warning error */
        !          1394:     }
        !          1395:     return error_in_archive;
        !          1396: 
        !          1397: } /* end function list_files() */
        !          1398: 
        !          1399: 
        !          1400: 
        !          1401: 
        !          1402: 
        !          1403: /**************************************/
        !          1404: /*  Function process_cdir_file_hdr()  */
        !          1405: /**************************************/
        !          1406: 
        !          1407: int process_cdir_file_hdr()    /* return PK-type error code */
        !          1408: {
        !          1409:     cdir_byte_hdr byterec;
        !          1410: 
        !          1411: 
        !          1412: /*---------------------------------------------------------------------------
        !          1413:     Read the next central directory entry and do any necessary machine-type
        !          1414:     conversions (byte ordering, structure padding compensation--do so by
        !          1415:     copying the data from the array into which it was read (byterec) to the
        !          1416:     usable struct (crec)).
        !          1417:   ---------------------------------------------------------------------------*/
        !          1418: 
        !          1419:     if (readbuf((char *) byterec, CREC_SIZE) <= 0)
        !          1420:         return 51;   /* 51:  unexpected EOF */
        !          1421: 
        !          1422:     crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
        !          1423:     crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
        !          1424:     crec.version_needed_to_extract[0] = byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
        !          1425:     crec.version_needed_to_extract[1] = byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
        !          1426: 
        !          1427:     crec.general_purpose_bit_flag =
        !          1428:         makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
        !          1429:     crec.compression_method =
        !          1430:         makeword(&byterec[C_COMPRESSION_METHOD]);
        !          1431:     crec.last_mod_file_time =
        !          1432:         makeword(&byterec[C_LAST_MOD_FILE_TIME]);
        !          1433:     crec.last_mod_file_date =
        !          1434:         makeword(&byterec[C_LAST_MOD_FILE_DATE]);
        !          1435:     crec.crc32 =
        !          1436:         makelong(&byterec[C_CRC32]);
        !          1437:     crec.compressed_size =
        !          1438:         makelong(&byterec[C_COMPRESSED_SIZE]);
        !          1439:     crec.uncompressed_size =
        !          1440:         makelong(&byterec[C_UNCOMPRESSED_SIZE]);
        !          1441:     crec.filename_length =
        !          1442:         makeword(&byterec[C_FILENAME_LENGTH]);
        !          1443:     crec.extra_field_length =
        !          1444:         makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
        !          1445:     crec.file_comment_length =
        !          1446:         makeword(&byterec[C_FILE_COMMENT_LENGTH]);
        !          1447:     crec.disk_number_start =
        !          1448:         makeword(&byterec[C_DISK_NUMBER_START]);
        !          1449:     crec.internal_file_attributes =
        !          1450:         makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
        !          1451:     crec.external_file_attributes =
        !          1452:         makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]);  /* LONG, not word! */
        !          1453:     crec.relative_offset_local_header =
        !          1454:         makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
        !          1455: 
        !          1456:     pInfo->hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
        !          1457: /*  extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
        !          1458:     methnum = MIN(crec.compression_method, NUM_METHODS);
        !          1459:     if (methnum == NUM_METHODS)
        !          1460:         sprintf(unkn, "Unk:%03d", crec.compression_method);
        !          1461: 
        !          1462: /*---------------------------------------------------------------------------
        !          1463:     Set flag for lowercase conversion of filename, depending on which OS the
        !          1464:     file is coming from.  This section could be ifdef'd if some people have
        !          1465:     come to love DOS uppercase filenames under Unix...but really, guys, get
        !          1466:     a life. :)  NOTE THAT ALL SYSTEM NAMES NOW HAVE TRAILING UNDERSCORES!!!
        !          1467:     This is to prevent interference with compiler command-line defines such
        !          1468:     as -DUNIX, for example, which are then used in "#ifdef UNIX" constructs.
        !          1469:   ---------------------------------------------------------------------------*/
        !          1470: 
        !          1471:     pInfo->lcflag = 0;
        !          1472:     if (!U_flag)   /* as long as user hasn't specified case-preservation */
        !          1473:         switch (pInfo->hostnum) {
        !          1474:             case DOS_OS2_FAT_:
        !          1475:         /*  case VMS_:              VMS Zip converts filenames to lowercase */
        !          1476:             case VM_CMS_:           /* all caps? */
        !          1477:             case CPM_:              /* like DOS, right? */
        !          1478:         /*  case ATARI_:            ? */
        !          1479:         /*  case Z_SYSTEM_:         ? */
        !          1480:         /*  case TOPS20_:           (if we had such a thing...) */
        !          1481:                 pInfo->lcflag = 1;  /* convert filename to lowercase */
        !          1482:                 break;
        !          1483: 
        !          1484:             default:                /* AMIGA_, UNIX_, (ATARI_), OS2_HPFS_, */
        !          1485:                 break;              /*   MAC_, (Z_SYSTEM_):  no conversion */
        !          1486:         }
        !          1487: 
        !          1488:     return 0;
        !          1489: 
        !          1490: } /* end function process_cdir_file_hdr() */
        !          1491: 
        !          1492: 
        !          1493: 
        !          1494: 
        !          1495: 
        !          1496: /***************************************/
        !          1497: /*  Function process_local_file_hdr()  */
        !          1498: /***************************************/
        !          1499: 
        !          1500: int process_local_file_hdr()    /* return PK-type error code */
        !          1501: {
        !          1502:     local_byte_hdr byterec;
        !          1503: 
        !          1504: 
        !          1505: /*---------------------------------------------------------------------------
        !          1506:     Read the next local file header and do any necessary machine-type con-
        !          1507:     versions (byte ordering, structure padding compensation--do so by copy-
        !          1508:     ing the data from the array into which it was read (byterec) to the
        !          1509:     usable struct (lrec)).
        !          1510:   ---------------------------------------------------------------------------*/
        !          1511: 
        !          1512:     if (readbuf((char *) byterec, LREC_SIZE) <= 0)
        !          1513:         return 51;   /* 51:  unexpected EOF */
        !          1514: 
        !          1515:     lrec.version_needed_to_extract[0] = byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
        !          1516:     lrec.version_needed_to_extract[1] = byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
        !          1517: 
        !          1518:     lrec.general_purpose_bit_flag = makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
        !          1519:     lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
        !          1520:     lrec.last_mod_file_time = makeword(&byterec[L_LAST_MOD_FILE_TIME]);
        !          1521:     lrec.last_mod_file_date = makeword(&byterec[L_LAST_MOD_FILE_DATE]);
        !          1522:     lrec.crc32 = makelong(&byterec[L_CRC32]);
        !          1523:     lrec.compressed_size = makelong(&byterec[L_COMPRESSED_SIZE]);
        !          1524:     lrec.uncompressed_size = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
        !          1525:     lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
        !          1526:     lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
        !          1527: 
        !          1528:     csize = (longint) lrec.compressed_size;
        !          1529:     ucsize = (longint) lrec.uncompressed_size;
        !          1530: 
        !          1531:     if ((lrec.general_purpose_bit_flag & 8) != 0) {
        !          1532:         /* Can't trust local header, use central directory: */
        !          1533:       lrec.crc32 = pInfo->crc;
        !          1534:         lrec.compressed_size = pInfo->compr_size;
        !          1535:         csize = (longint) lrec.compressed_size;
        !          1536:     }
        !          1537: 
        !          1538:     return 0;                 /* 0:  no error */
        !          1539: 
        !          1540: } /* end function process_local_file_hdr() */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.