⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extract.c

📁 WINDOWS下的ZIP解压软件,我是个学生,请让我加入这个网站学习
💻 C
📖 第 1 页 / 共 3 页
字号:
                            overwrite_none = TRUE;
                            overwrite_all = FALSE;  /* make sure */
                            force_flag = FALSE;     /* ditto */
                            /* FALL THROUGH, skip */
                        case 'n':
                            continue;   /* skip file */
                        default:
                            fprintf(stderr, "error:  invalid response [%c]\n",
                              *answerbuf);   /* warn the user */
                            goto reprompt;   /* why not another goto? */
                    } /* end switch (*answerbuf) */
#endif /* ?MSWIN */
                } /* end if (query) */
/*#endif*/ /* !VMS */
            } /* end if (extracting to disk) */

#ifdef CRYPT
            if (pInfo->encrypted && ((error = decrypt_member()) != 0)) {
                if (error == 10) {
                    if (error > error_in_archive)
                        error_in_archive = error;
                    fprintf(stderr,
                      " skipping: %-22s  unable to get password\n", filename);
                } else {  /* (error == 1) */
                    fprintf(stderr,
                      " skipping: %-22s  incorrect password\n", filename);
                    ++num_bad_pwd;
                }
                continue;   /* go on to next file */
            }
#endif /* CRYPT */
#ifdef MSWIN
        	SoundDuring();	/* play sound during extraction or test if requested	*/
#endif
            disk_full = 0;
            if ((error = extract_or_test_member()) != 0) {
                if (error > error_in_archive)
                    error_in_archive = error;       /* ...and keep going */
                if (disk_full > 1)
                    return error_in_archive;        /* (unless disk full) */
            }
        } /* end for-loop (i:  files in current block) */


        /*
         * Jump back to where we were in the central directory, then go and do
         * the next batch of files.
         */

        cur_zipfile_bufstart = lseek(zipfd, cd_bufstart, SEEK_SET);
        read(zipfd, (char *)inbuf, INBUFSIZ);  /* were there b4 ==> no error */
        inptr = cd_inptr;
        incnt = cd_incnt;
        ++blknum;

#ifdef TEST
        printf("\ncd_bufstart = %ld (%.8lXh)\n", cd_bufstart, cd_bufstart);
        printf("cur_zipfile_bufstart = %ld (%.8lXh)\n", cur_zipfile_bufstart,
          cur_zipfile_bufstart);
        printf("inptr-inbuf = %d\n", inptr-inbuf);
        printf("incnt = %d\n\n", incnt);
#endif

    } /* end while-loop (blocks of files in central directory) */

/*---------------------------------------------------------------------------
    Double-check that we're back at the end-of-central-directory record, and
    print quick summary of results, if we were just testing the archive.  We
    send the summary to stdout so that people doing the testing in the back-
    ground and redirecting to a file can just do a "tail" on the output file.
  ---------------------------------------------------------------------------*/

    readbuf(sig, 4);
    if (strncmp(sig, end_central_sig, 4)) {     /* just to make sure again */
        fprintf(stderr, EndSigMsg);  /* didn't find end-of-central-dir sig */
        fprintf(stderr, ReportMsg);  /* check binary transfers */
        if (!error_in_archive)       /* don't overwrite stronger error */
            error_in_archive = 1;    /* 1:  warning error */
    }
    if (tflag && (quietflg == 1)) {
        int num=filnum+1 - num_bad_pwd;

        if (error_in_archive)
            printf("At least one error was detected in %s.\n", zipfn);
        else if (num == 0)
            printf("Caution:  zero files tested in %s.\n", zipfn);
        else if (process_all_files && (num_skipped+num_bad_pwd == 0))
            printf("No errors detected in %s.\n", zipfn);
        else
            printf("No errors detected in %s for the %d file%s tested.\n",
              zipfn, num, (num==1)? "":"s");
        if (num_skipped > 0)
            printf("%d file%s skipped because of unsupported compression or\
 encoding.\n",
              num_skipped, (num_skipped==1)? "":"s");
#ifdef CRYPT
        if (num_bad_pwd > 0)
            printf("%d file%s skipped because of incorrect password.\n",
              num_bad_pwd, (num_bad_pwd==1)? "":"s");
#endif /* CRYPT */
    }
    if ((num_skipped > 0) && !error_in_archive)   /* files not tested or  */
        error_in_archive = 1;                     /*  extracted:  warning */
