zipfile.c

来自「infozip2.2源码」· C语言 代码 · 共 1,465 行 · 第 1/3 页

C
1,465
字号
        sprintf(errbuf, "%ld", (ulg)zcount + 1);        zipwarn("zero-length name for entry #", errbuf);#ifndef DEBUG        return ZE_FORM;#endif      }      if ((z->iname = malloc(n+1)) ==  NULL ||          (z->ext && (z->extra = malloc(z->ext)) == NULL))        return ZE_MEM;      if (fread(z->iname, n, 1, f) != 1 ||          (z->ext && fread(z->extra, z->ext, 1, f) != 1) ||          (s && fseek(f, (long)s, SEEK_CUR)))        return ferror(f) ? ZE_READ : ZE_EOF;      /* If there is an extended local header, s is either 0 or       * the correct compressed size.       */      z->iname[n] = 0;                  /* terminate name */      z->zname = in2ex(z->iname);       /* convert to external name */      if (z->zname == NULL)        return ZE_MEM;      z->name = z->zname;      z->cextra = z->extra;      if (noisy) fprintf(mesg, "zip: reading %s\n", z->zname);      /* Save offset, update for next header */      z->off = p;      p += 4 + LOCHEAD + n + z->ext + s;      zcount++;      /* Skip extended local header if there is one */      if ((flg & 8) != 0) {        /* Skip the compressed data if compressed size is unknown.         * For safety, we should use the central directory.         */        if (s == 0) {          for (;;) {            while ((m = getc(f)) != EOF && m != 0x50) ;  /* 0x50 == 'P' */            b[0] = (char) m;            if (fread(b+1, 15, 1, f) != 1 || LG(b) == EXTLOCSIG)              break;            if (fseek(f, -15L, SEEK_CUR))              return ferror(f) ? ZE_READ : ZE_EOF;          }          s = LG(4 + EXTSIZ + b);          p += s;          if ((ulg) ftell(f) != p+16L) {            zipwarn("bad extended local header for ", z->zname);            return ZE_FORM;          }        } else {          /* compressed size non-zero, assume that it is valid: */          Assert(p == ftell(f), "bad compressed size with extended header");          if (fseek(f, p, SEEK_SET) || fread(b, 16, 1, f) != 1)            return ferror(f) ? ZE_READ : ZE_EOF;          if (LG(b) != EXTLOCSIG) {            zipwarn("extended local header not found for ", z->zname);            return ZE_FORM;          }        }        /* overwrite the unknown values of the local header: */        /* already in host format */        z->crc = LG(4 + EXTCRC + b);        z->siz = s;        z->len = LG(4 + EXTLEN + b);        p += 16L;      }      else if (fix > 1) {        /* Don't trust the compressed size */        for (;;) {          while ((m = getc(f)) != EOF && m != 0x50) p++; /* 0x50 == 'P' */          b[0] = (char) m;          if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG || s == CENSIG)            break;          if (fseek(f, -3L, SEEK_CUR))            return ferror(f) ? ZE_READ : ZE_EOF;          p++;        }        s = p - (z->off + 4 + LOCHEAD + n + z->ext);        if (s != z->siz) {          fprintf(mesg, " compressed size %ld, actual size %ld for %s\n",                  z->siz, s, z->zname);          z->siz = s;        }        /* next LOCSIG already read at this point, don't read it again: */        continue;      }      /* Read next signature */      if (fread(b, 4, 1, f) != 1)          break;    }    s = p;                              /* save start of central */    if (LG(b) != CENSIG && noisy) {      fprintf(mesg, "zip warning: %s %s truncated.\n", zipfile,              fix > 1 ? "has been" : "would be");      if (fix == 1) {        fprintf(mesg,   "Retry with option -qF to truncate, with -FF to attempt full recovery\n");        ZIPERR(ZE_FORM, NULL);      }    }    cenbeg = s;    zcomlen = 0;    if (zipbeg && noisy)      fprintf(mesg, "%s: adjusting offsets for a preamble of %lu bytes\n",              zipfile, zipbeg);    /* Done with zip file for now */    fclose(f);    /* If one or more files, sort by name */    if (zcount)    {      if ((x = zsort =          (struct zlist far **)malloc(zcount * sizeof(struct zlist far *))) ==          NULL)        return ZE_MEM;      for (z = zfiles; z != NULL; z = z->nxt)        *x++ = z;      qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp);    }  }  return ZE_OK;}#endif /* !UTIL *//* * readzipfile starts searching for the End Signature at the end of the file * The End Signature points to the Central Directory Signature which points * to the Local Directory Signature * XXX probably some more consistency checks are needed */int readzipfile()/*   The name of the zip file is pointed to by the global "zipfile".  The   globals zfiles, zcount, zcomlen, zcomment, and zsort are filled in.   Return an error code in the ZE_ class.*/{  char b[CENHEAD];      /* buffer for central headers */  FILE *f;              /* zip file */  ush flg;              /* general purpose bit flag */  int m;                /* mismatch flag */  extent n;             /* length of name */  struct zlist far * far *x;    /* pointer last entry's link */  struct zlist far *z;  /* current zip entry structure */  char *t;              /* temporary pointer */  char far *u;          /* temporary variable */  int found;  char *buf;            /* temp buffer for reading zipfile */  long deltaoff;#ifndef UTIL  if (fix && !adjust)     return readzipfile2();#endif  /* Initialize zip file info */  zipbeg = 0;  zfiles = NULL;                        /* Points to first header */  zcomlen = 0;                          /* zip file comment length */  /* If zip file exists, read headers and check structure */#ifdef VMS  if (zipfile == NULL || !(*zipfile) || !strcmp(zipfile, "-"))    return ZE_OK;  {    int rtype;    if ((VMSmunch(zipfile, GET_RTYPE, (char *)&rtype) == RMS$_NORMAL) &&        (rtype == FAT$C_VARIABLE)) {      fprintf(stderr,     "\n     Error:  zipfile is in variable-length record format.  Please\n\     run \"bilf b %s\" to convert the zipfile to fixed-length\n\     record format.\n\n", zipfile);      return ZE_FORM;    }  }  if ((f = fopen(zipfile, FOPR)) != NULL)#else /* !VMS */  if (zipfile != NULL && *zipfile && strcmp(zipfile, "-") &&      (f = fopen(zipfile, FOPR)) != NULL)#endif /* ?VMS */  {    buf = malloc(4096 + 4);    if (buf == NULL)      return ZE_MEM;#ifdef HANDLE_AMIGA_SFX    amiga_sfx_offset = (fread(buf, 1, 4, f) == 4 && LG(buf) == 0xF3030000);    /* == 1 if this file is an Amiga executable (presumably UnZipSFX) */#endif    found = 0;    t = &buf[4096];    t[1] = '\0';    t[2] = '\0';    t[3] = '\0';    if (fseek(f, -4096L, SEEK_END) == 0) {      zipbeg = (ulg) (ftell(f) + 4096L);      while (!found && zipbeg >= 4096) {        zipbeg -= 4096L;        buf[4096] = t[1];        buf[4097] = t[2];        buf[4098] = t[3];/* * XXX error check ?? */        fread(buf, 1, 4096, f);        fseek(f, -8192L, SEEK_CUR);        t = &buf[4095];/* * XXX far pointer arithmetic in DOS */        while (t >= buf) {          /* Check for ENDSIG ("PK\5\6" in ASCII) */          if (LG(t) == ENDSIG) {            found = 1;/* * XXX error check ?? * XXX far pointer arithmetic in DOS */            zipbeg += (ulg) (t - buf);            fseek(f, (long) zipbeg + 4L, SEEK_SET);            break;          }          --t;        }      }    }    else       zipbeg = 4096L;/* * XXX warn: garbage at the end of the file ignored */    if (!found && zipbeg > 0) {      size_t s;      rewind(f);      s = fread(buf, 1, (size_t) zipbeg, f);      buf[s] = t[1];      buf[s + 1] = t[2];      buf[s + 2] = t[3];      t = &buf[s - 1];/* * XXX far pointer comparison in DOS */      while (t >= buf) {        /* Check for ENDSIG ("PK\5\6" in ASCII) */        if (LG(t) == ENDSIG) {          found = 1;/* * XXX far pointer arithmetic in DOS */          zipbeg = (ulg) (t - buf);          fseek(f, (long) zipbeg + 4L, SEEK_SET);          break;        }        --t;      }    }    free(buf);    if (!found) {      zipwarn("missing end signature--probably not a zip file (did you", "");      zipwarn("remember to use binary mode when you transferred it?)", "");      return ZE_FORM;    }    /* Read end header */    if (fread(b, ENDHEAD, 1, f) != 1)      return ferror(f) ? ZE_READ : ZE_EOF;    if (SH(ENDDSK + b) || SH(ENDBEG + b) ||        SH(ENDSUB + b) != SH(ENDTOT + b))      zipwarn("multiple disk information ignored", "");    zcomlen = SH(ENDCOM + b);    if (zcomlen)    {      if ((zcomment = malloc(zcomlen)) == NULL)        return ZE_MEM;      if (fread(zcomment, zcomlen, 1, f) != 1)      {        free((zvoid *)zcomment);        zcomment = NULL;        return ferror(f) ? ZE_READ : ZE_EOF;      }#ifdef EBCDIC      if (zcomment)         memtoebc(zcomment, zcomment, zcomlen);#endif /* EBCDIC */    }/* * XXX assumes central header immediately precedes end header */    cenbeg = zipbeg - LG(ENDSIZ + b);    deltaoff = adjust ? cenbeg - LG(b + ENDOFF) : 0L;    if (fseek(f, cenbeg, SEEK_SET) != 0) {        perror("fseek");        return ZE_FORM; /* XXX */    }    x = &zfiles;                        /* first link */    zcount = 0;                         /* number of files */    if (fread(b, 4, 1, f) != 1)      return ferror(f) ? ZE_READ : ZE_EOF;    while (LG(b) == CENSIG) {      /* Read central header. The portion of the central header that should         be in common with local header is read raw, for later comparison.         (this requires that the offset of ext in the zlist structure         be greater than or equal to LOCHEAD) */      if (fread(b, CENHEAD, 1, f) != 1)        return ferror(f) ? ZE_READ : ZE_EOF;      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)        return ZE_MEM;      z->vem = SH(CENVEM + b);      for (u = (char far *)(&(z->ver)), n = 0; n < (CENNAM-CENVER); n++)        u[n] = b[CENVER + n];      z->nam = SH(CENNAM + b);          /* used before comparing cen vs. loc */      z->cext = SH(CENEXT + b);         /* may be different from z->ext */      z->com = SH(CENCOM + b);      z->dsk = SH(CENDSK + b);      z->att = SH(CENATT + b);      z->atx = LG(CENATX + b);      z->off = LG(CENOFF + b) + deltaoff;      z->dosflag = (z->vem & 0xff00) == 0;      /* Initialize all fields pointing to malloced data to NULL */      z->zname = z->name = z->iname = z->extra = z->cextra = z->comment = NULL;      /* Link into list */      *x = z;      z->nxt = NULL;      x = &z->nxt;      /* Read file name, extra field and comment field */      if (z->nam == 0)      {        sprintf(errbuf, "%lu", (ulg)zcount + 1);        zipwarn("zero-length name for entry #", errbuf);#ifndef DEBUG        farfree((zvoid far *)z);        return ZE_FORM;#endif      }      if ((z->iname = malloc(z->nam+1)) ==  NULL ||          (z->cext && (z->cextra = malloc(z->cext)) == NULL) ||          (z->com && (z->comment = malloc(z->com)) == NULL))        return ZE_MEM;      if (fread(z->iname, z->nam, 1, f) != 1 ||          (z->cext && fread(z->cextra, z->cext, 1, f) != 1) ||          (z->com && fread(z->comment, z->com, 1, f) != 1))        return ferror(f) ? ZE_READ : ZE_EOF;      z->iname[z->nam] = 0;                  /* terminate name */#ifdef EBCDIC      if (z->com)         memtoebc(z->comment, z->comment, z->com);#endif /* EBCDIC */      /* Update zipbeg offset, prepare for next header */      if (z->off < zipbeg)         zipbeg = z->off;      zcount++;      /* Read next signature */      if (fread(b, 4, 1, f) != 1)          return ferror(f) ? ZE_READ : ZE_EOF;    }    /* Point to start of header list and read local headers */    z = zfiles;    while (z != NULL) {      /* Read next signature */      if (fseek(f, z->off, SEEK_SET) != 0 || fread(b, 4, 1, f) != 1)        return ferror(f) ? ZE_READ : ZE_EOF;      if (LG(b) == LOCSIG) {        if (fread(b, LOCHEAD, 1, f) != 1)            return ferror(f) ? ZE_READ : ZE_EOF;        z->lflg = SH(LOCFLG + b);        n = SH(LOCNAM + b);        z->ext = SH(LOCEXT + b);        /* Compare name and extra fields */        if (n != z->nam)        {#ifdef EBCDIC          strtoebc(z->iname, z->iname);#endif          zipwarn("name lengths in local and central differ for ", z->iname);          return ZE_FORM;        }        if ((t = malloc(z->nam)) == NULL)          return ZE_MEM;        if (fread(t, z->nam, 1, f) != 1)        {          free((zvoid *)t);          return ferror(f) ? ZE_READ : ZE_EOF;        }        if (memcmp(t, z->iname, z->nam))        {          free((zvoid *)t);#ifdef EBCDIC          strtoebc(z->iname, z->iname);#endif          zipwarn("names in local and central differ for ", z->iname);          return ZE_FORM;        }        free((zvoid *)t);        if (z->ext)        {          if ((z->extra = malloc(z->ext)) == NULL)            return ZE_MEM;          if (fread(z->extra, z->ext, 1, f) != 1)          {            free((zvoid *)(z->extra));            return ferror(f) ? ZE_READ : ZE_EOF;          }          if (z->ext == z->cext && memcmp(z->extra, z->cextra, z->ext) == 0)          {            free((zvoid *)(z->extra));            z->extra = z->cextra;          }        }        /* Check extended local header if there is one */        if ((z->lflg & 8) != 0)        {          char buf2[16];          ulg s;                        /* size of compressed data */          s = LG(LOCSIZ + b);          if (s == 0)            s = LG((CENSIZ-CENVER) + (char far *)(&(z->ver)));          if (fseek(f, (z->off + (4+LOCHEAD) + z->nam + z->ext + s), SEEK_SET)              || (fread(buf2, 16, 1, f) != 1))            return ferror(f) ? ZE_READ : ZE_EOF;          if (LG(buf2) != EXTLOCSIG)          {#ifdef EBCDIC            strtoebc(z->iname, z->iname);#endif            zipwarn("extended local header not found for ", z->iname);            return ZE_FORM;          }          /* overwrite the unknown values of the local header: */          for (n = 0; n < 12; n++)            b[LOCCRC+n] = buf2[4+n];        }        /* Compare local header with that part of central header (except           for the reserved bits in the general purpose flags and except           for the already checked entry name length */        u = (char far *)(&(z->ver));        flg = SH((CENFLG-CENVER) + u);          /* Save central flags word */        u[CENFLG-CENVER+1] &= 0x1f;             /* Mask reserved flag bits */        b[LOCFLG+1] &= 0x1f;        for (m = 0, n = 0; n < LOCNAM; n++)          if (b[n] != u[n])          {            if (!m)            {              zipwarn("local and central headers differ for ", z->zname);              m = 1;            }            if (noisy)            {              sprintf(errbuf, " offset %u--local = %02x, central = %02x",                      (unsigned)n, (uch)b[n], (uch)u[n]);              zipwarn(errbuf, "");            }          }        if (m && !adjust)          return ZE_FORM;        /* Complete the setup of the zlist entry by translating the remaining         * central header fields in memory, starting with the fields with         * highest offset. This order of the conversion commands takes into         * account potential buffer overlaps caused by structure padding.         */        z->len = LG((CENLEN-CENVER) + u);        z->siz = LG((CENSIZ-CENVER) + u);        z->crc = LG((CENCRC-CENVER) + u);        z->tim = LG((CENTIM-CENVER) + u);   /* time and date into one long */        z->how = SH((CENHOW-CENVER) + u);

⌨️ 快捷键说明

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