1*7dd7cddfSDavid du Colombier #include <u.h> 2*7dd7cddfSDavid du Colombier #include <libc.h> 3*7dd7cddfSDavid du Colombier #include <bio.h> 4*7dd7cddfSDavid du Colombier #include "zip.h" 5*7dd7cddfSDavid du Colombier #include "deflate.h" 6*7dd7cddfSDavid du Colombier 7*7dd7cddfSDavid du Colombier enum 8*7dd7cddfSDavid du Colombier { 9*7dd7cddfSDavid du Colombier HeadAlloc = 64, 10*7dd7cddfSDavid du Colombier NDirs = 64, 11*7dd7cddfSDavid du Colombier }; 12*7dd7cddfSDavid du Colombier 13*7dd7cddfSDavid du Colombier static void zip(Biobuf *bout, char *file, int stdout); 14*7dd7cddfSDavid du Colombier static void zipDir(Biobuf *bout, int fd, ZipHead *zh, int stdout); 15*7dd7cddfSDavid du Colombier static int crcread(void *fd, void *buf, int n); 16*7dd7cddfSDavid du Colombier static int zwrite(void *bout, void *buf, int n); 17*7dd7cddfSDavid du Colombier static void put4(Biobuf *b, ulong v); 18*7dd7cddfSDavid du Colombier static void put2(Biobuf *b, int v); 19*7dd7cddfSDavid du Colombier static void put1(Biobuf *b, int v); 20*7dd7cddfSDavid du Colombier static void header(Biobuf *bout, ZipHead *zh); 21*7dd7cddfSDavid du Colombier static void trailer(Biobuf *bout, ZipHead *zh, vlong off); 22*7dd7cddfSDavid du Colombier static void putCDir(Biobuf *bout); 23*7dd7cddfSDavid du Colombier 24*7dd7cddfSDavid du Colombier static void error(char*, ...); 25*7dd7cddfSDavid du Colombier #pragma varargck argpos error 1 26*7dd7cddfSDavid du Colombier 27*7dd7cddfSDavid du Colombier static Biobuf bout; 28*7dd7cddfSDavid du Colombier static ulong crc; 29*7dd7cddfSDavid du Colombier static int debug; 30*7dd7cddfSDavid du Colombier static int eof; 31*7dd7cddfSDavid du Colombier static int level; 32*7dd7cddfSDavid du Colombier static int nzheads; 33*7dd7cddfSDavid du Colombier static ulong totr; 34*7dd7cddfSDavid du Colombier static ulong totw; 35*7dd7cddfSDavid du Colombier static int verbose; 36*7dd7cddfSDavid du Colombier static int zhalloc; 37*7dd7cddfSDavid du Colombier static ZipHead *zheads; 38*7dd7cddfSDavid du Colombier static jmp_buf zjmp; 39*7dd7cddfSDavid du Colombier 40*7dd7cddfSDavid du Colombier void 41*7dd7cddfSDavid du Colombier usage(void) 42*7dd7cddfSDavid du Colombier { 43*7dd7cddfSDavid du Colombier fprint(2, "usage: zip [-vD] [-1-9] [-f zipfile] file ...\n"); 44*7dd7cddfSDavid du Colombier exits("usage"); 45*7dd7cddfSDavid du Colombier } 46*7dd7cddfSDavid du Colombier 47*7dd7cddfSDavid du Colombier void 48*7dd7cddfSDavid du Colombier main(int argc, char *argv[]) 49*7dd7cddfSDavid du Colombier { 50*7dd7cddfSDavid du Colombier char *zfile; 51*7dd7cddfSDavid du Colombier int i, fd; 52*7dd7cddfSDavid du Colombier 53*7dd7cddfSDavid du Colombier zfile = nil; 54*7dd7cddfSDavid du Colombier level = 6; 55*7dd7cddfSDavid du Colombier ARGBEGIN{ 56*7dd7cddfSDavid du Colombier case 'D': 57*7dd7cddfSDavid du Colombier debug++; 58*7dd7cddfSDavid du Colombier break; 59*7dd7cddfSDavid du Colombier case 'f': 60*7dd7cddfSDavid du Colombier zfile = ARGF(); 61*7dd7cddfSDavid du Colombier if(zfile == nil) 62*7dd7cddfSDavid du Colombier usage(); 63*7dd7cddfSDavid du Colombier break; 64*7dd7cddfSDavid du Colombier case 'v': 65*7dd7cddfSDavid du Colombier verbose++; 66*7dd7cddfSDavid du Colombier break; 67*7dd7cddfSDavid du Colombier case '1': case '2': case '3': case '4': 68*7dd7cddfSDavid du Colombier case '5': case '6': case '7': case '8': case '9': 69*7dd7cddfSDavid du Colombier level = ARGC() - '0'; 70*7dd7cddfSDavid du Colombier break; 71*7dd7cddfSDavid du Colombier default: 72*7dd7cddfSDavid du Colombier usage(); 73*7dd7cddfSDavid du Colombier break; 74*7dd7cddfSDavid du Colombier }ARGEND 75*7dd7cddfSDavid du Colombier 76*7dd7cddfSDavid du Colombier if(argc == 0) 77*7dd7cddfSDavid du Colombier usage(); 78*7dd7cddfSDavid du Colombier 79*7dd7cddfSDavid du Colombier mkcrctab(ZCrcPoly); 80*7dd7cddfSDavid du Colombier deflateinit(); 81*7dd7cddfSDavid du Colombier 82*7dd7cddfSDavid du Colombier if(zfile == nil) 83*7dd7cddfSDavid du Colombier fd = 1; 84*7dd7cddfSDavid du Colombier else{ 85*7dd7cddfSDavid du Colombier fd = create(zfile, OWRITE, 0664); 86*7dd7cddfSDavid du Colombier if(fd < 0) 87*7dd7cddfSDavid du Colombier sysfatal("can't create %s: %r\n", zfile); 88*7dd7cddfSDavid du Colombier } 89*7dd7cddfSDavid du Colombier Binit(&bout, fd, OWRITE); 90*7dd7cddfSDavid du Colombier 91*7dd7cddfSDavid du Colombier if(setjmp(zjmp)){ 92*7dd7cddfSDavid du Colombier if(zfile != nil){ 93*7dd7cddfSDavid du Colombier fprint(2, "zip: removing output file %s\n", zfile); 94*7dd7cddfSDavid du Colombier remove(zfile); 95*7dd7cddfSDavid du Colombier } 96*7dd7cddfSDavid du Colombier exits("errors"); 97*7dd7cddfSDavid du Colombier } 98*7dd7cddfSDavid du Colombier 99*7dd7cddfSDavid du Colombier for(i = 0; i < argc; i++) 100*7dd7cddfSDavid du Colombier zip(&bout, argv[i], zfile == nil); 101*7dd7cddfSDavid du Colombier 102*7dd7cddfSDavid du Colombier putCDir(&bout); 103*7dd7cddfSDavid du Colombier 104*7dd7cddfSDavid du Colombier exits(nil); 105*7dd7cddfSDavid du Colombier } 106*7dd7cddfSDavid du Colombier 107*7dd7cddfSDavid du Colombier static void 108*7dd7cddfSDavid du Colombier zip(Biobuf *bout, char *file, int stdout) 109*7dd7cddfSDavid du Colombier { 110*7dd7cddfSDavid du Colombier Tm *t; 111*7dd7cddfSDavid du Colombier ZipHead *zh; 112*7dd7cddfSDavid du Colombier Dir dir; 113*7dd7cddfSDavid du Colombier vlong off; 114*7dd7cddfSDavid du Colombier int fd; 115*7dd7cddfSDavid du Colombier 116*7dd7cddfSDavid du Colombier fd = open(file, OREAD); 117*7dd7cddfSDavid du Colombier if(fd < 0) 118*7dd7cddfSDavid du Colombier error("can't open %s: %r", file); 119*7dd7cddfSDavid du Colombier if(dirfstat(fd, &dir) < 0) 120*7dd7cddfSDavid du Colombier error("can't stat %s: %r", file); 121*7dd7cddfSDavid du Colombier 122*7dd7cddfSDavid du Colombier /* 123*7dd7cddfSDavid du Colombier * create the header 124*7dd7cddfSDavid du Colombier */ 125*7dd7cddfSDavid du Colombier if(nzheads >= zhalloc){ 126*7dd7cddfSDavid du Colombier zhalloc += HeadAlloc; 127*7dd7cddfSDavid du Colombier zheads = realloc(zheads, zhalloc * sizeof(ZipHead)); 128*7dd7cddfSDavid du Colombier if(zheads == nil) 129*7dd7cddfSDavid du Colombier error("out of memory"); 130*7dd7cddfSDavid du Colombier } 131*7dd7cddfSDavid du Colombier zh = &zheads[nzheads++]; 132*7dd7cddfSDavid du Colombier zh->madeos = ZDos; 133*7dd7cddfSDavid du Colombier zh->madevers = (2 * 10) + 0; 134*7dd7cddfSDavid du Colombier zh->extos = ZDos; 135*7dd7cddfSDavid du Colombier zh->extvers = (2 * 10) + 0; 136*7dd7cddfSDavid du Colombier 137*7dd7cddfSDavid du Colombier t = localtime(dir.mtime); 138*7dd7cddfSDavid du Colombier zh->modtime = (t->hour<<11) | (t->min<<5) | (t->sec>>1); 139*7dd7cddfSDavid du Colombier zh->moddate = ((t->year-80)<<9) | ((t->mon+1)<<5) | t->mday; 140*7dd7cddfSDavid du Colombier 141*7dd7cddfSDavid du Colombier zh->flags = 0; 142*7dd7cddfSDavid du Colombier zh->crc = 0; 143*7dd7cddfSDavid du Colombier zh->csize = 0; 144*7dd7cddfSDavid du Colombier zh->uncsize = 0; 145*7dd7cddfSDavid du Colombier zh->file = strdup(file); 146*7dd7cddfSDavid du Colombier if(zh->file == nil) 147*7dd7cddfSDavid du Colombier error("out of memory"); 148*7dd7cddfSDavid du Colombier zh->iattr = 0; 149*7dd7cddfSDavid du Colombier zh->eattr = ZDArch; 150*7dd7cddfSDavid du Colombier if((dir.mode & 0700) == 0) 151*7dd7cddfSDavid du Colombier zh->eattr |= ZDROnly; 152*7dd7cddfSDavid du Colombier zh->off = Boffset(bout); 153*7dd7cddfSDavid du Colombier 154*7dd7cddfSDavid du Colombier if(dir.mode & CHDIR){ 155*7dd7cddfSDavid du Colombier zh->eattr |= ZDDir; 156*7dd7cddfSDavid du Colombier zh->meth = 0; 157*7dd7cddfSDavid du Colombier zipDir(bout, fd, zh, stdout); 158*7dd7cddfSDavid du Colombier }else{ 159*7dd7cddfSDavid du Colombier zh->meth = 8; 160*7dd7cddfSDavid du Colombier if(stdout) 161*7dd7cddfSDavid du Colombier zh->flags |= ZTrailInfo; 162*7dd7cddfSDavid du Colombier off = Boffset(bout); 163*7dd7cddfSDavid du Colombier header(bout, zh); 164*7dd7cddfSDavid du Colombier 165*7dd7cddfSDavid du Colombier crc = 0; 166*7dd7cddfSDavid du Colombier eof = 0; 167*7dd7cddfSDavid du Colombier totr = 0; 168*7dd7cddfSDavid du Colombier totw = 0; 169*7dd7cddfSDavid du Colombier if(!deflate(bout, zwrite, (void*)fd, crcread, level, debug)) 170*7dd7cddfSDavid du Colombier error("deflate failed: %r"); 171*7dd7cddfSDavid du Colombier 172*7dd7cddfSDavid du Colombier zh->csize = totw; 173*7dd7cddfSDavid du Colombier zh->uncsize = totr; 174*7dd7cddfSDavid du Colombier zh->crc = crc; 175*7dd7cddfSDavid du Colombier trailer(bout, zh, off); 176*7dd7cddfSDavid du Colombier } 177*7dd7cddfSDavid du Colombier close(fd); 178*7dd7cddfSDavid du Colombier 179*7dd7cddfSDavid du Colombier } 180*7dd7cddfSDavid du Colombier 181*7dd7cddfSDavid du Colombier static void 182*7dd7cddfSDavid du Colombier zipDir(Biobuf *bout, int fd, ZipHead *zh, int stdout) 183*7dd7cddfSDavid du Colombier { 184*7dd7cddfSDavid du Colombier Dir dirs[NDirs]; 185*7dd7cddfSDavid du Colombier char *file, *pfile; 186*7dd7cddfSDavid du Colombier int i, nf, nd; 187*7dd7cddfSDavid du Colombier 188*7dd7cddfSDavid du Colombier nf = strlen(zh->file) + 1; 189*7dd7cddfSDavid du Colombier if(strcmp(zh->file, ".") == 0){ 190*7dd7cddfSDavid du Colombier nzheads--; 191*7dd7cddfSDavid du Colombier free(zh->file); 192*7dd7cddfSDavid du Colombier pfile = ""; 193*7dd7cddfSDavid du Colombier nf = 1; 194*7dd7cddfSDavid du Colombier }else{ 195*7dd7cddfSDavid du Colombier nf++; 196*7dd7cddfSDavid du Colombier pfile = malloc(nf); 197*7dd7cddfSDavid du Colombier if(pfile == nil) 198*7dd7cddfSDavid du Colombier error("out of memory"); 199*7dd7cddfSDavid du Colombier snprint(pfile, nf, "%s/", zh->file); 200*7dd7cddfSDavid du Colombier free(zh->file); 201*7dd7cddfSDavid du Colombier zh->file = pfile; 202*7dd7cddfSDavid du Colombier header(bout, zh); 203*7dd7cddfSDavid du Colombier } 204*7dd7cddfSDavid du Colombier 205*7dd7cddfSDavid du Colombier nf += NAMELEN; 206*7dd7cddfSDavid du Colombier file = malloc(nf); 207*7dd7cddfSDavid du Colombier if(file == nil) 208*7dd7cddfSDavid du Colombier error("out of memory"); 209*7dd7cddfSDavid du Colombier while((nd = dirread(fd, dirs, sizeof(Dir) * NDirs)) >= sizeof(Dir)){ 210*7dd7cddfSDavid du Colombier nd /= sizeof(Dir); 211*7dd7cddfSDavid du Colombier for(i = 0; i < nd; i++){ 212*7dd7cddfSDavid du Colombier snprint(file, nf, "%s%s", pfile, dirs[i].name); 213*7dd7cddfSDavid du Colombier zip(bout, file, stdout); 214*7dd7cddfSDavid du Colombier } 215*7dd7cddfSDavid du Colombier } 216*7dd7cddfSDavid du Colombier } 217*7dd7cddfSDavid du Colombier 218*7dd7cddfSDavid du Colombier static void 219*7dd7cddfSDavid du Colombier header(Biobuf *bout, ZipHead *zh) 220*7dd7cddfSDavid du Colombier { 221*7dd7cddfSDavid du Colombier int flen; 222*7dd7cddfSDavid du Colombier 223*7dd7cddfSDavid du Colombier if(verbose) 224*7dd7cddfSDavid du Colombier fprint(2, "adding %s\n", zh->file); 225*7dd7cddfSDavid du Colombier put4(bout, ZHeader); 226*7dd7cddfSDavid du Colombier put1(bout, zh->extvers); 227*7dd7cddfSDavid du Colombier put1(bout, zh->extos); 228*7dd7cddfSDavid du Colombier put2(bout, zh->flags); 229*7dd7cddfSDavid du Colombier put2(bout, zh->meth); 230*7dd7cddfSDavid du Colombier put2(bout, zh->modtime); 231*7dd7cddfSDavid du Colombier put2(bout, zh->moddate); 232*7dd7cddfSDavid du Colombier put4(bout, zh->crc); 233*7dd7cddfSDavid du Colombier put4(bout, zh->csize); 234*7dd7cddfSDavid du Colombier put4(bout, zh->uncsize); 235*7dd7cddfSDavid du Colombier flen = strlen(zh->file); 236*7dd7cddfSDavid du Colombier put2(bout, flen); 237*7dd7cddfSDavid du Colombier put2(bout, 0); 238*7dd7cddfSDavid du Colombier if(Bwrite(bout, zh->file, flen) != flen) 239*7dd7cddfSDavid du Colombier error("write error"); 240*7dd7cddfSDavid du Colombier } 241*7dd7cddfSDavid du Colombier 242*7dd7cddfSDavid du Colombier static void 243*7dd7cddfSDavid du Colombier trailer(Biobuf *bout, ZipHead *zh, vlong off) 244*7dd7cddfSDavid du Colombier { 245*7dd7cddfSDavid du Colombier vlong coff; 246*7dd7cddfSDavid du Colombier 247*7dd7cddfSDavid du Colombier coff = -1; 248*7dd7cddfSDavid du Colombier if(!(zh->flags & ZTrailInfo)){ 249*7dd7cddfSDavid du Colombier coff = Boffset(bout); 250*7dd7cddfSDavid du Colombier if(Bseek(bout, off + ZHeadCrc, 0) < 0) 251*7dd7cddfSDavid du Colombier error("can't seek in archive"); 252*7dd7cddfSDavid du Colombier } 253*7dd7cddfSDavid du Colombier put4(bout, zh->crc); 254*7dd7cddfSDavid du Colombier put4(bout, zh->csize); 255*7dd7cddfSDavid du Colombier put4(bout, zh->uncsize); 256*7dd7cddfSDavid du Colombier if(!(zh->flags & ZTrailInfo)){ 257*7dd7cddfSDavid du Colombier if(Bseek(bout, coff, 0) < 0) 258*7dd7cddfSDavid du Colombier error("can't seek in archive"); 259*7dd7cddfSDavid du Colombier } 260*7dd7cddfSDavid du Colombier } 261*7dd7cddfSDavid du Colombier 262*7dd7cddfSDavid du Colombier static void 263*7dd7cddfSDavid du Colombier cheader(Biobuf *bout, ZipHead *zh) 264*7dd7cddfSDavid du Colombier { 265*7dd7cddfSDavid du Colombier int flen; 266*7dd7cddfSDavid du Colombier 267*7dd7cddfSDavid du Colombier put4(bout, ZCHeader); 268*7dd7cddfSDavid du Colombier put1(bout, zh->madevers); 269*7dd7cddfSDavid du Colombier put1(bout, zh->madeos); 270*7dd7cddfSDavid du Colombier put1(bout, zh->extvers); 271*7dd7cddfSDavid du Colombier put1(bout, zh->extos); 272*7dd7cddfSDavid du Colombier put2(bout, zh->flags & ~ZTrailInfo); 273*7dd7cddfSDavid du Colombier put2(bout, zh->meth); 274*7dd7cddfSDavid du Colombier put2(bout, zh->modtime); 275*7dd7cddfSDavid du Colombier put2(bout, zh->moddate); 276*7dd7cddfSDavid du Colombier put4(bout, zh->crc); 277*7dd7cddfSDavid du Colombier put4(bout, zh->csize); 278*7dd7cddfSDavid du Colombier put4(bout, zh->uncsize); 279*7dd7cddfSDavid du Colombier flen = strlen(zh->file); 280*7dd7cddfSDavid du Colombier put2(bout, flen); 281*7dd7cddfSDavid du Colombier put2(bout, 0); 282*7dd7cddfSDavid du Colombier put2(bout, 0); 283*7dd7cddfSDavid du Colombier put2(bout, 0); 284*7dd7cddfSDavid du Colombier put2(bout, zh->iattr); 285*7dd7cddfSDavid du Colombier put4(bout, zh->eattr); 286*7dd7cddfSDavid du Colombier put4(bout, zh->off); 287*7dd7cddfSDavid du Colombier if(Bwrite(bout, zh->file, flen) != flen) 288*7dd7cddfSDavid du Colombier error("write error"); 289*7dd7cddfSDavid du Colombier } 290*7dd7cddfSDavid du Colombier 291*7dd7cddfSDavid du Colombier static void 292*7dd7cddfSDavid du Colombier putCDir(Biobuf *bout) 293*7dd7cddfSDavid du Colombier { 294*7dd7cddfSDavid du Colombier vlong hoff, ecoff; 295*7dd7cddfSDavid du Colombier int i; 296*7dd7cddfSDavid du Colombier 297*7dd7cddfSDavid du Colombier hoff = Boffset(bout); 298*7dd7cddfSDavid du Colombier 299*7dd7cddfSDavid du Colombier for(i = 0; i < nzheads; i++) 300*7dd7cddfSDavid du Colombier cheader(bout, &zheads[i]); 301*7dd7cddfSDavid du Colombier 302*7dd7cddfSDavid du Colombier ecoff = Boffset(bout); 303*7dd7cddfSDavid du Colombier 304*7dd7cddfSDavid du Colombier if(nzheads >= (1 << 16)) 305*7dd7cddfSDavid du Colombier error("too many entries in zip file: max %d", (1 << 16) - 1); 306*7dd7cddfSDavid du Colombier put4(bout, ZECHeader); 307*7dd7cddfSDavid du Colombier put2(bout, 0); 308*7dd7cddfSDavid du Colombier put2(bout, 0); 309*7dd7cddfSDavid du Colombier put2(bout, nzheads); 310*7dd7cddfSDavid du Colombier put2(bout, nzheads); 311*7dd7cddfSDavid du Colombier put4(bout, ecoff - hoff); 312*7dd7cddfSDavid du Colombier put4(bout, hoff); 313*7dd7cddfSDavid du Colombier put2(bout, 0); 314*7dd7cddfSDavid du Colombier } 315*7dd7cddfSDavid du Colombier 316*7dd7cddfSDavid du Colombier static int 317*7dd7cddfSDavid du Colombier crcread(void *fd, void *buf, int n) 318*7dd7cddfSDavid du Colombier { 319*7dd7cddfSDavid du Colombier int nr, m; 320*7dd7cddfSDavid du Colombier 321*7dd7cddfSDavid du Colombier nr = 0; 322*7dd7cddfSDavid du Colombier for(; !eof && n > 0; n -= m){ 323*7dd7cddfSDavid du Colombier m = read((int)fd, (char*)buf+nr, n); 324*7dd7cddfSDavid du Colombier if(m <= 0){ 325*7dd7cddfSDavid du Colombier eof = 1; 326*7dd7cddfSDavid du Colombier break; 327*7dd7cddfSDavid du Colombier } 328*7dd7cddfSDavid du Colombier nr += m; 329*7dd7cddfSDavid du Colombier } 330*7dd7cddfSDavid du Colombier crc = blockcrc(crc, buf, nr); 331*7dd7cddfSDavid du Colombier totr += nr; 332*7dd7cddfSDavid du Colombier return nr; 333*7dd7cddfSDavid du Colombier } 334*7dd7cddfSDavid du Colombier 335*7dd7cddfSDavid du Colombier static int 336*7dd7cddfSDavid du Colombier zwrite(void *bout, void *buf, int n) 337*7dd7cddfSDavid du Colombier { 338*7dd7cddfSDavid du Colombier if(n != Bwrite(bout, buf, n)){ 339*7dd7cddfSDavid du Colombier eof = 1; 340*7dd7cddfSDavid du Colombier return -1; 341*7dd7cddfSDavid du Colombier } 342*7dd7cddfSDavid du Colombier totw += n; 343*7dd7cddfSDavid du Colombier return n; 344*7dd7cddfSDavid du Colombier } 345*7dd7cddfSDavid du Colombier 346*7dd7cddfSDavid du Colombier static void 347*7dd7cddfSDavid du Colombier put4(Biobuf *b, ulong v) 348*7dd7cddfSDavid du Colombier { 349*7dd7cddfSDavid du Colombier int i; 350*7dd7cddfSDavid du Colombier 351*7dd7cddfSDavid du Colombier for(i = 0; i < 4; i++){ 352*7dd7cddfSDavid du Colombier if(Bputc(b, v) < 0) 353*7dd7cddfSDavid du Colombier error("write error"); 354*7dd7cddfSDavid du Colombier v >>= 8; 355*7dd7cddfSDavid du Colombier } 356*7dd7cddfSDavid du Colombier } 357*7dd7cddfSDavid du Colombier 358*7dd7cddfSDavid du Colombier static void 359*7dd7cddfSDavid du Colombier put2(Biobuf *b, int v) 360*7dd7cddfSDavid du Colombier { 361*7dd7cddfSDavid du Colombier int i; 362*7dd7cddfSDavid du Colombier 363*7dd7cddfSDavid du Colombier for(i = 0; i < 2; i++){ 364*7dd7cddfSDavid du Colombier if(Bputc(b, v) < 0) 365*7dd7cddfSDavid du Colombier error("write error"); 366*7dd7cddfSDavid du Colombier v >>= 8; 367*7dd7cddfSDavid du Colombier } 368*7dd7cddfSDavid du Colombier } 369*7dd7cddfSDavid du Colombier 370*7dd7cddfSDavid du Colombier static void 371*7dd7cddfSDavid du Colombier put1(Biobuf *b, int v) 372*7dd7cddfSDavid du Colombier { 373*7dd7cddfSDavid du Colombier if(Bputc(b, v)< 0) 374*7dd7cddfSDavid du Colombier error("unexpected eof reading file information"); 375*7dd7cddfSDavid du Colombier } 376*7dd7cddfSDavid du Colombier 377*7dd7cddfSDavid du Colombier static void 378*7dd7cddfSDavid du Colombier error(char *fmt, ...) 379*7dd7cddfSDavid du Colombier { 380*7dd7cddfSDavid du Colombier char buf[1024]; 381*7dd7cddfSDavid du Colombier va_list arg; 382*7dd7cddfSDavid du Colombier 383*7dd7cddfSDavid du Colombier va_start(arg, fmt); 384*7dd7cddfSDavid du Colombier doprint(buf, buf+sizeof(buf), fmt, arg); 385*7dd7cddfSDavid du Colombier va_end(arg); 386*7dd7cddfSDavid du Colombier fprint(2, "zip: %s\n", buf); 387*7dd7cddfSDavid du Colombier 388*7dd7cddfSDavid du Colombier longjmp(zjmp, 1); 389*7dd7cddfSDavid du Colombier } 390