#ifdef CRYPT
    if ((num_bad_pwd > 0) && !error_in_archive)   /* files not tested or  */
        error_in_archive = 1;                     /*  extracted:  warning */
#endif /* CRYPT */

    return (error_in_archive);

} /* end function extract_or_test_files() */





/***************************/
/*  Function store_info()  */
/***************************/

static int store_info()   /* return 1 if skipping, 0 if OK */
{
    ULONG tmp;

#define UNKN_COMPR \
   (crec.compression_method>IMPLODED && crec.compression_method!=DEFLATED)
#if 0  /* old */
#  define UNKN_COMPR   (crec.compression_method>IMPLODED)
#endif


/*---------------------------------------------------------------------------
    Check central directory info for version/compatibility requirements.
  ---------------------------------------------------------------------------*/

    pInfo->encrypted = crec.general_purpose_bit_flag & 1;    /* bit field */
    pInfo->ExtLocHdr = (crec.general_purpose_bit_flag & 8) == 8;  /* bit */
    pInfo->text = crec.internal_file_attributes & 1;         /* bit field */
    pInfo->crc = crec.crc32;
    pInfo->compr_size = crec.compressed_size;

    if (crec.version_needed_to_extract[1] == VMS_) {
        if (crec.version_needed_to_extract[0] > VMS_VERSION) {
            fprintf(stderr, VersionMsg, filename, "VMS",
              crec.version_needed_to_extract[0] / 10,
              crec.version_needed_to_extract[0] % 10,
              VMS_VERSION / 10, VMS_VERSION % 10);
            return 1;
        }
#ifndef VMS   /* won't be able to use extra field, but still have data */
        else if (!tflag && !force_flag) {  /* if forcing, extract regardless */
            fprintf(stderr,
              "\n%s:  stored in VMS format.  Extract anyway? (y/n) ",
              filename);
            FFLUSH   /* for Amiga and Mac MPW */
            fgets(answerbuf, 9, stdin);
            if ((*answerbuf != 'y') && (*answerbuf != 'Y'))
                return 1;
        }
#endif /* !VMS */
    /* usual file type:  don't need VMS to extract */
    } else if (crec.version_needed_to_extract[0] > UNZIP_VERSION) {
        fprintf(stderr, VersionMsg, filename, "PK",
          crec.version_needed_to_extract[0] / 10,
          crec.version_needed_to_extract[0] % 10,
          UNZIP_VERSION / 10, UNZIP_VERSION % 10);
        return 1;
    }

    if UNKN_COMPR {
        fprintf(stderr, ComprMsg, filename, crec.compression_method);
        return 1;
    }
#ifndef CRYPT
    if (pInfo->encrypted) {
        fprintf(stderr, " skipping: %-22s  encrypted (not supported)\n",
          filename);
        return 1;
    }
#endif /* !CRYPT */

/*---------------------------------------------------------------------------
    Store some central-directory information (encryption, file attributes,
    offsets) for later use.
  ---------------------------------------------------------------------------*/

    tmp = crec.external_file_attributes;

    pInfo->dos_attr = 32;   /* set archive bit:  file is not backed up */
    switch (pInfo->hostnum) {
        case UNIX_:
        case VMS_:
            pInfo->unix_attr = (unsigned) (tmp >> 16);
            break;
        case DOS_OS2_FAT_:
        case OS2_HPFS_:
            pInfo->dos_attr = (unsigned) tmp;
            tmp = (!(tmp & 1)) << 1;   /* read-only bit */
            pInfo->unix_attr = (unsigned) (0444 | (tmp<<6) | (tmp<<3) | tmp);
#ifdef UNIX
            umask( (int)(tmp=umask(0)) );
            pInfo->unix_attr &= ~tmp;
#endif
            break;
        case MAC_:
            pInfo->unix_attr = (unsigned) (tmp & 1);   /* read-only bit */
            break;
        default:
            pInfo->unix_attr = 0666;
            break;
    } /* end switch (host-OS-created-by) */

    pInfo->offset = (longint) crec.relative_offset_local_header;
    return 0;

} /* end function store_info() */





/***************************************/
/*  Function extract_or_test_member()  */
/***************************************/

