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

1.1     ! root        1: /*---------------------------------------------------------------------------
        !             2: 
        !             3:   zipinfo.c
        !             4: 
        !             5:   This program reads all sorts of totally nifty information, including the
        !             6:   central directory stuff, from a ZIP archive ("zipfile" for short).  It
        !             7:   started as just a testbed for fooling with zipfiles, but at this point
        !             8:   it's actually a moderately useful utility.  It also became the basis
        !             9:   for the rewrite of unzip (3.16 -> 4.0), using the central directory for
        !            10:   processing rather than the individual (local) file headers.
        !            11: 
        !            12:   For myself, I find it convenient to define an alias "ii" (under Unix and
        !            13:   VMS) or to rename the executable to "ii.exe" (OS/2 and DOS).  This nicely
        !            14:   complements my Unix long-listing "ll" alias (ls -lF), since zipinfo's de-
        !            15:   fault action is to produce a Unix-like listing of the archive's contents.
        !            16:   "ii zipfile" is easier to type than "zipinfo zipfile"...
        !            17: 
        !            18:   Another dandy product from your buddies at Newtware!
        !            19: 
        !            20:   ---------------------------------------------------------------------------
        !            21: 
        !            22:   To compile (partial instructions; some of this stuff doesn't exist yet):
        !            23: 
        !            24:      under Unix (cc):  make zipinfo
        !            25: 
        !            26:      under MS-DOS (TurboC):  make -fMKZIPINF.DOS   (edit appropriately)
        !            27: 
        !            28:      under MS-DOS (MSC):  make MKZIPINF.DOS
        !            29:        (or use Makefile if you have MSC 6.0:  "nmake zi_dos")
        !            30: 
        !            31:      under OS/2 (MSC):  make MKZIPINF.DOS   (edit appropriately)
        !            32:        (or use Makefile if you have MSC 6.0:  "nmake zi_os2")
        !            33: 
        !            34:      under Atari OS:  beats me...
        !            35: 
        !            36:      under VMS:  @MAKE_ZIPINFO     (see also VMSNOTES)
        !            37:                  ZIPINFO == $DISKNAME:[DIRECTORY]ZIPINFO.EXE
        !            38: 
        !            39:      under Macintosh OS:  who knows?
        !            40: 
        !            41:   ---------------------------------------------------------------------------
        !            42: 
        !            43:   Source:     unz50p1.zip (.tar.Z, etc.) for Unix, VMS, OS/2 and MS-DOS; see
        !            44:               `Where' in source distribution for ftp, uucp and mail-server
        !            45:               sites.
        !            46:   Author:     Greg Roelofs, [email protected], 23 August 1990
        !            47:   Copyright:  Portions copyright 1992 Greg Roelofs.  Portions adapted from
        !            48:               unzip 3.1.  SizeOfEAs() by Kai Uwe Rommel.
        !            49: 
        !            50:   ---------------------------------------------------------------------------*/
        !            51: 
        !            52: 
        !            53: 
        !            54: 
        !            55: #ifndef ZIPINFO
        !            56: #  define ZIPINFO   /* needed for Unix permissions in non-Unix environments */
        !            57: #endif /* !ZIPINFO */
        !            58: #include "unzip.h"
        !            59: 
        !            60: #define VERSION  "v1.0p1 of 10 January 1993"
        !            61: 
        !            62: #define LFLAG    3        /* for short "ls -l" type listing */
        !            63: 
        !            64: #define EAID     0x0009   /* OS/2 EA extra field ID */
        !            65: typedef struct {          /* for OS/2 info in OS/2 and non-OS/2 environments */
        !            66:     unsigned short nID;
        !            67:     unsigned short nSize;
        !            68:     ULONG lSize;
        !            69: } EAHEADER, *PEAHEADER;
        !            70: 
        !            71: 
        !            72: 
        !            73: 
        !            74: /**********************/
        !            75: /*  Global Variables  */
        !            76: /**********************/
        !            77: 
        !            78: #ifdef EBCDIC
        !            79:    int  aflag=1;        /* this is so you can read it on the screen  */
        !            80: #else                   /* (basically, entire program is "unzip -c") */
        !            81:    int  aflag=0;
        !            82: #endif
        !            83: int lflag=(-1);         /* '-1slmv':  listing format */
        !            84: int hflag=0;            /* '-h':  header line */
        !            85: int tflag=0;            /* '-t':  totals line */
        !            86: 
        !            87: byte *inbuf, *inptr;    /* input buffer (any size is legal) and pointer */
        !            88: int incnt;
        !            89: 
        !            90: int zipfd;              /* zipfile file handle */
        !            91: char zipfn[FILNAMSIZ];
        !            92: 
        !            93: char local_hdr_sig[5] = "\120";    /* remaining signature bytes come later:  */
        !            94: char central_hdr_sig[5] = "\120";  /*  must initialize at runtime so zipinfo */
        !            95: char end_central_sig[5] = "\120";  /*  executable won't look like a zipfile  */
        !            96: char extd_local_sig[5] = "\120";
        !            97: 
        !            98: cdir_file_hdr crec;             /* used in zipinfo.c, misc.c */
        !            99: local_file_hdr lrec;
        !           100: ecdir_rec ecrec;
        !           101: struct stat statbuf;            /* used by main() */
        !           102: 
        !           103: int process_all_files;
        !           104: longint real_ecrec_offset, expect_ecrec_offset;
        !           105: longint extra_bytes=0;          /* used in zipinfo.c, misc.c */
        !           106: longint cur_zipfile_bufstart;   /* find_end_central_dir, readbuf */
        !           107: 
        !           108: min_info info, *pInfo=(&info);
        !           109: 
        !           110: byte *extra_field = NULL;       /* used by VMS, Mac and OS/2 versions */
        !           111: byte *outbuf;                   /* buffer for rle look-back, zipfile comment */
        !           112: byte *outout;                   /* scratch pad for ASCII-native trans */
        !           113: 
        !           114: char filename[FILNAMSIZ];
        !           115: char sig[5];
        !           116: char *fnames[2] = {"*", NULL};    /* default filenames vector */
        !           117: char **fnv = fnames;
        !           118: 
        !           119: static byte *hold;
        !           120: static longint ziplen;
        !           121: static UWORD hostnum;
        !           122: static UWORD methnum;
        !           123: static UWORD extnum;
        !           124: 
        !           125: char *EndSigMsg = "\nwarning:\
        !           126:   didn't find end-of-central-dir signature at end of central dir.\n";
        !           127: char *CentSigMsg =
        !           128:   "error:  expected central file header signature not found (file #%u).\n";
        !           129: char *SeekMsg =
        !           130:   "error:  attempt to seek before beginning of zipfile\n%s";
        !           131: 
        !           132: #ifdef VMS
        !           133: char *ReportMsg = "\
        !           134:   (please check that you have transferred or created the zipfile in the\n\
        !           135:   appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n";
        !           136: #else /* !VMS */
        !           137: char *ReportMsg = "\
        !           138:   (please check that you have transferred or created the zipfile in the\n\
        !           139:   appropriate BINARY mode and that you have compiled unzip properly)\n";
        !           140: #endif /* ?VMS */
        !           141: 
        !           142: 
        !           143: 
        !           144: 
        !           145: 
        !           146: 
        !           147: /******************/
        !           148: /*  Main program  */
        !           149: /******************/
        !           150: 
        !           151: main(argc, argv)
        !           152:     int    argc;
        !           153:     char   *argv[];
        !           154: {
        !           155:     char   *s;
        !           156:     int    c, error=FALSE, negative=0;
        !           157:     int    hflag_slmv=TRUE, hflag_1=FALSE;  /* diff options => diff defaults */
        !           158:     int    tflag_slm=TRUE, tflag_1v=FALSE;
        !           159:     int    explicit_h=FALSE, explicit_t=FALSE;
        !           160: 
        !           161: 
        !           162: 
        !           163: /*---------------------------------------------------------------------------
        !           164:     Everybody is now "NOTINT16," but this is a nice little piece of code, so
        !           165:     just comment it out for future reference. :-)
        !           166:   ---------------------------------------------------------------------------*/
        !           167: 
        !           168: #if 0
        !           169: # ifndef KNOW_IT_WORKS  /* define this to save space, if things already work */
        !           170: # ifndef DOS_OS2        /* already works (no RISCy OS/2's yet...) */
        !           171: # ifndef NOTINT16       /* whole point is to see if this NEEDS defining */
        !           172:     {
        !           173:         int error=0;
        !           174:         long testsig;
        !           175:         static char *mach_type[3] = {"big-endian", "structure-padding",
        !           176:                                      "big-endian and structure-padding"};
        !           177: 
        !           178:         strcpy((char *)&testsig,"012");
        !           179:         if (testsig != 0x00323130)
        !           180:             error = 1;
        !           181:         if (sizeof(cdir_file_hdr) != CREC_SIZE)
        !           182:             error += 2;
        !           183:         if (error--)
        !           184:             fprintf(stderr, "It appears that your machine is %s.  If errors\n\
        !           185: occur, please try recompiling with \"NOTINT16\" defined (read the\n\
        !           186: Makefile, or try \"make zipinfo\").\n\n", mach_type[error]);
        !           187:     }
        !           188: # endif /* !NOTINT16 */
        !           189: # endif /* !DOS_OS2 */
        !           190: # endif /* !KNOW_IT_WORKS */
        !           191: #endif /* 0 */
        !           192: 
        !           193: /*---------------------------------------------------------------------------
        !           194:     Put environment-variable options into the queue, then rip through any
        !           195:     command-line options lurking about...
        !           196:   ---------------------------------------------------------------------------*/
        !           197: 
        !           198:     envargs(&argc, &argv, ENV_ZIPINFO);
        !           199: 
        !           200:     while (--argc > 0 && (*++argv)[0] == '-') {
        !           201:         s = argv[0] + 1;
        !           202:         while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
        !           203:             switch (c) {
        !           204:                 case '-':
        !           205:                     ++negative;
        !           206:                     break;
        !           207:                 case '1':      /* shortest listing:  just filenames */
        !           208:                     if (negative)
        !           209:                         lflag = -2, negative = 0;
        !           210:                     else
        !           211:                         lflag = 1;
        !           212:                     break;
        !           213:                 case 'h':      /* header line */
        !           214:                     if (negative)
        !           215:                         hflag_1 = hflag_slmv = FALSE, negative = 0;
        !           216:                     else {
        !           217:                         hflag_1 = hflag_slmv = explicit_h = TRUE;
        !           218:                         if (lflag == -1)
        !           219:                             lflag = 0;
        !           220:                     }
        !           221:                     break;
        !           222:                 case 'l':      /* longer form of "ls -l" type listing */
        !           223:                     if (negative)
        !           224:                         lflag = -2, negative = 0;
        !           225:                     else
        !           226:                         lflag = 5;
        !           227:                     break;
        !           228:                 case 'm':      /* medium form of "ls -l" type listing */
        !           229:                     if (negative)
        !           230:                         lflag = -2, negative = 0;
        !           231:                     else
        !           232:                         lflag = 4;
        !           233:                     break;
        !           234:                 case 's':      /* default:  shorter "ls -l" type listing */
        !           235:                     if (negative)
        !           236:                         lflag = -2, negative = 0;
        !           237:                     else
        !           238:                         lflag = 3;
        !           239:                     break;
        !           240:                 case 't':      /* totals line */
        !           241:                     if (negative)
        !           242:                         tflag_1v = tflag_slm = FALSE, negative = 0;
        !           243:                     else {
        !           244:                         tflag_1v = tflag_slm = explicit_t = TRUE;
        !           245:                         if (lflag == -1)
        !           246:                             lflag = 0;
        !           247:                     }
        !           248:                     break;
        !           249:                 case 'v':      /* turbo-verbose listing */
        !           250:                     if (negative)
        !           251:                         lflag = -2, negative = 0;
        !           252:                     else
        !           253:                         lflag = 10;
        !           254:                     break;
        !           255:                 default:
        !           256:                     error = TRUE;
        !           257:                     break;
        !           258:             }
        !           259:         }
        !           260:     }
        !           261:     if ((argc-- == 0) || error)
        !           262:         RETURN(usage(error));
        !           263: 
        !           264:     if (argc != 0)
        !           265:         process_all_files = FALSE;
        !           266:     else
        !           267:         process_all_files = TRUE;   /* for speed */
        !           268: 
        !           269:     /* if no listing options given (or all negated), or if only -h/-t given
        !           270:      * with individual files specified, use default listing format */
        !           271:     if ((lflag < 0) || (!process_all_files && (lflag == 0)))
        !           272:         lflag = LFLAG;
        !           273: 
        !           274:     /* set header and totals flags to default or specified values */
        !           275:     switch (lflag) {
        !           276:         case 0:   /* 0:  can only occur if either -t or -h explicitly given; */
        !           277:         case 1:   /*  therefore set both flags equal to normally false value */
        !           278:             hflag = hflag_1;
        !           279:             tflag = tflag_1v;
        !           280:             break;
        !           281:         case 3:
        !           282:         case 4:
        !           283:         case 5:
        !           284:             hflag = (!process_all_files && !explicit_h)? FALSE : hflag_slmv;
        !           285:             tflag = (!process_all_files && !explicit_t)? FALSE : tflag_slm;
        !           286:             break;
        !           287:         case 10:
        !           288:             hflag = hflag_slmv;
        !           289:             tflag = tflag_1v;
        !           290:             break;
        !           291:     }
        !           292: 
        !           293: /*---------------------------------------------------------------------------
        !           294:     Now get the zipfile name from the command line and see if it exists as a
        !           295:     regular (non-directory) file.  If not, append the ".zip" suffix.  We don't
        !           296:     immediately check to see if this results in a good name, but we will do so
        !           297:     later.  In the meantime, see if there are any member filespecs on the com-
        !           298:     mand line, and if so, set the filename pointer to point at them.
        !           299:   ---------------------------------------------------------------------------*/
        !           300: 
        !           301:     strcpy(zipfn, *argv++);
        !           302:     if (stat(zipfn, &statbuf) || (statbuf.st_mode & S_IFMT) == S_IFDIR)
        !           303:         strcat(zipfn, ZSUFX);
        !           304: #if defined(UNIX) && !defined(VMS)  /* Unix executables have no extension-- */
        !           305:     else if (statbuf.st_mode & S_IXUSR)  /* might find zip, not zip.zip; etc */
        !           306:         fprintf(stderr, "\nnote:  file [ %s ] may be an executable\n\n", zipfn);
        !           307: #endif /* UNIX && !VMS */
        !           308: 
        !           309:     if (stat(zipfn, &statbuf)) {    /* try again */
        !           310:         fprintf(stderr, "error:  can't find zipfile [ %s ]\n", zipfn);
        !           311:         RETURN(9);                  /* 9:  file not found */
        !           312:     } else
        !           313:         ziplen = statbuf.st_size;
        !           314: 
        !           315:     if (!process_all_files)
        !           316:         fnv = argv;
        !           317: 
        !           318: /*---------------------------------------------------------------------------
        !           319:     Okey dokey, we have everything we need to get started.  Let's roll.
        !           320:   ---------------------------------------------------------------------------*/
        !           321: 
        !           322:     inbuf = (byte *) (malloc(INBUFSIZ + 4));    /* 4 extra for hold[] (below) */
        !           323:     outbuf = (byte *) (malloc(OUTBUFSIZ + 1));  /* 1 extra for string termin. */
        !           324:     if (aflag)                  /* if need an ascebc scratch, */
        !           325:         outout = (byte *) (malloc(OUTBUFSIZ));
        !           326:     else                        /*  allocate it... */
        !           327:         outout = outbuf;        /*  else just point to outbuf */
        !           328: 
        !           329:     if ((inbuf == NULL) || (outbuf == NULL) || (outout == NULL)) {
        !           330:         fprintf(stderr, "error:  can't allocate zipinfo buffers\n");
        !           331:         RETURN(4);              /* 4-8:  insufficient memory */
        !           332:     }
        !           333:     hold = &inbuf[INBUFSIZ];    /* to check for boundary-spanning signatures */
        !           334: 
        !           335:     RETURN(process_zipfile());  /* keep passing errors back... */
        !           336: 
        !           337: } /* end main() */
        !           338: 
        !           339: 
        !           340: 
        !           341: 
        !           342: 
        !           343: /**********************/
        !           344: /*  Function usage()  */
        !           345: /**********************/
        !           346: 
        !           347: int usage(error)
        !           348:     int error;
        !           349: {
        !           350:     FILE *usagefp;
        !           351: 
        !           352: 
        !           353: /*---------------------------------------------------------------------------
        !           354:     If user requested usage, send it to stdout; else send to stderr.
        !           355:   ---------------------------------------------------------------------------*/
        !           356: 
        !           357:     if (error)
        !           358:         usagefp = (FILE *) stderr;
        !           359:     else
        !           360:         usagefp = (FILE *) stdout;
        !           361: 
        !           362:     fprintf(usagefp, "\
        !           363:    ZipInfo:  Zipfile Information Utility %s\n\
        !           364:    (brought to you by Newtware, Inc., and the fine folks at Info-ZIP)\n\n\
        !           365:    Usage:  zipinfo [-1smlvht] file[.zip] [filespec...]\n", VERSION);
        !           366:     fprintf(usagefp, "\
        !           367:      -1  list filenames only, one per line (useful for pipes)\n\
        !           368:      -s  list zipfile info in short Unix \"ls -l\" format:  default\n\
        !           369:      -m  list zipfile info in medium Unix \"ls -l\" format\n\
        !           370:      -l  list zipfile info in long Unix \"ls -l\" format\n\
        !           371:      -v  list zipfile information in verbose, multi-page format\n\
        !           372:      -h  list header line\n\
        !           373:      -t  list totals for files listed or for all files\n");
        !           374: /*
        !           375:      -p  disable automatic \"more\" function (for pipes) [not implemented]\n");
        !           376:  */
        !           377: 
        !           378: #ifdef VMS
        !           379:     fprintf(usagefp, "\nRemember that non-lowercase filespecs must be quoted\
        !           380:  in VMS (e.g., \"Makefile\").\n");
        !           381: #endif
        !           382: 
        !           383:     if (error)
        !           384:         return 10;    /* 10:  bad or illegal parameters specified */
        !           385:     else
        !           386:         return 0;     /* just wanted usage screen: no error */
        !           387: 
        !           388: } /* end function usage() */
        !           389: 
        !           390: 
        !           391: 
        !           392: 
        !           393: 
        !           394: /********************************/
        !           395: /*  Function process_zipfile()  */
        !           396: /********************************/
        !           397: 
        !           398: int process_zipfile()   /* return PK-type error code */
        !           399: {
        !           400:     int error=0, error_in_archive;
        !           401: 
        !           402: 
        !           403: /*---------------------------------------------------------------------------
        !           404:     Open the zipfile for reading and in BINARY mode to prevent CR/LF trans-
        !           405:     lation, which would corrupt the bitstreams.
        !           406:   ---------------------------------------------------------------------------*/
        !           407: 
        !           408: #ifdef VMS
        !           409:     if (check_format())         /* check for variable-length format */
        !           410:         return 2;               /* 2:  error in zipfile */
        !           411: #endif /* VMS */
        !           412: 
        !           413:     if (open_input_file())      /* this should never happen, given the */
        !           414:         return 9;               /*   stat() test in main(), but... */
        !           415: 
        !           416: /*---------------------------------------------------------------------------
        !           417:     Reconstruct the various PK signature strings, and find and process the
        !           418:     end-of-central-directory header.
        !           419:   ---------------------------------------------------------------------------*/
        !           420: 
        !           421:     strcat(local_hdr_sig, LOCAL_HDR_SIG);
        !           422:     strcat(central_hdr_sig, CENTRAL_HDR_SIG);
        !           423:     strcat(end_central_sig, END_CENTRAL_SIG);
        !           424:     strcat(extd_local_sig, EXTD_LOCAL_SIG);
        !           425: 
        !           426:     if (find_end_central_dir()) {   /* not found; nothing to do */
        !           427:         close(zipfd);
        !           428:         return 2;                   /* 2:  error in zipfile */
        !           429:     }
        !           430: 
        !           431:     real_ecrec_offset = cur_zipfile_bufstart + (inptr-inbuf);
        !           432: #ifdef TEST
        !           433:     printf("\n  found end-of-central-dir signature at offset %ld (%.8lXh)\n",
        !           434:       real_ecrec_offset, real_ecrec_offset);
        !           435:     printf("    from beginning of file; offset %d (%.4Xh) within block\n",
        !           436:       inptr-inbuf, inptr-inbuf);
        !           437: #endif
        !           438: 
        !           439:     /* sets expect_ecrec_offset: */
        !           440:     if ((error_in_archive = process_end_central_dir()) > 1) {
        !           441:         close(zipfd);
        !           442:         return error_in_archive;
        !           443:     }
        !           444: 
        !           445: /*---------------------------------------------------------------------------
        !           446:     Test the end-of-central-directory info for incompatibilities (multi-disk
        !           447:     archives) or inconsistencies (missing or extra bytes in zipfile).
        !           448:   ---------------------------------------------------------------------------*/
        !           449: 
        !           450:     if (ecrec.number_this_disk != ecrec.num_disk_with_start_central_dir) {
        !           451:         fprintf(stderr, "\n\
        !           452:      Zipfile is part of a multi-disk archive, and this is not the disk on\
        !           453:      which the central zipfile directory begins.\n");
        !           454:         error_in_archive = 11;  /* 11:  no files found */
        !           455:     } else {
        !           456:         if ((extra_bytes = real_ecrec_offset - expect_ecrec_offset) < 0) {
        !           457:             fprintf(stderr, "\nerror:  missing %ld bytes in zipfile (\
        !           458: attempting to process anyway)\n\n", -extra_bytes);
        !           459:             error_in_archive = 2;       /* 2:  (weak) error in zipfile */
        !           460:         } else if (extra_bytes > 0) {
        !           461:             if ((ecrec.offset_start_central_directory == 0) &&
        !           462:                 (ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
        !           463:             {
        !           464:                 fprintf(stderr, "\nerror:  NULL central directory offset (\
        !           465: attempting to process anyway)\n\n");
        !           466:                 error_in_archive = 2;   /* 2:  (weak) error in zipfile */
        !           467:             } else {
        !           468:                 fprintf(stderr, "\nwarning:  extra %ld bytes at beginning or\
        !           469:  within zipfile\n          (attempting to process anyway)\n\n", extra_bytes);
        !           470:                 error_in_archive = 1;   /* 1:  warning error */
        !           471:             }
        !           472:         }
        !           473: 
        !           474:     /*-----------------------------------------------------------------------
        !           475:         Check for empty zipfile and exit now if so.
        !           476:       -----------------------------------------------------------------------*/
        !           477: 
        !           478:         if (expect_ecrec_offset == 0L  &&  ecrec.size_central_directory == 0) {
        !           479:             printf("%sEmpty zipfile.\n", lflag>9 ? "\n  " : "");
        !           480:             close(zipfd);
        !           481:             return (error_in_archive > 1)? error_in_archive : 1;
        !           482:         }
        !           483: 
        !           484:     /*-----------------------------------------------------------------------
        !           485:         Compensate for missing or extra bytes, and seek to where the start
        !           486:         of central directory should be.  If header not found, uncompensate
        !           487:         and try again (necessary for at least some Atari archives created
        !           488:         with STZIP, as well as archives created by J.H. Holm's ZIPSPLIT).
        !           489:       -----------------------------------------------------------------------*/
        !           490: 
        !           491:         LSEEK( ecrec.offset_start_central_directory )
        !           492:         if ((readbuf(sig, 4) <= 0) || strncmp(sig, central_hdr_sig, 4)) {
        !           493:             longint tmp = extra_bytes;
        !           494: 
        !           495:             extra_bytes = 0;
        !           496:             LSEEK( ecrec.offset_start_central_directory )
        !           497:             if ((readbuf(sig, 4) <= 0) || strncmp(sig, central_hdr_sig, 4)) {
        !           498:                 fprintf(stderr,
        !           499:             "error:  start of central directory not found; zipfile corrupt.\n");
        !           500:                 fprintf(stderr, ReportMsg);
        !           501:                 close(zipfd);
        !           502:                 return 3;           /* 3:  severe error in zipfile */
        !           503:             }
        !           504:             fprintf(stderr, "error:  reported length of central directory is \
        !           505: %d bytes too\n        long (Atari STZIP zipfile?  J.H. Holm ZIPSPLIT zipfile?)\
        !           506: .\n        Compensating...\n\n", -tmp);
        !           507:             error_in_archive = 2;   /* 2:  (weak) error in zipfile */
        !           508:         }
        !           509: 
        !           510:     /*-----------------------------------------------------------------------
        !           511:         Seek to the start of the central directory one last time, since we
        !           512:         have just read the first entry's signature bytes; then do the central
        !           513:         directory and close the zipfile.
        !           514:       -----------------------------------------------------------------------*/
        !           515: 
        !           516:         LSEEK( ecrec.offset_start_central_directory )
        !           517:         if ((error = process_central_dir()) > error_in_archive)
        !           518:             error_in_archive = error;    /* don't overwrite stronger error */
        !           519:         if (lflag > 9)
        !           520:             printf("\n");
        !           521:     }
        !           522: 
        !           523:     close(zipfd);
        !           524:     return error_in_archive;
        !           525: 
        !           526: } /* end function process_zipfile() */
        !           527: 
        !           528: 
        !           529: 
        !           530: 
        !           531: 
        !           532: /*************************************/
        !           533: /*  Function find_end_central_dir()  */
        !           534: /*************************************/
        !           535: 
        !           536: int find_end_central_dir()   /* return 0 if found, 1 otherwise */
        !           537: {
        !           538:     int       i, numblks;
        !           539:     longint   tail_len;
        !           540: 
        !           541: 
        !           542: 
        !           543: /*---------------------------------------------------------------------------
        !           544:     Treat case of short zipfile separately.
        !           545:   ---------------------------------------------------------------------------*/
        !           546: 
        !           547:     if (ziplen <= INBUFSIZ) {
        !           548:         lseek(zipfd, 0L, SEEK_SET);
        !           549:         if ((incnt = read(zipfd,inbuf,(unsigned int)ziplen)) == (int)ziplen)
        !           550:             /* 'P' must be at least 22 bytes from end of zipfile */
        !           551:             for (inptr = inbuf+(int)ziplen-22;  inptr >= inbuf;  --inptr)
        !           552:                 if ((ascii_to_native(*inptr) == 'P')  &&
        !           553:                      !strncmp((char *)inptr, end_central_sig, 4)) {
        !           554:                     incnt -= inptr - inbuf;
        !           555:                     return 0;   /* found it! */
        !           556:                 }               /* ...otherwise fall through & fail */
        !           557: 
        !           558: /*---------------------------------------------------------------------------
        !           559:     Zipfile is longer than INBUFSIZ:  may need to loop.  Start with short
        !           560:     block at end of zipfile (if not TOO short).
        !           561:   ---------------------------------------------------------------------------*/
        !           562: 
        !           563:     } else {
        !           564:         if ((tail_len = ziplen % INBUFSIZ) > ECREC_SIZE) {
        !           565:             cur_zipfile_bufstart = lseek(zipfd, ziplen-tail_len, SEEK_SET);
        !           566:             if ((incnt = read(zipfd,inbuf,(unsigned int)tail_len)) !=
        !           567:                 (int)tail_len)
        !           568:                 goto fail;      /* shut up; it's expedient. */
        !           569: 
        !           570:             /* 'P' must be at least 22 bytes from end of zipfile */
        !           571:             for (inptr = inbuf+(int)tail_len-22;  inptr >= inbuf;  --inptr)
        !           572:                 if ((ascii_to_native(*inptr) == 'P')  &&
        !           573:                      !strncmp((char *)inptr, end_central_sig, 4)) {
        !           574:                     incnt -= inptr - inbuf;
        !           575:                     return 0;   /* found it */
        !           576:                 }               /* ...otherwise search next block */
        !           577:             /* sig may span block boundary: */
        !           578:             strncpy((char *)hold, (char *)inbuf, 3);
        !           579:         } else
        !           580:             cur_zipfile_bufstart = ziplen - tail_len;
        !           581: 
        !           582:         /*
        !           583:          * Loop through blocks of zipfile data, starting at the end and going
        !           584:          * toward the beginning.  Need only check last 65557 bytes of zipfile:
        !           585:          * comment may be up to 65535 bytes long, end-of-central-directory rec-
        !           586:          * ord is 18 bytes (shouldn't hardcode this number, but what the hell:
        !           587:          * already did so above (22=18+4)), and sig itself is 4 bytes.
        !           588:          * 
        !           589:          * zipinfo:  check the whole file, just in case some transfer protocol
        !           590:          * has appended a whole bunch of garbage at the end of the archive.
        !           591:          *
        !           592:          *                =todo=   ==done==   ==rounding==    =blksiz=      */
        !           593:         numblks = (int) ((ziplen - tail_len + (INBUFSIZ-1)) / INBUFSIZ);
        !           594: 
        !           595:         for (i = 1;  i <= numblks;  ++i) {
        !           596:             cur_zipfile_bufstart -= INBUFSIZ;
        !           597:             lseek(zipfd, cur_zipfile_bufstart, SEEK_SET);
        !           598:             if ((incnt = read(zipfd,inbuf,INBUFSIZ)) != INBUFSIZ)
        !           599:                 break;          /* fall through and fail */
        !           600: 
        !           601:             for (inptr = inbuf+INBUFSIZ-1;  inptr >= inbuf;  --inptr)
        !           602:                 if ((ascii_to_native(*inptr) == 'P')  &&
        !           603:                      !strncmp((char *)inptr, end_central_sig, 4)) {
        !           604:                     incnt -= inptr - inbuf;
        !           605:                     return 0;   /* found it */
        !           606:                 }
        !           607:             /* sig may span block boundary: */
        !           608:             strncpy((char *)hold, (char *)inbuf, 3);
        !           609:         }
        !           610: 
        !           611:     } /* end if (ziplen > INBUFSIZ) */
        !           612: 
        !           613: /*---------------------------------------------------------------------------
        !           614:     Searched through whole region where signature should be without finding
        !           615:     it.  Print informational message and die a horrible death.
        !           616:   ---------------------------------------------------------------------------*/
        !           617: 
        !           618: fail:
        !           619: 
        !           620:     fprintf(stderr, "\n\
        !           621:      %s:\n\n\
        !           622:      End-of-central-directory signature not found.  Either this file is not\n\
        !           623:      a zipfile, or it constitutes one disk of a multi-part archive.  In the\n\
        !           624:      latter case the central directory and zipfile comment will be found on\n\
        !           625:      the last disk(s) of this archive.\n", zipfn);
        !           626:     return 1;   /* failed */
        !           627: 
        !           628: } /* end function find_end_central_dir() */
        !           629: 
        !           630: 
        !           631: 
        !           632: 
        !           633: 
        !           634: /****************************************/
        !           635: /*  Function process_end_central_dir()  */
        !           636: /****************************************/
        !           637: 
        !           638: int process_end_central_dir()   /* return PK-type error code */
        !           639: {
        !           640:     ec_byte_rec   byterec;
        !           641:     int           error=0;
        !           642: 
        !           643: 
        !           644: /*--------------------------------------------------------------------------
        !           645:     Read the end-of-central-directory record and do any necessary machine-
        !           646:     type conversions (byte ordering, structure padding compensation) by
        !           647:     copying character array to struct.
        !           648:   ---------------------------------------------------------------------------*/
        !           649: 
        !           650:     if (readbuf((char *)byterec, ECREC_SIZE+4) <= 0)
        !           651:         return 51;
        !           652: 
        !           653:     ecrec.number_this_disk =
        !           654:         makeword(&byterec[NUMBER_THIS_DISK]);
        !           655:     ecrec.num_disk_with_start_central_dir =
        !           656:         makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]);
        !           657:     ecrec.num_entries_centrl_dir_ths_disk =
        !           658:         makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]);
        !           659:     ecrec.total_entries_central_dir =
        !           660:         makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]);
        !           661:     ecrec.size_central_directory =
        !           662:         makelong(&byterec[SIZE_CENTRAL_DIRECTORY]);
        !           663:     ecrec.offset_start_central_directory =
        !           664:         makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
        !           665:     ecrec.zipfile_comment_length =
        !           666:         makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
        !           667: 
        !           668:     expect_ecrec_offset = ecrec.offset_start_central_directory +
        !           669:                            ecrec.size_central_directory;
        !           670: 
        !           671: /*---------------------------------------------------------------------------
        !           672:     Print out various interesting things about the zipfile.
        !           673:   ---------------------------------------------------------------------------*/
        !           674: 
        !           675:     /* header fits on one line, for anything up to 10GB and 10000 files: */
        !           676:     if (hflag)
        !           677:         printf((strlen(zipfn)<39)? "Archive:  %s   %ld bytes   %d file%s\n"
        !           678:           : "Archive:  %s   %ld   %d\n", zipfn, ziplen,
        !           679:           ecrec.total_entries_central_dir,
        !           680:           (ecrec.total_entries_central_dir==1)? "":"s");
        !           681: 
        !           682:     /* verbose format */
        !           683:     if (lflag > 9) {
        !           684:         printf("\nEnd-of-central-directory record:\n");
        !           685:         printf("-------------------------------\n\n");
        !           686: 
        !           687:         printf("\
        !           688:   Actual offset of end-of-central-dir record:   %9ld (%.8lXh)\n\
        !           689:   Expected offset of end-of-central-dir record: %9ld (%.8lXh)\n\
        !           690:   (based on the length of the central directory and its expected offset)\n\n",
        !           691:           real_ecrec_offset, real_ecrec_offset,
        !           692:           expect_ecrec_offset, expect_ecrec_offset);
        !           693: 
        !           694:         if (ecrec.number_this_disk == 0) {
        !           695:             printf("\
        !           696:   This zipfile constitutes the sole disk of a single-part archive; its\n\
        !           697:   central directory contains %u %s.  The central directory is %lu\n\
        !           698:   (%.8lXh) bytes long, and its (expected) offset in bytes from the\n\
        !           699:   beginning of the zipfile is %lu (%.8lXh).\n\n",
        !           700:               ecrec.total_entries_central_dir,
        !           701:               (ecrec.total_entries_central_dir == 1)? "entry" : "entries",
        !           702:               ecrec.size_central_directory, ecrec.size_central_directory,
        !           703:               ecrec.offset_start_central_directory,
        !           704:               ecrec.offset_start_central_directory);
        !           705:         } else {
        !           706:             printf("\
        !           707:   This zipfile constitutes disk %u of a multi-part archive.  The central\n\
        !           708:   directory starts on disk %u; %u of its entries %s contained within\n\
        !           709:   this zipfile, out of a total of %u %s.  The entire central\n\
        !           710:   directory is %lu (%.8lXh) bytes long, and its offset in bytes from\n\
        !           711:   the beginning of the zipfile in which it begins is %lu (%.8lXh).\n\n",
        !           712:               ecrec.number_this_disk,
        !           713:               ecrec.num_disk_with_start_central_dir,
        !           714:               ecrec.num_entries_centrl_dir_ths_disk,
        !           715:               (ecrec.num_entries_centrl_dir_ths_disk == 1)? "is" : "are",
        !           716:               ecrec.total_entries_central_dir,
        !           717:               (ecrec.total_entries_central_dir == 1) ? "entry" : "entries",
        !           718:               ecrec.size_central_directory, ecrec.size_central_directory,
        !           719:               ecrec.offset_start_central_directory,
        !           720:               ecrec.offset_start_central_directory);
        !           721:         }
        !           722: 
        !           723:     /*-----------------------------------------------------------------------
        !           724:         Get the zipfile comment, if any, and print it out.  (Comment may be
        !           725:         up to 64KB long.  May the fleas of a thousand camels infest the arm-
        !           726:         pits of anyone who actually takes advantage of this fact.)
        !           727:       -----------------------------------------------------------------------*/
        !           728: 
        !           729:         if (!ecrec.zipfile_comment_length)
        !           730:             printf("  There is no zipfile comment.\n");
        !           731:         else {
        !           732:             printf("  The zipfile comment is %u bytes long and contains the following text:\n\n",
        !           733:               ecrec.zipfile_comment_length );
        !           734:             printf("======================== zipfile comment begins ==========================\n");
        !           735:             if (do_string(ecrec.zipfile_comment_length, DISPLAY))
        !           736:                 error = 1;          /* 1:  warning error */
        !           737:             printf("\n========================= zipfile comment ends ===========================\n");
        !           738:             if (error)
        !           739:                 printf("\n  The zipfile comment is truncated.\n");
        !           740:         } /* endif (comment exists) */
        !           741: 
        !           742:     } /* endif (verbose) */
        !           743: 
        !           744:     return error;
        !           745: 
        !           746: } /* end function process_end_central_dir() */
        !           747: 
        !           748: 
        !           749: 
        !           750: 
        !           751: 
        !           752: /************************************/
        !           753: /*  Function process_central_dir()  */
        !           754: /************************************/
        !           755: 
        !           756: int process_central_dir()   /* return PK-type error code */
        !           757: {
        !           758:     char    **fnamev;
        !           759:     int     do_this_file=FALSE, none_found=TRUE, error, error_in_archive=0;
        !           760:     UWORD   j, members=0;
        !           761:     ULONG   c=0L, uc=0L;
        !           762: 
        !           763: 
        !           764: /*---------------------------------------------------------------------------
        !           765:     Set file pointer to start of central directory, then loop through cen-
        !           766:     tral directory entries.  Check that directory-entry signature bytes are
        !           767:     actually there (just a precaution), then process the entry.  We know
        !           768:     the entire central directory is on this disk:  we wouldn't have any of
        !           769:     this information unless the end-of-central-directory record was on this
        !           770:     disk, and we wouldn't have gotten to this routine unless this is also
        !           771:     the disk on which the central directory starts.  In practice, this had
        !           772:     better be the *only* disk in the archive, but maybe someday we'll add
        !           773:     multi-disk support.
        !           774:   ---------------------------------------------------------------------------*/
        !           775: 
        !           776:     pInfo->lcflag = 0;   /* match(), do_string():  never TRUE in zipinfo */
        !           777: 
        !           778:     for (j = 0;  j < ecrec.total_entries_central_dir;  ++j) {
        !           779:         if (readbuf(sig, 4) <= 0)
        !           780:             return 51;          /* 51:  unexpected EOF */
        !           781:         if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
        !           782:             fprintf(stderr, CentSigMsg, j);  /* sig not found */
        !           783:             return 3;           /* 3:  error in zipfile */
        !           784:         }
        !           785:         if ((error = process_cdir_file_hdr()) != 0)
        !           786:             return error;       /* only 51 (EOF) defined */
        !           787:         if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
        !           788:           error_in_archive = error;   /* might be warning */
        !           789:           if (error > 1)        /* fatal */
        !           790:               return error;
        !           791:         }
        !           792: 
        !           793:         if (!process_all_files) {   /* check if specified on command line */
        !           794:             do_this_file = FALSE;
        !           795:             fnamev = fnv;       /* don't destroy permanent filename ptr */
        !           796:             for (--fnamev;  *++fnamev; )
        !           797:                 if (match(filename, *fnamev)) {
        !           798:                     do_this_file = TRUE;
        !           799:                     none_found = FALSE;
        !           800:                     break;      /* found match, so stop looping */
        !           801:                 }
        !           802:         }
        !           803: 
        !           804:     /*-----------------------------------------------------------------------
        !           805:         If current file was specified on command line, or if no names were
        !           806:         specified, do the listing for this file.  Otherwise, get rid of the
        !           807:         file comment and go back for the next file.
        !           808:       -----------------------------------------------------------------------*/
        !           809: 
        !           810:         if (process_all_files || do_this_file) {
        !           811:             switch (lflag) {
        !           812:                 case 1:
        !           813:                     printf("%s\n", filename);
        !           814:                     SKIP_(crec.extra_field_length)
        !           815:                     SKIP_(crec.file_comment_length)
        !           816:                     break;
        !           817: 
        !           818:                 case 3:
        !           819:                 case 4:
        !           820:                 case 5:
        !           821:                     if ((error = short_info()) != 0) {
        !           822:                         error_in_archive = error;   /* might be warning */
        !           823:                         if (error > 1)              /* fatal */
        !           824:                             return error;
        !           825:                     }
        !           826:                     break;
        !           827: 
        !           828:                 case 10:
        !           829: #ifdef VMS   /* GRR: FIX THIS (no pipes:  add cbreak-style "more" function) */
        !           830:                     printf("\nCentral directory entry #%d:\n", j);
        !           831: #else /* !VMS */
        !           832:                     /* formfeed/CR for piping to "more": */
        !           833:                     printf("%s\nCentral directory entry #%d:\n", "\014", j);
        !           834: #endif /* ?VMS */
        !           835:                     printf("---------------------------\n\n");
        !           836: 
        !           837:                     if ((error = long_info()) != 0) {
        !           838:                       error_in_archive = error;   /* might be warning */
        !           839:                       if (error > 1)              /* fatal */
        !           840:                           return error;
        !           841:                     }
        !           842:                     break;
        !           843: 
        !           844:                 default:
        !           845:                     SKIP_(crec.extra_field_length)
        !           846:                     SKIP_(crec.file_comment_length)
        !           847:                     break;
        !           848: 
        !           849:             } /* end switch (lflag) */
        !           850: 
        !           851:             uc += crec.uncompressed_size;
        !           852:             c += crec.compressed_size;
        !           853:             if (crec.general_purpose_bit_flag & 1)
        !           854:                 c -= 12;    /* if encrypted, don't count encryption header */
        !           855:             ++members;
        !           856: 
        !           857:         } else {   /* not listing */
        !           858:             SKIP_(crec.extra_field_length)
        !           859:             SKIP_(crec.file_comment_length)
        !           860: 
        !           861:         } /* end if (list member?) */
        !           862: 
        !           863:     } /* end for-loop (j: member files) */
        !           864: 
        !           865: /*---------------------------------------------------------------------------
        !           866:     Double check that we're back at the end-of-central-directory record.
        !           867:   ---------------------------------------------------------------------------*/
        !           868: 
        !           869:     readbuf(sig, 4);
        !           870:     if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
        !           871:         fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
        !           872:         error_in_archive = 1;        /* 1:  warning error */
        !           873:     }
        !           874: 
        !           875: /*---------------------------------------------------------------------------
        !           876:     Check that we actually found requested files; if so, print totals.
        !           877:   ---------------------------------------------------------------------------*/
        !           878: 
        !           879:     if (none_found && !process_all_files) {
        !           880:         fnamev = fnv;       /* don't destroy permanent filename ptr */
        !           881:         for (--fnamev;  *++fnamev; )
        !           882:             printf("zipinfo:  %s not found in %s\n", *fnamev, zipfn);
        !           883:     } else if (tflag)
        !           884:         printf(
        !           885:           "%d file%s, %lu bytes uncompressed, %lu bytes compressed:  %d%%\n",
        !           886:           members, (members==1)? "":"s", uc, c, (uc==0)? 0 : ((uc>2000000L)?
        !           887:           ((int)((uc-c)/(uc/1000L))+5)/10 : ((int)((1000L*(uc-c))/uc)+5)/10) );
        !           888: 
        !           889:     return error_in_archive;
        !           890: 
        !           891: } /* end function process_central_dir() */
        !           892: 
        !           893: 
        !           894: 
        !           895: 
        !           896: 
        !           897: /**************************************/
        !           898: /*  Function process_cdir_file_hdr()  */
        !           899: /**************************************/
        !           900: 
        !           901: int process_cdir_file_hdr()   /* return PK-type error code */
        !           902: {
        !           903:     cdir_byte_hdr   byterec;
        !           904: 
        !           905: 
        !           906: /*---------------------------------------------------------------------------
        !           907:     Read the next central directory entry and do any necessary machine-type
        !           908:     conversions (byte ordering, structure padding compensation--do so by
        !           909:     copying the data from the array into which it was read (byterec) to the
        !           910:     usable struct (crec)).
        !           911:   ---------------------------------------------------------------------------*/
        !           912: 
        !           913:     if (readbuf((char *) byterec, CREC_SIZE) <= 0)
        !           914:         return 51;   /* 51:  unexpected EOF */
        !           915: 
        !           916:     crec.version_made_by[0] = byterec[C_VERSION_MADE_BY_0];
        !           917:     crec.version_made_by[1] = byterec[C_VERSION_MADE_BY_1];
        !           918:     crec.version_needed_to_extract[0] = byterec[C_VERSION_NEEDED_TO_EXTRACT_0];
        !           919:     crec.version_needed_to_extract[1] = byterec[C_VERSION_NEEDED_TO_EXTRACT_1];
        !           920: 
        !           921:     crec.general_purpose_bit_flag =
        !           922:         makeword(&byterec[C_GENERAL_PURPOSE_BIT_FLAG]);
        !           923:     crec.compression_method =
        !           924:         makeword(&byterec[C_COMPRESSION_METHOD]);
        !           925:     crec.last_mod_file_time =
        !           926:         makeword(&byterec[C_LAST_MOD_FILE_TIME]);
        !           927:     crec.last_mod_file_date =
        !           928:         makeword(&byterec[C_LAST_MOD_FILE_DATE]);
        !           929:     crec.crc32 =
        !           930:         makelong(&byterec[C_CRC32]);
        !           931:     crec.compressed_size =
        !           932:         makelong(&byterec[C_COMPRESSED_SIZE]);
        !           933:     crec.uncompressed_size =
        !           934:         makelong(&byterec[C_UNCOMPRESSED_SIZE]);
        !           935:     crec.filename_length =
        !           936:         makeword(&byterec[C_FILENAME_LENGTH]);
        !           937:     crec.extra_field_length =
        !           938:         makeword(&byterec[C_EXTRA_FIELD_LENGTH]);
        !           939:     crec.file_comment_length =
        !           940:         makeword(&byterec[C_FILE_COMMENT_LENGTH]);
        !           941:     crec.disk_number_start =
        !           942:         makeword(&byterec[C_DISK_NUMBER_START]);
        !           943:     crec.internal_file_attributes =
        !           944:         makeword(&byterec[C_INTERNAL_FILE_ATTRIBUTES]);
        !           945:     crec.external_file_attributes =
        !           946:         makelong(&byterec[C_EXTERNAL_FILE_ATTRIBUTES]); /* LONG, not word! */
        !           947:     crec.relative_offset_local_header =
        !           948:         makelong(&byterec[C_RELATIVE_OFFSET_LOCAL_HEADER]);
        !           949: 
        !           950:     return 0;
        !           951: 
        !           952: } /* end function process_cdir_file_hdr() */
        !           953: 
        !           954: 
        !           955: 
        !           956: 
        !           957: /**************************/
        !           958: /*  Function long_info()  */
        !           959: /**************************/
        !           960: 
        !           961: int long_info()   /* return PK-type error code */
        !           962: {
        !           963:     int           error, error_in_archive=0;
        !           964:     UWORD         hostver, extver, xattr;
        !           965:     char          workspace[12], attribs[22];
        !           966:     static char   unkn[16];
        !           967:     static char   *os[NUM_HOSTS+1] = {"MS-DOS or OS/2 FAT", "Amiga", "VAX VMS",
        !           968:                       "Unix", "VM/CMS", "Atari ST", "OS/2 HPFS", "Macintosh",
        !           969:                       "Z-System", "CP/M", "unknown" };
        !           970:     static char   *method[NUM_METHODS+1] = {"none (stored)", "shrunk",
        !           971:                       "reduced (factor 1)", "reduced (factor 2)",
        !           972:                       "reduced (factor 3)", "reduced (factor 4)",
        !           973:                       "imploded", "tokenized", "deflated", unkn};
        !           974:     static char   *dtype[4] = {"normal", "maximum", "fast", "superfast"};
        !           975: 
        !           976: 
        !           977: /*---------------------------------------------------------------------------
        !           978:     Print out various interesting things about the compressed file.
        !           979:   ---------------------------------------------------------------------------*/
        !           980: 
        !           981:     hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
        !           982:     hostver = crec.version_made_by[0];
        !           983:     extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS);
        !           984:     extver = crec.version_needed_to_extract[0];
        !           985:     methnum = MIN(crec.compression_method, NUM_METHODS);
        !           986:     if (methnum == NUM_METHODS)
        !           987:         sprintf(unkn, "unknown (%d)", crec.compression_method);
        !           988: 
        !           989:     printf("  %s\n", filename);
        !           990: 
        !           991:     printf("\n  host operating system (created on):               %s\n",
        !           992:       os[hostnum]);
        !           993:     printf("  version of encoding software:                     %d.%d\n",
        !           994:       hostver/10, hostver%10);
        !           995:     printf("  minimum operating system compatibility required:  %s\n",
        !           996:       os[extnum]);
        !           997:     printf("  minimum software version required to extract:     %d.%d\n",
        !           998:       extver/10, extver%10);
        !           999:     printf("  compression method:                               %s\n",
        !          1000:       method[methnum]);
        !          1001:     if (methnum == IMPLODED) {
        !          1002:         printf("  size of sliding dictionary (implosion):           %cK\n",
        !          1003:           (crec.general_purpose_bit_flag & 2)? '8' : '4');
        !          1004:         printf("  number of Shannon-Fano trees (implosion):         %c\n",
        !          1005:           (crec.general_purpose_bit_flag & 4)? '3' : '2');
        !          1006:     } else if (methnum == DEFLATED) {
        !          1007:         UWORD  dnum=(crec.general_purpose_bit_flag>>1) & 3;
        !          1008:         printf("  compression sub-type (deflation):                 %s\n",
        !          1009:           dtype[dnum]);
        !          1010:     }
        !          1011:     printf("  file security status:                             %sencrypted\n",
        !          1012:       (crec.general_purpose_bit_flag & 1)? "" : "not ");
        !          1013:     printf("  extended local header:                            %s\n",
        !          1014:       (crec.general_purpose_bit_flag & 8)? "yes" : "no");
        !          1015:     /* print upper 3 bits for amusement? */
        !          1016:     printf("  file last modified on:                            %s\n",
        !          1017:       zipinfo_time(&crec.last_mod_file_date, &crec.last_mod_file_time));
        !          1018:     printf("  32-bit CRC value (hex):                           %.8lx\n",
        !          1019:       crec.crc32);
        !          1020:     printf("  compressed size:                                  %lu bytes\n",
        !          1021:       crec.compressed_size);
        !          1022:     printf("  uncompressed size:                                %lu bytes\n",
        !          1023:       crec.uncompressed_size);
        !          1024:     printf("  length of filename:                               %u characters\n",
        !          1025:       crec.filename_length);
        !          1026:     printf("  length of extra field:                            %u bytes\n",
        !          1027:       crec.extra_field_length);
        !          1028:     printf("  length of file comment:                           %u characters\n",
        !          1029:       crec.file_comment_length);
        !          1030:     printf("  disk number on which file begins:                 disk %u\n",
        !          1031:       crec.disk_number_start);
        !          1032:     printf("  apparent file type:                               %s\n",
        !          1033:       (crec.internal_file_attributes & 1)? "text" : "binary");
        !          1034: /*
        !          1035:     printf("  external file attributes (hex):                   %.8lx\n",
        !          1036:       crec.external_file_attributes);
        !          1037:  */
        !          1038:     xattr = (UWORD) ((crec.external_file_attributes >> 16) & 0xFFFF);
        !          1039:     if (hostnum == VMS_) {
        !          1040:         char   *p=attribs, *q=attribs+1;
        !          1041:         int    i, j, k;
        !          1042: 
        !          1043:         for (k = 0;  k < 12;  ++k)
        !          1044:             workspace[k] = 0;
        !          1045:         if (xattr & S_IRUSR)
        !          1046:             workspace[0] = 'R';
        !          1047:         if (xattr & S_IWUSR) {
        !          1048:             workspace[1] = 'W';
        !          1049:             workspace[3] = 'D';
        !          1050:         }
        !          1051:         if (xattr & S_IXUSR)
        !          1052:             workspace[2] = 'E';
        !          1053:         if (xattr & S_IRGRP)
        !          1054:             workspace[4] = 'R';
        !          1055:         if (xattr & S_IWGRP) {
        !          1056:             workspace[5] = 'W';
        !          1057:             workspace[7] = 'D';
        !          1058:         }
        !          1059:         if (xattr & S_IXGRP)
        !          1060:             workspace[6] = 'E';
        !          1061:         if (xattr & S_IROTH)
        !          1062:             workspace[8] = 'R';
        !          1063:         if (xattr & S_IWOTH) {
        !          1064:             workspace[9] = 'W';
        !          1065:             workspace[11] = 'D';
        !          1066:         }
        !          1067:         if (xattr & S_IXOTH)
        !          1068:             workspace[10] = 'E';
        !          1069: 
        !          1070:         *p++ = '(';
        !          1071:         for (k = j = 0;  j < 3;  ++j) {    /* loop over groups of permissions */
        !          1072:             for (i = 0;  i < 4;  ++i, ++k)  /* loop over perms within a group */
        !          1073:                 if (workspace[k])
        !          1074:                     *p++ = workspace[k];
        !          1075:             *p++ = ',';                      /* group separator */
        !          1076:             if (j == 0)
        !          1077:                 while ((*p++ = *q++) != ','); /* system, owner perms are same */
        !          1078:         }
        !          1079:         *p-- = 0;
        !          1080:         *p = ')';   /* overwrite last comma */
        !          1081:         printf("  VMS file attributes (%06o octal):               %s\n",
        !          1082:           xattr, attribs);
        !          1083: 
        !          1084:     } else if ((hostnum != DOS_OS2_FAT_) && (hostnum != OS2_HPFS_)) {
        !          1085:         /* assume Unix-like */
        !          1086:         switch (xattr & S_IFMT) {
        !          1087:             case S_IFREG:   attribs[0] = '-';  break;
        !          1088:             case S_IFLNK:   attribs[0] = 'l';  break;
        !          1089:             case S_IFBLK:   attribs[0] = 'b';  break;
        !          1090:             case S_IFCHR:   attribs[0] = 'c';  break;
        !          1091:             case S_IFIFO:   attribs[0] = 'p';  break;
        !          1092:             case S_IFSOCK:  attribs[0] = 's';  break;
        !          1093:             case S_IFDIR:   attribs[0] = 'd';  break;
        !          1094:             default:        attribs[0] = '?';  break;
        !          1095:         }
        !          1096:         if (xattr & S_IRUSR)        /* no read-permission: user */
        !          1097:             attribs[1] = 'r';
        !          1098:         else
        !          1099:             attribs[1] = '-';
        !          1100:         if (xattr & S_IWUSR)        /* no write-permission: user */
        !          1101:             attribs[2] = 'w';
        !          1102:         else
        !          1103:             attribs[2] = '-';
        !          1104:         if (xattr & S_IXUSR)        /* no execute-permission: user */
        !          1105:             if (xattr & S_ISUID)
        !          1106:                 attribs[3] = 's';
        !          1107:             else
        !          1108:                 attribs[3] = 'x';
        !          1109:         else
        !          1110:             if (xattr & S_ISUID)
        !          1111:                 attribs[3] = 'S';   /* undefined state */
        !          1112:             else
        !          1113:                 attribs[3] = '-';
        !          1114:         if (xattr & S_IRGRP)        /* no read-permission: group */
        !          1115:             attribs[4] = 'r';
        !          1116:         else
        !          1117:             attribs[4] = '-';
        !          1118:         if (xattr & S_IWGRP)        /* no write-permission: group */
        !          1119:             attribs[5] = 'w';
        !          1120:         else
        !          1121:             attribs[5] = '-';
        !          1122:         if (xattr & S_IXGRP)        /* no execute-permission: group */
        !          1123:             if (xattr & S_ISGID)
        !          1124:                 attribs[6] = 's';
        !          1125:             else
        !          1126:                 attribs[6] = 'x';
        !          1127:         else
        !          1128:             if (xattr & S_ISGID)    /* or could use S_ENFMT (same) */
        !          1129:                 attribs[6] = 'l';
        !          1130:             else
        !          1131:                 attribs[6] = '-';
        !          1132:         if (xattr & S_IROTH)        /* no read-permission: other */
        !          1133:             attribs[7] = 'r';
        !          1134:         else
        !          1135:             attribs[7] = '-';
        !          1136:         if (xattr & S_IWOTH)        /* no write-permission: other */
        !          1137:             attribs[8] = 'w';
        !          1138:         else
        !          1139:             attribs[8] = '-';
        !          1140:         if (xattr & S_IXOTH)        /* no execute-permission: other */
        !          1141:             if (xattr & S_ISVTX)    /* "sticky bit" */
        !          1142:                 attribs[9] = 't';
        !          1143:             else
        !          1144:                 attribs[9] = 'x';
        !          1145:         else
        !          1146:             if (xattr & S_ISVTX)
        !          1147:                 attribs[9] = 'T';   /* undefined state */
        !          1148:             else
        !          1149:                 attribs[9] = '-';
        !          1150:         attribs[10] = 0;
        !          1151:         printf("  Unix file attributes (%06o octal):              %s\n",
        !          1152:           xattr, attribs);
        !          1153: 
        !          1154:     } /* endif (hostnum: external attributes format) */
        !          1155: 
        !          1156:     if ((xattr=(UWORD)(crec.external_file_attributes & 0xFF)) == 0)
        !          1157:         printf("  MS-DOS file attributes (%02X hex):                  none\n",
        !          1158:           xattr);
        !          1159:     else if (xattr == 1)
        !          1160:         printf(
        !          1161:           "  MS-DOS file attributes (%02X hex):                  read-only\n",
        !          1162:           xattr);
        !          1163:     else
        !          1164:         printf(
        !          1165:          "  MS-DOS file attributes (%02X hex):                  %s%s%s%s%s%s\n",
        !          1166:           xattr, (xattr&1)?"rdo ":"", (xattr&2)?"hid ":"", (xattr&4)?"sys ":"",
        !          1167:           (xattr&8)?"lab ":"", (xattr&16)?"dir ":"", (xattr&32)?"arc":"");
        !          1168:     printf(
        !          1169:      "  offset of local header from start of archive:     %lu (%.8lXh) bytes\n",
        !          1170:       crec.relative_offset_local_header, crec.relative_offset_local_header);
        !          1171: 
        !          1172: /*---------------------------------------------------------------------------
        !          1173:     Skip the extra field, if any, and print the file comment, if any (the
        !          1174:     filename has already been printed, above).  That finishes up this file
        !          1175:     entry...
        !          1176:   ---------------------------------------------------------------------------*/
        !          1177: 
        !          1178:     if (crec.extra_field_length > 0) {
        !          1179: /* #ifdef OS2 */
        !          1180: #if TRUE
        !          1181:         ULONG ea_size;
        !          1182:         if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0) {
        !          1183:             error_in_archive = error;
        !          1184:             if (error > 1)      /* fatal:  can't continue */
        !          1185:                 return (error);
        !          1186:         }
        !          1187:         if ((ea_size = SizeOfEAs(extra_field)) != 0)
        !          1188:             printf("\n\
        !          1189:   This file has %lu bytes of OS/2 EA's in the local extra field.\n\
        !          1190:   (May not match OS/2 \"dir\" amount due to storage method.)\n\n",
        !          1191:               ea_size);
        !          1192:         else
        !          1193:             printf("\n  There is an unknown extra field (skipping).\n");
        !          1194: #else
        !          1195:         printf("\n  There is an extra field (skipping).\n");
        !          1196:         SKIP_(crec.extra_field_length)
        !          1197: #endif
        !          1198:     } else
        !          1199:         printf("\n");
        !          1200: 
        !          1201:     if (!crec.file_comment_length)
        !          1202:         printf("  There is no file comment.\n");
        !          1203:     else {
        !          1204:         printf("\
        !          1205: ------------------------- file comment begins ----------------------------\n");
        !          1206:         if ((error = do_string(crec.file_comment_length, DISPLAY)) != 0) {
        !          1207:           error_in_archive = error;   /* might be warning */
        !          1208:           if (error > 1)      /* fatal */
        !          1209:               return error;
        !          1210:         }
        !          1211:         printf("\n\
        !          1212: -------------------------- file comment ends -----------------------------\n");
        !          1213:     }
        !          1214: 
        !          1215:     return error_in_archive;
        !          1216: 
        !          1217: } /* end function long_info() */
        !          1218: 
        !          1219: 
        !          1220: 
        !          1221: 
        !          1222: 
        !          1223: /**************************/
        !          1224: /*  Function SizeOfEAs()  */
        !          1225: /**************************/
        !          1226: 
        !          1227: ULONG SizeOfEAs(extra_field)   /* Author: Kai Uwe Rommel */
        !          1228:     void   *extra_field;
        !          1229: {
        !          1230:     EAHEADER *pEAblock = (PEAHEADER) extra_field;
        !          1231: 
        !          1232:     if ( extra_field != NULL && pEAblock -> nID == EAID )
        !          1233:       return pEAblock -> lSize;
        !          1234: 
        !          1235:     return 0L;
        !          1236: }
        !          1237: 
        !          1238: 
        !          1239: 
        !          1240: 
        !          1241: 
        !          1242: /***************************/
        !          1243: /*  Function short_info()  */
        !          1244: /***************************/
        !          1245: 
        !          1246: int short_info()   /* return PK-type error code */
        !          1247: {
        !          1248:     int           k, error, error_in_archive=0;
        !          1249:     UWORD         hostver, xattr;
        !          1250:     char          workspace[12], attribs[16];
        !          1251:     static char   impl[5]="i#:#", defl[5]="def#", unkn[8];
        !          1252:     static char   dtype[5]="NXFS";  /* normal, maximum, fast, superfast */
        !          1253:     static char   *os[NUM_HOSTS+1] = {"dos", "ami", "vms", "unx", "cms",
        !          1254:                       "atr", "os2", "mac", "zzz", "cpm", "???" };
        !          1255:     static char   *method[NUM_METHODS+1] = {"stor", "shrk", "re:1", "re:2",
        !          1256:                       "re:3", "re:4", impl, "tokn", defl, unkn};
        !          1257: 
        !          1258: 
        !          1259: /*---------------------------------------------------------------------------
        !          1260:     Print out various interesting things about the compressed file.
        !          1261:   ---------------------------------------------------------------------------*/
        !          1262: 
        !          1263:     methnum = MIN(crec.compression_method, NUM_METHODS);
        !          1264:     hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
        !          1265:     hostver = crec.version_made_by[0];
        !          1266: /*
        !          1267:     extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS);
        !          1268:     extver = crec.version_needed_to_extract[0];
        !          1269:  */
        !          1270: 
        !          1271:     if (methnum == IMPLODED) {
        !          1272:         impl[1] = (crec.general_purpose_bit_flag & 2)? '8' : '4';
        !          1273:         impl[3] = (crec.general_purpose_bit_flag & 4)? '3' : '2';
        !          1274:     } else if (methnum == DEFLATED) {
        !          1275:         UWORD  dnum=(crec.general_purpose_bit_flag>>1) & 3;
        !          1276:         defl[3] = dtype[dnum];
        !          1277:     } else if (methnum == NUM_METHODS) {   /* unknown */
        !          1278:         sprintf(unkn, "u%03d", crec.compression_method);
        !          1279:     }
        !          1280: 
        !          1281:     for (k = 0;  k < 15;  ++k)
        !          1282:         attribs[k] = ' ';
        !          1283:     attribs[15] = 0;
        !          1284: 
        !          1285:     xattr = (UWORD) ((crec.external_file_attributes >> 16) & 0xFFFF);
        !          1286:     switch (hostnum) {
        !          1287:       case VMS_:
        !          1288:           {   char   *p=attribs;
        !          1289:               int    i, j;
        !          1290: 
        !          1291:               for (k = 0;  k < 12;  ++k)
        !          1292:                   workspace[k] = 0;
        !          1293:               if (xattr & S_IRUSR)
        !          1294:                   workspace[0] = 'R';
        !          1295:               if (xattr & S_IWUSR) {
        !          1296:                   workspace[1] = 'W';
        !          1297:                   workspace[3] = 'D';
        !          1298:               }
        !          1299:               if (xattr & S_IXUSR)
        !          1300:                   workspace[2] = 'E';
        !          1301:               if (xattr & S_IRGRP)
        !          1302:                   workspace[4] = 'R';
        !          1303:               if (xattr & S_IWGRP) {
        !          1304:                   workspace[5] = 'W';
        !          1305:                   workspace[7] = 'D';
        !          1306:               }
        !          1307:               if (xattr & S_IXGRP)
        !          1308:                 workspace[6] = 'E';
        !          1309:               if (xattr & S_IROTH)
        !          1310:                   workspace[8] = 'R';
        !          1311:               if (xattr & S_IWOTH) {
        !          1312:                   workspace[9] = 'W';
        !          1313:                   workspace[11] = 'D';
        !          1314:               }
        !          1315:               if (xattr & S_IXOTH)
        !          1316:                   workspace[10] = 'E';
        !          1317: 
        !          1318:               for (k = j = 0;  j < 3;  ++j) {     /* groups of permissions */
        !          1319:                   for (i = 0;  i < 4;  ++i, ++k)  /* perms within a group */
        !          1320:                       if (workspace[k])
        !          1321:                           *p++ = workspace[k];
        !          1322:                   *p++ = ',';                     /* group separator */
        !          1323:               }
        !          1324:               *--p = ' ';   /* overwrite last comma */
        !          1325:               if ((p - attribs) < 12)
        !          1326:                   sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
        !          1327:           }
        !          1328:           break;
        !          1329: 
        !          1330:       case DOS_OS2_FAT_:
        !          1331:       case OS2_HPFS_:
        !          1332:           xattr = (UWORD) (crec.external_file_attributes & 0xFF);
        !          1333:           sprintf(attribs, "%s,%s,%s,%s", (xattr&32)?"arc":"",
        !          1334:             (xattr&2)?"hid":"", (xattr&1)?"rdo":"rw", (xattr&4)?"sys":"");
        !          1335:           if ((k = strlen(attribs)) < 15)
        !          1336:               attribs[k] = ' ';   /* overwrite '\0' */
        !          1337:           if (k < 12)
        !          1338:               sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
        !          1339:           break;
        !          1340: 
        !          1341:       default:   /* assume Unix-like */
        !          1342:           switch (xattr & S_IFMT) {
        !          1343:               case S_IFREG:   attribs[0] = '-';  break;
        !          1344:               case S_IFLNK:   attribs[0] = 'l';  break;
        !          1345:               case S_IFBLK:   attribs[0] = 'b';  break;
        !          1346:               case S_IFCHR:   attribs[0] = 'c';  break;
        !          1347:               case S_IFIFO:   attribs[0] = 'p';  break;
        !          1348:               case S_IFSOCK:  attribs[0] = 's';  break;
        !          1349:               case S_IFDIR:   attribs[0] = 'd';  break;
        !          1350:               default:        attribs[0] = '?';  break;
        !          1351:           }
        !          1352:           if (xattr & S_IRUSR)        /* no read-permission: user */
        !          1353:               attribs[1] = 'r';
        !          1354:           else
        !          1355:               attribs[1] = '-';
        !          1356:           if (xattr & S_IWUSR)        /* no write-permission: user */
        !          1357:               attribs[2] = 'w';
        !          1358:           else
        !          1359:               attribs[2] = '-';
        !          1360:           if (xattr & S_IXUSR)        /* no execute-permission: user */
        !          1361:               if (xattr & S_ISUID)
        !          1362:                   attribs[3] = 's';
        !          1363:               else
        !          1364:                   attribs[3] = 'x';
        !          1365:           else
        !          1366:               if (xattr & S_ISUID)
        !          1367:                   attribs[3] = 'S';   /* undefined state */
        !          1368:               else
        !          1369:                   attribs[3] = '-';
        !          1370:           if (xattr & S_IRGRP)        /* no read-permission: group */
        !          1371:               attribs[4] = 'r';
        !          1372:           else
        !          1373:               attribs[4] = '-';
        !          1374:           if (xattr & S_IWGRP)        /* no write-permission: group */
        !          1375:               attribs[5] = 'w';
        !          1376:           else
        !          1377:               attribs[5] = '-';
        !          1378:           if (xattr & S_IXGRP)        /* no execute-permission: group */
        !          1379:               if (xattr & S_ISGID)
        !          1380:                   attribs[6] = 's';
        !          1381:               else
        !          1382:                   attribs[6] = 'x';
        !          1383:           else
        !          1384:               if (xattr & S_ISGID)    /* or could use S_ENFMT (same) */
        !          1385:                   attribs[6] = 'l';
        !          1386:               else
        !          1387:                   attribs[6] = '-';
        !          1388:           if (xattr & S_IROTH)        /* no read-permission: other */
        !          1389:               attribs[7] = 'r';
        !          1390:           else
        !          1391:               attribs[7] = '-';
        !          1392:           if (xattr & S_IWOTH)        /* no write-permission: other */
        !          1393:               attribs[8] = 'w';
        !          1394:           else
        !          1395:               attribs[8] = '-';
        !          1396:           if (xattr & S_IXOTH)        /* no execute-permission: other */
        !          1397:               if (xattr & S_ISVTX)    /* "sticky bit" */
        !          1398:                   attribs[9] = 't';
        !          1399:               else
        !          1400:                   attribs[9] = 'x';
        !          1401:           else
        !          1402:               if (xattr & S_ISVTX)
        !          1403:                   attribs[9] = 'T';   /* undefined state */
        !          1404:               else
        !          1405:                   attribs[9] = '-';
        !          1406:           sprintf(&attribs[12], "%d.%d", hostver/10, hostver%10);
        !          1407:           break;
        !          1408: 
        !          1409:     } /* end switch (hostnum: external attributes format) */
        !          1410: 
        !          1411:     printf("%s %s %7lu %c%c", attribs, os[hostnum], crec.uncompressed_size,
        !          1412:       (crec.general_purpose_bit_flag & 1)?
        !          1413:       ((crec.internal_file_attributes & 1)? 'T' : 'B') :   /* encrypted */
        !          1414:       ((crec.internal_file_attributes & 1)? 't' : 'b'),    /* plaintext */
        !          1415:       (crec.general_purpose_bit_flag & 8)? (crec.extra_field_length? 'X' : 'l')
        !          1416:                                         : (crec.extra_field_length? 'x' : '-'));
        !          1417:     if (lflag == 4) {
        !          1418:         longint c = (longint) crec.compressed_size;
        !          1419:         longint uc = (longint) crec.uncompressed_size;
        !          1420: 
        !          1421:         if (crec.general_purpose_bit_flag & 1)
        !          1422:             c -= 12;    /* if encrypted, don't count encryption header */
        !          1423:         /* risk signed overflow if blindly multiply: */
        !          1424:         printf("%3d%%", (uc==0)? 0 : ((uc>2000000L)?
        !          1425:           ((int)((uc-c)/(uc/1000L))+5)/10 : ((int)((1000L*(uc-c))/uc)+5)/10) );
        !          1426:     } else if (lflag == 5)
        !          1427:         printf(" %7lu", crec.compressed_size);
        !          1428: 
        !          1429:     printf(" %s %s %s\n", method[methnum],
        !          1430:       zipinfo_time(&crec.last_mod_file_date, &crec.last_mod_file_time),
        !          1431:       filename);
        !          1432: 
        !          1433: /*---------------------------------------------------------------------------
        !          1434:     Skip the extra field and/or the file comment, if any (the filename has
        !          1435:     already been printed, above).  That finishes up this file entry...
        !          1436:   ---------------------------------------------------------------------------*/
        !          1437: 
        !          1438:     SKIP_(crec.extra_field_length)
        !          1439:     SKIP_(crec.file_comment_length)
        !          1440: 
        !          1441:     return error_in_archive;
        !          1442: 
        !          1443: } /* end function short_info() */
        !          1444: 
        !          1445: 
        !          1446: 
        !          1447: 
        !          1448: 
        !          1449: /*****************************/
        !          1450: /*  Function zipinfo_time()  */
        !          1451: /*****************************/
        !          1452: 
        !          1453: char *zipinfo_time(datez, timez)
        !          1454:     UWORD   *datez, *timez;
        !          1455: {
        !          1456:     UWORD         yr, mo, dy, hh, mm, ss;
        !          1457:     static char   d_t_str[21];
        !          1458:     static char   *month[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
        !          1459:                                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
        !          1460: 
        !          1461: 
        !          1462: 
        !          1463: /*---------------------------------------------------------------------------
        !          1464:     Convert the file-modification date and time info to a string of the form 
        !          1465:     "23 Feb 1990 17:15:00" or "23-Feb-91 17:15," depending on value of lflag.
        !          1466:   ---------------------------------------------------------------------------*/
        !          1467: 
        !          1468:     yr = ((*datez >> 9) & 0x7f) + 80;     /* dissect date */
        !          1469:     mo = ((*datez >> 5) & 0x0f) - 1;
        !          1470:     dy = *datez & 0x1f;
        !          1471: 
        !          1472:     hh = (*timez >> 11) & 0x1f;           /* dissect time */
        !          1473:     mm = (*timez >> 5) & 0x3f;
        !          1474:     ss = (*timez & 0x1f) * 2;
        !          1475: 
        !          1476:     if ((lflag >= 3) && (lflag <= 5))
        !          1477:         sprintf(d_t_str, "%2u-%s-%u %02u:%02u", dy, month[mo], yr, hh, mm);
        !          1478:     else if (lflag > 9)  /* verbose listing format */
        !          1479:         sprintf(d_t_str, "%u %s %u %02u:%02u:%02u", dy, month[mo], yr+1900,
        !          1480:           hh, mm, ss);
        !          1481: 
        !          1482:     return d_t_str;
        !          1483: 
        !          1484: } /* end function zipinfo_time() */
        !          1485: 
        !          1486: 
        !          1487: 
        !          1488: 
        !          1489: 
        !          1490: /********************************/
        !          1491: /*  Function open_input_file()  */
        !          1492: /********************************/
        !          1493: 
        !          1494: int open_input_file()   /* return 1 if open failed */
        !          1495: {
        !          1496:     /*
        !          1497:      *  open the zipfile for reading and in BINARY mode to prevent cr/lf
        !          1498:      *  translation, which would corrupt the bitstreams
        !          1499:      */
        !          1500: 
        !          1501: #ifdef VMS
        !          1502:     zipfd = open(zipfn, O_RDONLY, 0, "ctx=stm");
        !          1503: #else /* !VMS */
        !          1504: #ifdef UNIX
        !          1505:     zipfd = open(zipfn, O_RDONLY);
        !          1506: #else /* !UNIX */
        !          1507: #ifdef MACOS
        !          1508:     zipfd = open(zipfn, 0);
        !          1509: #else /* !MACOS */
        !          1510:     zipfd = open(zipfn, O_RDONLY | O_BINARY);
        !          1511: #endif /* ?MACOS */
        !          1512: #endif /* ?UNIX */
        !          1513: #endif /* ?VMS */
        !          1514:     if (zipfd < 1) {
        !          1515:         fprintf(stderr, "error:  can't open zipfile [ %s ]\n", zipfn);
        !          1516:         return 1;
        !          1517:     }
        !          1518:     return 0;
        !          1519: 
        !          1520: } /* end function open_input_file() */
        !          1521: 
        !          1522: 
        !          1523: 
        !          1524: 
        !          1525: 
        !          1526: /************************/
        !          1527: /*  Function readbuf()  */
        !          1528: /************************/
        !          1529: 
        !          1530: int readbuf(buf, size)   /* return number of bytes read into buf */
        !          1531:     char *buf;
        !          1532:     register unsigned size;
        !          1533: {
        !          1534:     register int count;
        !          1535:     int n;
        !          1536: 
        !          1537:     n = size;
        !          1538:     while (size) {
        !          1539:         if (incnt == 0) {
        !          1540:             if ((incnt = read(zipfd, inbuf, INBUFSIZ)) <= 0)
        !          1541:                 return (n-size);
        !          1542:             /* buffer ALWAYS starts on a block boundary:  */
        !          1543:             cur_zipfile_bufstart += INBUFSIZ;
        !          1544:             inptr = inbuf;
        !          1545:         }
        !          1546:         count = MIN(size, (unsigned)incnt);
        !          1547:         memcpy(buf, inptr, count);
        !          1548:         buf += count;
        !          1549:         inptr += count;
        !          1550:         incnt -= count;
        !          1551:         size -= count;
        !          1552:     }
        !          1553:     return n;
        !          1554: 
        !          1555: } /* end function readbuf() */

unix.superglobalmegacorp.com

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