📄 process.c
字号:
Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileEmpty), G.zipfn)); CLOSE_INFILE(); return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN; } /*----------------------------------------------------------------------- Compensate for missing or extra bytes, and seek to where the start of central directory should be. If header not found, uncompensate and try again (necessary for at least some Atari archives created with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1). -----------------------------------------------------------------------*/ ZLSEEK( G.ecrec.offset_start_central_directory )#ifdef OLD_SEEK_TEST if (readbuf(G.sig, 4) == 0) { CLOSE_INFILE(); return PK_ERR; /* file may be locked, or possibly disk error(?) */ } if (strncmp(G.sig, central_hdr_sig, 4))#else if ((readbuf(__G__ G.sig, 4) == 0) || strncmp(G.sig, central_hdr_sig, 4))#endif {#ifndef SFX long tmp = G.extra_bytes;#endif G.extra_bytes = 0; ZLSEEK( G.ecrec.offset_start_central_directory ) if ((readbuf(__G__ G.sig, 4) == 0) || strncmp(G.sig, central_hdr_sig, 4)) { Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirStartNotFound), G.zipfn, LoadFarStringSmall(ReportMsg))); CLOSE_INFILE(); return PK_BADERR; }#ifndef SFX Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirTooLong), G.zipfn, -tmp));#endif error_in_archive = PK_ERR; } /*----------------------------------------------------------------------- Seek to the start of the central directory one last time, since we have just read the first entry's signature bytes; then list, extract or test member files as instructed, and close the zipfile. -----------------------------------------------------------------------*/ Trace((stderr, "about to extract/list files (error = %d)\n", error_in_archive)); ZLSEEK( G.ecrec.offset_start_central_directory )#ifdef DLL /* G.fValidate is used only to look at an archive to see if it appears to be a valid archive. There is no interest in what the archive contains, nor in validating that the entries in the archive are in good condition. This is currently used only in the Windows DLLs for purposes of checking archives within an archive to determine whether or not to display the inner archives. */ if (!G.fValidate)#endif {#ifndef NO_ZIPINFO if (uO.zipinfo_mode) error = zipinfo(__G); /* ZIPINFO 'EM */ else#endif#ifndef SFX#ifdef TIMESTAMP if (uO.T_flag) error = get_time_stamp(__G__ &uxstamp, &nmember); else#endif if (uO.vflag && !uO.tflag && !uO.cflag) error = list_files(__G); /* LIST 'EM */ else#endif /* !SFX */ error = extract_or_test_files(__G); /* EXTRACT OR TEST 'EM */ Trace((stderr, "done with extract/list files (error = %d)\n", error)); } if (error > error_in_archive) /* don't overwrite stronger error */ error_in_archive = error; /* with (for example) a warning */#ifndef SFX } /* end if (!too_weird_to_continue) */#endif CLOSE_INFILE();#ifdef TIMESTAMP if (uO.T_flag && !uO.zipinfo_mode && (nmember > 0)) {# ifdef WIN32 if (stamp_file(__G__ G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */# else if (stamp_file(G.zipfn, uxstamp)) { /* TIME-STAMP 'EM */# endif Info(slide, 0x201, ((char *)slide, "warning: cannot set time for %s\n", G.zipfn)); if (error_in_archive < PK_WARN) error_in_archive = PK_WARN; } }#endif return error_in_archive;} /* end function do_seekable() *//*************************//* Function find_ecrec() *//*************************/static int find_ecrec(__G__ searchlen) /* return PK-class error */ __GDEF long searchlen;{ int i, numblks, found=FALSE; LONGINT tail_len; ec_byte_rec byterec;/*--------------------------------------------------------------------------- Treat case of short zipfile separately. ---------------------------------------------------------------------------*/ if (G.ziplen <= INBUFSIZ) { lseek(G.zipfd, 0L, SEEK_SET); if ((G.incnt = read(G.zipfd,(char *)G.inbuf,(unsigned int)G.ziplen)) == (int)G.ziplen) /* 'P' must be at least 22 bytes from end of zipfile */ for (G.inptr = G.inbuf+(int)G.ziplen-22; G.inptr >= G.inbuf; --G.inptr) if ((native(*G.inptr) == 'P') && !strncmp((char *)G.inptr, end_central_sig, 4)) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; }/*--------------------------------------------------------------------------- Zipfile is longer than INBUFSIZ: may need to loop. Start with short block at end of zipfile (if not TOO short). ---------------------------------------------------------------------------*/ } else { if ((tail_len = G.ziplen % INBUFSIZ) > ECREC_SIZE) {#ifdef USE_STRM_INPUT fseek((FILE *)G.zipfd, G.ziplen-tail_len, SEEK_SET); G.cur_zipfile_bufstart = ftell((FILE *)G.zipfd);#else /* !USE_STRM_INPUT */ G.cur_zipfile_bufstart = lseek(G.zipfd, G.ziplen-tail_len, SEEK_SET);#endif /* ?USE_STRM_INPUT */ if ((G.incnt = read(G.zipfd, (char *)G.inbuf, (unsigned int)tail_len)) != (int)tail_len) goto fail; /* it's expedient... */ /* 'P' must be at least 22 bytes from end of zipfile */ for (G.inptr = G.inbuf+(int)tail_len-22; G.inptr >= G.inbuf; --G.inptr) if ((native(*G.inptr) == 'P') && !strncmp((char *)G.inptr, end_central_sig, 4)) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } /* sig may span block boundary: */ strncpy((char *)G.hold, (char *)G.inbuf, 3); } else G.cur_zipfile_bufstart = G.ziplen - tail_len; /*----------------------------------------------------------------------- Loop through blocks of zipfile data, starting at the end and going toward the beginning. In general, need not check whole zipfile for signature, but may want to do so if testing. -----------------------------------------------------------------------*/ numblks = (int)((searchlen - tail_len + (INBUFSIZ-1)) / INBUFSIZ); /* ==amount= ==done== ==rounding== =blksiz= */ for (i = 1; !found && (i <= numblks); ++i) { G.cur_zipfile_bufstart -= INBUFSIZ; lseek(G.zipfd, G.cur_zipfile_bufstart, SEEK_SET); if ((G.incnt = read(G.zipfd,(char *)G.inbuf,INBUFSIZ)) != INBUFSIZ) break; /* fall through and fail */ for (G.inptr = G.inbuf+INBUFSIZ-1; G.inptr >= G.inbuf; --G.inptr) if ((native(*G.inptr) == 'P') && !strncmp((char *)G.inptr, end_central_sig, 4)) { G.incnt -= (int)(G.inptr - G.inbuf); found = TRUE; break; } /* sig may span block boundary: */ strncpy((char *)G.hold, (char *)G.inbuf, 3); } } /* end if (ziplen > INBUFSIZ) *//*--------------------------------------------------------------------------- Searched through whole region where signature should be without finding it. Print informational message and die a horrible death. ---------------------------------------------------------------------------*/fail: if (!found) { if (uO.qflag || uO.zipinfo_mode) Info(slide, 0x401, ((char *)slide, "[%s]\n", G.zipfn)); Info(slide, 0x401, ((char *)slide, LoadFarString(CentDirEndSigNotFound))); return PK_ERR; /* failed */ }/*--------------------------------------------------------------------------- Found the signature, so get the end-central data before returning. Do any necessary machine-type conversions (byte ordering, structure padding compensation) by reading data into character array and copying to struct. ---------------------------------------------------------------------------*/ G.real_ecrec_offset = G.cur_zipfile_bufstart + (G.inptr-G.inbuf);#ifdef TEST printf("\n found end-of-central-dir signature at offset %ld (%.8lXh)\n", G.real_ecrec_offset, G.real_ecrec_offset); printf(" from beginning of file; offset %d (%.4Xh) within block\n", G.inptr-G.inbuf, G.inptr-G.inbuf);#endif if (readbuf(__G__ (char *)byterec, ECREC_SIZE+4) == 0) return PK_EOF; G.ecrec.number_this_disk = makeword(&byterec[NUMBER_THIS_DISK]); G.ecrec.num_disk_start_cdir = makeword(&byterec[NUM_DISK_WITH_START_CENTRAL_DIR]); G.ecrec.num_entries_centrl_dir_ths_disk = makeword(&byterec[NUM_ENTRIES_CENTRL_DIR_THS_DISK]); G.ecrec.total_entries_central_dir = makeword(&byterec[TOTAL_ENTRIES_CENTRAL_DIR]); G.ecrec.size_central_directory = makelong(&byterec[SIZE_CENTRAL_DIRECTORY]); G.ecrec.offset_start_central_directory = makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]); G.ecrec.zipfile_comment_length = makeword(&byterec[ZIPFILE_COMMENT_LENGTH]); G.expect_ecrec_offset = G.ecrec.offset_start_central_directory + G.ecrec.size_central_directory; return PK_COOL;} /* end function find_ecrec() *//*****************************//* Function uz_end_central() *//*****************************/int uz_end_central(__G) /* return PK-type error code */ __GDEF{ int error = PK_COOL;/*--------------------------------------------------------------------------- Get the zipfile comment (up to 64KB long), if any, and print it out. Then position the file pointer to the beginning of the central directory and fill buffer. ---------------------------------------------------------------------------*/#ifdef WINDLL /* for comment button: */ if ((!G.fValidate) && (G.lpUserFunctions != NULL)) G.lpUserFunctions->cchComment = G.ecrec.zipfile_comment_length; if (G.ecrec.zipfile_comment_length && (uO.zflag > 0))#else /* !WINDLL */ if (G.ecrec.zipfile_comment_length && (uO.zflag > 0 || (uO.zflag == 0 &&#ifdef TIMESTAMP !uO.T_flag &&#endif !uO.qflag)))#endif /* ?WINDLL */ { if (do_string(__G__ G.ecrec.zipfile_comment_length, DISPLAY)) { Info(slide, 0x401, ((char *)slide, LoadFarString(ZipfileCommTrunc1))); error = PK_WARN; } } return error;} /* end function uz_end_central() *//************************************//* Function process_cdir_file_hdr() *//************************************/int process_cdir_file_hdr(__G) /* return PK-type error code */ __GDEF{ int error;/*--------------------------------------------------------------------------- Get central directory info, save host and method numbers, and set flag for lowercase conversion of filename, depending on the OS from which the file is coming. ---------------------------------------------------------------------------*/ if ((error = get_cdir_ent(__G)) != 0) return error; G.pInfo->hostnum = MIN(G.crec.version_made_by[1], NUM_HOSTS);/* extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */ G.pInfo->lcflag = 0; if (uO.L_flag) /* user specified case-conversion */ switch (G.pInfo->hostnum) { case FS_FAT_: /* PKZIP and zip -k store in uppercase */ case CPM_: /* like MS-DOS, right? */ case VM_CMS_: /* all caps? */ case MVS_: /* all caps? */ case TANDEM_: case TOPS20_:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -