17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <bio.h> 480ee5cbfSDavid du Colombier #include <flate.h> 57dd7cddfSDavid du Colombier #include "zip.h" 67dd7cddfSDavid du Colombier 77dd7cddfSDavid du Colombier enum 87dd7cddfSDavid du Colombier { 97dd7cddfSDavid du Colombier BufSize = 4096 107dd7cddfSDavid du Colombier }; 117dd7cddfSDavid du Colombier 127dd7cddfSDavid du Colombier static int cheader(Biobuf *bin, ZipHead *zh); 137dd7cddfSDavid du Colombier static int copyout(int ofd, Biobuf *bin, long len); 147dd7cddfSDavid du Colombier static int crcwrite(void *ofd, void *buf, int n); 157dd7cddfSDavid du Colombier static int findCDir(Biobuf *bin, char *file); 167dd7cddfSDavid du Colombier static int get1(Biobuf *b); 177dd7cddfSDavid du Colombier static int get2(Biobuf *b); 187dd7cddfSDavid du Colombier static ulong get4(Biobuf *b); 197dd7cddfSDavid du Colombier static char *getname(Biobuf *b, int len); 207dd7cddfSDavid du Colombier static int header(Biobuf *bin, ZipHead *zh); 217dd7cddfSDavid du Colombier static long msdos2time(int time, int date); 227dd7cddfSDavid du Colombier static int sunzip(Biobuf *bin); 237dd7cddfSDavid du Colombier static int sunztable(Biobuf *bin); 247dd7cddfSDavid du Colombier static void trailer(Biobuf *bin, ZipHead *zh); 257dd7cddfSDavid du Colombier static int unzip(Biobuf *bin, char *file); 267dd7cddfSDavid du Colombier static int unzipEntry(Biobuf *bin, ZipHead *czh); 277dd7cddfSDavid du Colombier static int unztable(Biobuf *bin, char *file); 287dd7cddfSDavid du Colombier static int wantFile(char *file); 297dd7cddfSDavid du Colombier 307dd7cddfSDavid du Colombier static void *emalloc(ulong); 317dd7cddfSDavid du Colombier static void error(char*, ...); 327dd7cddfSDavid du Colombier #pragma varargck argpos error 1 337dd7cddfSDavid du Colombier 347dd7cddfSDavid du Colombier static Biobuf bin; 357dd7cddfSDavid du Colombier static ulong crc; 3680ee5cbfSDavid du Colombier static ulong *crctab; 377dd7cddfSDavid du Colombier static int debug; 387dd7cddfSDavid du Colombier static char *delfile; 397dd7cddfSDavid du Colombier static int lower; 407dd7cddfSDavid du Colombier static int nwant; 417dd7cddfSDavid du Colombier static ulong rlen; 427dd7cddfSDavid du Colombier static int settimes; 437dd7cddfSDavid du Colombier static int stdout; 447dd7cddfSDavid du Colombier static int verbose; 457dd7cddfSDavid du Colombier static char **want; 467dd7cddfSDavid du Colombier static int wbad; 477dd7cddfSDavid du Colombier static ulong wlen; 487dd7cddfSDavid du Colombier static jmp_buf zjmp; 49c03fc8d3SDavid du Colombier static jmp_buf seekjmp; 50*21abd8f2SDavid du Colombier static int autodir; 517dd7cddfSDavid du Colombier 527dd7cddfSDavid du Colombier static void 537dd7cddfSDavid du Colombier usage(void) 547dd7cddfSDavid du Colombier { 557dd7cddfSDavid du Colombier fprint(2, "usage: unzip [-tsv] [-f zipfile] [file ...]\n"); 567dd7cddfSDavid du Colombier exits("usage"); 577dd7cddfSDavid du Colombier } 587dd7cddfSDavid du Colombier 597dd7cddfSDavid du Colombier void 607dd7cddfSDavid du Colombier main(int argc, char *argv[]) 617dd7cddfSDavid du Colombier { 627dd7cddfSDavid du Colombier char *zfile; 637dd7cddfSDavid du Colombier int fd, ok, table, stream; 647dd7cddfSDavid du Colombier 657dd7cddfSDavid du Colombier table = 0; 667dd7cddfSDavid du Colombier stream = 0; 677dd7cddfSDavid du Colombier zfile = nil; 687dd7cddfSDavid du Colombier ARGBEGIN{ 69*21abd8f2SDavid du Colombier case 'a': 70*21abd8f2SDavid du Colombier autodir++; 71*21abd8f2SDavid du Colombier break; 727dd7cddfSDavid du Colombier case 'D': 737dd7cddfSDavid du Colombier debug++; 747dd7cddfSDavid du Colombier break; 757dd7cddfSDavid du Colombier case 'c': 767dd7cddfSDavid du Colombier stdout++; 777dd7cddfSDavid du Colombier break; 787dd7cddfSDavid du Colombier case 'i': 797dd7cddfSDavid du Colombier lower++; 807dd7cddfSDavid du Colombier break; 817dd7cddfSDavid du Colombier case 'f': 827dd7cddfSDavid du Colombier zfile = ARGF(); 837dd7cddfSDavid du Colombier if(zfile == nil) 847dd7cddfSDavid du Colombier usage(); 857dd7cddfSDavid du Colombier break; 867dd7cddfSDavid du Colombier case 's': 877dd7cddfSDavid du Colombier stream++; 887dd7cddfSDavid du Colombier break; 897dd7cddfSDavid du Colombier case 't': 907dd7cddfSDavid du Colombier table++; 917dd7cddfSDavid du Colombier break; 927dd7cddfSDavid du Colombier case 'T': 937dd7cddfSDavid du Colombier settimes++; 947dd7cddfSDavid du Colombier break; 957dd7cddfSDavid du Colombier case 'v': 967dd7cddfSDavid du Colombier verbose++; 977dd7cddfSDavid du Colombier break; 987dd7cddfSDavid du Colombier default: 997dd7cddfSDavid du Colombier usage(); 1007dd7cddfSDavid du Colombier break; 1017dd7cddfSDavid du Colombier }ARGEND 1027dd7cddfSDavid du Colombier 1037dd7cddfSDavid du Colombier nwant = argc; 1047dd7cddfSDavid du Colombier want = argv; 1057dd7cddfSDavid du Colombier 10680ee5cbfSDavid du Colombier crctab = mkcrctab(ZCrcPoly); 10780ee5cbfSDavid du Colombier ok = inflateinit(); 10880ee5cbfSDavid du Colombier if(ok != FlateOk) 10980ee5cbfSDavid du Colombier sysfatal("inflateinit failed: %s\n", flateerr(ok)); 1107dd7cddfSDavid du Colombier 1117dd7cddfSDavid du Colombier if(zfile == nil){ 1127dd7cddfSDavid du Colombier Binit(&bin, 0, OREAD); 1137dd7cddfSDavid du Colombier zfile = "<stdin>"; 1147dd7cddfSDavid du Colombier }else{ 1157dd7cddfSDavid du Colombier fd = open(zfile, OREAD); 1167dd7cddfSDavid du Colombier if(fd < 0) 1177dd7cddfSDavid du Colombier sysfatal("can't open %s: %r", zfile); 1187dd7cddfSDavid du Colombier Binit(&bin, fd, OREAD); 1197dd7cddfSDavid du Colombier } 1207dd7cddfSDavid du Colombier 121c03fc8d3SDavid du Colombier if(setjmp(seekjmp)){ 122c03fc8d3SDavid du Colombier fprint(2, "trying to re-run assuming -s\n"); 123c03fc8d3SDavid du Colombier stream = 1; 124c03fc8d3SDavid du Colombier Bseek(&bin, 0, 0); 125c03fc8d3SDavid du Colombier } 126c03fc8d3SDavid du Colombier 1277dd7cddfSDavid du Colombier if(table){ 1287dd7cddfSDavid du Colombier if(stream) 1297dd7cddfSDavid du Colombier ok = sunztable(&bin); 1307dd7cddfSDavid du Colombier else 1317dd7cddfSDavid du Colombier ok = unztable(&bin, zfile); 1327dd7cddfSDavid du Colombier }else{ 1337dd7cddfSDavid du Colombier if(stream) 1347dd7cddfSDavid du Colombier ok = sunzip(&bin); 1357dd7cddfSDavid du Colombier else 1367dd7cddfSDavid du Colombier ok = unzip(&bin, zfile); 1377dd7cddfSDavid du Colombier } 1387dd7cddfSDavid du Colombier 1397dd7cddfSDavid du Colombier exits(ok ? nil: "errors"); 1407dd7cddfSDavid du Colombier } 1417dd7cddfSDavid du Colombier 1427dd7cddfSDavid du Colombier /* 1437dd7cddfSDavid du Colombier * print the table of contents from the "central directory structure" 1447dd7cddfSDavid du Colombier */ 1457dd7cddfSDavid du Colombier static int 1467dd7cddfSDavid du Colombier unztable(Biobuf *bin, char *file) 1477dd7cddfSDavid du Colombier { 1487dd7cddfSDavid du Colombier ZipHead zh; 1497dd7cddfSDavid du Colombier int entries; 1507dd7cddfSDavid du Colombier 1517dd7cddfSDavid du Colombier entries = findCDir(bin, file); 1527dd7cddfSDavid du Colombier if(entries < 0) 1537dd7cddfSDavid du Colombier return 0; 1547dd7cddfSDavid du Colombier 1557dd7cddfSDavid du Colombier if(verbose > 1) 1567dd7cddfSDavid du Colombier print("%d items in the archive\n", entries); 1577dd7cddfSDavid du Colombier while(entries-- > 0){ 1587dd7cddfSDavid du Colombier if(setjmp(zjmp)){ 1597dd7cddfSDavid du Colombier free(zh.file); 1607dd7cddfSDavid du Colombier return 0; 1617dd7cddfSDavid du Colombier } 1627dd7cddfSDavid du Colombier 1637dd7cddfSDavid du Colombier memset(&zh, 0, sizeof(zh)); 1647dd7cddfSDavid du Colombier if(!cheader(bin, &zh)) 1657dd7cddfSDavid du Colombier return 1; 1667dd7cddfSDavid du Colombier 1677dd7cddfSDavid du Colombier if(wantFile(zh.file)){ 1687dd7cddfSDavid du Colombier if(verbose) 1697dd7cddfSDavid du Colombier print("%-32s %10lud %s", zh.file, zh.uncsize, ctime(msdos2time(zh.modtime, zh.moddate))); 1707dd7cddfSDavid du Colombier else 1717dd7cddfSDavid du Colombier print("%s\n", zh.file); 1727dd7cddfSDavid du Colombier 1737dd7cddfSDavid du Colombier if(verbose > 1){ 1747dd7cddfSDavid du Colombier print("\tmade by os %d vers %d.%d\n", zh.madeos, zh.madevers/10, zh.madevers % 10); 1757dd7cddfSDavid du Colombier print("\textract by os %d vers %d.%d\n", zh.extos, zh.extvers/10, zh.extvers % 10); 1767dd7cddfSDavid du Colombier print("\tflags %x\n", zh.flags); 1777dd7cddfSDavid du Colombier print("\tmethod %d\n", zh.meth); 1787dd7cddfSDavid du Colombier print("\tmod time %d\n", zh.modtime); 1797dd7cddfSDavid du Colombier print("\tmod date %d\n", zh.moddate); 1807dd7cddfSDavid du Colombier print("\tcrc %lux\n", zh.crc); 1817dd7cddfSDavid du Colombier print("\tcompressed size %lud\n", zh.csize); 1827dd7cddfSDavid du Colombier print("\tuncompressed size %lud\n", zh.uncsize); 1837dd7cddfSDavid du Colombier print("\tinternal attributes %ux\n", zh.iattr); 1847dd7cddfSDavid du Colombier print("\texternal attributes %lux\n", zh.eattr); 1857dd7cddfSDavid du Colombier print("\tstarts at %ld\n", zh.off); 1867dd7cddfSDavid du Colombier } 1877dd7cddfSDavid du Colombier } 1887dd7cddfSDavid du Colombier 1897dd7cddfSDavid du Colombier free(zh.file); 1907dd7cddfSDavid du Colombier zh.file = nil; 1917dd7cddfSDavid du Colombier } 1927dd7cddfSDavid du Colombier 1937dd7cddfSDavid du Colombier return 1; 1947dd7cddfSDavid du Colombier } 1957dd7cddfSDavid du Colombier 1967dd7cddfSDavid du Colombier /* 1977dd7cddfSDavid du Colombier * print the "local file header" table of contents 1987dd7cddfSDavid du Colombier */ 1997dd7cddfSDavid du Colombier static int 2007dd7cddfSDavid du Colombier sunztable(Biobuf *bin) 2017dd7cddfSDavid du Colombier { 2027dd7cddfSDavid du Colombier ZipHead zh; 2037dd7cddfSDavid du Colombier vlong off; 2047dd7cddfSDavid du Colombier ulong hcrc, hcsize, huncsize; 20580ee5cbfSDavid du Colombier int ok, err; 2067dd7cddfSDavid du Colombier 2077dd7cddfSDavid du Colombier ok = 1; 2087dd7cddfSDavid du Colombier for(;;){ 2097dd7cddfSDavid du Colombier if(setjmp(zjmp)){ 2107dd7cddfSDavid du Colombier free(zh.file); 2117dd7cddfSDavid du Colombier return 0; 2127dd7cddfSDavid du Colombier } 2137dd7cddfSDavid du Colombier 2147dd7cddfSDavid du Colombier memset(&zh, 0, sizeof(zh)); 2157dd7cddfSDavid du Colombier if(!header(bin, &zh)) 2167dd7cddfSDavid du Colombier return ok; 2177dd7cddfSDavid du Colombier 2187dd7cddfSDavid du Colombier hcrc = zh.crc; 2197dd7cddfSDavid du Colombier hcsize = zh.csize; 2207dd7cddfSDavid du Colombier huncsize = zh.uncsize; 2217dd7cddfSDavid du Colombier 2227dd7cddfSDavid du Colombier wlen = 0; 2237dd7cddfSDavid du Colombier rlen = 0; 2247dd7cddfSDavid du Colombier crc = 0; 2257dd7cddfSDavid du Colombier wbad = 0; 2267dd7cddfSDavid du Colombier 2277dd7cddfSDavid du Colombier if(zh.meth == 0){ 2287dd7cddfSDavid du Colombier if(!copyout(-1, bin, zh.csize)) 2297dd7cddfSDavid du Colombier error("reading data for %s failed: %r", zh.file); 2307dd7cddfSDavid du Colombier }else if(zh.meth == 8){ 2317dd7cddfSDavid du Colombier off = Boffset(bin); 23280ee5cbfSDavid du Colombier err = inflate((void*)-1, crcwrite, bin, (int(*)(void*))Bgetc); 23380ee5cbfSDavid du Colombier if(err != FlateOk) 23480ee5cbfSDavid du Colombier error("inflate %s failed: %s", zh.file, flateerr(err)); 2357dd7cddfSDavid du Colombier rlen = Boffset(bin) - off; 2367dd7cddfSDavid du Colombier }else 2377dd7cddfSDavid du Colombier error("can't handle compression method %d for %s", zh.meth, zh.file); 2387dd7cddfSDavid du Colombier 2397dd7cddfSDavid du Colombier trailer(bin, &zh); 2407dd7cddfSDavid du Colombier 2417dd7cddfSDavid du Colombier if(wantFile(zh.file)){ 2427dd7cddfSDavid du Colombier if(verbose) 2437dd7cddfSDavid du Colombier print("%-32s %10lud %s", zh.file, zh.uncsize, ctime(msdos2time(zh.modtime, zh.moddate))); 2447dd7cddfSDavid du Colombier else 2457dd7cddfSDavid du Colombier print("%s\n", zh.file); 2467dd7cddfSDavid du Colombier 2477dd7cddfSDavid du Colombier if(verbose > 1){ 2487dd7cddfSDavid du Colombier print("\textract by os %d vers %d.%d\n", zh.extos, zh.extvers / 10, zh.extvers % 10); 2497dd7cddfSDavid du Colombier print("\tflags %x\n", zh.flags); 2507dd7cddfSDavid du Colombier print("\tmethod %d\n", zh.meth); 2517dd7cddfSDavid du Colombier print("\tmod time %d\n", zh.modtime); 2527dd7cddfSDavid du Colombier print("\tmod date %d\n", zh.moddate); 2537dd7cddfSDavid du Colombier print("\tcrc %lux\n", zh.crc); 2547dd7cddfSDavid du Colombier print("\tcompressed size %lud\n", zh.csize); 2557dd7cddfSDavid du Colombier print("\tuncompressed size %lud\n", zh.uncsize); 2567dd7cddfSDavid du Colombier if((zh.flags & ZTrailInfo) && (hcrc || hcsize || huncsize)){ 2577dd7cddfSDavid du Colombier print("\theader crc %lux\n", zh.crc); 2587dd7cddfSDavid du Colombier print("\theader compressed size %lud\n", zh.csize); 2597dd7cddfSDavid du Colombier print("\theader uncompressed size %lud\n", zh.uncsize); 2607dd7cddfSDavid du Colombier } 2617dd7cddfSDavid du Colombier } 2627dd7cddfSDavid du Colombier } 2637dd7cddfSDavid du Colombier 2647dd7cddfSDavid du Colombier if(zh.crc != crc) 2657dd7cddfSDavid du Colombier error("crc mismatch for %s", zh.file); 2667dd7cddfSDavid du Colombier if(zh.uncsize != wlen) 2677dd7cddfSDavid du Colombier error("output size mismatch for %s", zh.file); 2687dd7cddfSDavid du Colombier if(zh.csize != rlen) 2697dd7cddfSDavid du Colombier error("input size mismatch for %s", zh.file); 2707dd7cddfSDavid du Colombier 2717dd7cddfSDavid du Colombier 2727dd7cddfSDavid du Colombier free(zh.file); 2737dd7cddfSDavid du Colombier zh.file = nil; 2747dd7cddfSDavid du Colombier } 2757dd7cddfSDavid du Colombier } 2767dd7cddfSDavid du Colombier 2777dd7cddfSDavid du Colombier /* 2787dd7cddfSDavid du Colombier * extract files using the info in the central directory structure 2797dd7cddfSDavid du Colombier */ 2807dd7cddfSDavid du Colombier static int 2817dd7cddfSDavid du Colombier unzip(Biobuf *bin, char *file) 2827dd7cddfSDavid du Colombier { 2837dd7cddfSDavid du Colombier ZipHead zh; 2847dd7cddfSDavid du Colombier vlong off; 2857dd7cddfSDavid du Colombier int ok, eok, entries; 2867dd7cddfSDavid du Colombier 2877dd7cddfSDavid du Colombier entries = findCDir(bin, file); 2887dd7cddfSDavid du Colombier if(entries < 0) 2897dd7cddfSDavid du Colombier return 0; 2907dd7cddfSDavid du Colombier 2917dd7cddfSDavid du Colombier ok = 1; 2927dd7cddfSDavid du Colombier while(entries-- > 0){ 2937dd7cddfSDavid du Colombier if(setjmp(zjmp)){ 2947dd7cddfSDavid du Colombier free(zh.file); 2957dd7cddfSDavid du Colombier return 0; 2967dd7cddfSDavid du Colombier } 2977dd7cddfSDavid du Colombier memset(&zh, 0, sizeof(zh)); 2987dd7cddfSDavid du Colombier if(!cheader(bin, &zh)) 2997dd7cddfSDavid du Colombier return ok; 3007dd7cddfSDavid du Colombier 3017dd7cddfSDavid du Colombier 3027dd7cddfSDavid du Colombier off = Boffset(bin); 3037dd7cddfSDavid du Colombier if(wantFile(zh.file)){ 3047dd7cddfSDavid du Colombier if(Bseek(bin, zh.off, 0) < 0){ 3057dd7cddfSDavid du Colombier fprint(2, "unzip: can't seek to start of %s, skipping\n", zh.file); 3067dd7cddfSDavid du Colombier ok = 0; 3077dd7cddfSDavid du Colombier }else{ 3087dd7cddfSDavid du Colombier eok = unzipEntry(bin, &zh); 3097dd7cddfSDavid du Colombier if(eok <= 0){ 3107dd7cddfSDavid du Colombier fprint(2, "unzip: skipping %s\n", zh.file); 3117dd7cddfSDavid du Colombier ok = 0; 3127dd7cddfSDavid du Colombier } 3137dd7cddfSDavid du Colombier } 3147dd7cddfSDavid du Colombier } 3157dd7cddfSDavid du Colombier 3167dd7cddfSDavid du Colombier free(zh.file); 3177dd7cddfSDavid du Colombier zh.file = nil; 3187dd7cddfSDavid du Colombier 3197dd7cddfSDavid du Colombier if(Bseek(bin, off, 0) < 0){ 3207dd7cddfSDavid du Colombier fprint(2, "unzip: can't seek to start of next entry, terminating extraction\n"); 3217dd7cddfSDavid du Colombier return 0; 3227dd7cddfSDavid du Colombier } 3237dd7cddfSDavid du Colombier } 3247dd7cddfSDavid du Colombier 3257dd7cddfSDavid du Colombier return ok; 3267dd7cddfSDavid du Colombier } 3277dd7cddfSDavid du Colombier 3287dd7cddfSDavid du Colombier /* 3297dd7cddfSDavid du Colombier * extract files using the info the "local file headers" 3307dd7cddfSDavid du Colombier */ 3317dd7cddfSDavid du Colombier static int 3327dd7cddfSDavid du Colombier sunzip(Biobuf *bin) 3337dd7cddfSDavid du Colombier { 3347dd7cddfSDavid du Colombier int eok; 3357dd7cddfSDavid du Colombier 3367dd7cddfSDavid du Colombier for(;;){ 3377dd7cddfSDavid du Colombier eok = unzipEntry(bin, nil); 3387dd7cddfSDavid du Colombier if(eok == 0) 3397dd7cddfSDavid du Colombier return 1; 3407dd7cddfSDavid du Colombier if(eok < 0) 3417dd7cddfSDavid du Colombier return 0; 3427dd7cddfSDavid du Colombier } 3437dd7cddfSDavid du Colombier } 3447dd7cddfSDavid du Colombier 345*21abd8f2SDavid du Colombier static int mkdirs(char *); 346*21abd8f2SDavid du Colombier 347*21abd8f2SDavid du Colombier /* 348*21abd8f2SDavid du Colombier * if any directories leading up to path don't exist, create them. 349*21abd8f2SDavid du Colombier * modifies but restores path. 350*21abd8f2SDavid du Colombier */ 351*21abd8f2SDavid du Colombier static int 352*21abd8f2SDavid du Colombier mkpdirs(char *path) 353*21abd8f2SDavid du Colombier { 354*21abd8f2SDavid du Colombier int rv = 0; 355*21abd8f2SDavid du Colombier char *sl = strrchr(path, '/'); 356*21abd8f2SDavid du Colombier print("%s\n", path); 357*21abd8f2SDavid du Colombier if (sl != nil) { 358*21abd8f2SDavid du Colombier *sl = '\0'; 359*21abd8f2SDavid du Colombier rv = mkdirs(path); 360*21abd8f2SDavid du Colombier *sl = '/'; 361*21abd8f2SDavid du Colombier } 362*21abd8f2SDavid du Colombier return rv; 363*21abd8f2SDavid du Colombier } 364*21abd8f2SDavid du Colombier 365*21abd8f2SDavid du Colombier /* 366*21abd8f2SDavid du Colombier * if path or any directories leading up to it don't exist, create them. 367*21abd8f2SDavid du Colombier * modifies but restores path. 368*21abd8f2SDavid du Colombier */ 369*21abd8f2SDavid du Colombier static int 370*21abd8f2SDavid du Colombier mkdirs(char *path) 371*21abd8f2SDavid du Colombier { 372*21abd8f2SDavid du Colombier int fd; 373*21abd8f2SDavid du Colombier 374*21abd8f2SDavid du Colombier if (access(path, AEXIST) >= 0) 375*21abd8f2SDavid du Colombier return 0; 376*21abd8f2SDavid du Colombier 377*21abd8f2SDavid du Colombier /* make presumed-missing intermediate directories */ 378*21abd8f2SDavid du Colombier if (mkpdirs(path) < 0) 379*21abd8f2SDavid du Colombier return -1; 380*21abd8f2SDavid du Colombier 381*21abd8f2SDavid du Colombier /* make final directory */ 382*21abd8f2SDavid du Colombier fd = create(path, OREAD, 0755|DMDIR); 383*21abd8f2SDavid du Colombier if (fd < 0) 384*21abd8f2SDavid du Colombier /* 385*21abd8f2SDavid du Colombier * we may have lost a race; if the directory now exists, 386*21abd8f2SDavid du Colombier * it's okay. 387*21abd8f2SDavid du Colombier */ 388*21abd8f2SDavid du Colombier return access(path, AEXIST) < 0? -1: 0; 389*21abd8f2SDavid du Colombier close(fd); 390*21abd8f2SDavid du Colombier return 0; 391*21abd8f2SDavid du Colombier } 392*21abd8f2SDavid du Colombier 393*21abd8f2SDavid du Colombier 3947dd7cddfSDavid du Colombier /* 3957dd7cddfSDavid du Colombier * extracts a single entry from a zip file 3967dd7cddfSDavid du Colombier * czh is the optional corresponding central directory entry 3977dd7cddfSDavid du Colombier */ 3987dd7cddfSDavid du Colombier static int 3997dd7cddfSDavid du Colombier unzipEntry(Biobuf *bin, ZipHead *czh) 4007dd7cddfSDavid du Colombier { 4019a747e4fSDavid du Colombier Dir *d; 4027dd7cddfSDavid du Colombier ZipHead zh; 4037dd7cddfSDavid du Colombier char *p; 4047dd7cddfSDavid du Colombier vlong off; 40580ee5cbfSDavid du Colombier int fd, isdir, ok, err; 4067dd7cddfSDavid du Colombier 4077dd7cddfSDavid du Colombier zh.file = nil; 4087dd7cddfSDavid du Colombier if(setjmp(zjmp)){ 4097dd7cddfSDavid du Colombier delfile = nil; 4107dd7cddfSDavid du Colombier free(zh.file); 4117dd7cddfSDavid du Colombier return -1; 4127dd7cddfSDavid du Colombier } 4137dd7cddfSDavid du Colombier 4147dd7cddfSDavid du Colombier memset(&zh, 0, sizeof(zh)); 4157dd7cddfSDavid du Colombier if(!header(bin, &zh)) 4167dd7cddfSDavid du Colombier return 0; 4177dd7cddfSDavid du Colombier 4187dd7cddfSDavid du Colombier ok = 1; 4197dd7cddfSDavid du Colombier isdir = 0; 4207dd7cddfSDavid du Colombier 4217dd7cddfSDavid du Colombier fd = -1; 4227dd7cddfSDavid du Colombier if(wantFile(zh.file)){ 4237dd7cddfSDavid du Colombier if(verbose) 4247dd7cddfSDavid du Colombier fprint(2, "extracting %s\n", zh.file); 4257dd7cddfSDavid du Colombier 4267dd7cddfSDavid du Colombier if(czh != nil && czh->extos == ZDos){ 4277dd7cddfSDavid du Colombier isdir = czh->eattr & ZDDir; 4287dd7cddfSDavid du Colombier if(isdir && zh.uncsize != 0) 4297dd7cddfSDavid du Colombier fprint(2, "unzip: ignoring directory data for %s\n", zh.file); 430d9dc5dd1SDavid du Colombier } 431d9dc5dd1SDavid du Colombier if(zh.meth == 0 && zh.uncsize == 0){ 4327dd7cddfSDavid du Colombier p = strchr(zh.file, '\0'); 4337dd7cddfSDavid du Colombier if(p > zh.file && p[-1] == '/') 4347dd7cddfSDavid du Colombier isdir = 1; 4357dd7cddfSDavid du Colombier } 4367dd7cddfSDavid du Colombier 4377dd7cddfSDavid du Colombier if(stdout){ 4387dd7cddfSDavid du Colombier if(ok && !isdir) 4397dd7cddfSDavid du Colombier fd = 1; 4407dd7cddfSDavid du Colombier }else if(isdir){ 4419a747e4fSDavid du Colombier fd = create(zh.file, OREAD, DMDIR | 0775); 4427dd7cddfSDavid du Colombier if(fd < 0){ 4439a747e4fSDavid du Colombier d = dirstat(zh.file); 4449a747e4fSDavid du Colombier if(d == nil || (d->mode & DMDIR) != DMDIR){ 4457dd7cddfSDavid du Colombier fprint(2, "unzip: can't create directory %s: %r\n", zh.file); 4467dd7cddfSDavid du Colombier ok = 0; 4477dd7cddfSDavid du Colombier } 4489a747e4fSDavid du Colombier free(d); 4497dd7cddfSDavid du Colombier } 4507dd7cddfSDavid du Colombier }else if(ok){ 451*21abd8f2SDavid du Colombier if(autodir) 452*21abd8f2SDavid du Colombier mkpdirs(zh.file); 4537dd7cddfSDavid du Colombier fd = create(zh.file, OWRITE, 0664); 4547dd7cddfSDavid du Colombier if(fd < 0){ 4557dd7cddfSDavid du Colombier fprint(2, "unzip: can't create %s: %r\n", zh.file); 4567dd7cddfSDavid du Colombier ok = 0; 4577dd7cddfSDavid du Colombier }else 4587dd7cddfSDavid du Colombier delfile = zh.file; 4597dd7cddfSDavid du Colombier } 4607dd7cddfSDavid du Colombier } 4617dd7cddfSDavid du Colombier 4627dd7cddfSDavid du Colombier wlen = 0; 4637dd7cddfSDavid du Colombier rlen = 0; 4647dd7cddfSDavid du Colombier crc = 0; 4657dd7cddfSDavid du Colombier wbad = 0; 4667dd7cddfSDavid du Colombier 4677dd7cddfSDavid du Colombier if(zh.meth == 0){ 4687dd7cddfSDavid du Colombier if(!copyout(fd, bin, zh.csize)) 4697dd7cddfSDavid du Colombier error("copying data for %s failed: %r", zh.file); 4707dd7cddfSDavid du Colombier }else if(zh.meth == 8){ 4717dd7cddfSDavid du Colombier off = Boffset(bin); 47280ee5cbfSDavid du Colombier err = inflate((void*)fd, crcwrite, bin, (int(*)(void*))Bgetc); 47380ee5cbfSDavid du Colombier if(err != FlateOk) 47480ee5cbfSDavid du Colombier error("inflate failed: %s", flateerr(err)); 4757dd7cddfSDavid du Colombier rlen = Boffset(bin) - off; 4767dd7cddfSDavid du Colombier }else 4777dd7cddfSDavid du Colombier error("can't handle compression method %d for %s", zh.meth, zh.file); 4787dd7cddfSDavid du Colombier 4797dd7cddfSDavid du Colombier trailer(bin, &zh); 4807dd7cddfSDavid du Colombier 4817dd7cddfSDavid du Colombier if(zh.crc != crc) 4827dd7cddfSDavid du Colombier error("crc mismatch for %s", zh.file); 4837dd7cddfSDavid du Colombier if(zh.uncsize != wlen) 4847dd7cddfSDavid du Colombier error("output size mismatch for %s", zh.file); 4857dd7cddfSDavid du Colombier if(zh.csize != rlen) 4867dd7cddfSDavid du Colombier error("input size mismatch for %s", zh.file); 4877dd7cddfSDavid du Colombier 4887dd7cddfSDavid du Colombier delfile = nil; 4897dd7cddfSDavid du Colombier free(zh.file); 4907dd7cddfSDavid du Colombier 4917dd7cddfSDavid du Colombier if(fd >= 0 && !stdout){ 4927dd7cddfSDavid du Colombier if(settimes){ 4939a747e4fSDavid du Colombier d = dirfstat(fd); 4949a747e4fSDavid du Colombier if(d != nil){ 4959a747e4fSDavid du Colombier d->mtime = msdos2time(zh.modtime, zh.moddate); 4969a747e4fSDavid du Colombier if(d->mtime) 4979a747e4fSDavid du Colombier dirfwstat(fd, d); 4987dd7cddfSDavid du Colombier } 4997dd7cddfSDavid du Colombier } 5007dd7cddfSDavid du Colombier close(fd); 5017dd7cddfSDavid du Colombier } 5027dd7cddfSDavid du Colombier 5037dd7cddfSDavid du Colombier return ok; 5047dd7cddfSDavid du Colombier } 5057dd7cddfSDavid du Colombier 5067dd7cddfSDavid du Colombier static int 5077dd7cddfSDavid du Colombier wantFile(char *file) 5087dd7cddfSDavid du Colombier { 5097dd7cddfSDavid du Colombier int i, n; 5107dd7cddfSDavid du Colombier 5117dd7cddfSDavid du Colombier if(nwant == 0) 5127dd7cddfSDavid du Colombier return 1; 5137dd7cddfSDavid du Colombier for(i = 0; i < nwant; i++){ 5147dd7cddfSDavid du Colombier if(strcmp(want[i], file) == 0) 5157dd7cddfSDavid du Colombier return 1; 5167dd7cddfSDavid du Colombier n = strlen(want[i]); 5177dd7cddfSDavid du Colombier if(strncmp(want[i], file, n) == 0 && file[n] == '/') 5187dd7cddfSDavid du Colombier return 1; 5197dd7cddfSDavid du Colombier } 5207dd7cddfSDavid du Colombier return 0; 5217dd7cddfSDavid du Colombier } 5227dd7cddfSDavid du Colombier 5237dd7cddfSDavid du Colombier /* 5247dd7cddfSDavid du Colombier * find the start of the central directory 5257dd7cddfSDavid du Colombier * returns the number of entries in the directory, 5267dd7cddfSDavid du Colombier * or -1 if there was an error 5277dd7cddfSDavid du Colombier */ 5287dd7cddfSDavid du Colombier static int 5297dd7cddfSDavid du Colombier findCDir(Biobuf *bin, char *file) 5307dd7cddfSDavid du Colombier { 5317dd7cddfSDavid du Colombier vlong ecoff; 532c03fc8d3SDavid du Colombier long off, size, m; 5337dd7cddfSDavid du Colombier int entries, zclen, dn, ds, de; 5347dd7cddfSDavid du Colombier 5357dd7cddfSDavid du Colombier ecoff = Bseek(bin, -ZECHeadSize, 2); 5367dd7cddfSDavid du Colombier if(ecoff < 0){ 537c03fc8d3SDavid du Colombier fprint(2, "unzip: can't seek to contents of %s\n", file); 538c03fc8d3SDavid du Colombier longjmp(seekjmp, 1); 5397dd7cddfSDavid du Colombier return -1; 5407dd7cddfSDavid du Colombier } 5417dd7cddfSDavid du Colombier if(setjmp(zjmp)) 5427dd7cddfSDavid du Colombier return -1; 5437dd7cddfSDavid du Colombier 544c03fc8d3SDavid du Colombier if((m=get4(bin)) != ZECHeader){ 545c03fc8d3SDavid du Colombier fprint(2, "unzip: bad magic number for table of contents of %s: %#.8lx\n", file, m); 546c03fc8d3SDavid du Colombier longjmp(seekjmp, 1); 5477dd7cddfSDavid du Colombier return -1; 5487dd7cddfSDavid du Colombier } 5497dd7cddfSDavid du Colombier dn = get2(bin); 5507dd7cddfSDavid du Colombier ds = get2(bin); 5517dd7cddfSDavid du Colombier de = get2(bin); 5527dd7cddfSDavid du Colombier entries = get2(bin); 5537dd7cddfSDavid du Colombier size = get4(bin); 5547dd7cddfSDavid du Colombier off = get4(bin); 5557dd7cddfSDavid du Colombier zclen = get2(bin); 5567dd7cddfSDavid du Colombier while(zclen-- > 0) 5577dd7cddfSDavid du Colombier get1(bin); 5587dd7cddfSDavid du Colombier 5597dd7cddfSDavid du Colombier if(verbose > 1){ 5607dd7cddfSDavid du Colombier print("table starts at %ld for %ld bytes\n", off, size); 5617dd7cddfSDavid du Colombier if(ecoff - size != off) 5627dd7cddfSDavid du Colombier print("\ttable should start at %lld-%ld=%lld\n", ecoff, size, ecoff-size); 5637dd7cddfSDavid du Colombier if(dn || ds || de != entries) 5647dd7cddfSDavid du Colombier print("\tcurrent disk=%d start disk=%d table entries on this disk=%d\n", dn, ds, de); 5657dd7cddfSDavid du Colombier } 5667dd7cddfSDavid du Colombier 5677dd7cddfSDavid du Colombier if(Bseek(bin, off, 0) != off){ 5687dd7cddfSDavid du Colombier fprint(2, "unzip: can't seek to start of contents of %s\n", file); 569c03fc8d3SDavid du Colombier longjmp(seekjmp, 1); 5707dd7cddfSDavid du Colombier return -1; 5717dd7cddfSDavid du Colombier } 5727dd7cddfSDavid du Colombier 5737dd7cddfSDavid du Colombier return entries; 5747dd7cddfSDavid du Colombier } 5757dd7cddfSDavid du Colombier 5767dd7cddfSDavid du Colombier static int 5777dd7cddfSDavid du Colombier cheader(Biobuf *bin, ZipHead *zh) 5787dd7cddfSDavid du Colombier { 5797dd7cddfSDavid du Colombier ulong v; 5807dd7cddfSDavid du Colombier int flen, xlen, fclen; 5817dd7cddfSDavid du Colombier 5827dd7cddfSDavid du Colombier v = get4(bin); 5837dd7cddfSDavid du Colombier if(v != ZCHeader){ 5847dd7cddfSDavid du Colombier if(v == ZECHeader) 5857dd7cddfSDavid du Colombier return 0; 5867dd7cddfSDavid du Colombier error("bad magic number %lux", v); 5877dd7cddfSDavid du Colombier } 5887dd7cddfSDavid du Colombier zh->madevers = get1(bin); 5897dd7cddfSDavid du Colombier zh->madeos = get1(bin); 5907dd7cddfSDavid du Colombier zh->extvers = get1(bin); 5917dd7cddfSDavid du Colombier zh->extos = get1(bin); 5927dd7cddfSDavid du Colombier zh->flags = get2(bin); 5937dd7cddfSDavid du Colombier zh->meth = get2(bin); 5947dd7cddfSDavid du Colombier zh->modtime = get2(bin); 5957dd7cddfSDavid du Colombier zh->moddate = get2(bin); 5967dd7cddfSDavid du Colombier zh->crc = get4(bin); 5977dd7cddfSDavid du Colombier zh->csize = get4(bin); 5987dd7cddfSDavid du Colombier zh->uncsize = get4(bin); 5997dd7cddfSDavid du Colombier flen = get2(bin); 6007dd7cddfSDavid du Colombier xlen = get2(bin); 6017dd7cddfSDavid du Colombier fclen = get2(bin); 6027dd7cddfSDavid du Colombier get2(bin); /* disk number start */ 6037dd7cddfSDavid du Colombier zh->iattr = get2(bin); 6047dd7cddfSDavid du Colombier zh->eattr = get4(bin); 6057dd7cddfSDavid du Colombier zh->off = get4(bin); 6067dd7cddfSDavid du Colombier 6077dd7cddfSDavid du Colombier zh->file = getname(bin, flen); 6087dd7cddfSDavid du Colombier 6097dd7cddfSDavid du Colombier while(xlen-- > 0) 6107dd7cddfSDavid du Colombier get1(bin); 6117dd7cddfSDavid du Colombier 6127dd7cddfSDavid du Colombier while(fclen-- > 0) 6137dd7cddfSDavid du Colombier get1(bin); 6147dd7cddfSDavid du Colombier 6157dd7cddfSDavid du Colombier return 1; 6167dd7cddfSDavid du Colombier } 6177dd7cddfSDavid du Colombier 6187dd7cddfSDavid du Colombier static int 6197dd7cddfSDavid du Colombier header(Biobuf *bin, ZipHead *zh) 6207dd7cddfSDavid du Colombier { 6217dd7cddfSDavid du Colombier ulong v; 6227dd7cddfSDavid du Colombier int flen, xlen; 6237dd7cddfSDavid du Colombier 6247dd7cddfSDavid du Colombier v = get4(bin); 6257dd7cddfSDavid du Colombier if(v != ZHeader){ 6267dd7cddfSDavid du Colombier if(v == ZCHeader) 6277dd7cddfSDavid du Colombier return 0; 6287dd7cddfSDavid du Colombier error("bad magic number %lux at %lld", v, Boffset(bin)-4); 6297dd7cddfSDavid du Colombier } 6307dd7cddfSDavid du Colombier zh->extvers = get1(bin); 6317dd7cddfSDavid du Colombier zh->extos = get1(bin); 6327dd7cddfSDavid du Colombier zh->flags = get2(bin); 6337dd7cddfSDavid du Colombier zh->meth = get2(bin); 6347dd7cddfSDavid du Colombier zh->modtime = get2(bin); 6357dd7cddfSDavid du Colombier zh->moddate = get2(bin); 6367dd7cddfSDavid du Colombier zh->crc = get4(bin); 6377dd7cddfSDavid du Colombier zh->csize = get4(bin); 6387dd7cddfSDavid du Colombier zh->uncsize = get4(bin); 6397dd7cddfSDavid du Colombier flen = get2(bin); 6407dd7cddfSDavid du Colombier xlen = get2(bin); 6417dd7cddfSDavid du Colombier 6427dd7cddfSDavid du Colombier zh->file = getname(bin, flen); 6437dd7cddfSDavid du Colombier 6447dd7cddfSDavid du Colombier while(xlen-- > 0) 6457dd7cddfSDavid du Colombier get1(bin); 6467dd7cddfSDavid du Colombier 6477dd7cddfSDavid du Colombier return 1; 6487dd7cddfSDavid du Colombier } 6497dd7cddfSDavid du Colombier 6507dd7cddfSDavid du Colombier static void 6517dd7cddfSDavid du Colombier trailer(Biobuf *bin, ZipHead *zh) 6527dd7cddfSDavid du Colombier { 6537dd7cddfSDavid du Colombier if(zh->flags & ZTrailInfo){ 6547dd7cddfSDavid du Colombier zh->crc = get4(bin); 6557dd7cddfSDavid du Colombier zh->csize = get4(bin); 6567dd7cddfSDavid du Colombier zh->uncsize = get4(bin); 6577dd7cddfSDavid du Colombier } 6587dd7cddfSDavid du Colombier } 6597dd7cddfSDavid du Colombier 6607dd7cddfSDavid du Colombier static char* 6617dd7cddfSDavid du Colombier getname(Biobuf *bin, int len) 6627dd7cddfSDavid du Colombier { 6637dd7cddfSDavid du Colombier char *s; 6647dd7cddfSDavid du Colombier int i, c; 6657dd7cddfSDavid du Colombier 6667dd7cddfSDavid du Colombier s = emalloc(len + 1); 6677dd7cddfSDavid du Colombier for(i = 0; i < len; i++){ 6687dd7cddfSDavid du Colombier c = get1(bin); 6697dd7cddfSDavid du Colombier if(lower) 6707dd7cddfSDavid du Colombier c = tolower(c); 6717dd7cddfSDavid du Colombier s[i] = c; 6727dd7cddfSDavid du Colombier } 6737dd7cddfSDavid du Colombier s[i] = '\0'; 6747dd7cddfSDavid du Colombier return s; 6757dd7cddfSDavid du Colombier } 6767dd7cddfSDavid du Colombier 6777dd7cddfSDavid du Colombier static int 6787dd7cddfSDavid du Colombier crcwrite(void *out, void *buf, int n) 6797dd7cddfSDavid du Colombier { 6807dd7cddfSDavid du Colombier int fd, nw; 6817dd7cddfSDavid du Colombier 6827dd7cddfSDavid du Colombier wlen += n; 68380ee5cbfSDavid du Colombier crc = blockcrc(crctab, crc, buf, n); 68474f16c81SDavid du Colombier fd = (int)(uintptr)out; 6857dd7cddfSDavid du Colombier if(fd < 0) 6867dd7cddfSDavid du Colombier return n; 6877dd7cddfSDavid du Colombier nw = write(fd, buf, n); 6887dd7cddfSDavid du Colombier if(nw != n) 6897dd7cddfSDavid du Colombier wbad = 1; 6907dd7cddfSDavid du Colombier return nw; 6917dd7cddfSDavid du Colombier } 6927dd7cddfSDavid du Colombier 6937dd7cddfSDavid du Colombier static int 6947dd7cddfSDavid du Colombier copyout(int ofd, Biobuf *bin, long len) 6957dd7cddfSDavid du Colombier { 6967dd7cddfSDavid du Colombier char buf[BufSize]; 6977dd7cddfSDavid du Colombier int n; 6987dd7cddfSDavid du Colombier 6997dd7cddfSDavid du Colombier for(; len > 0; len -= n){ 7007dd7cddfSDavid du Colombier n = len; 7017dd7cddfSDavid du Colombier if(n > BufSize) 7027dd7cddfSDavid du Colombier n = BufSize; 7037dd7cddfSDavid du Colombier n = Bread(bin, buf, n); 7047dd7cddfSDavid du Colombier if(n <= 0) 7057dd7cddfSDavid du Colombier return 0; 7067dd7cddfSDavid du Colombier rlen += n; 7077dd7cddfSDavid du Colombier if(crcwrite((void*)ofd, buf, n) != n) 7087dd7cddfSDavid du Colombier return 0; 7097dd7cddfSDavid du Colombier } 7107dd7cddfSDavid du Colombier return 1; 7117dd7cddfSDavid du Colombier } 7127dd7cddfSDavid du Colombier 7137dd7cddfSDavid du Colombier static ulong 7147dd7cddfSDavid du Colombier get4(Biobuf *b) 7157dd7cddfSDavid du Colombier { 7167dd7cddfSDavid du Colombier ulong v; 7177dd7cddfSDavid du Colombier int i, c; 7187dd7cddfSDavid du Colombier 7197dd7cddfSDavid du Colombier v = 0; 7207dd7cddfSDavid du Colombier for(i = 0; i < 4; i++){ 7217dd7cddfSDavid du Colombier c = Bgetc(b); 7227dd7cddfSDavid du Colombier if(c < 0) 7237dd7cddfSDavid du Colombier error("unexpected eof reading file information"); 7247dd7cddfSDavid du Colombier v |= c << (i * 8); 7257dd7cddfSDavid du Colombier } 7267dd7cddfSDavid du Colombier return v; 7277dd7cddfSDavid du Colombier } 7287dd7cddfSDavid du Colombier 7297dd7cddfSDavid du Colombier static int 7307dd7cddfSDavid du Colombier get2(Biobuf *b) 7317dd7cddfSDavid du Colombier { 7327dd7cddfSDavid du Colombier int i, c, v; 7337dd7cddfSDavid du Colombier 7347dd7cddfSDavid du Colombier v = 0; 7357dd7cddfSDavid du Colombier for(i = 0; i < 2; i++){ 7367dd7cddfSDavid du Colombier c = Bgetc(b); 7377dd7cddfSDavid du Colombier if(c < 0) 7387dd7cddfSDavid du Colombier error("unexpected eof reading file information"); 7397dd7cddfSDavid du Colombier v |= c << (i * 8); 7407dd7cddfSDavid du Colombier } 7417dd7cddfSDavid du Colombier return v; 7427dd7cddfSDavid du Colombier } 7437dd7cddfSDavid du Colombier 7447dd7cddfSDavid du Colombier static int 7457dd7cddfSDavid du Colombier get1(Biobuf *b) 7467dd7cddfSDavid du Colombier { 7477dd7cddfSDavid du Colombier int c; 7487dd7cddfSDavid du Colombier 7497dd7cddfSDavid du Colombier c = Bgetc(b); 7507dd7cddfSDavid du Colombier if(c < 0) 7517dd7cddfSDavid du Colombier error("unexpected eof reading file information"); 7527dd7cddfSDavid du Colombier return c; 7537dd7cddfSDavid du Colombier } 7547dd7cddfSDavid du Colombier 7557dd7cddfSDavid du Colombier static long 7567dd7cddfSDavid du Colombier msdos2time(int time, int date) 7577dd7cddfSDavid du Colombier { 7587dd7cddfSDavid du Colombier Tm tm; 7597dd7cddfSDavid du Colombier 7607dd7cddfSDavid du Colombier tm.hour = time >> 11; 7617dd7cddfSDavid du Colombier tm.min = (time >> 5) & 63; 7627dd7cddfSDavid du Colombier tm.sec = (time & 31) << 1; 7637dd7cddfSDavid du Colombier tm.year = 80 + (date >> 9); 7647dd7cddfSDavid du Colombier tm.mon = ((date >> 5) & 15) - 1; 7657dd7cddfSDavid du Colombier tm.mday = date & 31; 7667dd7cddfSDavid du Colombier tm.zone[0] = '\0'; 7676b6b9ac8SDavid du Colombier tm.yday = 0; 7687dd7cddfSDavid du Colombier 7697dd7cddfSDavid du Colombier return tm2sec(&tm); 7707dd7cddfSDavid du Colombier } 7717dd7cddfSDavid du Colombier 7727dd7cddfSDavid du Colombier static void* 7737dd7cddfSDavid du Colombier emalloc(ulong n) 7747dd7cddfSDavid du Colombier { 7757dd7cddfSDavid du Colombier void *p; 7767dd7cddfSDavid du Colombier 7777dd7cddfSDavid du Colombier p = malloc(n); 7787dd7cddfSDavid du Colombier if(p == nil) 7797dd7cddfSDavid du Colombier sysfatal("out of memory"); 7807dd7cddfSDavid du Colombier return p; 7817dd7cddfSDavid du Colombier } 7827dd7cddfSDavid du Colombier 7837dd7cddfSDavid du Colombier static void 7847dd7cddfSDavid du Colombier error(char *fmt, ...) 7857dd7cddfSDavid du Colombier { 7867dd7cddfSDavid du Colombier va_list arg; 7877dd7cddfSDavid du Colombier 7889a747e4fSDavid du Colombier fprint(2, "unzip: "); 7897dd7cddfSDavid du Colombier va_start(arg, fmt); 7909a747e4fSDavid du Colombier vfprint(2, fmt, arg); 7917dd7cddfSDavid du Colombier va_end(arg); 7929a747e4fSDavid du Colombier fprint(2, "\n"); 7937dd7cddfSDavid du Colombier 7947dd7cddfSDavid du Colombier if(delfile != nil){ 7957dd7cddfSDavid du Colombier fprint(2, "unzip: removing output file %s\n", delfile); 7967dd7cddfSDavid du Colombier remove(delfile); 7977dd7cddfSDavid du Colombier delfile = nil; 7987dd7cddfSDavid du Colombier } 7997dd7cddfSDavid du Colombier 8007dd7cddfSDavid du Colombier longjmp(zjmp, 1); 8017dd7cddfSDavid du Colombier } 802