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

1.1     ! root        1: /*---------------------------------------------------------------------------
        !             2: 
        !             3:   extract.c
        !             4: 
        !             5:   This file contains the high-level routines ("driver routines") for extrac-
        !             6:   ting and testing zipfile members.  It calls the low-level routines in files
        !             7:   explode.c, inflate.c, unreduce.c and unshrink.c.
        !             8: 
        !             9:   ---------------------------------------------------------------------------*/
        !            10: 
        !            11: 
        !            12: #include "unzip.h"
        !            13: #ifdef  MSWIN
        !            14: #  include "wizunzip.h"
        !            15: #  include "replace.h"
        !            16: #endif /* MSWIN */
        !            17: 
        !            18: 
        !            19: /************************************/
        !            20: /*  Extract Local Prototypes, etc.  */
        !            21: /************************************/
        !            22: 
        !            23: static int store_info __((void));
        !            24: static int extract_or_test_member __((void));
        !            25: #ifdef CRYPT
        !            26:    static int decrypt_member __((void));
        !            27:    static int testp __((byte *hdr));
        !            28: #endif
        !            29: 
        !            30: static byte *mem_i_buffer;
        !            31: static byte *mem_o_buffer;
        !            32: static ULONG mem_i_size, mem_i_offset;
        !            33: static ULONG mem_o_size, mem_o_offset;
        !            34: 
        !            35: static char *VersionMsg =
        !            36:   " skipping: %-22s  need %s compat. v%u.%u (can do v%u.%u)\n";
        !            37: static char *ComprMsg =
        !            38:   " skipping: %-22s  compression method %d\n";
        !            39: static char *FilNamMsg =
        !            40:   "%s:  bad filename length (%s)\n";
        !            41: static char *ExtFieldMsg =
        !            42:   "%s:  bad extra field length (%s)\n";
        !            43: static char *OffsetMsg =
        !            44:   "file #%d:  bad zipfile offset (%s)\n";
        !            45: 
        !            46: 
        !            47: 
        !            48: 
        !            49: 
        !            50: /**************************************/
        !            51: /*  Function extract_or_test_files()  */
        !            52: /**************************************/
        !            53: 
        !            54: int extract_or_test_files()    /* return PK-type error code */
        !            55: {
        !            56:     char **fnamev;
        !            57:     byte *cd_inptr;
        !            58:     int cd_incnt, error, error_in_archive=0;
        !            59:     int renamed, query, len, filnum=(-1), blknum=0;
        !            60: #ifdef OS2
        !            61:     extern int longname;  /* from os2unzip.c */
        !            62: #endif
        !            63:     UWORD i, j, members_remaining, num_skipped=0, num_bad_pwd=0;
        !            64:     longint cd_bufstart, bufstart, inbuf_offset, request;
        !            65:     min_info info[DIR_BLKSIZ];
        !            66: 
        !            67: 
        !            68: /*---------------------------------------------------------------------------
        !            69:     The basic idea of this function is as follows.  Since the central di-
        !            70:     rectory lies at the end of the zipfile and the member files lie at the
        !            71:     beginning or middle or wherever, it is not very desirable to simply
        !            72:     read a central directory entry, jump to the member and extract it, and
        !            73:     then jump back to the central directory.  In the case of a large zipfile
        !            74:     this would lead to a whole lot of disk-grinding, especially if each mem-
        !            75:     ber file is small.  Instead, we read from the central directory the per-
        !            76:     tinent information for a block of files, then go extract/test the whole
        !            77:     block.  Thus this routine contains two small(er) loops within a very
        !            78:     large outer loop:  the first of the small ones reads a block of files
        !            79:     from the central directory; the second extracts or tests each file; and
        !            80:     the outer one loops over blocks.  There's some file-pointer positioning
        !            81:     stuff in between, but that's about it.  Btw, it's because of this jump-
        !            82:     ing around that we can afford to be lenient if an error occurs in one of
        !            83:     the member files:  we should still be able to go find the other members,
        !            84:     since we know the offset of each from the beginning of the zipfile.
        !            85: 
        !            86:     Begin main loop over blocks of member files.  We know the entire central
        !            87:     directory is on this disk:  we would not have any of this information un-
        !            88:     less the end-of-central-directory record was on this disk, and we would
        !            89:     not have gotten to this routine unless this is also the disk on which
        !            90:     the central directory starts.  In practice, this had better be the ONLY
        !            91:     disk in the archive, but maybe someday we'll add multi-disk support.
        !            92:   ---------------------------------------------------------------------------*/
        !            93: 
        !            94:     pInfo = info;
        !            95:     members_remaining = ecrec.total_entries_central_dir;
        !            96: 
        !            97:     while (members_remaining) {
        !            98:         j = 0;
        !            99: 
        !           100:         /*
        !           101:          * Loop through files in central directory, storing offsets, file
        !           102:          * attributes, and case-conversion flags until block size is reached.
        !           103:          */
        !           104: 
        !           105:         while (members_remaining && (j < DIR_BLKSIZ)) {
        !           106:             --members_remaining;
        !           107:             pInfo = &info[j];
        !           108: 
        !           109:             if (readbuf(sig, 4) <= 0) {
        !           110:                 error_in_archive = 51;  /* 51:  unexpected EOF */
        !           111:                 members_remaining = 0;  /* ...so no more left to do */
        !           112:                 break;
        !           113:             }
        !           114:             if (strncmp(sig, central_hdr_sig, 4)) {  /* just to make sure */
        !           115:                 fprintf(stderr, CentSigMsg, j);  /* sig not found */
        !           116:                 fprintf(stderr, ReportMsg);   /* check binary transfers */
        !           117:                 error_in_archive = 3;   /* 3:  error in zipfile */
        !           118:                 members_remaining = 0;  /* ...so no more left to do */
        !           119:                 break;
        !           120:             }
        !           121:             /* process_cdir_file_hdr() sets pInfo->hostnum, pInfo->lcflag */
        !           122:             if ((error = process_cdir_file_hdr()) != 0) {
        !           123:                 error_in_archive = error;   /* only 51 (EOF) defined */
        !           124:                 members_remaining = 0;  /* ...so no more left to do */
        !           125:                 break;
        !           126:             }
        !           127:             if ((error = do_string(crec.filename_length, FILENAME)) != 0) {
        !           128:                 if (error > error_in_archive)
        !           129:                     error_in_archive = error;
        !           130:                 if (error > 1) {  /* fatal:  no more left to do */
        !           131:                     fprintf(stderr, FilNamMsg, filename, "central");
        !           132:                     members_remaining = 0;
        !           133:                     break;
        !           134:                 }
        !           135:             }
        !           136:             if ((error = do_string(crec.extra_field_length, EXTRA_FIELD)) != 0)
        !           137:             {
        !           138:                 if (error > error_in_archive)
        !           139:                     error_in_archive = error;
        !           140:                 if (error > 1) {  /* fatal */
        !           141:                     fprintf(stderr, ExtFieldMsg, filename, "central");
        !           142:                     members_remaining = 0;
        !           143:                     break;
        !           144:                 }
        !           145:             }
        !           146:             if ((error = do_string(crec.file_comment_length, SKIP)) != 0) {
        !           147:                 if (error > error_in_archive)
        !           148:                     error_in_archive = error;
        !           149:                 if (error > 1) {  /* fatal */
        !           150:                     fprintf(stderr, "\n%s:  bad file comment length\n",
        !           151:                             filename);
        !           152:                     members_remaining = 0;
        !           153:                     break;
        !           154:                 }
        !           155:             }
        !           156:             if (process_all_files) {
        !           157:                 if (store_info())
        !           158:                     ++num_skipped;
        !           159:                 else
        !           160:                     ++j;  /* file is OK: save info[] and continue with next */
        !           161:             } else {
        !           162:                 fnamev = fnv;   /* don't destroy permanent filename pointer */
        !           163:                 for (--fnamev; *++fnamev;)
        !           164:                     if (match(filename, *fnamev)) {
        !           165:                         if (store_info())
        !           166:                             ++num_skipped;
        !           167:                         else
        !           168:                             ++j;   /* file is OK */
        !           169:                         break;  /* found match for filename, so stop looping */
        !           170:                     } /* end if (match), for-loop (fnamev) */
        !           171:             } /* end if (process_all_files) */
        !           172: 
        !           173:         } /* end while-loop (adding files to current block) */
        !           174: 
        !           175:         /* save position in central directory so can come back later */
        !           176:         cd_bufstart = cur_zipfile_bufstart;
        !           177:         cd_inptr = inptr;
        !           178:         cd_incnt = incnt;
        !           179: 
        !           180:     /*-----------------------------------------------------------------------
        !           181:         Second loop:  process files in current block, extracting or testing
        !           182:         each one.
        !           183:       -----------------------------------------------------------------------*/
        !           184: 
        !           185:         for (i = 0; i < j; ++i) {
        !           186:             filnum = i + blknum*DIR_BLKSIZ;
        !           187:             pInfo = &info[i];
        !           188:             /*
        !           189:              * if the target position is not within the current input buffer
        !           190:              * (either haven't yet read far enough, or (maybe) skipping back-
        !           191:              * ward) skip to the target position and reset readbuf().
        !           192:              */
        !           193:             /* LSEEK(pInfo->offset):  */
        !           194:             request = pInfo->offset + extra_bytes;
        !           195:             inbuf_offset = request % INBUFSIZ;
        !           196:             bufstart = request - inbuf_offset;
        !           197: 
        !           198:             if (request < 0) {
        !           199:                 fprintf(stderr, SeekMsg, ReportMsg);
        !           200:                 error_in_archive = 3;       /* 3:  severe error in zipfile, */
        !           201:                 continue;                   /*  but can still go on */
        !           202:             } else if (bufstart != cur_zipfile_bufstart) {
        !           203:                 cur_zipfile_bufstart = lseek(zipfd, bufstart, SEEK_SET);
        !           204:                 if ((incnt = read(zipfd,(char *)inbuf,INBUFSIZ)) <= 0) {
        !           205:                     fprintf(stderr, OffsetMsg, filnum, "lseek");
        !           206:                     error_in_archive = 3;   /* 3:  error in zipfile, but */
        !           207:                     continue;               /*  can still do next file   */
        !           208:                 }
        !           209:                 inptr = inbuf + (int)inbuf_offset;
        !           210:                 incnt -= (int)inbuf_offset;
        !           211:             } else {
        !           212:                 incnt += (inptr-inbuf) - (int)inbuf_offset;
        !           213:                 inptr = inbuf + (int)inbuf_offset;
        !           214:             }
        !           215: 
        !           216:             /* should be in proper position now, so check for sig */
        !           217:             if (readbuf(sig, 4) <= 0) {  /* bad offset */
        !           218:                 fprintf(stderr, OffsetMsg, filnum, "EOF");
        !           219:                 error_in_archive = 3;    /* 3:  error in zipfile */
        !           220:                 continue;       /* but can still try next one */
        !           221:             }
        !           222:             if (strncmp(sig, local_hdr_sig, 4)) {
        !           223:                 fprintf(stderr, OffsetMsg, filnum,
        !           224:                         "can't find local header sig");   /* bad offset */
        !           225:                 error_in_archive = 3;
        !           226:                 continue;
        !           227:             }
        !           228:             if ((error = process_local_file_hdr()) != 0) {
        !           229:                 fprintf(stderr, "\nfile #%d:  bad local header\n", filnum);
        !           230:                 error_in_archive = error;       /* only 51 (EOF) defined */
        !           231:                 continue;       /* can still try next one */
        !           232:             }
        !           233:             if ((error = do_string(lrec.filename_length, FILENAME)) != 0) {
        !           234:                 if (error > error_in_archive)
        !           235:                     error_in_archive = error;
        !           236:                 if (error > 1) {
        !           237:                     fprintf(stderr, FilNamMsg, filename, "local");
        !           238:                     continue;   /* go on to next one */
        !           239:                 }
        !           240:             }
        !           241:             if (extra_field != (byte *)NULL)
        !           242:                 free(extra_field);
        !           243:             extra_field = (byte *)NULL;
        !           244:             if ((error = do_string(lrec.extra_field_length, EXTRA_FIELD)) != 0)
        !           245:             {
        !           246:                 if (error > error_in_archive)
        !           247:                     error_in_archive = error;
        !           248:                 if (error > 1) {
        !           249:                     fprintf(stderr, ExtFieldMsg, filename, "local");
        !           250:                     continue;   /* go on */
        !           251:                 }
        !           252:             }
        !           253: 
        !           254:             /*
        !           255:              * just about to extract file:  if extracting to disk, check if
        !           256:              * already exists, and if so, take appropriate action according to
        !           257:              * fflag/uflag/overwrite_all/etc. (we couldn't do this in upper
        !           258:              * loop because we don't store the possibly renamed filename[] in
        !           259:              * info[])
        !           260:              */
        !           261:             if (!tflag && !cflag) {
        !           262:                 renamed = FALSE;   /* user hasn't renamed output file yet */
        !           263: #ifdef OS2
        !           264:                 longname = FALSE;  /* no long name has yet been stored */
        !           265: #endif
        !           266: 
        !           267: startover:
        !           268:                 query = FALSE;
        !           269: #ifdef MACOS
        !           270:                 macflag = (pInfo->hostnum == MAC_);
        !           271: #endif
        !           272:                 /* mapname can create dirs if not freshening or if renamed */
        !           273:                 if ((error = mapname(!fflag || renamed)) > 1) {    /* skip */
        !           274:                     if ((error > 2) && (error_in_archive < 2))
        !           275:                         error_in_archive = 2;   /* (weak) error in zipfile */
        !           276:                     continue;   /* go on to next file */
        !           277:                 }
        !           278: 
        !           279:                 switch (check_for_newer(filename)) {
        !           280:                     case DOES_NOT_EXIST:
        !           281:                         if (fflag && !renamed)  /* don't skip if just renamed */
        !           282:                             continue;   /* freshen (no new files):  skip */
        !           283:                         break;
        !           284:                     case EXISTS_AND_OLDER:
        !           285:                         if (overwrite_none)
        !           286:                             continue;   /* never overwrite:  skip file */
        !           287:                         if (!overwrite_all && !force_flag)
        !           288:                             query = TRUE;
        !           289:                         break;
        !           290:                     case EXISTS_AND_NEWER:             /* (or equal) */
        !           291:                         if (overwrite_none || (uflag && !renamed))
        !           292:                             continue;  /* skip if update/freshen & orig name */
        !           293:                         if (!overwrite_all && !force_flag)
        !           294:                             query = TRUE;
        !           295:                         break;
        !           296:                 }
        !           297: /*#ifndef VMS*/ /* VMS creates higher version number instead of overwriting
        !           298:                  * (will have to modify for VMS-style names with specific
        !           299:                  *  version numbers:  just check V_flag?  don't use stat?) */
        !           300:                 if (query) {
        !           301: #ifdef MSWIN
        !           302:                     FARPROC lpfnprocReplace;
        !           303:                     int ReplaceDlgRetVal;   /* replace dialog return value */
        !           304: 
        !           305:                     ShowCursor(FALSE);      /* turn off cursor */
        !           306:                     SetCursor(hSaveCursor); /* restore the cursor */
        !           307:                     lpfnprocReplace = MakeProcInstance(ReplaceProc, hInst);
        !           308:                     ReplaceDlgRetVal = DialogBoxParam(hInst, "Replace",
        !           309:                       hWndMain, lpfnprocReplace, (DWORD)(LPSTR)filename);
        !           310:                     FreeProcInstance(lpfnprocReplace);
        !           311:                     hSaveCursor = SetCursor(hHourGlass);
        !           312:                     ShowCursor(TRUE);
        !           313:                     switch (ReplaceDlgRetVal) {
        !           314:                         case IDM_REPLACE_RENAME:
        !           315:                             renamed = TRUE;
        !           316:                             goto startover;   /* sorry for a goto */
        !           317:                         case IDM_REPLACE_YES:
        !           318:                             break;
        !           319:                         case IDM_REPLACE_ALL:
        !           320:                             overwrite_all = TRUE;
        !           321:                             overwrite_none = FALSE;  /* just to make sure */
        !           322:                             break;
        !           323:                         case IDM_REPLACE_NONE:
        !           324:                             overwrite_none = TRUE;
        !           325:                             overwrite_all = FALSE;  /* make sure */
        !           326:                             force_flag = FALSE;     /* ditto */
        !           327:                             /* FALL THROUGH, skip */
        !           328:                         case IDM_REPLACE_NO:
        !           329:                             continue;
        !           330:                     }
        !           331: #else /* !MSWIN */
        !           332: reprompt:
        !           333:                     fprintf(stderr,
        !           334:                       "replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ",
        !           335:                       filename);
        !           336:                     FFLUSH   /* for Amiga and Mac MPW */
        !           337:                     fgets(answerbuf, 9, stdin);
        !           338:                     switch (*answerbuf) {
        !           339:                         case 'A':   /* dangerous option:  force caps */
        !           340:                             overwrite_all = TRUE;
        !           341:                             overwrite_none = FALSE;  /* just to make sure */
        !           342:                             break;
        !           343:                         case 'r':
        !           344:                         case 'R':
        !           345:                             do {
        !           346:                                 fprintf(stderr, "new name: ");
        !           347:                                 FFLUSH   /* for AMIGA and Mac MPW */
        !           348:                                 fgets(filename, FILNAMSIZ, stdin);
        !           349:                                 /* usually get \n here:  better check for it */
        !           350:                                 len = strlen(filename);
        !           351:                                 if (filename[len-1] == '\n')
        !           352:                                     filename[--len] = 0;
        !           353:                             } while (len == 0);
        !           354:                             renamed = TRUE;
        !           355:                             goto startover;   /* sorry for a goto */
        !           356:                         case 'y':
        !           357:                         case 'Y':
        !           358:                             break;
        !           359:                         case 'N':
        !           360:                             overwrite_none = TRUE;
        !           361:                             overwrite_all = FALSE;  /* make sure */
        !           362:                             force_flag = FALSE;     /* ditto */
        !           363:                             /* FALL THROUGH, skip */
        !           364:                         case 'n':
        !           365:                             continue;   /* skip file */
        !           366:                         default:
        !           367:                             fprintf(stderr, "error:  invalid response [%c]\n",
        !           368:                               *answerbuf);   /* warn the user */
        !           369:                             goto reprompt;   /* why not another goto? */
        !           370:                     } /* end switch (*answerbuf) */
        !           371: #endif /* ?MSWIN */
        !           372:                 } /* end if (query) */
        !           373: /*#endif*/ /* !VMS */
        !           374:             } /* end if (extracting to disk) */
        !           375: 
        !           376: #ifdef CRYPT
        !           377:             if (pInfo->encrypted && ((error = decrypt_member()) != 0)) {
        !           378:                 if (error == 10) {
        !           379:                     if (error > error_in_archive)
        !           380:                         error_in_archive = error;
        !           381:                     fprintf(stderr,
        !           382:                       " skipping: %-22s  unable to get password\n", filename);
        !           383:                 } else {  /* (error == 1) */
        !           384:                     fprintf(stderr,
        !           385:                       " skipping: %-22s  incorrect password\n", filename);
        !           386:                     ++num_bad_pwd;
        !           387:                 }
        !           388:                 continue;   /* go on to next file */
        !           389:             }
        !           390: #endif /* CRYPT */
        !           391:             disk_full = 0;
        !           392:             if ((error = extract_or_test_member()) != 0) {
        !           393:                 if (error > error_in_archive)
        !           394:                     error_in_archive = error;       /* ...and keep going */
        !           395:                 if (disk_full > 1)
        !           396:                     return error_in_archive;        /* (unless disk full) */
        !           397:             }
        !           398:         } /* end for-loop (i:  files in current block) */
        !           399: 
        !           400: 
        !           401:         /*
        !           402:          * Jump back to where we were in the central directory, then go and do
        !           403:          * the next batch of files.
        !           404:          */
        !           405: 
        !           406:         cur_zipfile_bufstart = lseek(zipfd, cd_bufstart, SEEK_SET);
        !           407:         read(zipfd, (char *)inbuf, INBUFSIZ);  /* were there b4 ==> no error */
        !           408:         inptr = cd_inptr;
        !           409:         incnt = cd_incnt;
        !           410:         ++blknum;
        !           411: 
        !           412: #ifdef TEST
        !           413:         printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
        !           414:         printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
        !           415:           cur_zipfile_bufstart);
        !           416:         printf("inptr-inbuf = %d\n", inptr-inbuf);
        !           417:         printf("incnt = %d\n\n", incnt);
        !           418: #endif
        !           419: 
        !           420:     } /* end while-loop (blocks of files in central directory) */
        !           421: 
        !           422: /*---------------------------------------------------------------------------
        !           423:     Double-check that we're back at the end-of-central-directory record, and
        !           424:     print quick summary of results, if we were just testing the archive.  We
        !           425:     send the summary to stdout so that people doing the testing in the back-
        !           426:     ground and redirecting to a file can just do a "tail" on the output file.
        !           427:   ---------------------------------------------------------------------------*/
        !           428: 
        !           429:     readbuf(sig, 4);
        !           430:     if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
        !           431:         fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
        !           432:         fprintf(stderr, ReportMsg);  /* check binary transfers */
        !           433:         if (!error_in_archive)       /* don't overwrite stronger error */
        !           434:             error_in_archive = 1;    /* 1:  warning error */
        !           435:     }
        !           436:     if (tflag && (quietflg == 1)) {
        !           437:         int num=filnum+1 - num_bad_pwd;
        !           438: 
        !           439:         if (error_in_archive)
        !           440:             printf("At least one error was detected in %s.\n", zipfn);
        !           441:         else if (num == 0)
        !           442:             printf("Caution:  zero files tested in %s.\n", zipfn);
        !           443:         else if (process_all_files && (num_skipped+num_bad_pwd == 0))
        !           444:             printf("No errors detected in %s.\n", zipfn);
        !           445:         else
        !           446:             printf("No errors detected in %s for the %d file%s tested.\n",
        !           447:               zipfn, num, (num==1)? "":"s");
        !           448:         if (num_skipped > 0)
        !           449:             printf("%d file%s skipped because of unsupported compression or\
        !           450:  encoding.\n",
        !           451:               num_skipped, (num_skipped==1)? "":"s");
        !           452: #ifdef CRYPT
        !           453:         if (num_bad_pwd > 0)
        !           454:             printf("%d file%s skipped because of incorrect password.\n",
        !           455:               num_bad_pwd, (num_bad_pwd==1)? "":"s");
        !           456: #endif /* CRYPT */
        !           457:     }
        !           458:     if ((num_skipped > 0) && !error_in_archive)   /* files not tested or  */
        !           459:         error_in_archive = 1;                     /*  extracted:  warning */
        !           460: #ifdef CRYPT
        !           461:     if ((num_bad_pwd > 0) && !error_in_archive)   /* files not tested or  */
        !           462:         error_in_archive = 1;                     /*  extracted:  warning */
        !           463: #endif /* CRYPT */
        !           464: 
        !           465:     return (error_in_archive);
        !           466: 
        !           467: } /* end function extract_or_test_files() */
        !           468: 
        !           469: 
        !           470: 
        !           471: 
        !           472: 
        !           473: /***************************/
        !           474: /*  Function store_info()  */
        !           475: /***************************/
        !           476: 
        !           477: static int store_info()   /* return 1 if skipping, 0 if OK */
        !           478: {
        !           479:     ULONG tmp;
        !           480: 
        !           481: #define UNKN_COMPR \
        !           482:    (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
        !           483: #if 0  /* old */
        !           484: #  define UNKN_COMPR   (crec.compression_method>IMPLODED)
        !           485: #endif
        !           486: 
        !           487: 
        !           488: /*---------------------------------------------------------------------------
        !           489:     Check central directory info for version/compatibility requirements.
        !           490:   ---------------------------------------------------------------------------*/
        !           491: 
        !           492:     pInfo->encrypted = crec.general_purpose_bit_flag & 1;    /* bit field */
        !           493:     pInfo->ExtLocHdr = (crec.general_purpose_bit_flag & 8) == 8;  /* bit */
        !           494:     pInfo->text = crec.internal_file_attributes & 1;         /* bit field */
        !           495:     pInfo->crc = crec.crc32;
        !           496:     pInfo->compr_size = crec.compressed_size;
        !           497: 
        !           498:     if (crec.version_needed_to_extract[1] == VMS_) {
        !           499:         if (crec.version_needed_to_extract[0] > VMS_VERSION) {
        !           500:             fprintf(stderr, VersionMsg, filename, "VMS",
        !           501:               crec.version_needed_to_extract[0] / 10,
        !           502:               crec.version_needed_to_extract[0] % 10,
        !           503:               VMS_VERSION / 10, VMS_VERSION % 10);
        !           504:             return 1;
        !           505:         }
        !           506: #ifndef VMS   /* won't be able to use extra field, but still have data */
        !           507:         else if (!tflag && !force_flag) {  /* if forcing, extract regardless */
        !           508:             fprintf(stderr,
        !           509:               "\n%s:  stored in VMS format.  Extract anyway? (y/n) ",
        !           510:               filename);
        !           511:             FFLUSH   /* for Amiga and Mac MPW */
        !           512:             fgets(answerbuf, 9, stdin);
        !           513:             if ((*answerbuf != 'y') && (*answerbuf != 'Y'))
        !           514:                 return 1;
        !           515:         }
        !           516: #endif /* !VMS */
        !           517:     /* usual file type:  don't need VMS to extract */
        !           518:     } else if (crec.version_needed_to_extract[0] > UNZIP_VERSION) {
        !           519:         fprintf(stderr, VersionMsg, filename, "PK",
        !           520:           crec.version_needed_to_extract[0] / 10,
        !           521:           crec.version_needed_to_extract[0] % 10,
        !           522:           UNZIP_VERSION / 10, UNZIP_VERSION % 10);
        !           523:         return 1;
        !           524:     }
        !           525: 
        !           526:     if UNKN_COMPR {
        !           527:         fprintf(stderr, ComprMsg, filename, crec.compression_method);
        !           528:         return 1;
        !           529:     }
        !           530: #ifndef CRYPT
        !           531:     if (pInfo->encrypted) {
        !           532:         fprintf(stderr, " skipping: %-22s  encrypted (not supported)\n",
        !           533:           filename);
        !           534:         return 1;
        !           535:     }
        !           536: #endif /* !CRYPT */
        !           537: 
        !           538: /*---------------------------------------------------------------------------
        !           539:     Store some central-directory information (encryption, file attributes,
        !           540:     offsets) for later use.
        !           541:   ---------------------------------------------------------------------------*/
        !           542: 
        !           543:     tmp = crec.external_file_attributes;
        !           544: 
        !           545:     pInfo->dos_attr = 32;   /* set archive bit:  file is not backed up */
        !           546:     switch (pInfo->hostnum) {
        !           547:         case UNIX_:
        !           548:         case VMS_:
        !           549:             pInfo->unix_attr = (unsigned) (tmp >> 16);
        !           550:             break;
        !           551:         case DOS_OS2_FAT_:
        !           552:         case OS2_HPFS_:
        !           553:             pInfo->dos_attr = (unsigned) tmp;
        !           554:             tmp = (!(tmp & 1)) << 1;   /* read-only bit */
        !           555:             pInfo->unix_attr = (unsigned) (0444 | (tmp<<6) | (tmp<<3) | tmp);
        !           556: #ifdef UNIX
        !           557:             umask( (int)(tmp=umask(0)) );
        !           558:             pInfo->unix_attr &= ~tmp;
        !           559: #endif
        !           560:             break;
        !           561:         case MAC_:
        !           562:             pInfo->unix_attr = (unsigned) (tmp & 1);   /* read-only bit */
        !           563:             break;
        !           564:         default:
        !           565:             pInfo->unix_attr = 0666;
        !           566:             break;
        !           567:     } /* end switch (host-OS-created-by) */
        !           568: 
        !           569:     pInfo->offset = (longint) crec.relative_offset_local_header;
        !           570:     return 0;
        !           571: 
        !           572: } /* end function store_info() */
        !           573: 
        !           574: 
        !           575: 
        !           576: 
        !           577: 
        !           578: /***************************************/
        !           579: /*  Function extract_or_test_member()  */
        !           580: /***************************************/
        !           581: 
        !           582: static int extract_or_test_member()    /* return PK-type error code */
        !           583: {
        !           584: #ifdef S_IFLNK
        !           585:     int symlnk=FALSE;
        !           586: #endif /* S_IFLNK */
        !           587:     int r, error=0;
        !           588:     UWORD b;
        !           589: 
        !           590: 
        !           591: 
        !           592: /*---------------------------------------------------------------------------
        !           593:     Initialize variables, buffers, etc.
        !           594:   ---------------------------------------------------------------------------*/
        !           595: 
        !           596:     bits_left = 0;
        !           597:     bitbuf = 0L;
        !           598:     outpos = 0L;
        !           599:     outcnt = 0;
        !           600:     outptr = outbuf;
        !           601:     zipeof = 0;
        !           602:     crc32val = 0xFFFFFFFFL;
        !           603: 
        !           604: #ifdef S_IFLNK
        !           605:     if ((pInfo->unix_attr & S_IFMT) == S_IFLNK  &&  (pInfo->hostnum == UNIX_)
        !           606:         && !tflag && !cflag)
        !           607:         symlnk = TRUE;
        !           608: #endif /* S_IFLNK */
        !           609: 
        !           610:     memset(outbuf, 0xaa, OUTBUFSIZ);
        !           611: #if (!defined(DOS_OS2) || defined(MSWIN))
        !           612:     if (aflag)                  /* if we have a scratchpad, clear it out */
        !           613: #ifdef MSWIN
        !           614:         _fmemset(outout, 0xaa, OUTBUFSIZ);
        !           615: #else /* !MSWIN */
        !           616:         memset(outout, 0xaa, OUTBUFSIZ);
        !           617: #endif /* ?MSWIN */
        !           618: #endif /* !DOS_OS2 || MSWIN */
        !           619: 
        !           620:     if (tflag) {
        !           621:         if (!quietflg) {
        !           622:             fprintf(stdout, "  Testing: %-22s ", filename);
        !           623:             fflush(stdout);
        !           624:         }
        !           625:     } else {
        !           626:         if (cflag) {            /* output to stdout (copy of it) */
        !           627: #if (defined(MACOS) || defined(AMIGA))
        !           628:             outfd = 1;
        !           629: #else /* !(MACOS || AMIGA) */
        !           630:             outfd = dup(1);     /* GRR: change this to #define for Mac/Amiga */
        !           631: #endif /* ?(MACOS || AMIGA) */
        !           632: #ifdef DOS_OS2
        !           633:             if (!aflag)
        !           634:                 setmode(outfd, O_BINARY);
        !           635: #endif /* DOS_OS2 */
        !           636: #ifdef VMS
        !           637:             if (create_output_file())   /* VMS version required for stdout! */
        !           638:                 return 50;      /* 50:  disk full (?) */
        !           639: #endif
        !           640:         } else
        !           641: #ifdef S_IFLNK
        !           642:         if (!symlnk)    /* symlink() takes care of file creation */
        !           643: #endif /* !S_IFLNK */
        !           644:         {
        !           645:             if (create_output_file())
        !           646:                 return 50;      /* 50:  disk full (?) */
        !           647:         }
        !           648:     } /* endif (!tflag) */
        !           649: 
        !           650: /*---------------------------------------------------------------------------
        !           651:     Unpack the file.
        !           652:   ---------------------------------------------------------------------------*/
        !           653: 
        !           654:     switch (lrec.compression_method) {
        !           655: 
        !           656:     case STORED:
        !           657:         if (!tflag && (quietflg < 2)) {
        !           658:             fprintf(stdout, " Extracting: %-22s ", filename);
        !           659:             if (cflag)
        !           660:                 fprintf(stdout, "\n");
        !           661:             fflush(stdout);
        !           662:         }
        !           663: #ifdef S_IFLNK
        !           664:         /*
        !           665:          * If file came from Unix and is a symbolic link and we are extracting
        !           666:          * to disk, allocate a storage area, put the data in it, and create the
        !           667:          * link.  Since we know it's a symbolic link to start with, shouldn't
        !           668:          * have to worry about overflowing unsigned ints with unsigned longs.
        !           669:          * (This doesn't do anything for compressed symlinks, but that can be
        !           670:          * added later...it also doesn't set the time or permissions of the
        !           671:          * link, but does anyone really care?)
        !           672:          */
        !           673:         if (symlnk) {
        !           674: #if (defined(MTS) || defined(MACOS))
        !           675:             fprintf(stdout, "\n  warning:  symbolic link ignored\n");
        !           676:             error = 1;          /* 1:  warning error */
        !           677: #else /* !(MTS || MACOS) */
        !           678:             char *orig = (char *)malloc((unsigned)lrec.uncompressed_size+1);
        !           679:             char *p = orig;
        !           680: 
        !           681:             while (ReadByte(&b))
        !           682:                 *p++ = b;
        !           683:             *p = 0;   /* terminate string */
        !           684:             UpdateCRC((unsigned char *)orig, p-orig);
        !           685:             if (symlink(orig, filename))
        !           686:                 if ((errno == EEXIST) && overwrite_all) {  /* OK to overwrite */
        !           687:                     unlink(filename);
        !           688:                     if (symlink(orig, filename))
        !           689:                         perror("symlink error");
        !           690:                 } else
        !           691:                     perror("symlink error");
        !           692:             free(orig);
        !           693: #endif /* ?(MTS || MACOS) */
        !           694:         } else
        !           695: #endif /* S_IFLNK */
        !           696:         while (ReadByte(&b) && !disk_full)
        !           697:             OUTB(b)
        !           698:         break;
        !           699: 
        !           700:     case SHRUNK:
        !           701:         if (!tflag && (quietflg < 2)) {
        !           702:             fprintf(stdout, "UnShrinking: %-22s ", filename);
        !           703:             if (cflag)
        !           704:                 fprintf(stdout, "\n");
        !           705:             fflush(stdout);
        !           706:         }
        !           707: #ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
        !           708:         if (symlnk) {
        !           709:             fprintf(stdout, "\n  warning:  symbolic link ignored\n");
        !           710:             error = 1;          /* 1:  warning error */
        !           711:         }
        !           712: #endif /* S_IFLNK */
        !           713:         unShrink();
        !           714:         break;
        !           715: 
        !           716:     case REDUCED1:
        !           717:     case REDUCED2:
        !           718:     case REDUCED3:
        !           719:     case REDUCED4:
        !           720:         if (!tflag && (quietflg < 2)) {
        !           721:             fprintf(stdout, "  Expanding: %-22s ", filename);
        !           722:             if (cflag)
        !           723:                 fprintf(stdout, "\n");
        !           724:             fflush(stdout);
        !           725:         }
        !           726: #ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
        !           727:         if (symlnk) {
        !           728:             fprintf(stdout, "\n  warning:  symbolic link ignored\n");
        !           729:             error = 1;          /* 1:  warning error */
        !           730:         }
        !           731: #endif /* S_IFLNK */
        !           732:         unReduce();
        !           733:         break;
        !           734: 
        !           735:     case IMPLODED:
        !           736:         if (!tflag && (quietflg < 2)) {
        !           737:             fprintf(stdout, "  Exploding: %-22s ", filename);
        !           738:             if (cflag)
        !           739:                 fprintf(stdout, "\n");
        !           740:             fflush(stdout);
        !           741:         }
        !           742: #ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
        !           743:         if (symlnk) {
        !           744:             fprintf(stdout, "\n  warning:  symbolic link ignored\n");
        !           745:             error = 1;          /* 1:  warning error */
        !           746:         }
        !           747: #endif /* S_IFLNK */
        !           748:         if (((r = explode()) != 0) && (r != 5)) {   /* ignore 5 if seekable */
        !           749:             if ((tflag && quietflg) || (!tflag && (quietflg > 1)))
        !           750:                 fprintf(stderr, "  error:  %s%s\n", r == 3?
        !           751:                   "not enough memory to explode " :
        !           752:                   "invalid compressed (imploded) data for ", filename);
        !           753:             else
        !           754:                 fprintf(stderr, "\n  error:  %s\n", r == 3?
        !           755:                   "not enough memory for explode operation" :
        !           756:                   "invalid compressed data for explode format");
        !           757:             error = (r == 3)? 5 : 2;
        !           758:         }
        !           759:         break;
        !           760: 
        !           761:     case DEFLATED:
        !           762:         if (!tflag && (quietflg < 2)) {
        !           763:             fprintf(stdout, "  Inflating: %-22s ", filename);
        !           764:             if (cflag)
        !           765:                 fprintf(stdout, "\n");
        !           766:             fflush(stdout);
        !           767:         }
        !           768: #ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
        !           769:         if (symlnk) {
        !           770:             fprintf(stdout, "\n  warning:  symbolic link ignored\n");
        !           771:             error = 1;          /* 1:  warning error */
        !           772:         }
        !           773: #endif /* S_IFLNK */
        !           774:         if ((r = inflate()) != 0) {
        !           775:             if ((tflag && quietflg) || (!tflag && (quietflg > 1)))
        !           776:                 fprintf(stderr, "  error:  %s%s\n", r == 3?
        !           777:                   "not enough memory to inflate " :
        !           778:                   "invalid compressed (deflated) data for ", filename);
        !           779:             else
        !           780:                 fprintf(stderr, "\n  error:  %s\n", r == 3?
        !           781:                   "not enough memory for inflate operation" :
        !           782:                   "invalid compressed data for inflate format");
        !           783:             error = (r == 3)? 5 : 2;
        !           784:         }
        !           785:         break;
        !           786: 
        !           787:     default:   /* should never get to this point */
        !           788:         fprintf(stderr, "%s:  unknown compression method\n", filename);
        !           789:         /* close and delete file before return? */
        !           790:         return 1;               /* 1:  warning error */
        !           791: 
        !           792:     } /* end switch (compression method) */
        !           793: 
        !           794:     if (disk_full) {            /* set by FlushOutput()/OUTB() macro */
        !           795:         if (disk_full > 1)
        !           796:             return 50;          /* 50:  disk full */
        !           797:         error = 1;              /* 1:  warning error */
        !           798:     }
        !           799: 
        !           800: /*---------------------------------------------------------------------------
        !           801:     Write the last partial buffer, if any; set the file date and time; and
        !           802:     close the file (not necessarily in that order).  Then make sure CRC came
        !           803:     out OK and print result.
        !           804:   ---------------------------------------------------------------------------*/
        !           805: 
        !           806: #ifdef S_IFLNK
        !           807:     if (!symlnk) {
        !           808: #endif /* S_IFLNK */
        !           809:     if (!disk_full && FlushOutput())
        !           810:         if (disk_full > 1)
        !           811:             return 50;          /* 50:  disk full */
        !           812:         else {                  /* disk_full == 1 */
        !           813:             fprintf(stderr, "%s:  probably corrupt\n", filename);
        !           814:             error = 1;          /* 1:  warning error */
        !           815:         }
        !           816: 
        !           817:     if (!tflag)
        !           818: #ifdef VMS
        !           819:         CloseOutputFile();
        !           820: #else /* !VMS */
        !           821: #ifdef MTS                      /* MTS can't set file time */
        !           822:         close(outfd);
        !           823: #else /* !MTS */
        !           824:         set_file_time_and_close();
        !           825: #endif /* ?MTS */
        !           826: #endif /* ?VMS */
        !           827: 
        !           828: #ifdef S_IFLNK
        !           829:     } /* endif (!symlnk) */
        !           830: #endif /* S_IFLNK */
        !           831: 
        !           832:     if (error > 1)   /* don't print redundant CRC error if error already */
        !           833:         return error;
        !           834: 
        !           835:     /* logical-AND crc32val for 64-bit machines */
        !           836:     if ((crc32val = ((~crc32val) & 0xFFFFFFFFL)) != lrec.crc32) {
        !           837:         /* if quietflg is set, we haven't output the filename yet:  do it */
        !           838:         if (quietflg)
        !           839:             printf("%-22s: ", filename);
        !           840:         fprintf(stdout, " Bad CRC %08lx  (should be %08lx)\n", crc32val,
        !           841:                 lrec.crc32);
        !           842:         error = 1;              /* 1:  warning error */
        !           843:     } else if (tflag) {
        !           844:         if (!quietflg)
        !           845:             fprintf(stdout, " OK\n");
        !           846:     } else {
        !           847:         if ((quietflg < 2) && !error)
        !           848:             fprintf(stdout, "\n");
        !           849:     }
        !           850: 
        !           851:     return error;
        !           852: 
        !           853: }       /* end function extract_or_test_member() */
        !           854: 
        !           855: 
        !           856: 
        !           857: 
        !           858: 
        !           859: #ifdef CRYPT
        !           860: 
        !           861: /*******************************/
        !           862: /*  Function decrypt_member()  */
        !           863: /*******************************/
        !           864: 
        !           865: static int decrypt_member()   /* return 10 if out of memory or can't get */
        !           866: {                             /*  tty; 1 if password bad; 0 if password OK */
        !           867:     UWORD b;
        !           868:     int n, r;
        !           869:     static int nopwd=FALSE;
        !           870:     char *m, *prompt;
        !           871:     byte h[12];
        !           872: 
        !           873: 
        !           874:     /* get header once (turn off "encrypted" flag temporarily so we don't
        !           875:      * try to decrypt the same data twice) */
        !           876:     pInfo->encrypted = FALSE;
        !           877:     for (n = 0; n < 12; n++) {
        !           878:         ReadByte(&b);
        !           879:         h[n] = (byte) b;
        !           880:     }
        !           881:     pInfo->encrypted = TRUE;
        !           882: 
        !           883:     /* if have key already, test it; else allocate memory for it */
        !           884:     if (key) {
        !           885:         if (!testp(h))
        !           886:             return 0;      /* existing password OK (else prompt for new) */
        !           887:         else if (nopwd)
        !           888:             return 1;      /* user indicated no more prompting */
        !           889:     } else if ((key = (char *)malloc(PWLEN+1)) == (char *)NULL)
        !           890:         return 10;
        !           891: 
        !           892:     if ((prompt = (char *)malloc(FILNAMSIZ+15)) != (char *)NULL) {
        !           893:         sprintf(prompt, "%s password: ", filename);
        !           894:         m = prompt;
        !           895:     } else
        !           896:         m = "Enter password: ";
        !           897: 
        !           898:     /* try a few keys */
        !           899:     for (r = 0;  r < 3;  ++r) {
        !           900:         m = getp(m, key, PWLEN+1);
        !           901:         if (prompt != (char *)NULL) {
        !           902:             free(prompt);
        !           903:             prompt = (char *)NULL;
        !           904:         }
        !           905:         if (m == (char *)NULL)
        !           906:             return 10;
        !           907:         if (!testp(h))
        !           908:             return 0;
        !           909:         if (*key == '\0') {
        !           910:             nopwd = TRUE;
        !           911:             return 1;
        !           912:         }
        !           913:         m = "password incorrect--reenter: ";
        !           914:     }
        !           915:     return 1;
        !           916: }
        !           917: 
        !           918: 
        !           919: 
        !           920: 
        !           921: 
        !           922: /**********************/
        !           923: /*  Function testp()  */
        !           924: /**********************/
        !           925: 
        !           926: static int testp(h)   /* return -1 if bad password; 0 if OK */
        !           927:     byte *h;
        !           928: {
        !           929:     UWORD b;
        !           930:     int n, t;
        !           931:     byte *p;
        !           932: 
        !           933:     /* set keys */
        !           934:     init_keys(key);
        !           935: 
        !           936:     /* check password */
        !           937:     for (n = 0; n < 12; n++)
        !           938:         b = DECRYPT(h[n]);
        !           939: 
        !           940: #ifdef CRYPT_DEBUG
        !           941:     printf("   lrec.crc = %08lx  crec.crc = %08lx  pInfo->ExtLocHdr = %s\n",
        !           942:       lrec.crc32, pInfo->crc, pInfo->ExtLocHdr? "true":"false");
        !           943:     printf("   incnt = %d  unzip offset into zipfile = %ld\n", incnt,
        !           944:       cur_zipfile_bufstart+(inptr-inbuf));
        !           945:     printf("   b = %02x  (crc >> 24) = %02x  (lrec.time >> 8) = %02x\n",
        !           946:       b, (UWORD)(lrec.crc32 >> 24), (lrec.last_mod_file_time >> 8));
        !           947: #endif /* CRYPT_DEBUG */
        !           948: 
        !           949:     /* same test as in zipbare() in crypt.c (now check only one byte): */
        !           950:     if (b != (pInfo->ExtLocHdr? lrec.last_mod_file_time >> 8 :
        !           951:         (UWORD)(lrec.crc32 >> 24)))
        !           952:         return -1;  /* bad */
        !           953: 
        !           954:     /* password OK:  decrypt current buffer contents before leaving */
        !           955:     for (n = (longint)incnt > csize ? (int)csize : incnt, p = inptr; n--; p++)
        !           956:         *p = (byte) DECRYPT(*p);
        !           957:     return 0;       /* OK */
        !           958: 
        !           959: } /* end function testp() */
        !           960: 
        !           961: #endif /* CRYPT */
        !           962: 
        !           963: 
        !           964: 
        !           965: 
        !           966: 
        !           967: /*******************************/
        !           968: /*  Function ReadMemoryByte()  */
        !           969: /*******************************/
        !           970: 
        !           971: int ReadMemoryByte(x)   /* return PK-type error code */
        !           972:     UWORD *x;
        !           973: {
        !           974:     if (mem_i_offset < mem_i_size) {
        !           975:         *x = (UWORD) mem_i_buffer[mem_i_offset++];
        !           976:         return 8;
        !           977:     } else
        !           978:         return 0;
        !           979: }
        !           980: 
        !           981: 
        !           982: 
        !           983: 
        !           984: 
        !           985: /****************************/
        !           986: /*  Function FlushMemory()  */
        !           987: /****************************/
        !           988: 
        !           989: int FlushMemory()   /* return PK-type error code */
        !           990: {
        !           991:     if (outcnt == 0)
        !           992:         return 0;
        !           993: 
        !           994:     if (mem_o_offset + outcnt <= mem_o_size) {
        !           995:         memcpy((char *)(mem_o_buffer+(UWORD)mem_o_offset), (char *)outbuf,
        !           996:           outcnt);
        !           997:         mem_o_offset += outcnt;
        !           998:         return 0;
        !           999:     } else
        !          1000:         return 50;
        !          1001: }
        !          1002: 
        !          1003: 
        !          1004: 
        !          1005: 
        !          1006: 
        !          1007: /***************************/
        !          1008: /*  Function memextract()  */   /* extract compressed extra field block */
        !          1009: /***************************/
        !          1010: 
        !          1011: int memextract(tgt, tgtsize, src, srcsize)  /* return 0 if success, 1 if not */
        !          1012:     byte *tgt, *src;
        !          1013:     ULONG tgtsize, srcsize;
        !          1014: {
        !          1015:     UWORD method, error = 0;
        !          1016:     ULONG crc, oldcrc;
        !          1017:     int r;
        !          1018: 
        !          1019:     method = makeword(src);
        !          1020:     crc = makelong(src+2);
        !          1021: 
        !          1022:     mem_i_buffer = src + 2 + 4;      /* method and crc */
        !          1023:     mem_i_size   = srcsize - 2 - 4;
        !          1024:     mem_i_offset = 0;
        !          1025:   
        !          1026:     mem_o_buffer = tgt;
        !          1027:     mem_o_size   = tgtsize;
        !          1028:     mem_o_offset = 0;
        !          1029: 
        !          1030:     mem_mode = 1;
        !          1031: 
        !          1032:     bits_left = 0;
        !          1033:     bitbuf = 0L;
        !          1034:     outpos = 0L;
        !          1035:     outcnt = 0;
        !          1036:     outptr = outbuf;
        !          1037:     zipeof = 0;
        !          1038: 
        !          1039:     switch (method) {
        !          1040:         case STORED:
        !          1041:             memcpy(tgt, src + 2 + 4, (extent) (srcsize - 2 - 4));
        !          1042:             break;
        !          1043:         case DEFLATED:
        !          1044:             if ((r = inflate()) != 0) {
        !          1045:                 fprintf(stderr, "error:  %s\n", r == 3 ?
        !          1046:                   "not enough memory for inflate operation" :
        !          1047:                   "invalid compressed data for the inflate format");
        !          1048:                 error = (r == 3)? 5 : 2;
        !          1049:             }
        !          1050:             FlushOutput();
        !          1051:             break;
        !          1052:         default:
        !          1053:             fprintf(stderr,
        !          1054:               "warning:  unsupported extra field compression type--skipping\n");
        !          1055:             error = 1;   /* GRR:  this should be passed on up via SetEAs() */
        !          1056:             break;
        !          1057:     }
        !          1058: 
        !          1059:     mem_mode = 0;
        !          1060: 
        !          1061:     if (!error) {
        !          1062:         oldcrc = crc32val;
        !          1063:         crc32val = 0xFFFFFFFFL;
        !          1064:         UpdateCRC((unsigned char *) mem_o_buffer, (int) mem_o_size);
        !          1065:         crc32val = (~crc32val) & 0xFFFFFFFFL;
        !          1066: 
        !          1067:         if (crc32val != crc) {
        !          1068:             printf("(Bad extra field CRC %08lx, should be %08lx)\n", crc32val,
        !          1069:               crc);
        !          1070:             error = 1;
        !          1071:         }
        !          1072:         crc32val = oldcrc; /* grrr ... this ugly kludge should be fixed */
        !          1073:     }
        !          1074: 
        !          1075:     return error;
        !          1076: }

unix.superglobalmegacorp.com

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