📄 zipfile.c
字号:
{ 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); z->flg = flg; /* may be different from z->lflg */ z->ver = SH((CENVER-CENVER) + u); /* Clear actions */ z->mark = 0; z->trash = 0;#ifdef UTIL/* We only need z->iname in the utils */ z->name = z->iname;#ifdef EBCDIC/* z->zname is used for printing and must be coded in native charset */ if ((z->zname = malloc(z->nam+1)) == NULL) return ZE_MEM; strtoebc(z->zname, z->iname);#else z->zname = z->iname;#endif#else /* !UTIL */ z->zname = in2ex(z->iname); /* convert to external name */ if (z->zname == NULL) return ZE_MEM; z->name = z->zname;#endif /* ?UTIL */ } else {#ifdef EBCDIC strtoebc(z->iname, z->iname);#endif zipwarn("local header not found for ", z->iname); return ZE_FORM; }#ifndef UTIL if (verbose) zipoddities(z);#endif z = z->nxt; } if (zipbeg && noisy) fprintf(mesg, "%s: %s a preamble of %lu bytes\n", zipfile, adjust ? "adjusting offsets for" : "found", zipbeg);#ifdef HANDLE_AMIGA_SFX if (zipbeg < 12 || (zipbeg & 3) != 0 /* must be longword aligned */) amiga_sfx_offset = 0; else if (amiga_sfx_offset) { char buf2[16]; if (!fseek(f, zipbeg - 12, SEEK_SET) && fread(buf2, 12, 1, f) == 1) { if (LG(buf2 + 4) == 0xF1030000 /* 1009 in Motorola byte order */) /* could also check if LG(buf2) == 0xF2030000... no for now */ amiga_sfx_offset = zipbeg - 4; else amiga_sfx_offset = 0L; } }#endif /* HANDLE_AMIGA_SFX */ return ZE_OK;}/* * readzipfile initializes the global variables that hold the zipfile * directory info and opens the zipfile. For the actual zipfile scan, * the subroutine scanzipf_reg() or scanzipf_fix() is called, * depending on the mode of operation (regular processing, or zipfix mode). */int readzipfile()/* The name of the zip file is pointed to by the global "zipfile". The globals zipbeg, zfiles, zcount, and zcomlen are initialized. Return an error code in the ZE_ class.*/{ FILE *f; /* zip file */ int retval; /* return code */ int readable; /* 1 if zipfile exists and is readable */ /* Initialize zip file info */ zipbeg = 0; zfiles = NULL; /* Points to first header */ zcount = 0; /* number of files */ zcomlen = 0; /* zip file comment length */ retval = ZE_OK; f = NULL; /* shut up some compilers */ /* 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; } } readable = ((f = fopen(zipfile, FOPR)) != NULL);#else /* !VMS */ readable = (zipfile != NULL && *zipfile && strcmp(zipfile, "-") && (f = fopen(zipfile, FOPR)) != NULL);#endif /* ?VMS */#ifdef MVS /* Very nasty special case for MVS. Just because the zipfile has been * opened for reading does not mean that we can actually read the data. * Typical JCL to create a zipfile is * * //ZIPFILE DD DISP=(NEW,CATLG),DSN=prefix.ZIP, * // SPACE=(CYL,(10,10)) * * That creates a VTOC entry with an end of file marker (DS1LSTAR) of zero. * Alas the VTOC end of file marker is only used when the file is opened in * append mode. When a file is opened in read mode, the "other" end of file * marker is used, a zero length data block signals end of file when reading. * With a brand new file which has not been written to yet, it is undefined * what you read off the disk. In fact you read whatever data was in the same * disk tracks before the zipfile was allocated. You would be amazed at the * number of application programmers who still do not understand this. Makes * for interesting and semi-random errors, GIGO. * * Newer versions of SMS will automatically write a zero length block when a * file is allocated. However not all sites run SMS or they run older levels * so we cannot rely on that. The only safe thing to do is close the file, * open in append mode (we already know that the file exists), close it again, * reopen in read mode and try to read a data block. Opening and closing in * append mode will write a zero length block where DS1LSTAR points, making * sure that the VTOC and internal end of file markers are in sync. Then it * is safe to read data. If we cannot read one byte of data after all that, * it is a brand new zipfile and must not be read. */ if (readable) { char c; fclose(f); /* append mode */ if ((f = fopen(zipfile, "ab")) == NULL) { ZIPERR(ZE_OPEN, zipfile); } fclose(f); /* read mode again */ if ((f = fopen(zipfile, FOPR)) == NULL) { ZIPERR(ZE_OPEN, zipfile); } if (fread(&c, 1, 1, f) != 1) { /* no actual data */ readable = 0; fclose(f); } else{ fseek(f, 0, SEEK_SET); /* at least one byte in zipfile, back to the start */ } }#endif /* MVS */ if (readable) {#ifndef UTIL retval = (fix && !adjust) ? scanzipf_fix(f) : scanzipf_reg(f);#else retval = scanzipf_reg(f);#endif /* Done with zip file for now */ fclose(f); /* If one or more files, sort by name */ if (zcount) { struct zlist far * far *x; /* pointer into zsort array */ struct zlist far *z; /* pointer into zfiles linked list */ extent zl_size = zcount * sizeof(struct zlist far *); if (zl_size / sizeof(struct zlist far *) != zcount || (x = zsort = (struct zlist far **)malloc(zl_size)) == NULL) return ZE_MEM; for (z = zfiles; z != NULL; z = z->nxt) *x++ = z; qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp); } } return retval;}int putlocal(z, f)struct zlist far *z; /* zip entry to write local header for */FILE *f; /* file to write to *//* Write a local header described by *z to file *f. Return an error code in the ZE_ class. */{ PUTLG(LOCSIG, f); PUTSH(z->ver, f); PUTSH(z->lflg, f); PUTSH(z->how, f); PUTLG(z->tim, f); PUTLG(z->crc, f); PUTLG(z->siz, f); PUTLG(z->len, f); PUTSH(z->nam, f); PUTSH(z->ext, f); if (fwrite(z->iname, 1, z->nam, f) != z->nam || (z->ext && fwrite(z->extra, 1, z->ext, f) != z->ext)) return ZE_TEMP; return ZE_OK;}int putextended(z, f)struct zlist far *z; /* zip entry to write local header for */FILE *f; /* file to write to *//* Write an extended local header described by *z to file *f. * Return an error code in the ZE_ class. */{ PUTLG(EXTLOCSIG, f); PUTLG(z->crc, f); PUTLG(z->siz, f); PUTLG(z->len, f); return ZE_OK;}int putcentral(z, f)struct zlist far *z; /* zip entry to write central header for */FILE *f; /* file to write to *//* Write a central header described by *z to file *f. Return an error code in the ZE_ class. */{ PUTLG(CENSIG, f); PUTSH(z->vem, f); PUTSH(z->ver, f); PUTSH(z->flg, f); PUTSH(z->how, f);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -