xref: /plan9/sys/src/cmd/disk/9660/write.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
1*80ee5cbfSDavid du Colombier #include <u.h>
2*80ee5cbfSDavid du Colombier #include <libc.h>
3*80ee5cbfSDavid du Colombier #include <bio.h>
4*80ee5cbfSDavid du Colombier #include <libsec.h>
5*80ee5cbfSDavid du Colombier 
6*80ee5cbfSDavid du Colombier #include "iso9660.h"
7*80ee5cbfSDavid du Colombier 
8*80ee5cbfSDavid du Colombier static void
9*80ee5cbfSDavid du Colombier writelittlebig4(uchar *buf, ulong x)
10*80ee5cbfSDavid du Colombier {
11*80ee5cbfSDavid du Colombier 	buf[0] = buf[7] = x;
12*80ee5cbfSDavid du Colombier 	buf[1] = buf[6] = x>>8;
13*80ee5cbfSDavid du Colombier 	buf[2] = buf[5] = x>>16;
14*80ee5cbfSDavid du Colombier 	buf[3] = buf[4] = x>>24;
15*80ee5cbfSDavid du Colombier }
16*80ee5cbfSDavid du Colombier 
17*80ee5cbfSDavid du Colombier void
18*80ee5cbfSDavid du Colombier rewritedot(Cdimg *cd, Direc *d)
19*80ee5cbfSDavid du Colombier {
20*80ee5cbfSDavid du Colombier 	uchar buf[Blocksize];
21*80ee5cbfSDavid du Colombier 	Cdir *c;
22*80ee5cbfSDavid du Colombier 
23*80ee5cbfSDavid du Colombier 	Creadblock(cd, buf, d->block, Blocksize);
24*80ee5cbfSDavid du Colombier 	c = (Cdir*)buf;
25*80ee5cbfSDavid du Colombier 	assert(c->len != 0);
26*80ee5cbfSDavid du Colombier 	assert(c->namelen == 1 && c->name[0] == '\0');	/* dot */
27*80ee5cbfSDavid du Colombier 	writelittlebig4(c->dloc, d->block);
28*80ee5cbfSDavid du Colombier 	writelittlebig4(c->dlen, d->length);
29*80ee5cbfSDavid du Colombier 
30*80ee5cbfSDavid du Colombier 	Cwseek(cd, d->block*Blocksize);
31*80ee5cbfSDavid du Colombier 	Cwrite(cd, buf, Blocksize);
32*80ee5cbfSDavid du Colombier }
33*80ee5cbfSDavid du Colombier 
34*80ee5cbfSDavid du Colombier void
35*80ee5cbfSDavid du Colombier rewritedotdot(Cdimg *cd, Direc *d, Direc *dparent)
36*80ee5cbfSDavid du Colombier {
37*80ee5cbfSDavid du Colombier 	uchar buf[Blocksize];
38*80ee5cbfSDavid du Colombier 	Cdir *c;
39*80ee5cbfSDavid du Colombier 
40*80ee5cbfSDavid du Colombier 	Creadblock(cd, buf, d->block, Blocksize);
41*80ee5cbfSDavid du Colombier 	c = (Cdir*)buf;
42*80ee5cbfSDavid du Colombier 	assert(c->len != 0);
43*80ee5cbfSDavid du Colombier 	assert(c->namelen == 1 && c->name[0] == '\0');	/* dot */
44*80ee5cbfSDavid du Colombier 
45*80ee5cbfSDavid du Colombier 	c = (Cdir*)(buf+c->len);
46*80ee5cbfSDavid du Colombier 	assert(c->len != 0);
47*80ee5cbfSDavid du Colombier 	assert(c->namelen == 1 && c->name[0] == '\001');	/* dotdot*/
48*80ee5cbfSDavid du Colombier 
49*80ee5cbfSDavid du Colombier 	writelittlebig4(c->dloc, dparent->block);
50*80ee5cbfSDavid du Colombier 	writelittlebig4(c->dlen, dparent->length);
51*80ee5cbfSDavid du Colombier 
52*80ee5cbfSDavid du Colombier 	Cwseek(cd, d->block*Blocksize);
53*80ee5cbfSDavid du Colombier 	Cwrite(cd, buf, Blocksize);
54*80ee5cbfSDavid du Colombier }
55*80ee5cbfSDavid du Colombier 
56*80ee5cbfSDavid du Colombier /*
57*80ee5cbfSDavid du Colombier  * Write each non-directory file.  We copy the file to
58*80ee5cbfSDavid du Colombier  * the cd image, and then if it turns out that we've
59*80ee5cbfSDavid du Colombier  * seen this stream of bits before, we push the next block
60*80ee5cbfSDavid du Colombier  * pointer back.  This ensures consistency between the MD5s
61*80ee5cbfSDavid du Colombier  * and the data on the CD image.  MD5 summing on one pass
62*80ee5cbfSDavid du Colombier  * and copying on another would not ensure this.
63*80ee5cbfSDavid du Colombier  */
64*80ee5cbfSDavid du Colombier void
65*80ee5cbfSDavid du Colombier writefiles(Dump *d, Cdimg *cd, Direc *direc)
66*80ee5cbfSDavid du Colombier {
67*80ee5cbfSDavid du Colombier 	int i;
68*80ee5cbfSDavid du Colombier 	uchar buf[8192], digest[MD5dlen];
69*80ee5cbfSDavid du Colombier 	ulong length, n, start;
70*80ee5cbfSDavid du Colombier 	Biobuf *b;
71*80ee5cbfSDavid du Colombier 	DigestState *s;
72*80ee5cbfSDavid du Colombier 	Dumpdir *dd;
73*80ee5cbfSDavid du Colombier 
74*80ee5cbfSDavid du Colombier 	if(direc->mode & CHDIR) {
75*80ee5cbfSDavid du Colombier 		for(i=0; i<direc->nchild; i++)
76*80ee5cbfSDavid du Colombier 			writefiles(d, cd, &direc->child[i]);
77*80ee5cbfSDavid du Colombier 		return;
78*80ee5cbfSDavid du Colombier 	}
79*80ee5cbfSDavid du Colombier 
80*80ee5cbfSDavid du Colombier 	assert(direc->block == 0);
81*80ee5cbfSDavid du Colombier 
82*80ee5cbfSDavid du Colombier 	if((b = Bopen(direc->srcfile, OREAD)) == nil){
83*80ee5cbfSDavid du Colombier 		fprint(2, "warning: cannot open '%s': %r", direc->srcfile);
84*80ee5cbfSDavid du Colombier 		direc->block = 0;
85*80ee5cbfSDavid du Colombier 		direc->length = 0;
86*80ee5cbfSDavid du Colombier 		return;
87*80ee5cbfSDavid du Colombier 	}
88*80ee5cbfSDavid du Colombier 
89*80ee5cbfSDavid du Colombier 	start = cd->nextblock;
90*80ee5cbfSDavid du Colombier 	assert(start != 0);
91*80ee5cbfSDavid du Colombier 
92*80ee5cbfSDavid du Colombier 	Cwseek(cd, start*Blocksize);
93*80ee5cbfSDavid du Colombier 
94*80ee5cbfSDavid du Colombier 	s = md5(nil, 0, nil, nil);
95*80ee5cbfSDavid du Colombier 	length = 0;
96*80ee5cbfSDavid du Colombier 	while((n = Bread(b, buf, sizeof buf)) > 0) {
97*80ee5cbfSDavid du Colombier 		md5(buf, n, nil, s);
98*80ee5cbfSDavid du Colombier 		Cwrite(cd, buf, n);
99*80ee5cbfSDavid du Colombier 		length += n;
100*80ee5cbfSDavid du Colombier 	}
101*80ee5cbfSDavid du Colombier 	md5(nil, 0, digest, s);
102*80ee5cbfSDavid du Colombier 	Bterm(b);
103*80ee5cbfSDavid du Colombier 	Cpadblock(cd);
104*80ee5cbfSDavid du Colombier 
105*80ee5cbfSDavid du Colombier 	if(length != direc->length) {
106*80ee5cbfSDavid du Colombier 		fprint(2, "warning: %s changed size underfoot\n", direc->srcfile);
107*80ee5cbfSDavid du Colombier 		direc->length = length;
108*80ee5cbfSDavid du Colombier 	}
109*80ee5cbfSDavid du Colombier 
110*80ee5cbfSDavid du Colombier 	if(length == 0)
111*80ee5cbfSDavid du Colombier 		direc->block = 0;
112*80ee5cbfSDavid du Colombier 	else if((dd = lookupmd5(d, digest))) {
113*80ee5cbfSDavid du Colombier 		assert(dd->length == length);
114*80ee5cbfSDavid du Colombier 		assert(dd->block != 0);
115*80ee5cbfSDavid du Colombier 		direc->block = dd->block;
116*80ee5cbfSDavid du Colombier 		cd->nextblock = start;
117*80ee5cbfSDavid du Colombier 	} else {
118*80ee5cbfSDavid du Colombier 		direc->block = start;
119*80ee5cbfSDavid du Colombier 		insertmd5(d, atom(direc->name), digest, start, length);
120*80ee5cbfSDavid du Colombier 	}
121*80ee5cbfSDavid du Colombier }
122*80ee5cbfSDavid du Colombier 
123*80ee5cbfSDavid du Colombier /*
124*80ee5cbfSDavid du Colombier  * Write a directory tree.  We work from the leaves,
125*80ee5cbfSDavid du Colombier  * and patch the dotdot pointers afterward.
126*80ee5cbfSDavid du Colombier  */
127*80ee5cbfSDavid du Colombier static void
128*80ee5cbfSDavid du Colombier _writedirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int), int level)
129*80ee5cbfSDavid du Colombier {
130*80ee5cbfSDavid du Colombier 	int i, l, ll;
131*80ee5cbfSDavid du Colombier 	ulong start, next;
132*80ee5cbfSDavid du Colombier 
133*80ee5cbfSDavid du Colombier 	if((d->mode & CHDIR) == 0)
134*80ee5cbfSDavid du Colombier 		return;
135*80ee5cbfSDavid du Colombier 
136*80ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
137*80ee5cbfSDavid du Colombier 		writedirs(cd, &d->child[i], put);
138*80ee5cbfSDavid du Colombier 
139*80ee5cbfSDavid du Colombier 	l = 0;
140*80ee5cbfSDavid du Colombier 	l += put(cd, d, (level == 0) ? DTrootdot : DTdot, 0, l);
141*80ee5cbfSDavid du Colombier 	l += put(cd, nil, DTdotdot, 0, l);
142*80ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
143*80ee5cbfSDavid du Colombier 		l += put(cd, &d->child[i], DTiden, 0, l);
144*80ee5cbfSDavid du Colombier 
145*80ee5cbfSDavid du Colombier 	start = cd->nextblock;
146*80ee5cbfSDavid du Colombier 	cd->nextblock += (l+Blocksize-1)/Blocksize;
147*80ee5cbfSDavid du Colombier 	next = cd->nextblock;
148*80ee5cbfSDavid du Colombier 
149*80ee5cbfSDavid du Colombier 	Cwseek(cd, start*Blocksize);
150*80ee5cbfSDavid du Colombier 	ll = 0;
151*80ee5cbfSDavid du Colombier 	ll += put(cd, d, (level == 0) ? DTrootdot : DTdot, 1, ll);
152*80ee5cbfSDavid du Colombier 	ll += put(cd, nil, DTdotdot, 1, ll);
153*80ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
154*80ee5cbfSDavid du Colombier 		ll += put(cd, &d->child[i], DTiden, 1, ll);
155*80ee5cbfSDavid du Colombier 	assert(ll == l);
156*80ee5cbfSDavid du Colombier 	Cpadblock(cd);
157*80ee5cbfSDavid du Colombier 	assert(Cwoffset(cd) == next*Blocksize);
158*80ee5cbfSDavid du Colombier 
159*80ee5cbfSDavid du Colombier 	d->block = start;
160*80ee5cbfSDavid du Colombier 	d->length = (next - start) * Blocksize;
161*80ee5cbfSDavid du Colombier 	rewritedot(cd, d);
162*80ee5cbfSDavid du Colombier 	rewritedotdot(cd, d, d);
163*80ee5cbfSDavid du Colombier 
164*80ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
165*80ee5cbfSDavid du Colombier 		if(d->child[i].mode & CHDIR)
166*80ee5cbfSDavid du Colombier 			rewritedotdot(cd, &d->child[i], d);
167*80ee5cbfSDavid du Colombier }
168*80ee5cbfSDavid du Colombier 
169*80ee5cbfSDavid du Colombier void
170*80ee5cbfSDavid du Colombier writedirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int))
171*80ee5cbfSDavid du Colombier {
172*80ee5cbfSDavid du Colombier 	/*
173*80ee5cbfSDavid du Colombier 	 * If we're writing a mk9660 image, then the root really
174*80ee5cbfSDavid du Colombier 	 * is the root, so start at level 0.  If we're writing a dump image,
175*80ee5cbfSDavid du Colombier 	 * then the "root" is really going to be two levels down once
176*80ee5cbfSDavid du Colombier 	 * we patch in the dump hierarchy above it, so start at level non-zero.
177*80ee5cbfSDavid du Colombier 	 */
178*80ee5cbfSDavid du Colombier 	_writedirs(cd, d, put, mk9660 ? 0 : 1);
179*80ee5cbfSDavid du Colombier }
180*80ee5cbfSDavid du Colombier 
181*80ee5cbfSDavid du Colombier 
182*80ee5cbfSDavid du Colombier /*
183*80ee5cbfSDavid du Colombier  * Write the dump tree.  This is like writedirs but once we get to
184*80ee5cbfSDavid du Colombier  * the roots of the individual days we just patch the parent dotdot blocks.
185*80ee5cbfSDavid du Colombier  */
186*80ee5cbfSDavid du Colombier static void
187*80ee5cbfSDavid du Colombier _writedumpdirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int), int level)
188*80ee5cbfSDavid du Colombier {
189*80ee5cbfSDavid du Colombier 	int i;
190*80ee5cbfSDavid du Colombier 	ulong start;
191*80ee5cbfSDavid du Colombier 
192*80ee5cbfSDavid du Colombier 	switch(level) {
193*80ee5cbfSDavid du Colombier 	case 0:
194*80ee5cbfSDavid du Colombier 		/* write root, list of years, also conform.map */
195*80ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
196*80ee5cbfSDavid du Colombier 			if(d->child[i].mode & CHDIR)
197*80ee5cbfSDavid du Colombier 				_writedumpdirs(cd, &d->child[i], put, level+1);
198*80ee5cbfSDavid du Colombier 		chat("write dump root dir at %lud\n", cd->nextblock);
199*80ee5cbfSDavid du Colombier 		goto Writedir;
200*80ee5cbfSDavid du Colombier 
201*80ee5cbfSDavid du Colombier 	case 1:	/* write year, list of days */
202*80ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
203*80ee5cbfSDavid du Colombier 			_writedumpdirs(cd, &d->child[i], put, level+1);
204*80ee5cbfSDavid du Colombier 		chat("write dump %s dir at %lud\n", d->name, cd->nextblock);
205*80ee5cbfSDavid du Colombier 		goto Writedir;
206*80ee5cbfSDavid du Colombier 
207*80ee5cbfSDavid du Colombier 	Writedir:
208*80ee5cbfSDavid du Colombier 		start = cd->nextblock;
209*80ee5cbfSDavid du Colombier 		Cwseek(cd, start*Blocksize);
210*80ee5cbfSDavid du Colombier 
211*80ee5cbfSDavid du Colombier 		put(cd, d, (level == 0) ? DTrootdot : DTdot, 1, Cwoffset(cd));
212*80ee5cbfSDavid du Colombier 		put(cd, nil, DTdotdot, 1, Cwoffset(cd));
213*80ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
214*80ee5cbfSDavid du Colombier 			put(cd, &d->child[i], DTiden, 1, Cwoffset(cd));
215*80ee5cbfSDavid du Colombier 		Cpadblock(cd);
216*80ee5cbfSDavid du Colombier 
217*80ee5cbfSDavid du Colombier 		d->block = start;
218*80ee5cbfSDavid du Colombier 		d->length = (cd->nextblock - start) * Blocksize;
219*80ee5cbfSDavid du Colombier 
220*80ee5cbfSDavid du Colombier 		rewritedot(cd, d);
221*80ee5cbfSDavid du Colombier 		rewritedotdot(cd, d, d);
222*80ee5cbfSDavid du Colombier 
223*80ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
224*80ee5cbfSDavid du Colombier 			if(d->child[i].mode & CHDIR)
225*80ee5cbfSDavid du Colombier 				rewritedotdot(cd, &d->child[i], d);
226*80ee5cbfSDavid du Colombier 		break;
227*80ee5cbfSDavid du Colombier 
228*80ee5cbfSDavid du Colombier 	case 2:	/* write day: already written, do nothing */
229*80ee5cbfSDavid du Colombier 		break;
230*80ee5cbfSDavid du Colombier 
231*80ee5cbfSDavid du Colombier 	default:
232*80ee5cbfSDavid du Colombier 		assert(0);
233*80ee5cbfSDavid du Colombier 	}
234*80ee5cbfSDavid du Colombier }
235*80ee5cbfSDavid du Colombier 
236*80ee5cbfSDavid du Colombier void
237*80ee5cbfSDavid du Colombier writedumpdirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int))
238*80ee5cbfSDavid du Colombier {
239*80ee5cbfSDavid du Colombier 	_writedumpdirs(cd, d, put, 0);
240*80ee5cbfSDavid du Colombier }
241*80ee5cbfSDavid du Colombier 
242*80ee5cbfSDavid du Colombier static int
243*80ee5cbfSDavid du Colombier Cputplan9(Cdimg *cd, Direc *d, int dot, int dowrite)
244*80ee5cbfSDavid du Colombier {
245*80ee5cbfSDavid du Colombier 	int l, n;
246*80ee5cbfSDavid du Colombier 
247*80ee5cbfSDavid du Colombier 	if(dot != DTiden)
248*80ee5cbfSDavid du Colombier 		return 0;
249*80ee5cbfSDavid du Colombier 
250*80ee5cbfSDavid du Colombier 	l = 0;
251*80ee5cbfSDavid du Colombier 	if(d->flags & Dbadname) {
252*80ee5cbfSDavid du Colombier 		n = strlen(d->name);
253*80ee5cbfSDavid du Colombier 		l += 1+n;
254*80ee5cbfSDavid du Colombier 		if(dowrite) {
255*80ee5cbfSDavid du Colombier 			Cputc(cd, n);
256*80ee5cbfSDavid du Colombier 			Cputs(cd, d->name, n);
257*80ee5cbfSDavid du Colombier 		}
258*80ee5cbfSDavid du Colombier 	} else {
259*80ee5cbfSDavid du Colombier 		l++;
260*80ee5cbfSDavid du Colombier 		if(dowrite)
261*80ee5cbfSDavid du Colombier 			Cputc(cd, 0);
262*80ee5cbfSDavid du Colombier 	}
263*80ee5cbfSDavid du Colombier 
264*80ee5cbfSDavid du Colombier 	n = strlen(d->uid);
265*80ee5cbfSDavid du Colombier 	l += 1+n;
266*80ee5cbfSDavid du Colombier 	if(dowrite) {
267*80ee5cbfSDavid du Colombier 		Cputc(cd, n);
268*80ee5cbfSDavid du Colombier 		Cputs(cd, d->uid, n);
269*80ee5cbfSDavid du Colombier 	}
270*80ee5cbfSDavid du Colombier 
271*80ee5cbfSDavid du Colombier 	n = strlen(d->gid);
272*80ee5cbfSDavid du Colombier 	l += 1+n;
273*80ee5cbfSDavid du Colombier 	if(dowrite) {
274*80ee5cbfSDavid du Colombier 		Cputc(cd, n);
275*80ee5cbfSDavid du Colombier 		Cputs(cd, d->gid, n);
276*80ee5cbfSDavid du Colombier 	}
277*80ee5cbfSDavid du Colombier 
278*80ee5cbfSDavid du Colombier 	if(l & 1) {
279*80ee5cbfSDavid du Colombier 		l++;
280*80ee5cbfSDavid du Colombier 		if(dowrite)
281*80ee5cbfSDavid du Colombier 			Cputc(cd, 0);
282*80ee5cbfSDavid du Colombier 	}
283*80ee5cbfSDavid du Colombier 	l += 8;
284*80ee5cbfSDavid du Colombier 	if(dowrite)
285*80ee5cbfSDavid du Colombier 		Cputn(cd, d->mode, 4);
286*80ee5cbfSDavid du Colombier 
287*80ee5cbfSDavid du Colombier 	return l;
288*80ee5cbfSDavid du Colombier }
289*80ee5cbfSDavid du Colombier 
290*80ee5cbfSDavid du Colombier /*
291*80ee5cbfSDavid du Colombier  * Write a directory entry.
292*80ee5cbfSDavid du Colombier  */
293*80ee5cbfSDavid du Colombier static int
294*80ee5cbfSDavid du Colombier genputdir(Cdimg *cd, Direc *d, int dot, int joliet, int dowrite, int offset)
295*80ee5cbfSDavid du Colombier {
296*80ee5cbfSDavid du Colombier 	int f, n, l, lp;
297*80ee5cbfSDavid du Colombier 	long o;
298*80ee5cbfSDavid du Colombier 
299*80ee5cbfSDavid du Colombier 	f = 0;
300*80ee5cbfSDavid du Colombier 	if(dot != DTiden || (d->mode & CHDIR))
301*80ee5cbfSDavid du Colombier 		f |= 2;
302*80ee5cbfSDavid du Colombier 
303*80ee5cbfSDavid du Colombier 	n = 1;
304*80ee5cbfSDavid du Colombier 	if(dot == DTiden) {
305*80ee5cbfSDavid du Colombier 		if(joliet)
306*80ee5cbfSDavid du Colombier 			n = 2*utflen(d->confname);
307*80ee5cbfSDavid du Colombier 		else
308*80ee5cbfSDavid du Colombier 			n = strlen(d->confname);
309*80ee5cbfSDavid du Colombier 	}
310*80ee5cbfSDavid du Colombier 
311*80ee5cbfSDavid du Colombier 	l = 33+n;
312*80ee5cbfSDavid du Colombier 	if(l & 1)
313*80ee5cbfSDavid du Colombier 		l++;
314*80ee5cbfSDavid du Colombier 	assert(l <= 255);
315*80ee5cbfSDavid du Colombier 
316*80ee5cbfSDavid du Colombier 	if(joliet == 0) {
317*80ee5cbfSDavid du Colombier 		if(cd->flags & CDplan9)
318*80ee5cbfSDavid du Colombier 			l += Cputplan9(cd, d, dot, 0);
319*80ee5cbfSDavid du Colombier 		else if(cd->flags & CDrockridge)
320*80ee5cbfSDavid du Colombier 			l += Cputsysuse(cd, d, dot, 0, l);
321*80ee5cbfSDavid du Colombier 		assert(l <= 255);
322*80ee5cbfSDavid du Colombier 	}
323*80ee5cbfSDavid du Colombier 
324*80ee5cbfSDavid du Colombier 	if(dowrite == 0) {
325*80ee5cbfSDavid du Colombier 		if(Blocksize - offset%Blocksize < l)
326*80ee5cbfSDavid du Colombier 			l += Blocksize - offset%Blocksize;
327*80ee5cbfSDavid du Colombier 		return l;
328*80ee5cbfSDavid du Colombier 	}
329*80ee5cbfSDavid du Colombier 
330*80ee5cbfSDavid du Colombier 	assert(offset%Blocksize == Cwoffset(cd)%Blocksize);
331*80ee5cbfSDavid du Colombier 
332*80ee5cbfSDavid du Colombier 	o = Cwoffset(cd);
333*80ee5cbfSDavid du Colombier 	lp = 0;
334*80ee5cbfSDavid du Colombier 	if(Blocksize - Cwoffset(cd)%Blocksize < l) {
335*80ee5cbfSDavid du Colombier 		lp = Blocksize - Cwoffset(cd)%Blocksize;
336*80ee5cbfSDavid du Colombier 		Cpadblock(cd);
337*80ee5cbfSDavid du Colombier 	}
338*80ee5cbfSDavid du Colombier 
339*80ee5cbfSDavid du Colombier 	Cputc(cd, l);			/* length of directory record */
340*80ee5cbfSDavid du Colombier 	Cputc(cd, 0);			/* extended attribute record length */
341*80ee5cbfSDavid du Colombier 	if(d) {
342*80ee5cbfSDavid du Colombier 		if((d->mode & CHDIR) == 0)
343*80ee5cbfSDavid du Colombier 			assert(d->length == 0 || d->block >= 18);
344*80ee5cbfSDavid du Colombier 
345*80ee5cbfSDavid du Colombier 		Cputn(cd, d->block, 4);		/* location of extent */
346*80ee5cbfSDavid du Colombier 		Cputn(cd, d->length, 4);		/* data length */
347*80ee5cbfSDavid du Colombier 	} else {
348*80ee5cbfSDavid du Colombier 		Cputn(cd, 0, 4);
349*80ee5cbfSDavid du Colombier 		Cputn(cd, 0, 4);
350*80ee5cbfSDavid du Colombier 	}
351*80ee5cbfSDavid du Colombier 	Cputdate(cd, d ? d->mtime : now);		/* recorded date */
352*80ee5cbfSDavid du Colombier 	Cputc(cd, f);			/* file flags */
353*80ee5cbfSDavid du Colombier 	Cputc(cd, 0);			/* file unit size */
354*80ee5cbfSDavid du Colombier 	Cputc(cd, 0);			/* interleave gap size */
355*80ee5cbfSDavid du Colombier 	Cputn(cd, 1, 2);	       	/* volume sequence number */
356*80ee5cbfSDavid du Colombier 	Cputc(cd, n);			/* length of file identifier */
357*80ee5cbfSDavid du Colombier 
358*80ee5cbfSDavid du Colombier 	if(dot == DTiden) {		/* identifier */
359*80ee5cbfSDavid du Colombier 		if(joliet)
360*80ee5cbfSDavid du Colombier 			Cputrscvt(cd, d->confname, n);
361*80ee5cbfSDavid du Colombier 		else
362*80ee5cbfSDavid du Colombier 			Cputs(cd, d->confname, n);
363*80ee5cbfSDavid du Colombier 	}else
364*80ee5cbfSDavid du Colombier 	if(dot == DTdotdot)
365*80ee5cbfSDavid du Colombier 		Cputc(cd, 1);
366*80ee5cbfSDavid du Colombier 	else
367*80ee5cbfSDavid du Colombier 		Cputc(cd, 0);
368*80ee5cbfSDavid du Colombier 
369*80ee5cbfSDavid du Colombier 	if(Cwoffset(cd) & 1)			/* pad */
370*80ee5cbfSDavid du Colombier 		Cputc(cd, 0);
371*80ee5cbfSDavid du Colombier 
372*80ee5cbfSDavid du Colombier 	if(joliet == 0) {
373*80ee5cbfSDavid du Colombier 		if(cd->flags & CDplan9)
374*80ee5cbfSDavid du Colombier 			Cputplan9(cd, d, dot, 1);
375*80ee5cbfSDavid du Colombier 		else if(cd->flags & CDrockridge)
376*80ee5cbfSDavid du Colombier 			Cputsysuse(cd, d, dot, 1, Cwoffset(cd)-(o+lp));
377*80ee5cbfSDavid du Colombier 	}
378*80ee5cbfSDavid du Colombier 
379*80ee5cbfSDavid du Colombier 	assert(o+lp+l == Cwoffset(cd));
380*80ee5cbfSDavid du Colombier 	return lp+l;
381*80ee5cbfSDavid du Colombier }
382*80ee5cbfSDavid du Colombier 
383*80ee5cbfSDavid du Colombier int
384*80ee5cbfSDavid du Colombier Cputisodir(Cdimg *cd, Direc *d, int dot, int dowrite, int offset)
385*80ee5cbfSDavid du Colombier {
386*80ee5cbfSDavid du Colombier 	return genputdir(cd, d, dot, 0, dowrite, offset);
387*80ee5cbfSDavid du Colombier }
388*80ee5cbfSDavid du Colombier 
389*80ee5cbfSDavid du Colombier int
390*80ee5cbfSDavid du Colombier Cputjolietdir(Cdimg *cd, Direc *d, int dot, int dowrite, int offset)
391*80ee5cbfSDavid du Colombier {
392*80ee5cbfSDavid du Colombier 	return genputdir(cd, d, dot, 1, dowrite, offset);
393*80ee5cbfSDavid du Colombier }
394*80ee5cbfSDavid du Colombier 
395*80ee5cbfSDavid du Colombier void
396*80ee5cbfSDavid du Colombier Cputendvd(Cdimg *cd)
397*80ee5cbfSDavid du Colombier {
398*80ee5cbfSDavid du Colombier 	Cputc(cd, 255);				/* volume descriptor set terminator */
399*80ee5cbfSDavid du Colombier 	Cputs(cd, "CD001", 5);			/* standard identifier */
400*80ee5cbfSDavid du Colombier 	Cputc(cd, 1);				/* volume descriptor version */
401*80ee5cbfSDavid du Colombier 	Cpadblock(cd);
402*80ee5cbfSDavid du Colombier }
403