?? zipfile.c
字號:
return ferror(f) ? ZE_READ : ZE_EOF; } } /* Point to start of header list and read central headers */ z = zfiles; s = p; /* save start of central */ if (fix) { 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"); err(ZE_FORM, NULL); } } } else while (LG(b) == CENSIG) { if (z == NULL) { warn("extraneous central header signature", ""); return ZE_FORM; } /* Read central header */ if (fread(b, CENHEAD, 1, f) != 1) return ferror(f) ? ZE_READ : ZE_EOF; /* Compare local header with that part of central header (except for the reserved bits in the general purpose flags and except for length of extra fields--authentication can make these different in central and local headers) */ z->lflg = SH(LOCFLG + (uch far *)z); /* Save reserved bits */ r = b[CENFLG+1]; ((uch far *)z)[LOCFLG+1] &= 0x1f; /* Zero out reserved bits */ b[CENFLG+1] &= 0x1f; for (m = 0, u = (char far *)z, n = 0; n < LOCHEAD - 2; n++) if (u[n] != b[n+2]) { if (!m && noisy) warn("local and central headers differ for ", z->zname); m = 1; sprintf(errbuf, " offset %d--local = %02x, central = %02x", n, (uch)u[n], (uch)b[n+2]); if (noisy) warn(errbuf, ""); b[n+2] = u[n]; /* fix the zipfile */ } if (m) return ZE_FORM; b[CENFLG+1] = r; /* Restore reserved bits */ /* Overwrite local header with translated central header */ z->vem = SH(CENVEM + b); z->ver = SH(CENVER + b); z->flg = SH(CENFLG + b); /* may be different from z->lflg */ z->how = SH(CENHOW + b); z->tim = LG(CENTIM + b); /* time and date into one long */ z->crc = LG(CENCRC + b); z->siz = LG(CENSIZ + b); z->len = LG(CENLEN + b); z->nam = SH(CENNAM + b); 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->dosflag = (z->vem & 0xff00) == 0; if (z->off != LG(CENOFF + b)) { warn("local offset in central header incorrect for ", z->zname); return ZE_FORM; } /* Compare name and extra fields and read comment field */ if ((t = malloc(z->nam)) == NULL) return ZE_MEM; if (fread(t, z->nam, 1, f) != 1) { free((voidp *)t); return ferror(f) ? ZE_READ : ZE_EOF; } if (memcmp(t, z->zname, z->nam)) { free((voidp *)t); warn("names in local and central differ for ", z->zname); return ZE_FORM; } free((voidp *)t); if (z->cext) { if ((z->cextra = malloc(z->cext)) == NULL) return ZE_MEM; if (fread(z->cextra, z->cext, 1, f) != 1) { free((voidp *)(z->cextra)); return ferror(f) ? ZE_READ : ZE_EOF; } if (z->ext == z->cext && memcmp(z->extra, z->cextra, z->ext) == 0) { free((voidp *)(z->cextra)); z->cextra = z->extra; } } if (z->com) { if ((z->comment = malloc(z->com)) == NULL) return ZE_MEM; if (fread(z->comment, z->com, 1, f) != 1) { free((voidp *)(z->comment)); return ferror(f) ? ZE_READ : ZE_EOF; } } /* Note oddities */ if (verbose) { if (z->vem != 10 && z->vem != 11 && z->vem != 20 && (n = z->vem >> 8) != 3 && n != 2 && n != 6 && n != 0) { sprintf(errbuf, "made by version %d.%d on system type %d: ", (ush)(z->vem & 0xff) / (ush)10, (ush)(z->vem & 0xff) % (ush)10, z->vem >> 8); warn(errbuf, z->zname); } if (z->ver != 10 && z->ver != 11 && z->ver != 20) { sprintf(errbuf, "needs unzip %d.%d on system type %d: ", (ush)(z->ver & 0xff) / (ush)10, (ush)(z->ver & 0xff) % (ush)10, z->ver >> 8); warn(errbuf, z->zname); } if (z->flg != z->lflg) { sprintf(errbuf, "local flags = 0x%04x, central = 0x%04x: ", z->lflg, z->flg); warn(errbuf, z->zname); } else if (z->flg & ~0xf) { sprintf(errbuf, "undefined bits used in flags = 0x%04x: ", z->flg); warn(errbuf, z->zname); } if (z->how > DEFLATE) { sprintf(errbuf, "unknown compression method %u: ", z->how); warn(errbuf, z->zname); } if (z->dsk) { sprintf(errbuf, "starts on disk %u: ", z->dsk); warn(errbuf, z->zname); } if (z->att & ~1) { sprintf(errbuf, "unknown internal attributes = 0x%04x: ", z->att); warn(errbuf, z->zname); } if (((n = z->vem >> 8) != 3) && n != 2 && z->atx & ~0xffL) { sprintf(errbuf, "unknown external attributes = 0x%08lx: ", z->atx); warn(errbuf, z->zname); } if (z->ext || z->cext) if (z->ext == z->cext && z->extra == z->cextra) { sprintf(errbuf, "has %d bytes of extra data: ", z->ext); warn(errbuf, z->zname); } else { sprintf(errbuf, "local extra (%d bytes) != central extra (%d bytes): ", z->ext, z->cext); warn(errbuf, z->zname); } } /* Clear actions */ z->mark = 0; z->trash = 0; /* Update file offset */ p += 4 + CENHEAD + z->nam + z->cext + z->com; /* Advance to next header structure */ z = z->nxt; /* Read next signature */ if (fread(b, 4, 1, f) != 1) return ferror(f) ? ZE_READ : ZE_EOF; } /* Read end header */ if (!fix) { if (z != NULL || LG(b) != ENDSIG) { warn("missing end signature--probably not a zip file (did you", ""); warn("remember to use binary mode when you transferred it?)", ""); return ZE_FORM; } 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)) warn("multiple disk information ignored", ""); if (zcount != SH(ENDSUB + b)) { warn("count in end of central directory incorrect", ""); return ZE_FORM; } if (LG(ENDSIZ + b) != p - s) { warn("central directory size is incorrect (made by stzip?)", ""); /* stzip 0.9 gets this wrong, so be tolerant */ /* return ZE_FORM; */ } if (LG(ENDOFF + b) != s) { warn("central directory start is incorrect", ""); return ZE_FORM; } } cenbeg = s; zcomlen = fix ? 0 : SH(ENDCOM + b); if (zcomlen) { if ((zcomment = malloc(zcomlen)) == NULL) return ZE_MEM; if (fread(zcomment, zcomlen, 1, f) != 1) { free((voidp *)zcomment); return ferror(f) ? ZE_READ : ZE_EOF; } } if (zipbeg) { sprintf(errbuf, " has a preamble of %ld bytes", zipbeg); warn(zipfile, errbuf); } if (!fix && getc(f) != EOF) warn("garbage at end of zip file ignored", ""); /* 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;}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->zname, 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); PUTLG(z->tim, f); PUTLG(z->crc, f); PUTLG(z->siz, f); PUTLG(z->len, f); PUTSH(z->nam, f); PUTSH(z->cext, f); PUTSH(z->com, f); PUTSH(z->dsk, f); PUTSH(z->att, f); PUTLG(z->atx, f); PUTLG(z->off, f); if (fwrite(z->zname, 1, z->nam, f) != z->nam || (z->cext && fwrite(z->cextra, 1, z->cext, f) != z->cext) || (z->com && fwrite(z->comment, 1, z->com, f) != z->com)) return ZE_TEMP; return ZE_OK;}int putend(n, s, c, m, z, f)int n; /* number of entries in central directory */ulg s; /* size of central directory */ulg c; /* offset of central directory */extent m; /* length of zip file comment (0 if none) */char *z; /* zip file comment if m != 0 */FILE *f; /* file to write to *//* Write the end of central directory data to file *f. Return an error code in the ZE_ class. */{ PUTLG(ENDSIG, f); PUTSH(0, f); PUTSH(0, f); PUTSH(n, f); PUTSH(n, f); PUTLG(s, f); PUTLG(c, f); PUTSH(m, f); if (m && fwrite(z, 1, m, f) != m) return ZE_TEMP; return ZE_OK;}#ifndef UTILlocal void cutpath(p)char *p; /* path string *//* Cut the last path component off the name *p in place. * This should work on both internal and external names. */{ char *r; /* pointer to last path delimiter */#ifdef VMS /* change [w.x.y]z to [w.x]y.DIR */ if ((r = strrchr(p, ']')) != NULL) { *r = 0; if ((r = strrchr(p, '.')) != NULL) { *r = ']'; strcat(r, ".DIR;1"); /* this assumes a little padding--see PAD */ } else { *p = 0; } } else { *p = 0; }#endif /* ?VMS */ if ((r = strrchr(p, '/')) != NULL) *r = 0; else *p = 0;}int trash()/* Delete the compressed files and the directories that contained the deleted files, if empty. Return an error code in the ZE_ class. Failure of destroy() or deletedir() is ignored. */{ extent i; /* counter on deleted names */ extent n; /* number of directories to delete */ struct zlist far **s; /* table of zip entries to handle, sorted */ struct zlist far *z; /* current zip entry */ /* Delete marked names and count directories */ n = 0; for (z = zfiles; z != NULL; z = z->nxt) if (z->mark || z->trash) { z->mark = 1; if (z->zname[z->nam - 1] != '/') { /* don't unlink directory */ if (verbose) fprintf(mesg, "zip diagnostic: trashing file %s\n", z->name); destroy(z->name); /* Try to delete all paths that lead up to marked names. This is * necessary only without the -D option. */ if (!dirnames) { cutpath(z->name); cutpath(z->zname); if (z->zname[0] != '\0') { strcat(z->zname, "/"); } z->nam = strlen(z->zname); if (z->nam > 0) n++; } } else { n++; } } /* Construct the list of all marked directories. Some may be duplicated * if -D was used. */ if (n) { if ((s = (struct zlist far **)malloc(n*sizeof(struct zlist far *))) == NULL) return ZE_MEM; n = 0; for (z = zfiles; z != NULL; z = z->nxt) { if (z->mark && z->nam > 0 && z->zname[z->nam - 1] == '/' && (n == 0 || strcmp(z->zname, s[n-1]->zname) != 0)) { s[n++] = z; } } /* Sort the files in reverse order to get subdirectories first. * To avoid problems with strange naming conventions as in VMS, * we sort on the internal names, so x/y/z will always be removed * before x/y. On VMS, x/y/z > x/y but [x.y.z] < [x.y] */ qsort((char *)s, n, sizeof(struct zlist far *), rqcmp); for (i = 0; i < n; i++) { char *p = s[i]->name; if (*p == '\0') continue; if (p[strlen(p) - 1] == '/') { /* keep VMS [x.y]z.dir;1 intact */ p[strlen(p) - 1] = '\0'; } if (i == 0 || strcmp(s[i]->zname, s[i-1]->zname) != 0) { if (verbose) { fprintf(mesg, "zip diagnostic: trashing directory %s (if empty)\n", s[i]->name); } deletedir(s[i]->name); } } free((voidp *)s); } return ZE_OK;}#endif /* !UTIL */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -