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

📄 zipfile.c

📁 给出了 zip 压缩算法的完整实现过程。
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif    /* Find start of zip structures */    for (;;) {      while ((m = getc(f)) != EOF && m != 0x50)    /* 0x50 == 'P' */      {#ifdef HANDLE_AMIGA_SFX        if (p == 0 && m == 0)          amiga_sfx_offset = 1L;        else if (amiga_sfx_offset) {          if ((p == 1 && m != 0) || (p == 2 && m != 3)                                 || (p == 3 && (uch) m != 0xF3))            amiga_sfx_offset = 0L;        }#endif /* HANDLE_AMIGA_SFX */        p++;      }      b[0] = (char) m;      if (fread(b+1, 3, 1, f) != 1 || (s = LG(b)) == LOCSIG || s == ENDSIG)        break;      if (fseek(f, -3L, SEEK_CUR))        return ferror(f) ? ZE_READ : ZE_EOF;      p++;    }    zipbeg = p;#ifdef HANDLE_AMIGA_SFX    if (amiga_sfx_offset && zipbeg >= 12 && (zipbeg & 3) == 0        && fseek(f, -12L, SEEK_CUR) == 0 && fread(b, 12, 1, f) == 1        && LG(b + 4) == 0xF1030000 /* 1009 in Motorola byte order */)      amiga_sfx_offset = zipbeg - 4;    else      amiga_sfx_offset = 0L;#endif /* HANDLE_AMIGA_SFX */    /* Read local headers */    while (LG(b) == LOCSIG)    {      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL ||          zcount + 1 < zcount)        return ZE_MEM;      if (fread(b, LOCHEAD, 1, f) != 1) {          farfree((zvoid far *)z);          break;      }      z->ver = SH(LOCVER + b);      z->vem = (ush)(dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);      z->dosflag = dosify;      flg = z->flg = z->lflg = SH(LOCFLG + b);      z->how = SH(LOCHOW + b);      z->tim = LG(LOCTIM + b);          /* time and date into one long */      z->crc = LG(LOCCRC + b);      z->siz = LG(LOCSIZ + b);      z->len = LG(LOCLEN + b);      n = z->nam = SH(LOCNAM + b);      z->cext = z->ext = SH(LOCEXT + b);      z->com = 0;      z->dsk = 0;      z->att = 0;      z->atx = dosify ? a & 0xff : a;     /* Attributes from filetime() */      z->mark = 0;      z->trash = 0;      s = fix > 1 ? 0L : z->siz; /* discard compressed size with -FF */      /* 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 and extra field and skip data */      if (n == 0)      {        sprintf(errbuf, "%lu", (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;    if (zipbeg && noisy)      fprintf(mesg, "%s: adjusting offsets for a preamble of %lu bytes\n",              zipfile, zipbeg);    return ZE_OK;}#endif /* !UTIL *//* * scanzipf_reg 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 */local int scanzipf_reg(f)  FILE *f;                      /* zip file *//*   The name of the zip file is pointed to by the global "zipfile".  The globals   zipbeg, cenbeg, zfiles, zcount, zcomlen, zcomment, and zsort are filled in.   Return an error code in the ZE_ class.*/{    char b[CENHEAD];            /* buffer for central headers */    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;    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 the End Of Central Directory Record signature             ("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;      fseek(f, 0L, SEEK_SET);      clearerr(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 the End Of Central Directory Record */    /* 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 */    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)

⌨️ 快捷键说明

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