/* * print the table of contents from the "central directory structure" */ static int unztable(Biobuf *bin, char *file) { ZipHead zh; int entries; entries = findCDir(bin, file); if(entries < 0) return 0; if(verbose > 1) print("%d items in the archive\n", entries); while(entries-- > 0){ if(setjmp(zjmp)){ free(zh.file); return 0; } memset(&zh, 0, sizeof(zh)); if(!cheader(bin, &zh)) return 1; if(wantFile(zh.file)){ if(verbose) print("%-32s %10lu %s", zh.file, zh.uncsize, ctime(msdos2time(zh.modtime, zh.moddate))); else print("%s\n", zh.file); if(verbose > 1){ print("\tmade by os %d vers %d.%d\n", zh.madeos, zh.madevers/10, zh.madevers % 10); print("\textract by os %d vers %d.%d\n", zh.extos, zh.extvers/10, zh.extvers % 10); print("\tflags %x\n", zh.flags); print("\tmethod %d\n", zh.meth); print("\tmod time %d\n", zh.modtime); print("\tmod date %d\n", zh.moddate); print("\tcrc %lx\n", zh.crc); print("\tcompressed size %lu\n", zh.csize); print("\tuncompressed size %lu\n", zh.uncsize); print("\tinternal attributes %x\n", zh.iattr); print("\texternal attributes %lx\n", zh.eattr); print("\tstarts at %ld\n", zh.off); } } free(zh.file); zh.file = nil; } return 1; }
void populate(char *name) { char *p; Fileinf f; ZipHead zh; int ok, entries; crctab = mkcrctab(ZCrcPoly); ok = inflateinit(); if(ok != FlateOk) sysfatal("inflateinit failed: %s", flateerr(ok)); bin = Bopen(name, OREAD); if (bin == nil) error("Can't open argument file"); entries = findCDir(bin); if(entries < 0) sysfatal("empty file"); while(entries-- > 0){ memset(&zh, 0, sizeof(zh)); if(!cheader(bin, &zh)) break; f.addr = zh.off; if(zh.iattr & IS_TEXT) f.addr |= High64; f.mode = (zh.madevers == IS_MSDOS && zh.eattr & IS_RDONLY)? 0444: 0644; if (zh.meth == 0 && zh.uncsize == 0){ p = strchr(zh.file, '\0'); if(p > zh.file && p[-1] == '/') f.mode |= (DMDIR | 0111); } f.uid = 0; f.gid = 0; f.size = zh.uncsize; f.mdate = msdos2time(zh.modtime, zh.moddate); f.name = zh.file + ((zh.file[0] == '/')? 1: 0); poppath(f, 1); free(zh.file); } return ; }
/* * extracts a single entry from a zip file * czh is the optional corresponding central directory entry */ static int unzipEntry(Biobuf *bin, ZipHead *czh) { Dir *d; ZipHead zh; char *p; int64_t off; int fd, isdir, ok, err; zh.file = nil; if(setjmp(zjmp)){ delfile = nil; free(zh.file); return -1; } memset(&zh, 0, sizeof(zh)); if(!header(bin, &zh)) return 0; ok = 1; isdir = 0; fd = -1; if(wantFile(zh.file)){ if(verbose) fprint(2, "extracting %s\n", zh.file); if(czh != nil && czh->extos == ZDos){ isdir = czh->eattr & ZDDir; if(isdir && zh.uncsize != 0) fprint(2, "unzip: ignoring directory data for %s\n", zh.file); } if(zh.meth == 0 && zh.uncsize == 0){ p = strchr(zh.file, '\0'); if(p > zh.file && p[-1] == '/') isdir = 1; } if(stdout){ if(ok && !isdir) fd = 1; }else if(isdir){ fd = create(zh.file, OREAD, DMDIR | 0775); if(fd < 0){ d = dirstat(zh.file); if(d == nil || (d->mode & DMDIR) != DMDIR){ fprint(2, "unzip: can't create directory %s: %r\n", zh.file); ok = 0; } free(d); } }else if(ok){ if(autodir) mkpdirs(zh.file); fd = create(zh.file, OWRITE, 0664); if(fd < 0){ fprint(2, "unzip: can't create %s: %r\n", zh.file); ok = 0; }else delfile = zh.file; } } wlen = 0; rlen = 0; crc = 0; wbad = 0; if(zh.meth == 0){ if(!copyout(fd, bin, zh.csize)) error("copying data for %s failed: %r", zh.file); }else if(zh.meth == 8){ off = Boffset(bin); err = inflate((void*)fd, crcwrite, bin, (int(*)(void*))Bgetc); if(err != FlateOk) error("inflate failed: %s", flateerr(err)); rlen = Boffset(bin) - off; }else error("can't handle compression method %d for %s", zh.meth, zh.file); trailer(bin, &zh); if(zh.crc != crc) error("crc mismatch for %s", zh.file); if(zh.uncsize != wlen) error("output size mismatch for %s", zh.file); if(zh.csize != rlen) error("input size mismatch for %s", zh.file); delfile = nil; free(zh.file); if(fd >= 0 && !stdout){ if(settimes){ d = dirfstat(fd); if(d != nil){ d->mtime = msdos2time(zh.modtime, zh.moddate); if(d->mtime) dirfwstat(fd, d); } } close(fd); } return ok; }
/* * print the "local file header" table of contents */ static int sunztable(Biobuf *bin) { ZipHead zh; int64_t off; uint32_t hcrc, hcsize, huncsize; int ok, err; ok = 1; for(;;){ if(setjmp(zjmp)){ free(zh.file); return 0; } memset(&zh, 0, sizeof(zh)); if(!header(bin, &zh)) return ok; hcrc = zh.crc; hcsize = zh.csize; huncsize = zh.uncsize; wlen = 0; rlen = 0; crc = 0; wbad = 0; if(zh.meth == 0){ if(!copyout(-1, bin, zh.csize)) error("reading data for %s failed: %r", zh.file); }else if(zh.meth == 8){ off = Boffset(bin); err = inflate((void*)-1, crcwrite, bin, (int(*)(void*))Bgetc); if(err != FlateOk) error("inflate %s failed: %s", zh.file, flateerr(err)); rlen = Boffset(bin) - off; }else error("can't handle compression method %d for %s", zh.meth, zh.file); trailer(bin, &zh); if(wantFile(zh.file)){ if(verbose) print("%-32s %10lu %s", zh.file, zh.uncsize, ctime(msdos2time(zh.modtime, zh.moddate))); else print("%s\n", zh.file); if(verbose > 1){ print("\textract by os %d vers %d.%d\n", zh.extos, zh.extvers / 10, zh.extvers % 10); print("\tflags %x\n", zh.flags); print("\tmethod %d\n", zh.meth); print("\tmod time %d\n", zh.modtime); print("\tmod date %d\n", zh.moddate); print("\tcrc %lx\n", zh.crc); print("\tcompressed size %lu\n", zh.csize); print("\tuncompressed size %lu\n", zh.uncsize); if((zh.flags & ZTrailInfo) && (hcrc || hcsize || huncsize)){ print("\theader crc %lx\n", zh.crc); print("\theader compressed size %lu\n", zh.csize); print("\theader uncompressed size %lu\n", zh.uncsize); } } } if(zh.crc != crc) error("crc mismatch for %s", zh.file); if(zh.uncsize != wlen) error("output size mismatch for %s", zh.file); if(zh.csize != rlen) error("input size mismatch for %s", zh.file); free(zh.file); zh.file = nil; } }