xref: /plan9-contrib/sys/src/cmd/gzip/zip.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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