xref: /plan9/sys/src/cmd/disk/9660/write.c (revision 73ee67a1775bb9176ad6f77775e030678f092526)
180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <bio.h>
480ee5cbfSDavid du Colombier #include <libsec.h>
580ee5cbfSDavid du Colombier 
680ee5cbfSDavid du Colombier #include "iso9660.h"
780ee5cbfSDavid du Colombier 
880ee5cbfSDavid du Colombier static void
writelittlebig4(uchar * buf,ulong x)980ee5cbfSDavid du Colombier writelittlebig4(uchar *buf, ulong x)
1080ee5cbfSDavid du Colombier {
1180ee5cbfSDavid du Colombier 	buf[0] = buf[7] = x;
1280ee5cbfSDavid du Colombier 	buf[1] = buf[6] = x>>8;
1380ee5cbfSDavid du Colombier 	buf[2] = buf[5] = x>>16;
1480ee5cbfSDavid du Colombier 	buf[3] = buf[4] = x>>24;
1580ee5cbfSDavid du Colombier }
1680ee5cbfSDavid du Colombier 
1780ee5cbfSDavid du Colombier void
rewritedot(Cdimg * cd,Direc * d)1880ee5cbfSDavid du Colombier rewritedot(Cdimg *cd, Direc *d)
1980ee5cbfSDavid du Colombier {
2080ee5cbfSDavid du Colombier 	uchar buf[Blocksize];
2180ee5cbfSDavid du Colombier 	Cdir *c;
2280ee5cbfSDavid du Colombier 
2380ee5cbfSDavid du Colombier 	Creadblock(cd, buf, d->block, Blocksize);
2480ee5cbfSDavid du Colombier 	c = (Cdir*)buf;
2580ee5cbfSDavid du Colombier 	assert(c->len != 0);
2680ee5cbfSDavid du Colombier 	assert(c->namelen == 1 && c->name[0] == '\0');	/* dot */
2780ee5cbfSDavid du Colombier 	writelittlebig4(c->dloc, d->block);
2880ee5cbfSDavid du Colombier 	writelittlebig4(c->dlen, d->length);
2980ee5cbfSDavid du Colombier 
30*73ee67a1SDavid du Colombier 	Cwseek(cd, (vlong)d->block * Blocksize);
3180ee5cbfSDavid du Colombier 	Cwrite(cd, buf, Blocksize);
3280ee5cbfSDavid du Colombier }
3380ee5cbfSDavid du Colombier 
3480ee5cbfSDavid du Colombier void
rewritedotdot(Cdimg * cd,Direc * d,Direc * dparent)3580ee5cbfSDavid du Colombier rewritedotdot(Cdimg *cd, Direc *d, Direc *dparent)
3680ee5cbfSDavid du Colombier {
3780ee5cbfSDavid du Colombier 	uchar buf[Blocksize];
3880ee5cbfSDavid du Colombier 	Cdir *c;
3980ee5cbfSDavid du Colombier 
4080ee5cbfSDavid du Colombier 	Creadblock(cd, buf, d->block, Blocksize);
4180ee5cbfSDavid du Colombier 	c = (Cdir*)buf;
4280ee5cbfSDavid du Colombier 	assert(c->len != 0);
4380ee5cbfSDavid du Colombier 	assert(c->namelen == 1 && c->name[0] == '\0');	/* dot */
4480ee5cbfSDavid du Colombier 
4580ee5cbfSDavid du Colombier 	c = (Cdir*)(buf+c->len);
4680ee5cbfSDavid du Colombier 	assert(c->len != 0);
4780ee5cbfSDavid du Colombier 	assert(c->namelen == 1 && c->name[0] == '\001');	/* dotdot*/
4880ee5cbfSDavid du Colombier 
4980ee5cbfSDavid du Colombier 	writelittlebig4(c->dloc, dparent->block);
5080ee5cbfSDavid du Colombier 	writelittlebig4(c->dlen, dparent->length);
5180ee5cbfSDavid du Colombier 
52*73ee67a1SDavid du Colombier 	Cwseek(cd, (vlong)d->block * Blocksize);
5380ee5cbfSDavid du Colombier 	Cwrite(cd, buf, Blocksize);
5480ee5cbfSDavid du Colombier }
5580ee5cbfSDavid du Colombier 
5680ee5cbfSDavid du Colombier /*
5780ee5cbfSDavid du Colombier  * Write each non-directory file.  We copy the file to
5880ee5cbfSDavid du Colombier  * the cd image, and then if it turns out that we've
5980ee5cbfSDavid du Colombier  * seen this stream of bits before, we push the next block
6080ee5cbfSDavid du Colombier  * pointer back.  This ensures consistency between the MD5s
6180ee5cbfSDavid du Colombier  * and the data on the CD image.  MD5 summing on one pass
6280ee5cbfSDavid du Colombier  * and copying on another would not ensure this.
6380ee5cbfSDavid du Colombier  */
6480ee5cbfSDavid du Colombier void
writefiles(Dump * d,Cdimg * cd,Direc * direc)6580ee5cbfSDavid du Colombier writefiles(Dump *d, Cdimg *cd, Direc *direc)
6680ee5cbfSDavid du Colombier {
6780ee5cbfSDavid du Colombier 	int i;
6880ee5cbfSDavid du Colombier 	uchar buf[8192], digest[MD5dlen];
6980ee5cbfSDavid du Colombier 	ulong length, n, start;
7080ee5cbfSDavid du Colombier 	Biobuf *b;
7180ee5cbfSDavid du Colombier 	DigestState *s;
7280ee5cbfSDavid du Colombier 	Dumpdir *dd;
7380ee5cbfSDavid du Colombier 
749a747e4fSDavid du Colombier 	if(direc->mode & DMDIR) {
7580ee5cbfSDavid du Colombier 		for(i=0; i<direc->nchild; i++)
7680ee5cbfSDavid du Colombier 			writefiles(d, cd, &direc->child[i]);
7780ee5cbfSDavid du Colombier 		return;
7880ee5cbfSDavid du Colombier 	}
7980ee5cbfSDavid du Colombier 
8080ee5cbfSDavid du Colombier 	assert(direc->block == 0);
8180ee5cbfSDavid du Colombier 
8280ee5cbfSDavid du Colombier 	if((b = Bopen(direc->srcfile, OREAD)) == nil){
839a747e4fSDavid du Colombier 		fprint(2, "warning: cannot open '%s': %r\n", direc->srcfile);
8480ee5cbfSDavid du Colombier 		direc->block = 0;
8580ee5cbfSDavid du Colombier 		direc->length = 0;
8680ee5cbfSDavid du Colombier 		return;
8780ee5cbfSDavid du Colombier 	}
8880ee5cbfSDavid du Colombier 
8980ee5cbfSDavid du Colombier 	start = cd->nextblock;
9080ee5cbfSDavid du Colombier 	assert(start != 0);
914fec87e5SDavid du Colombier 	if(blocksize && start%blocksize)
924fec87e5SDavid du Colombier 		start += blocksize-start%blocksize;
9380ee5cbfSDavid du Colombier 
94*73ee67a1SDavid du Colombier 	Cwseek(cd, (vlong)start * Blocksize);
9580ee5cbfSDavid du Colombier 
9680ee5cbfSDavid du Colombier 	s = md5(nil, 0, nil, nil);
9780ee5cbfSDavid du Colombier 	length = 0;
9880ee5cbfSDavid du Colombier 	while((n = Bread(b, buf, sizeof buf)) > 0) {
9980ee5cbfSDavid du Colombier 		md5(buf, n, nil, s);
10080ee5cbfSDavid du Colombier 		Cwrite(cd, buf, n);
10180ee5cbfSDavid du Colombier 		length += n;
10280ee5cbfSDavid du Colombier 	}
10380ee5cbfSDavid du Colombier 	md5(nil, 0, digest, s);
10480ee5cbfSDavid du Colombier 	Bterm(b);
10580ee5cbfSDavid du Colombier 	Cpadblock(cd);
10680ee5cbfSDavid du Colombier 
10780ee5cbfSDavid du Colombier 	if(length != direc->length) {
10880ee5cbfSDavid du Colombier 		fprint(2, "warning: %s changed size underfoot\n", direc->srcfile);
10980ee5cbfSDavid du Colombier 		direc->length = length;
11080ee5cbfSDavid du Colombier 	}
11180ee5cbfSDavid du Colombier 
11280ee5cbfSDavid du Colombier 	if(length == 0)
11380ee5cbfSDavid du Colombier 		direc->block = 0;
11480ee5cbfSDavid du Colombier 	else if((dd = lookupmd5(d, digest))) {
11580ee5cbfSDavid du Colombier 		assert(dd->length == length);
11680ee5cbfSDavid du Colombier 		assert(dd->block != 0);
11780ee5cbfSDavid du Colombier 		direc->block = dd->block;
11880ee5cbfSDavid du Colombier 		cd->nextblock = start;
11980ee5cbfSDavid du Colombier 	} else {
12080ee5cbfSDavid du Colombier 		direc->block = start;
1215d459b5aSDavid du Colombier 		if(chatty > 1)
122b7b24591SDavid du Colombier 			fprint(2, "lookup %.16H %lud (%s) failed\n", digest, length, direc->name);
12380ee5cbfSDavid du Colombier 		insertmd5(d, atom(direc->name), digest, start, length);
12480ee5cbfSDavid du Colombier 	}
12580ee5cbfSDavid du Colombier }
12680ee5cbfSDavid du Colombier 
12780ee5cbfSDavid du Colombier /*
12880ee5cbfSDavid du Colombier  * Write a directory tree.  We work from the leaves,
12980ee5cbfSDavid du Colombier  * and patch the dotdot pointers afterward.
13080ee5cbfSDavid du Colombier  */
13180ee5cbfSDavid du Colombier static void
_writedirs(Cdimg * cd,Direc * d,int (* put)(Cdimg *,Direc *,int,int,int),int level)13280ee5cbfSDavid du Colombier _writedirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int), int level)
13380ee5cbfSDavid du Colombier {
13480ee5cbfSDavid du Colombier 	int i, l, ll;
13580ee5cbfSDavid du Colombier 	ulong start, next;
13680ee5cbfSDavid du Colombier 
1379a747e4fSDavid du Colombier 	if((d->mode & DMDIR) == 0)
13880ee5cbfSDavid du Colombier 		return;
13980ee5cbfSDavid du Colombier 
1405d459b5aSDavid du Colombier 	if(chatty)
1415d459b5aSDavid du Colombier 		fprint(2, "%*s%s\n", 4*level, "", d->name);
1425d459b5aSDavid du Colombier 
14380ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
1445d459b5aSDavid du Colombier 		_writedirs(cd, &d->child[i], put, level+1);
14580ee5cbfSDavid du Colombier 
14680ee5cbfSDavid du Colombier 	l = 0;
14780ee5cbfSDavid du Colombier 	l += put(cd, d, (level == 0) ? DTrootdot : DTdot, 0, l);
14880ee5cbfSDavid du Colombier 	l += put(cd, nil, DTdotdot, 0, l);
14980ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
15080ee5cbfSDavid du Colombier 		l += put(cd, &d->child[i], DTiden, 0, l);
15180ee5cbfSDavid du Colombier 
15280ee5cbfSDavid du Colombier 	start = cd->nextblock;
15380ee5cbfSDavid du Colombier 	cd->nextblock += (l+Blocksize-1)/Blocksize;
15480ee5cbfSDavid du Colombier 	next = cd->nextblock;
15580ee5cbfSDavid du Colombier 
156*73ee67a1SDavid du Colombier 	Cwseek(cd, (vlong)start * Blocksize);
15780ee5cbfSDavid du Colombier 	ll = 0;
15880ee5cbfSDavid du Colombier 	ll += put(cd, d, (level == 0) ? DTrootdot : DTdot, 1, ll);
15980ee5cbfSDavid du Colombier 	ll += put(cd, nil, DTdotdot, 1, ll);
16080ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
16180ee5cbfSDavid du Colombier 		ll += put(cd, &d->child[i], DTiden, 1, ll);
16280ee5cbfSDavid du Colombier 	assert(ll == l);
16380ee5cbfSDavid du Colombier 	Cpadblock(cd);
164*73ee67a1SDavid du Colombier 	assert(Cwoffset(cd) == (vlong)next * Blocksize);
16580ee5cbfSDavid du Colombier 
16680ee5cbfSDavid du Colombier 	d->block = start;
167*73ee67a1SDavid du Colombier 	d->length = (vlong)(next - start) * Blocksize;
16880ee5cbfSDavid du Colombier 	rewritedot(cd, d);
16980ee5cbfSDavid du Colombier 	rewritedotdot(cd, d, d);
17080ee5cbfSDavid du Colombier 
17180ee5cbfSDavid du Colombier 	for(i=0; i<d->nchild; i++)
1729a747e4fSDavid du Colombier 		if(d->child[i].mode & DMDIR)
17380ee5cbfSDavid du Colombier 			rewritedotdot(cd, &d->child[i], d);
17480ee5cbfSDavid du Colombier }
17580ee5cbfSDavid du Colombier 
17680ee5cbfSDavid du Colombier void
writedirs(Cdimg * cd,Direc * d,int (* put)(Cdimg *,Direc *,int,int,int))17780ee5cbfSDavid du Colombier writedirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int))
17880ee5cbfSDavid du Colombier {
17980ee5cbfSDavid du Colombier 	/*
18080ee5cbfSDavid du Colombier 	 * If we're writing a mk9660 image, then the root really
18180ee5cbfSDavid du Colombier 	 * is the root, so start at level 0.  If we're writing a dump image,
18280ee5cbfSDavid du Colombier 	 * then the "root" is really going to be two levels down once
18380ee5cbfSDavid du Colombier 	 * we patch in the dump hierarchy above it, so start at level non-zero.
18480ee5cbfSDavid du Colombier 	 */
1855d459b5aSDavid du Colombier 	if(chatty)
1865d459b5aSDavid du Colombier 		fprint(2, ">>> writedirs\n");
18780ee5cbfSDavid du Colombier 	_writedirs(cd, d, put, mk9660 ? 0 : 1);
18880ee5cbfSDavid du Colombier }
18980ee5cbfSDavid du Colombier 
19080ee5cbfSDavid du Colombier 
19180ee5cbfSDavid du Colombier /*
19280ee5cbfSDavid du Colombier  * Write the dump tree.  This is like writedirs but once we get to
19380ee5cbfSDavid du Colombier  * the roots of the individual days we just patch the parent dotdot blocks.
19480ee5cbfSDavid du Colombier  */
19580ee5cbfSDavid du Colombier static void
_writedumpdirs(Cdimg * cd,Direc * d,int (* put)(Cdimg *,Direc *,int,int,int),int level)19680ee5cbfSDavid du Colombier _writedumpdirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int), int level)
19780ee5cbfSDavid du Colombier {
19880ee5cbfSDavid du Colombier 	int i;
19980ee5cbfSDavid du Colombier 	ulong start;
20080ee5cbfSDavid du Colombier 
20180ee5cbfSDavid du Colombier 	switch(level) {
20280ee5cbfSDavid du Colombier 	case 0:
20380ee5cbfSDavid du Colombier 		/* write root, list of years, also conform.map */
20480ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
2059a747e4fSDavid du Colombier 			if(d->child[i].mode & DMDIR)
20680ee5cbfSDavid du Colombier 				_writedumpdirs(cd, &d->child[i], put, level+1);
20780ee5cbfSDavid du Colombier 		chat("write dump root dir at %lud\n", cd->nextblock);
20880ee5cbfSDavid du Colombier 		goto Writedir;
20980ee5cbfSDavid du Colombier 
21080ee5cbfSDavid du Colombier 	case 1:	/* write year, list of days */
21180ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
21280ee5cbfSDavid du Colombier 			_writedumpdirs(cd, &d->child[i], put, level+1);
21380ee5cbfSDavid du Colombier 		chat("write dump %s dir at %lud\n", d->name, cd->nextblock);
21480ee5cbfSDavid du Colombier 		goto Writedir;
21580ee5cbfSDavid du Colombier 
21680ee5cbfSDavid du Colombier 	Writedir:
21780ee5cbfSDavid du Colombier 		start = cd->nextblock;
218*73ee67a1SDavid du Colombier 		Cwseek(cd, (vlong)start * Blocksize);
21980ee5cbfSDavid du Colombier 
22080ee5cbfSDavid du Colombier 		put(cd, d, (level == 0) ? DTrootdot : DTdot, 1, Cwoffset(cd));
22180ee5cbfSDavid du Colombier 		put(cd, nil, DTdotdot, 1, Cwoffset(cd));
22280ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
22380ee5cbfSDavid du Colombier 			put(cd, &d->child[i], DTiden, 1, Cwoffset(cd));
22480ee5cbfSDavid du Colombier 		Cpadblock(cd);
22580ee5cbfSDavid du Colombier 
22680ee5cbfSDavid du Colombier 		d->block = start;
227*73ee67a1SDavid du Colombier 		d->length = (vlong)(cd->nextblock - start) * Blocksize;
22880ee5cbfSDavid du Colombier 
22980ee5cbfSDavid du Colombier 		rewritedot(cd, d);
23080ee5cbfSDavid du Colombier 		rewritedotdot(cd, d, d);
23180ee5cbfSDavid du Colombier 
23280ee5cbfSDavid du Colombier 		for(i=0; i<d->nchild; i++)
2339a747e4fSDavid du Colombier 			if(d->child[i].mode & DMDIR)
23480ee5cbfSDavid du Colombier 				rewritedotdot(cd, &d->child[i], d);
23580ee5cbfSDavid du Colombier 		break;
23680ee5cbfSDavid du Colombier 
23780ee5cbfSDavid du Colombier 	case 2:	/* write day: already written, do nothing */
23880ee5cbfSDavid du Colombier 		break;
23980ee5cbfSDavid du Colombier 
24080ee5cbfSDavid du Colombier 	default:
24180ee5cbfSDavid du Colombier 		assert(0);
24280ee5cbfSDavid du Colombier 	}
24380ee5cbfSDavid du Colombier }
24480ee5cbfSDavid du Colombier 
24580ee5cbfSDavid du Colombier void
writedumpdirs(Cdimg * cd,Direc * d,int (* put)(Cdimg *,Direc *,int,int,int))24680ee5cbfSDavid du Colombier writedumpdirs(Cdimg *cd, Direc *d, int (*put)(Cdimg*, Direc*, int, int, int))
24780ee5cbfSDavid du Colombier {
24880ee5cbfSDavid du Colombier 	_writedumpdirs(cd, d, put, 0);
24980ee5cbfSDavid du Colombier }
25080ee5cbfSDavid du Colombier 
25180ee5cbfSDavid du Colombier static int
Cputplan9(Cdimg * cd,Direc * d,int dot,int dowrite)25280ee5cbfSDavid du Colombier Cputplan9(Cdimg *cd, Direc *d, int dot, int dowrite)
25380ee5cbfSDavid du Colombier {
25480ee5cbfSDavid du Colombier 	int l, n;
25580ee5cbfSDavid du Colombier 
25680ee5cbfSDavid du Colombier 	if(dot != DTiden)
25780ee5cbfSDavid du Colombier 		return 0;
25880ee5cbfSDavid du Colombier 
25980ee5cbfSDavid du Colombier 	l = 0;
26080ee5cbfSDavid du Colombier 	if(d->flags & Dbadname) {
26180ee5cbfSDavid du Colombier 		n = strlen(d->name);
26280ee5cbfSDavid du Colombier 		l += 1+n;
26380ee5cbfSDavid du Colombier 		if(dowrite) {
26480ee5cbfSDavid du Colombier 			Cputc(cd, n);
26580ee5cbfSDavid du Colombier 			Cputs(cd, d->name, n);
26680ee5cbfSDavid du Colombier 		}
26780ee5cbfSDavid du Colombier 	} else {
26880ee5cbfSDavid du Colombier 		l++;
26980ee5cbfSDavid du Colombier 		if(dowrite)
27080ee5cbfSDavid du Colombier 			Cputc(cd, 0);
27180ee5cbfSDavid du Colombier 	}
27280ee5cbfSDavid du Colombier 
27380ee5cbfSDavid du Colombier 	n = strlen(d->uid);
27480ee5cbfSDavid du Colombier 	l += 1+n;
27580ee5cbfSDavid du Colombier 	if(dowrite) {
27680ee5cbfSDavid du Colombier 		Cputc(cd, n);
27780ee5cbfSDavid du Colombier 		Cputs(cd, d->uid, n);
27880ee5cbfSDavid du Colombier 	}
27980ee5cbfSDavid du Colombier 
28080ee5cbfSDavid du Colombier 	n = strlen(d->gid);
28180ee5cbfSDavid du Colombier 	l += 1+n;
28280ee5cbfSDavid du Colombier 	if(dowrite) {
28380ee5cbfSDavid du Colombier 		Cputc(cd, n);
28480ee5cbfSDavid du Colombier 		Cputs(cd, d->gid, n);
28580ee5cbfSDavid du Colombier 	}
28680ee5cbfSDavid du Colombier 
28780ee5cbfSDavid du Colombier 	if(l & 1) {
28880ee5cbfSDavid du Colombier 		l++;
28980ee5cbfSDavid du Colombier 		if(dowrite)
29080ee5cbfSDavid du Colombier 			Cputc(cd, 0);
29180ee5cbfSDavid du Colombier 	}
29280ee5cbfSDavid du Colombier 	l += 8;
29380ee5cbfSDavid du Colombier 	if(dowrite)
29480ee5cbfSDavid du Colombier 		Cputn(cd, d->mode, 4);
29580ee5cbfSDavid du Colombier 
29680ee5cbfSDavid du Colombier 	return l;
29780ee5cbfSDavid du Colombier }
29880ee5cbfSDavid du Colombier 
29980ee5cbfSDavid du Colombier /*
30080ee5cbfSDavid du Colombier  * Write a directory entry.
30180ee5cbfSDavid du Colombier  */
30280ee5cbfSDavid du Colombier static int
genputdir(Cdimg * cd,Direc * d,int dot,int joliet,int dowrite,int offset)30380ee5cbfSDavid du Colombier genputdir(Cdimg *cd, Direc *d, int dot, int joliet, int dowrite, int offset)
30480ee5cbfSDavid du Colombier {
30580ee5cbfSDavid du Colombier 	int f, n, l, lp;
306*73ee67a1SDavid du Colombier 	vlong o;
30780ee5cbfSDavid du Colombier 
30880ee5cbfSDavid du Colombier 	f = 0;
3099a747e4fSDavid du Colombier 	if(dot != DTiden || (d->mode & DMDIR))
31080ee5cbfSDavid du Colombier 		f |= 2;
31180ee5cbfSDavid du Colombier 
31280ee5cbfSDavid du Colombier 	n = 1;
31380ee5cbfSDavid du Colombier 	if(dot == DTiden) {
31480ee5cbfSDavid du Colombier 		if(joliet)
31580ee5cbfSDavid du Colombier 			n = 2*utflen(d->confname);
31680ee5cbfSDavid du Colombier 		else
31780ee5cbfSDavid du Colombier 			n = strlen(d->confname);
31880ee5cbfSDavid du Colombier 	}
31980ee5cbfSDavid du Colombier 
32080ee5cbfSDavid du Colombier 	l = 33+n;
32180ee5cbfSDavid du Colombier 	if(l & 1)
32280ee5cbfSDavid du Colombier 		l++;
32380ee5cbfSDavid du Colombier 	assert(l <= 255);
32480ee5cbfSDavid du Colombier 
32580ee5cbfSDavid du Colombier 	if(joliet == 0) {
32680ee5cbfSDavid du Colombier 		if(cd->flags & CDplan9)
32780ee5cbfSDavid du Colombier 			l += Cputplan9(cd, d, dot, 0);
32880ee5cbfSDavid du Colombier 		else if(cd->flags & CDrockridge)
32980ee5cbfSDavid du Colombier 			l += Cputsysuse(cd, d, dot, 0, l);
33080ee5cbfSDavid du Colombier 		assert(l <= 255);
33180ee5cbfSDavid du Colombier 	}
33280ee5cbfSDavid du Colombier 
33380ee5cbfSDavid du Colombier 	if(dowrite == 0) {
33480ee5cbfSDavid du Colombier 		if(Blocksize - offset%Blocksize < l)
33580ee5cbfSDavid du Colombier 			l += Blocksize - offset%Blocksize;
33680ee5cbfSDavid du Colombier 		return l;
33780ee5cbfSDavid du Colombier 	}
33880ee5cbfSDavid du Colombier 
33980ee5cbfSDavid du Colombier 	assert(offset%Blocksize == Cwoffset(cd)%Blocksize);
34080ee5cbfSDavid du Colombier 
34180ee5cbfSDavid du Colombier 	o = Cwoffset(cd);
34280ee5cbfSDavid du Colombier 	lp = 0;
34380ee5cbfSDavid du Colombier 	if(Blocksize - Cwoffset(cd)%Blocksize < l) {
34480ee5cbfSDavid du Colombier 		lp = Blocksize - Cwoffset(cd)%Blocksize;
34580ee5cbfSDavid du Colombier 		Cpadblock(cd);
34680ee5cbfSDavid du Colombier 	}
34780ee5cbfSDavid du Colombier 
34880ee5cbfSDavid du Colombier 	Cputc(cd, l);			/* length of directory record */
34980ee5cbfSDavid du Colombier 	Cputc(cd, 0);			/* extended attribute record length */
35080ee5cbfSDavid du Colombier 	if(d) {
3519a747e4fSDavid du Colombier 		if((d->mode & DMDIR) == 0)
35280ee5cbfSDavid du Colombier 			assert(d->length == 0 || d->block >= 18);
35380ee5cbfSDavid du Colombier 
35480ee5cbfSDavid du Colombier 		Cputn(cd, d->block, 4);		/* location of extent */
35580ee5cbfSDavid du Colombier 		Cputn(cd, d->length, 4);		/* data length */
35680ee5cbfSDavid du Colombier 	} else {
35780ee5cbfSDavid du Colombier 		Cputn(cd, 0, 4);
35880ee5cbfSDavid du Colombier 		Cputn(cd, 0, 4);
35980ee5cbfSDavid du Colombier 	}
36080ee5cbfSDavid du Colombier 	Cputdate(cd, d ? d->mtime : now);		/* recorded date */
36180ee5cbfSDavid du Colombier 	Cputc(cd, f);			/* file flags */
36280ee5cbfSDavid du Colombier 	Cputc(cd, 0);			/* file unit size */
36380ee5cbfSDavid du Colombier 	Cputc(cd, 0);			/* interleave gap size */
36480ee5cbfSDavid du Colombier 	Cputn(cd, 1, 2);	       	/* volume sequence number */
36580ee5cbfSDavid du Colombier 	Cputc(cd, n);			/* length of file identifier */
36680ee5cbfSDavid du Colombier 
36780ee5cbfSDavid du Colombier 	if(dot == DTiden) {		/* identifier */
36880ee5cbfSDavid du Colombier 		if(joliet)
36980ee5cbfSDavid du Colombier 			Cputrscvt(cd, d->confname, n);
37080ee5cbfSDavid du Colombier 		else
37180ee5cbfSDavid du Colombier 			Cputs(cd, d->confname, n);
37280ee5cbfSDavid du Colombier 	}else
37380ee5cbfSDavid du Colombier 	if(dot == DTdotdot)
37480ee5cbfSDavid du Colombier 		Cputc(cd, 1);
37580ee5cbfSDavid du Colombier 	else
37680ee5cbfSDavid du Colombier 		Cputc(cd, 0);
37780ee5cbfSDavid du Colombier 
37880ee5cbfSDavid du Colombier 	if(Cwoffset(cd) & 1)			/* pad */
37980ee5cbfSDavid du Colombier 		Cputc(cd, 0);
38080ee5cbfSDavid du Colombier 
38180ee5cbfSDavid du Colombier 	if(joliet == 0) {
38280ee5cbfSDavid du Colombier 		if(cd->flags & CDplan9)
38380ee5cbfSDavid du Colombier 			Cputplan9(cd, d, dot, 1);
38480ee5cbfSDavid du Colombier 		else if(cd->flags & CDrockridge)
38580ee5cbfSDavid du Colombier 			Cputsysuse(cd, d, dot, 1, Cwoffset(cd)-(o+lp));
38680ee5cbfSDavid du Colombier 	}
38780ee5cbfSDavid du Colombier 
38880ee5cbfSDavid du Colombier 	assert(o+lp+l == Cwoffset(cd));
38980ee5cbfSDavid du Colombier 	return lp+l;
39080ee5cbfSDavid du Colombier }
39180ee5cbfSDavid du Colombier 
39280ee5cbfSDavid du Colombier int
Cputisodir(Cdimg * cd,Direc * d,int dot,int dowrite,int offset)39380ee5cbfSDavid du Colombier Cputisodir(Cdimg *cd, Direc *d, int dot, int dowrite, int offset)
39480ee5cbfSDavid du Colombier {
39580ee5cbfSDavid du Colombier 	return genputdir(cd, d, dot, 0, dowrite, offset);
39680ee5cbfSDavid du Colombier }
39780ee5cbfSDavid du Colombier 
39880ee5cbfSDavid du Colombier int
Cputjolietdir(Cdimg * cd,Direc * d,int dot,int dowrite,int offset)39980ee5cbfSDavid du Colombier Cputjolietdir(Cdimg *cd, Direc *d, int dot, int dowrite, int offset)
40080ee5cbfSDavid du Colombier {
40180ee5cbfSDavid du Colombier 	return genputdir(cd, d, dot, 1, dowrite, offset);
40280ee5cbfSDavid du Colombier }
40380ee5cbfSDavid du Colombier 
40480ee5cbfSDavid du Colombier void
Cputendvd(Cdimg * cd)40580ee5cbfSDavid du Colombier Cputendvd(Cdimg *cd)
40680ee5cbfSDavid du Colombier {
40780ee5cbfSDavid du Colombier 	Cputc(cd, 255);				/* volume descriptor set terminator */
40880ee5cbfSDavid du Colombier 	Cputs(cd, "CD001", 5);			/* standard identifier */
40980ee5cbfSDavid du Colombier 	Cputc(cd, 1);				/* volume descriptor version */
41080ee5cbfSDavid du Colombier 	Cpadblock(cd);
41180ee5cbfSDavid du Colombier }
412