static int extract_or_test_member()    /* return PK-type error code */
{
#ifdef S_IFLNK
    int symlnk=FALSE;
#endif /* S_IFLNK */
    int r, error=0;
    UWORD b;



/*---------------------------------------------------------------------------
    Initialize variables, buffers, etc.
  ---------------------------------------------------------------------------*/

    bits_left = 0;
    bitbuf = 0L;
    outpos = 0L;
    outcnt = 0;
    outptr = outbuf;
    zipeof = 0;
    crc32val = 0xFFFFFFFFL;

#ifdef S_IFLNK
    if ((pInfo->unix_attr & S_IFMT) == S_IFLNK  &&  (pInfo->hostnum == UNIX_)
        && !tflag && !cflag)
        symlnk = TRUE;
#endif /* S_IFLNK */

    memset(outbuf, 0xaa, OUTBUFSIZ);
#ifndef DOS_OS2
    if (aflag)                  /* if we have a scratchpad, clear it out */
        memset(outout, 0xaa, OUTBUFSIZ);
#endif /* !DOS_OS2 */

    if (tflag) {
        if (!quietflg) {
            fprintf(stdout, "  Testing: %-22s ", filename);
            fflush(stdout);
        }
    } else {
        if (cflag) {            /* output to stdout (copy of it) */
#if (defined(MACOS) || defined(AMIGA))
            outfd = 1;
#else /* !(MACOS || AMIGA) */
            outfd = dup(1);     /* GRR: change this to #define for Mac/Amiga */
#endif /* ?(MACOS || AMIGA) */
#ifdef DOS_OS2
            if (!aflag)
                setmode(outfd, O_BINARY);
#endif /* DOS_OS2 */
#ifdef VMS
            if (create_output_file())   /* VMS version required for stdout! */
                return 50;      /* 50:  disk full (?) */
#endif
        } else
#ifdef S_IFLNK
        if (!symlnk)    /* symlink() takes care of file creation */
#endif /* !S_IFLNK */
        {
            if (create_output_file())
                return 50;      /* 50:  disk full (?) */
        }
    } /* endif (!tflag) */

/*---------------------------------------------------------------------------
    Unpack the file.
  ---------------------------------------------------------------------------*/

    switch (lrec.compression_method) {

    case STORED:
        if (!tflag && (quietflg < 2)) {
            fprintf(stdout, " Extracting: %-22s ", filename);
            if (cflag)
                fprintf(stdout, "\n");
            fflush(stdout);
        }
#ifdef S_IFLNK
        /*
         * If file came from Unix and is a symbolic link and we are extracting
         * to disk, allocate a storage area, put the data in it, and create the
         * link.  Since we know it's a symbolic link to start with, shouldn't
         * have to worry about overflowing unsigned ints with unsigned longs.
         * (This doesn't do anything for compressed symlinks, but that can be
         * added later...it also doesn't set the time or permissions of the
         * link, but does anyone really care?)
         */
        if (symlnk) {
#if (defined(MTS) || defined(MACOS))
            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
            error = 1;          /* 1:  warning error */
#else /* !(MTS || MACOS) */
            char *orig = (char *)malloc((unsigned)lrec.uncompressed_size+1);
            char *p = orig;

            while (ReadByte(&b))
                *p++ = b;
            *p = 0;   /* terminate string */
            UpdateCRC((unsigned char *)orig, p-orig);
            if (symlink(orig, filename))
                if ((errno == EEXIST) && overwrite_all) {  /* OK to overwrite */
                    unlink(filename);
                    if (symlink(orig, filename))
                        perror("symlink error");
                } else
                    perror("symlink error");
            free(orig);
#endif /* ?(MTS || MACOS) */
        } else
#endif /* S_IFLNK */
        while (ReadByte(&b) && !disk_full)
            OUTB(b)
        break;

    case SHRUNK:
        if (!tflag && (quietflg < 2)) {
            fprintf(stdout, "UnShrinking: %-22s ", filename);
            if (cflag)
                fprintf(stdout, "\n");
            fflush(stdout);
        }
#ifdef S_IFLNK   /* !!! This code needs to be added to unShrink, etc. !!! */
        if (symlnk) {
            fprintf(stdout, "\n  warning:  symbolic link ignored\n");
            error = 1;          /* 1:  warning error */
        }
#endif /* S_IFLNK */
        unShrink();
        break;

    case REDUCED1:
    case REDUCED2:
    case REDUCED3:
    case REDUCED4:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -