xref: /plan9/sys/src/cmd/disk/9660/dump9660.c (revision a587111c8770e522e3667ff2b63cba8a77811dd9)
180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <bio.h>
480ee5cbfSDavid du Colombier #include <disk.h>
580ee5cbfSDavid du Colombier #include <libsec.h>
680ee5cbfSDavid du Colombier #include "iso9660.h"
780ee5cbfSDavid du Colombier 
880ee5cbfSDavid du Colombier ulong now;
980ee5cbfSDavid du Colombier int chatty;
1080ee5cbfSDavid du Colombier int doabort;
1180ee5cbfSDavid du Colombier int docolon;
1280ee5cbfSDavid du Colombier int mk9660;
1373ee67a1SDavid du Colombier vlong dataoffset;
144fec87e5SDavid du Colombier int blocksize;
1580ee5cbfSDavid du Colombier Conform *map;
1680ee5cbfSDavid du Colombier 
1780ee5cbfSDavid du Colombier static void addprotofile(char *new, char *old, Dir *d, void *a);
1880ee5cbfSDavid du Colombier void usage(void);
1980ee5cbfSDavid du Colombier 
2080ee5cbfSDavid du Colombier char *argv0;
2180ee5cbfSDavid du Colombier 
2280ee5cbfSDavid du Colombier void
usage(void)2380ee5cbfSDavid du Colombier usage(void)
2480ee5cbfSDavid du Colombier {
2580ee5cbfSDavid du Colombier 	if(mk9660)
269b7bf7dfSDavid du Colombier 		fprint(2, "usage: disk/mk9660 [-D:] [-9cjr] "
279b7bf7dfSDavid du Colombier 			"[-[bB] bootfile] [-o offset blocksize] "
289b7bf7dfSDavid du Colombier 			"[-p proto] [-s src] cdimage\n");
2980ee5cbfSDavid du Colombier 	else
309b7bf7dfSDavid du Colombier 		fprint(2, "usage: disk/dump9660 [-D:] [-9cjr] "
319b7bf7dfSDavid du Colombier 			"[-m maxsize] [-n now] "
329b7bf7dfSDavid du Colombier 			"[-p proto] [-s src] cdimage\n");
3380ee5cbfSDavid du Colombier 	exits("usage");
3480ee5cbfSDavid du Colombier }
3580ee5cbfSDavid du Colombier 
3673ee67a1SDavid du Colombier void
main(int argc,char ** argv)3780ee5cbfSDavid du Colombier main(int argc, char **argv)
3880ee5cbfSDavid du Colombier {
3980ee5cbfSDavid du Colombier 	int fix;
4073ee67a1SDavid du Colombier 	ulong block, newnull, cblock;
4173ee67a1SDavid du Colombier 	vlong maxsize;
4273ee67a1SDavid du Colombier 	uvlong length, clength;
4380ee5cbfSDavid du Colombier 	char buf[256], *dumpname, *proto, *s, *src, *status;
4480ee5cbfSDavid du Colombier 	Cdimg *cd;
4580ee5cbfSDavid du Colombier 	Cdinfo info;
4680ee5cbfSDavid du Colombier 	XDir dir;
4780ee5cbfSDavid du Colombier 	Direc *iconform, idumproot, iroot, *jconform, jdumproot, jroot, *r;
4880ee5cbfSDavid du Colombier 	Dump *dump;
4980ee5cbfSDavid du Colombier 
5080ee5cbfSDavid du Colombier 	fix = 0;
5180ee5cbfSDavid du Colombier 	status = nil;
5280ee5cbfSDavid du Colombier 	memset(&info, 0, sizeof info);
5380ee5cbfSDavid du Colombier 	proto = "/sys/lib/sysconfig/proto/allproto";
5480ee5cbfSDavid du Colombier 	src = "./";
5580ee5cbfSDavid du Colombier 
5680ee5cbfSDavid du Colombier 	info.volumename = atom("9CD");
5780ee5cbfSDavid du Colombier 	info.volumeset = atom("9VolumeSet");
5880ee5cbfSDavid du Colombier 	info.publisher = atom("9Publisher");
5980ee5cbfSDavid du Colombier 	info.preparer = atom("dump9660");
6080ee5cbfSDavid du Colombier 	info.application = atom("dump9660");
6180ee5cbfSDavid du Colombier 	info.flags = CDdump;
6280ee5cbfSDavid du Colombier 	maxsize = 0;
6380ee5cbfSDavid du Colombier 	mk9660 = 0;
64b7b24591SDavid du Colombier 	fmtinstall('H', encodefmt);
6580ee5cbfSDavid du Colombier 
6680ee5cbfSDavid du Colombier 	ARGBEGIN{
6780ee5cbfSDavid du Colombier 	case 'D':
6880ee5cbfSDavid du Colombier 		chatty++;
6980ee5cbfSDavid du Colombier 		break;
7080ee5cbfSDavid du Colombier 	case 'M':
7180ee5cbfSDavid du Colombier 		mk9660 = 1;
7280ee5cbfSDavid du Colombier 		argv0 = "disk/mk9660";
7380ee5cbfSDavid du Colombier 		info.flags &= ~CDdump;
7480ee5cbfSDavid du Colombier 		break;
7580ee5cbfSDavid du Colombier 	case '9':
7680ee5cbfSDavid du Colombier 		info.flags |= CDplan9;
7780ee5cbfSDavid du Colombier 		break;
7880ee5cbfSDavid du Colombier 	case ':':
7980ee5cbfSDavid du Colombier 		docolon = 1;
8080ee5cbfSDavid du Colombier 		break;
8180ee5cbfSDavid du Colombier 	case 'a':
8280ee5cbfSDavid du Colombier 		doabort = 1;
8380ee5cbfSDavid du Colombier 		break;
8443751f27SDavid du Colombier 	case 'B':
8543751f27SDavid du Colombier 		info.flags |= CDbootnoemu;
8643751f27SDavid du Colombier 		/* fall through */
879a747e4fSDavid du Colombier 	case 'b':
889a747e4fSDavid du Colombier 		if(!mk9660)
899a747e4fSDavid du Colombier 			usage();
909a747e4fSDavid du Colombier 		info.flags |= CDbootable;
919a747e4fSDavid du Colombier 		info.bootimage = EARGF(usage());
929a747e4fSDavid du Colombier 		break;
9380ee5cbfSDavid du Colombier 	case 'c':
9480ee5cbfSDavid du Colombier 		info.flags |= CDconform;
9580ee5cbfSDavid du Colombier 		break;
9680ee5cbfSDavid du Colombier 	case 'f':
9780ee5cbfSDavid du Colombier 		fix = 1;
9880ee5cbfSDavid du Colombier 		break;
9980ee5cbfSDavid du Colombier 	case 'j':
10080ee5cbfSDavid du Colombier 		info.flags |= CDjoliet;
10180ee5cbfSDavid du Colombier 		break;
10280ee5cbfSDavid du Colombier 	case 'n':
10380ee5cbfSDavid du Colombier 		now = atoi(EARGF(usage()));
10480ee5cbfSDavid du Colombier 		break;
10580ee5cbfSDavid du Colombier 	case 'm':
10673ee67a1SDavid du Colombier 		maxsize = strtoull(EARGF(usage()), 0, 0);
10780ee5cbfSDavid du Colombier 		break;
1084fec87e5SDavid du Colombier 	case 'o':
10973ee67a1SDavid du Colombier 		dataoffset = atoll(EARGF(usage()));
1104fec87e5SDavid du Colombier 		blocksize = atoi(EARGF(usage()));
1114fec87e5SDavid du Colombier 		if(blocksize%Blocksize)
1124fec87e5SDavid du Colombier 			sysfatal("bad block size %d -- must be multiple of 2048", blocksize);
1134fec87e5SDavid du Colombier 		blocksize /= Blocksize;
1144fec87e5SDavid du Colombier 		break;
11580ee5cbfSDavid du Colombier 	case 'p':
11680ee5cbfSDavid du Colombier 		proto = EARGF(usage());
11780ee5cbfSDavid du Colombier 		break;
11880ee5cbfSDavid du Colombier 	case 'r':
11980ee5cbfSDavid du Colombier 		info.flags |= CDrockridge;
12080ee5cbfSDavid du Colombier 		break;
12180ee5cbfSDavid du Colombier 	case 's':
12280ee5cbfSDavid du Colombier 		src = EARGF(usage());
12380ee5cbfSDavid du Colombier 		break;
12480ee5cbfSDavid du Colombier 	case 'v':
12580ee5cbfSDavid du Colombier 		info.volumename = atom(EARGF(usage()));
12680ee5cbfSDavid du Colombier 		break;
127f7db6155SDavid du Colombier 	case 'x':
128f7db6155SDavid du Colombier 		info.flags |= CDpbs;
129f7db6155SDavid du Colombier 		info.loader = EARGF(usage());
130f7db6155SDavid du Colombier 		break;
13180ee5cbfSDavid du Colombier 	default:
13280ee5cbfSDavid du Colombier 		usage();
13380ee5cbfSDavid du Colombier 	}ARGEND
13480ee5cbfSDavid du Colombier 
135f7db6155SDavid du Colombier 	if(info.flags & CDpbs && !(info.flags & CDbootnoemu))
136f7db6155SDavid du Colombier 		usage();
137f7db6155SDavid du Colombier 
13880ee5cbfSDavid du Colombier 	if(mk9660 && (fix || now || maxsize))
13980ee5cbfSDavid du Colombier 		usage();
14080ee5cbfSDavid du Colombier 
14180ee5cbfSDavid du Colombier 	if(argc != 1)
14280ee5cbfSDavid du Colombier 		usage();
14380ee5cbfSDavid du Colombier 
14480ee5cbfSDavid du Colombier 	if(now == 0)
14580ee5cbfSDavid du Colombier 		now = (ulong)time(0);
14680ee5cbfSDavid du Colombier 	if(mk9660){
14780ee5cbfSDavid du Colombier 		if((cd = createcd(argv[0], info)) == nil)
14880ee5cbfSDavid du Colombier 			sysfatal("cannot create '%s': %r", argv[0]);
14980ee5cbfSDavid du Colombier 	}else{
15080ee5cbfSDavid du Colombier 		if((cd = opencd(argv[0], info)) == nil)
15180ee5cbfSDavid du Colombier 			sysfatal("cannot open '%s': %r", argv[0]);
15280ee5cbfSDavid du Colombier 		if(!(cd->flags & CDdump))
15380ee5cbfSDavid du Colombier 			sysfatal("not a dump cd");
15480ee5cbfSDavid du Colombier 	}
15580ee5cbfSDavid du Colombier 
15680ee5cbfSDavid du Colombier 	/* create ISO9660/Plan 9 tree in memory */
15780ee5cbfSDavid du Colombier 	memset(&dir, 0, sizeof dir);
15880ee5cbfSDavid du Colombier 	dir.name = atom("");
15980ee5cbfSDavid du Colombier 	dir.uid = atom("sys");
16080ee5cbfSDavid du Colombier 	dir.gid = atom("sys");
16180ee5cbfSDavid du Colombier 	dir.uidno = 0;
16280ee5cbfSDavid du Colombier 	dir.gidno = 0;
1639a747e4fSDavid du Colombier 	dir.mode = DMDIR | 0755;
16480ee5cbfSDavid du Colombier 	dir.mtime = now;
16580ee5cbfSDavid du Colombier 	dir.atime = now;
16680ee5cbfSDavid du Colombier 	dir.ctime = now;
16780ee5cbfSDavid du Colombier 
16880ee5cbfSDavid du Colombier 	mkdirec(&iroot, &dir);
16980ee5cbfSDavid du Colombier 	iroot.srcfile = src;
17080ee5cbfSDavid du Colombier 
17180ee5cbfSDavid du Colombier 	/*
17280ee5cbfSDavid du Colombier 	 * Read new files into memory
17380ee5cbfSDavid du Colombier 	 */
17480ee5cbfSDavid du Colombier 	if(rdproto(proto, src, addprotofile, nil, &iroot) < 0)
17580ee5cbfSDavid du Colombier 		sysfatal("rdproto: %r");
17680ee5cbfSDavid du Colombier 
17780ee5cbfSDavid du Colombier 	if(mk9660){
17880ee5cbfSDavid du Colombier 		dump = emalloc(sizeof *dump);
17980ee5cbfSDavid du Colombier 		dumpname = nil;
18080ee5cbfSDavid du Colombier 	}else{
18180ee5cbfSDavid du Colombier 		/*
18280ee5cbfSDavid du Colombier 		 * Read current dump tree and _conform.map.
18380ee5cbfSDavid du Colombier 		 */
18480ee5cbfSDavid du Colombier 		idumproot = readdumpdirs(cd, &dir, isostring);
18580ee5cbfSDavid du Colombier 		readdumpconform(cd);
18680ee5cbfSDavid du Colombier 		if(cd->flags & CDjoliet)
18780ee5cbfSDavid du Colombier 			jdumproot = readdumpdirs(cd, &dir, jolietstring);
18880ee5cbfSDavid du Colombier 
18980ee5cbfSDavid du Colombier 		if(fix){
19080ee5cbfSDavid du Colombier 			dumpname = nil;
19180ee5cbfSDavid du Colombier 			cd->nextblock = cd->nulldump+1;
19280ee5cbfSDavid du Colombier 			cd->nulldump = 0;
19373ee67a1SDavid du Colombier 			Cwseek(cd, (vlong)cd->nextblock * Blocksize);
19480ee5cbfSDavid du Colombier 			goto Dofix;
19580ee5cbfSDavid du Colombier 		}
19680ee5cbfSDavid du Colombier 
19780ee5cbfSDavid du Colombier 		dumpname = adddumpdir(&idumproot, now, &dir);
19880ee5cbfSDavid du Colombier 		/* note that we assume all names are conforming and thus sorted */
19980ee5cbfSDavid du Colombier 		if(cd->flags & CDjoliet) {
20080ee5cbfSDavid du Colombier 			s = adddumpdir(&jdumproot, now, &dir);
20180ee5cbfSDavid du Colombier 			if(s != dumpname)
20214cc0f53SDavid du Colombier 				sysfatal("dumpnames don't match %s %s", dumpname, s);
20380ee5cbfSDavid du Colombier 		}
20480ee5cbfSDavid du Colombier 		dump = dumpcd(cd, &idumproot);
20580ee5cbfSDavid du Colombier 		cd->nextblock = cd->nulldump+1;
20680ee5cbfSDavid du Colombier 	}
20780ee5cbfSDavid du Colombier 
20880ee5cbfSDavid du Colombier 	/*
20980ee5cbfSDavid du Colombier 	 * Write new files, starting where the dump tree was.
21080ee5cbfSDavid du Colombier  	 * Must be done before creation of the Joliet tree so that
21180ee5cbfSDavid du Colombier  	 * blocks and lengths are correct.
21280ee5cbfSDavid du Colombier 	 */
21373ee67a1SDavid du Colombier 	if(dataoffset > (vlong)cd->nextblock * Blocksize)
2144fec87e5SDavid du Colombier 		cd->nextblock = (dataoffset+Blocksize-1)/Blocksize;
21573ee67a1SDavid du Colombier 	Cwseek(cd, (vlong)cd->nextblock * Blocksize);
21680ee5cbfSDavid du Colombier 	writefiles(dump, cd, &iroot);
21780ee5cbfSDavid du Colombier 
2189a747e4fSDavid du Colombier 	if(cd->bootimage){
2199a747e4fSDavid du Colombier 		findbootimage(cd, &iroot);
220f7db6155SDavid du Colombier 		if(cd->loader)
221f7db6155SDavid du Colombier 			findloader(cd, &iroot);
2229a747e4fSDavid du Colombier 		Cupdatebootcat(cd);
2239a747e4fSDavid du Colombier 	}
2249a747e4fSDavid du Colombier 
22580ee5cbfSDavid du Colombier 	/* create Joliet tree */
22680ee5cbfSDavid du Colombier 	if(cd->flags & CDjoliet)
22780ee5cbfSDavid du Colombier 		copydirec(&jroot, &iroot);
22880ee5cbfSDavid du Colombier 
22980ee5cbfSDavid du Colombier 	if(info.flags & CDconform) {
23080ee5cbfSDavid du Colombier 		checknames(&iroot, isbadiso9660);
23180ee5cbfSDavid du Colombier 		convertnames(&iroot, struprcpy);
23280ee5cbfSDavid du Colombier 	} else
23380ee5cbfSDavid du Colombier 		convertnames(&iroot, (void *) strcpy);
23480ee5cbfSDavid du Colombier 
23580ee5cbfSDavid du Colombier //	isoabstract = findconform(&iroot, abstract);
23680ee5cbfSDavid du Colombier //	isobiblio = findconform(&iroot, biblio);
23780ee5cbfSDavid du Colombier //	isonotice = findconform(&iroot, notice);
23880ee5cbfSDavid du Colombier 
23980ee5cbfSDavid du Colombier 	dsort(&iroot, isocmp);
24080ee5cbfSDavid du Colombier 
24180ee5cbfSDavid du Colombier 	if(cd->flags & CDjoliet) {
24280ee5cbfSDavid du Colombier 	//	jabstract = findconform(&jroot, abstract);
24380ee5cbfSDavid du Colombier 	//	jbiblio = findconform(&jroot, biblio);
24480ee5cbfSDavid du Colombier 	//	jnotice = findconform(&jroot, notice);
24580ee5cbfSDavid du Colombier 
24680ee5cbfSDavid du Colombier 		checknames(&jroot, isbadjoliet);
24780ee5cbfSDavid du Colombier 		convertnames(&jroot, (void *) strcpy);
24880ee5cbfSDavid du Colombier 		dsort(&jroot, jolietcmp);
24980ee5cbfSDavid du Colombier 	}
25080ee5cbfSDavid du Colombier 
25180ee5cbfSDavid du Colombier 	/*
25280ee5cbfSDavid du Colombier 	 * Write directories.
25380ee5cbfSDavid du Colombier 	 */
25480ee5cbfSDavid du Colombier 	writedirs(cd, &iroot, Cputisodir);
25580ee5cbfSDavid du Colombier 	if(cd->flags & CDjoliet)
25680ee5cbfSDavid du Colombier 		writedirs(cd, &jroot, Cputjolietdir);
25780ee5cbfSDavid du Colombier 
25880ee5cbfSDavid du Colombier 	if(mk9660){
25980ee5cbfSDavid du Colombier 		cblock = 0;
26080ee5cbfSDavid du Colombier 		clength = 0;
26180ee5cbfSDavid du Colombier 		newnull = 0;
26280ee5cbfSDavid du Colombier 	}else{
26380ee5cbfSDavid du Colombier 		/*
26480ee5cbfSDavid du Colombier 		 * Write incremental _conform.map block.
26580ee5cbfSDavid du Colombier 		 */
26680ee5cbfSDavid du Colombier 		wrconform(cd, cd->nconform, &cblock, &clength);
26780ee5cbfSDavid du Colombier 
26880ee5cbfSDavid du Colombier 		/* jump here if we're just fixing up the cd */
26980ee5cbfSDavid du Colombier Dofix:
27080ee5cbfSDavid du Colombier 		/*
27180ee5cbfSDavid du Colombier 		 * Write null dump header block; everything after this will be
27280ee5cbfSDavid du Colombier 		 * overwritten at the next dump.  Because of this, it needs to be
27380ee5cbfSDavid du Colombier 		 * reconstructable.  We reconstruct the _conform.map and dump trees
27480ee5cbfSDavid du Colombier 		 * from the header blocks in dump.c, and we reconstruct the path
27580ee5cbfSDavid du Colombier 		 * tables by walking the cd.
27680ee5cbfSDavid du Colombier 		 */
27780ee5cbfSDavid du Colombier 		newnull = Cputdumpblock(cd);
27880ee5cbfSDavid du Colombier 	}
279f7db6155SDavid du Colombier 	if(info.flags & CDpbs)
280f7db6155SDavid du Colombier 		Cfillpbs(cd);
28180ee5cbfSDavid du Colombier 
28280ee5cbfSDavid du Colombier 	/*
28380ee5cbfSDavid du Colombier 	 * Write _conform.map.
28480ee5cbfSDavid du Colombier 	 */
28580ee5cbfSDavid du Colombier 	dir.mode = 0444;
28680ee5cbfSDavid du Colombier 	if(cd->flags & (CDconform|CDjoliet)) {
28780ee5cbfSDavid du Colombier 		if(!mk9660 && cd->nconform == 0){
28880ee5cbfSDavid du Colombier 			block = cblock;
28980ee5cbfSDavid du Colombier 			length = clength;
29080ee5cbfSDavid du Colombier 		}else
29180ee5cbfSDavid du Colombier 			wrconform(cd, 0, &block, &length);
29280ee5cbfSDavid du Colombier 
29380ee5cbfSDavid du Colombier 		if(mk9660)
29480ee5cbfSDavid du Colombier {
29580ee5cbfSDavid du Colombier 			idumproot = iroot;
29680ee5cbfSDavid du Colombier 			jdumproot = jroot;
29780ee5cbfSDavid du Colombier 		}
29880ee5cbfSDavid du Colombier 		if(length) {
29980ee5cbfSDavid du Colombier 			/* The ISO9660 name will get turned into uppercase when written. */
30080ee5cbfSDavid du Colombier 			if((iconform = walkdirec(&idumproot, "_conform.map")) == nil)
30180ee5cbfSDavid du Colombier 				iconform = adddirec(&idumproot, "_conform.map", &dir);
30280ee5cbfSDavid du Colombier 			jconform = nil;
30380ee5cbfSDavid du Colombier 			if(cd->flags & CDjoliet) {
30480ee5cbfSDavid du Colombier 				if((jconform = walkdirec(&jdumproot, "_conform.map")) == nil)
30580ee5cbfSDavid du Colombier 					jconform = adddirec(&jdumproot, "_conform.map", &dir);
30680ee5cbfSDavid du Colombier 			}
30780ee5cbfSDavid du Colombier 			iconform->block = block;
30880ee5cbfSDavid du Colombier 			iconform->length = length;
30980ee5cbfSDavid du Colombier 			if(cd->flags & CDjoliet) {
31080ee5cbfSDavid du Colombier 				jconform->block = block;
31180ee5cbfSDavid du Colombier 				jconform->length = length;
31280ee5cbfSDavid du Colombier 			}
31380ee5cbfSDavid du Colombier 		}
31480ee5cbfSDavid du Colombier 		if(mk9660) {
31580ee5cbfSDavid du Colombier 			iroot = idumproot;
31680ee5cbfSDavid du Colombier 			jroot = jdumproot;
31780ee5cbfSDavid du Colombier 		}
31880ee5cbfSDavid du Colombier 	}
31980ee5cbfSDavid du Colombier 
32080ee5cbfSDavid du Colombier 	if(mk9660){
32180ee5cbfSDavid du Colombier 		/*
32280ee5cbfSDavid du Colombier 		 * Patch in root directories.
32380ee5cbfSDavid du Colombier 		 */
32480ee5cbfSDavid du Colombier 		setroot(cd, cd->iso9660pvd, iroot.block, iroot.length);
325*a587111cSDavid du Colombier 		setvolsize(cd, cd->iso9660pvd, cd->nextblock);
32680ee5cbfSDavid du Colombier 		if(cd->flags & CDjoliet){
32780ee5cbfSDavid du Colombier 			setroot(cd, cd->jolietsvd, jroot.block, jroot.length);
328*a587111cSDavid du Colombier 			setvolsize(cd, cd->jolietsvd, cd->nextblock);
32980ee5cbfSDavid du Colombier 		}
33080ee5cbfSDavid du Colombier 	}else{
33180ee5cbfSDavid du Colombier 		/*
33280ee5cbfSDavid du Colombier 		 * Write dump tree at end.  We assume the name characters
33380ee5cbfSDavid du Colombier 		 * are all conforming, so everything is already sorted properly.
33480ee5cbfSDavid du Colombier 		 */
33580ee5cbfSDavid du Colombier 		convertnames(&idumproot, (info.flags & CDconform) ? (void *) struprcpy : (void *) strcpy);
33680ee5cbfSDavid du Colombier 		if(cd->nulldump) {
33780ee5cbfSDavid du Colombier 			r = walkdirec(&idumproot, dumpname);
33880ee5cbfSDavid du Colombier 			assert(r != nil);
33980ee5cbfSDavid du Colombier 			copybutname(r, &iroot);
34080ee5cbfSDavid du Colombier 		}
34180ee5cbfSDavid du Colombier 		if(cd->flags & CDjoliet) {
34280ee5cbfSDavid du Colombier 			convertnames(&jdumproot, (void *) strcpy);
34380ee5cbfSDavid du Colombier 			if(cd->nulldump) {
34480ee5cbfSDavid du Colombier 				r = walkdirec(&jdumproot, dumpname);
34580ee5cbfSDavid du Colombier 				assert(r != nil);
34680ee5cbfSDavid du Colombier 				copybutname(r, &jroot);
34780ee5cbfSDavid du Colombier 			}
34880ee5cbfSDavid du Colombier 		}
34980ee5cbfSDavid du Colombier 
35080ee5cbfSDavid du Colombier 		writedumpdirs(cd, &idumproot, Cputisodir);
35180ee5cbfSDavid du Colombier 		if(cd->flags & CDjoliet)
35280ee5cbfSDavid du Colombier 			writedumpdirs(cd, &jdumproot, Cputjolietdir);
35380ee5cbfSDavid du Colombier 
35480ee5cbfSDavid du Colombier 		/*
35580ee5cbfSDavid du Colombier 		 * Patch in new root directory entry.
35680ee5cbfSDavid du Colombier 		 */
35780ee5cbfSDavid du Colombier 		setroot(cd, cd->iso9660pvd, idumproot.block, idumproot.length);
358*a587111cSDavid du Colombier 		setvolsize(cd, cd->iso9660pvd, cd->nextblock);
35980ee5cbfSDavid du Colombier 		if(cd->flags & CDjoliet){
36080ee5cbfSDavid du Colombier 			setroot(cd, cd->jolietsvd, jdumproot.block, jdumproot.length);
361*a587111cSDavid du Colombier 			setvolsize(cd, cd->jolietsvd, cd->nextblock);
36280ee5cbfSDavid du Colombier 		}
36380ee5cbfSDavid du Colombier 	}
36480ee5cbfSDavid du Colombier 	writepathtables(cd);
36580ee5cbfSDavid du Colombier 
36680ee5cbfSDavid du Colombier 	if(!mk9660){
36780ee5cbfSDavid du Colombier 		/*
36880ee5cbfSDavid du Colombier 		 * If we've gotten too big, truncate back to what we started with,
36980ee5cbfSDavid du Colombier 		 * fix up the cd, and exit with a non-zero status.
37080ee5cbfSDavid du Colombier 		 */
37180ee5cbfSDavid du Colombier 		Cwflush(cd);
37280ee5cbfSDavid du Colombier 		if(cd->nulldump && maxsize && Cwoffset(cd) > maxsize){
37380ee5cbfSDavid du Colombier 			fprint(2, "too big; writing old tree back\n");
37480ee5cbfSDavid du Colombier 			status = "cd too big; aborted";
37580ee5cbfSDavid du Colombier 
37680ee5cbfSDavid du Colombier 			rmdumpdir(&idumproot, dumpname);
37780ee5cbfSDavid du Colombier 			rmdumpdir(&jdumproot, dumpname);
37880ee5cbfSDavid du Colombier 
37980ee5cbfSDavid du Colombier 			cd->nextblock = cd->nulldump+1;
38080ee5cbfSDavid du Colombier 			cd->nulldump = 0;
38173ee67a1SDavid du Colombier 			Cwseek(cd, (vlong)cd->nextblock * Blocksize);
38280ee5cbfSDavid du Colombier 			goto Dofix;
38380ee5cbfSDavid du Colombier 		}
38480ee5cbfSDavid du Colombier 
38580ee5cbfSDavid du Colombier 		/*
38680ee5cbfSDavid du Colombier 		 * Write old null header block; this commits all our changes.
38780ee5cbfSDavid du Colombier 		 */
38880ee5cbfSDavid du Colombier 		if(cd->nulldump){
38973ee67a1SDavid du Colombier 			Cwseek(cd, (vlong)cd->nulldump * Blocksize);
39080ee5cbfSDavid du Colombier 			sprint(buf, "plan 9 dump cd\n");
39173ee67a1SDavid du Colombier 			sprint(buf+strlen(buf), "%s %lud %lud %lud %llud %lud %lud",
39273ee67a1SDavid du Colombier 				dumpname, now, newnull, cblock, clength,
39373ee67a1SDavid du Colombier 				iroot.block, iroot.length);
39480ee5cbfSDavid du Colombier 			if(cd->flags & CDjoliet)
39580ee5cbfSDavid du Colombier 				sprint(buf+strlen(buf), " %lud %lud",
39680ee5cbfSDavid du Colombier 					jroot.block, jroot.length);
39780ee5cbfSDavid du Colombier 			strcat(buf, "\n");
39880ee5cbfSDavid du Colombier 			Cwrite(cd, buf, strlen(buf));
39980ee5cbfSDavid du Colombier 			Cpadblock(cd);
40080ee5cbfSDavid du Colombier 			Cwflush(cd);
40180ee5cbfSDavid du Colombier 		}
40280ee5cbfSDavid du Colombier 	}
40373ee67a1SDavid du Colombier 	fdtruncate(cd->fd, (vlong)cd->nextblock * Blocksize);
40480ee5cbfSDavid du Colombier 	exits(status);
40580ee5cbfSDavid du Colombier }
40680ee5cbfSDavid du Colombier 
40780ee5cbfSDavid du Colombier static void
addprotofile(char * new,char * old,Dir * d,void * a)40880ee5cbfSDavid du Colombier addprotofile(char *new, char *old, Dir *d, void *a)
40980ee5cbfSDavid du Colombier {
41080ee5cbfSDavid du Colombier 	char *name, *p;
41180ee5cbfSDavid du Colombier 	Direc *direc;
41280ee5cbfSDavid du Colombier 	XDir xd;
41380ee5cbfSDavid du Colombier 
41480ee5cbfSDavid du Colombier 	dirtoxdir(&xd, d);
41580ee5cbfSDavid du Colombier 	name = nil;
41680ee5cbfSDavid du Colombier 	if(docolon && strchr(new, ':')) {
41780ee5cbfSDavid du Colombier 		name = emalloc(strlen(new)+1);
41880ee5cbfSDavid du Colombier 		strcpy(name, new);
41980ee5cbfSDavid du Colombier 		while((p=strchr(name, ':')))
42080ee5cbfSDavid du Colombier 			*p=' ';
42180ee5cbfSDavid du Colombier 		new = name;
42280ee5cbfSDavid du Colombier 	}
42380ee5cbfSDavid du Colombier 	if((direc = adddirec((Direc*)a, new, &xd))) {
42480ee5cbfSDavid du Colombier 		direc->srcfile = atom(old);
42580ee5cbfSDavid du Colombier 
42680ee5cbfSDavid du Colombier 		// BUG: abstract, biblio, notice
42780ee5cbfSDavid du Colombier 	}
42880ee5cbfSDavid du Colombier 	if(name)
42980ee5cbfSDavid du Colombier 		free(name);
43080ee5cbfSDavid du Colombier }
431