xref: /plan9/sys/src/cmd/disk/9660/dump.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 #include <ctype.h>
680ee5cbfSDavid du Colombier #include "iso9660.h"
780ee5cbfSDavid du Colombier 
880ee5cbfSDavid du Colombier static void
md5cd(Cdimg * cd,ulong block,ulong length,uchar * digest)980ee5cbfSDavid du Colombier md5cd(Cdimg *cd, ulong block, ulong length, uchar *digest)
1080ee5cbfSDavid du Colombier {
1180ee5cbfSDavid du Colombier 	int n;
1280ee5cbfSDavid du Colombier 	uchar buf[Blocksize];
1380ee5cbfSDavid du Colombier 	DigestState *s;
1480ee5cbfSDavid du Colombier 
1580ee5cbfSDavid du Colombier 	s = md5(nil, 0, nil, nil);
1680ee5cbfSDavid du Colombier 	while(length > 0) {
1780ee5cbfSDavid du Colombier 		n = length;
1880ee5cbfSDavid du Colombier 		if(n > Blocksize)
1980ee5cbfSDavid du Colombier 			n = Blocksize;
2080ee5cbfSDavid du Colombier 
2180ee5cbfSDavid du Colombier 		Creadblock(cd, buf, block, n);
2280ee5cbfSDavid du Colombier 
2380ee5cbfSDavid du Colombier 		md5(buf, n, nil, s);
2480ee5cbfSDavid du Colombier 
2580ee5cbfSDavid du Colombier 		block++;
2680ee5cbfSDavid du Colombier 		length -= n;
2780ee5cbfSDavid du Colombier 	}
2880ee5cbfSDavid du Colombier 	md5(nil, 0, digest, s);
2980ee5cbfSDavid du Colombier }
3080ee5cbfSDavid du Colombier 
3180ee5cbfSDavid du Colombier static Dumpdir*
mkdumpdir(char * name,uchar * md5,ulong block,ulong length)3280ee5cbfSDavid du Colombier mkdumpdir(char *name, uchar *md5, ulong block, ulong length)
3380ee5cbfSDavid du Colombier {
3480ee5cbfSDavid du Colombier 	Dumpdir *d;
3580ee5cbfSDavid du Colombier 
3680ee5cbfSDavid du Colombier 	assert(block != 0);
3780ee5cbfSDavid du Colombier 
3880ee5cbfSDavid du Colombier 	d = emalloc(sizeof *d);
3980ee5cbfSDavid du Colombier 	d->name = name;
4080ee5cbfSDavid du Colombier 	memmove(d->md5, md5, sizeof d->md5);
4180ee5cbfSDavid du Colombier 	d->block = block;
4280ee5cbfSDavid du Colombier 	d->length = length;
4380ee5cbfSDavid du Colombier 
4480ee5cbfSDavid du Colombier 	return d;
4580ee5cbfSDavid du Colombier }
4680ee5cbfSDavid du Colombier 
4780ee5cbfSDavid du Colombier static Dumpdir**
ltreewalkmd5(Dumpdir ** l,uchar * md5)4880ee5cbfSDavid du Colombier ltreewalkmd5(Dumpdir **l, uchar *md5)
4980ee5cbfSDavid du Colombier {
5080ee5cbfSDavid du Colombier 	int i;
5180ee5cbfSDavid du Colombier 
5280ee5cbfSDavid du Colombier 	while(*l) {
5380ee5cbfSDavid du Colombier 		i = memcmp(md5, (*l)->md5, MD5dlen);
5480ee5cbfSDavid du Colombier 		if(i < 0)
5580ee5cbfSDavid du Colombier 			l = &(*l)->md5left;
5680ee5cbfSDavid du Colombier 		else if(i == 0)
5780ee5cbfSDavid du Colombier 			return l;
5880ee5cbfSDavid du Colombier 		else
5980ee5cbfSDavid du Colombier 			l = &(*l)->md5right;
6080ee5cbfSDavid du Colombier 	}
6180ee5cbfSDavid du Colombier 	return l;
6280ee5cbfSDavid du Colombier }
6380ee5cbfSDavid du Colombier 
6480ee5cbfSDavid du Colombier static Dumpdir**
ltreewalkblock(Dumpdir ** l,ulong block)6580ee5cbfSDavid du Colombier ltreewalkblock(Dumpdir **l, ulong block)
6680ee5cbfSDavid du Colombier {
6780ee5cbfSDavid du Colombier 	while(*l) {
6880ee5cbfSDavid du Colombier 		if(block < (*l)->block)
6980ee5cbfSDavid du Colombier 			l = &(*l)->blockleft;
7080ee5cbfSDavid du Colombier 		else if(block == (*l)->block)
7180ee5cbfSDavid du Colombier 			return l;
7280ee5cbfSDavid du Colombier 		else
7380ee5cbfSDavid du Colombier 			l = &(*l)->blockright;
7480ee5cbfSDavid du Colombier 	}
7580ee5cbfSDavid du Colombier 	return l;
7680ee5cbfSDavid du Colombier }
7780ee5cbfSDavid du Colombier 
7880ee5cbfSDavid du Colombier /*
7980ee5cbfSDavid du Colombier  * Add a particular file to our binary tree.
8080ee5cbfSDavid du Colombier  */
8180ee5cbfSDavid du Colombier static void
addfile(Cdimg * cd,Dump * d,char * name,Direc * dir)8280ee5cbfSDavid du Colombier addfile(Cdimg *cd, Dump *d, char *name, Direc *dir)
8380ee5cbfSDavid du Colombier {
8480ee5cbfSDavid du Colombier 	uchar md5[MD5dlen];
8580ee5cbfSDavid du Colombier 	Dumpdir **lblock;
8680ee5cbfSDavid du Colombier 
879a747e4fSDavid du Colombier 	assert((dir->mode & DMDIR) == 0);
8880ee5cbfSDavid du Colombier 
8980ee5cbfSDavid du Colombier 	if(dir->length == 0)
9080ee5cbfSDavid du Colombier 		return;
9180ee5cbfSDavid du Colombier 
9280ee5cbfSDavid du Colombier 	lblock = ltreewalkblock(&d->blockroot, dir->block);
9380ee5cbfSDavid du Colombier 	if(*lblock != nil) {
9480ee5cbfSDavid du Colombier 		if((*lblock)->length == dir->length)
9580ee5cbfSDavid du Colombier 			return;
9680ee5cbfSDavid du Colombier 		fprint(2, "block %lud length %lud %s %lud %s\n", dir->block, (*lblock)->length, (*lblock)->name,
9780ee5cbfSDavid du Colombier 			dir->length, dir->name);
9880ee5cbfSDavid du Colombier 		assert(0);
9980ee5cbfSDavid du Colombier 	}
10080ee5cbfSDavid du Colombier 
10180ee5cbfSDavid du Colombier 	md5cd(cd, dir->block, dir->length, md5);
1025d459b5aSDavid du Colombier 	if(chatty > 1)
103b7b24591SDavid du Colombier 		fprint(2, "note file %.16H %lud (%s)\n", md5, dir->length, dir->name);
10480ee5cbfSDavid du Colombier 	insertmd5(d, name, md5, dir->block, dir->length);
10580ee5cbfSDavid du Colombier }
10680ee5cbfSDavid du Colombier 
10780ee5cbfSDavid du Colombier void
insertmd5(Dump * d,char * name,uchar * md5,ulong block,ulong length)10880ee5cbfSDavid du Colombier insertmd5(Dump *d, char *name, uchar *md5, ulong block, ulong length)
10980ee5cbfSDavid du Colombier {
11080ee5cbfSDavid du Colombier 	Dumpdir **lmd5;
11180ee5cbfSDavid du Colombier 	Dumpdir **lblock;
11280ee5cbfSDavid du Colombier 
11380ee5cbfSDavid du Colombier 	lblock = ltreewalkblock(&d->blockroot, block);
11480ee5cbfSDavid du Colombier 	if(*lblock != nil) {
11580ee5cbfSDavid du Colombier 		if((*lblock)->length == length)
11680ee5cbfSDavid du Colombier 			return;
11780ee5cbfSDavid du Colombier 		fprint(2, "block %lud length %lud %lud\n", block, (*lblock)->length, length);
11880ee5cbfSDavid du Colombier 		assert(0);
11980ee5cbfSDavid du Colombier 	}
12080ee5cbfSDavid du Colombier 
12180ee5cbfSDavid du Colombier 	assert(length != 0);
12280ee5cbfSDavid du Colombier 	*lblock = mkdumpdir(name, md5, block, length);
12380ee5cbfSDavid du Colombier 
12480ee5cbfSDavid du Colombier 	lmd5 = ltreewalkmd5(&d->md5root, md5);
12580ee5cbfSDavid du Colombier 	if(*lmd5 != nil)
12680ee5cbfSDavid du Colombier 		fprint(2, "warning: data duplicated on CD\n");
12780ee5cbfSDavid du Colombier 	else
12880ee5cbfSDavid du Colombier 		*lmd5 = *lblock;
12980ee5cbfSDavid du Colombier }
13080ee5cbfSDavid du Colombier 
13180ee5cbfSDavid du Colombier /*
13280ee5cbfSDavid du Colombier  * Fill all the children entries for a particular directory;
13380ee5cbfSDavid du Colombier  * all we care about is block, length, and whether it is a directory.
13480ee5cbfSDavid du Colombier  */
13580ee5cbfSDavid du Colombier void
readkids(Cdimg * cd,Direc * dir,char * (* cvt)(uchar *,int))13680ee5cbfSDavid du Colombier readkids(Cdimg *cd, Direc *dir, char *(*cvt)(uchar*, int))
13780ee5cbfSDavid du Colombier {
13880ee5cbfSDavid du Colombier 	char *dot, *dotdot;
13980ee5cbfSDavid du Colombier 	int m, n;
14080ee5cbfSDavid du Colombier 	uchar buf[Blocksize], *ebuf, *p;
14180ee5cbfSDavid du Colombier 	ulong b, nb;
14280ee5cbfSDavid du Colombier 	Cdir *c;
14380ee5cbfSDavid du Colombier 	Direc dx;
14480ee5cbfSDavid du Colombier 
1459a747e4fSDavid du Colombier 	assert(dir->mode & DMDIR);
14680ee5cbfSDavid du Colombier 
14780ee5cbfSDavid du Colombier 	dot = atom(".");
14880ee5cbfSDavid du Colombier 	dotdot = atom("..");
14980ee5cbfSDavid du Colombier 	ebuf = buf+Blocksize;
15080ee5cbfSDavid du Colombier 	nb = (dir->length+Blocksize-1) / Blocksize;
15180ee5cbfSDavid du Colombier 
15280ee5cbfSDavid du Colombier 	n = 0;
15380ee5cbfSDavid du Colombier 	for(b=0; b<nb; b++) {
15480ee5cbfSDavid du Colombier 		Creadblock(cd, buf, dir->block + b, Blocksize);
15580ee5cbfSDavid du Colombier 		p = buf;
15680ee5cbfSDavid du Colombier 		while(p < ebuf) {
15780ee5cbfSDavid du Colombier 			c = (Cdir*)p;
15880ee5cbfSDavid du Colombier 			if(c->len == 0)
15980ee5cbfSDavid du Colombier 				break;
16080ee5cbfSDavid du Colombier 			if(p+c->len > ebuf)
16180ee5cbfSDavid du Colombier 				break;
16280ee5cbfSDavid du Colombier 			if(parsedir(cd, &dx, p, ebuf-p, cvt) == 0 && dx.name != dot && dx.name != dotdot)
16380ee5cbfSDavid du Colombier 				n++;
16480ee5cbfSDavid du Colombier 			p += c->len;
16580ee5cbfSDavid du Colombier 		}
16680ee5cbfSDavid du Colombier 	}
16780ee5cbfSDavid du Colombier 
16880ee5cbfSDavid du Colombier 	m = (n+Ndirblock-1)/Ndirblock * Ndirblock;
16980ee5cbfSDavid du Colombier 	dir->child = emalloc(m*sizeof dir->child[0]);
17080ee5cbfSDavid du Colombier 	dir->nchild = n;
17180ee5cbfSDavid du Colombier 
17280ee5cbfSDavid du Colombier 	n = 0;
17380ee5cbfSDavid du Colombier 	for(b=0; b<nb; b++) {
17480ee5cbfSDavid du Colombier 		assert(n <= dir->nchild);
17580ee5cbfSDavid du Colombier 		Creadblock(cd, buf, dir->block + b, Blocksize);
17680ee5cbfSDavid du Colombier 		p = buf;
17780ee5cbfSDavid du Colombier 		while(p < ebuf) {
17880ee5cbfSDavid du Colombier 			c = (Cdir*)p;
17980ee5cbfSDavid du Colombier 			if(c->len == 0)
18080ee5cbfSDavid du Colombier 				break;
18180ee5cbfSDavid du Colombier 			if(p+c->len > ebuf)
18280ee5cbfSDavid du Colombier 				break;
18380ee5cbfSDavid du Colombier 			if(parsedir(cd, &dx, p, ebuf-p, cvt) == 0 && dx.name != dot && dx.name != dotdot) {
18480ee5cbfSDavid du Colombier 				assert(n < dir->nchild);
18580ee5cbfSDavid du Colombier 				dir->child[n++] = dx;
18680ee5cbfSDavid du Colombier 			}
18780ee5cbfSDavid du Colombier 			p += c->len;
18880ee5cbfSDavid du Colombier 		}
18980ee5cbfSDavid du Colombier 	}
19080ee5cbfSDavid du Colombier }
19180ee5cbfSDavid du Colombier 
19280ee5cbfSDavid du Colombier /*
19380ee5cbfSDavid du Colombier  * Free the children.  Make sure their children are free too.
19480ee5cbfSDavid du Colombier  */
19580ee5cbfSDavid du Colombier void
freekids(Direc * dir)19680ee5cbfSDavid du Colombier freekids(Direc *dir)
19780ee5cbfSDavid du Colombier {
19880ee5cbfSDavid du Colombier 	int i;
19980ee5cbfSDavid du Colombier 
20080ee5cbfSDavid du Colombier 	for(i=0; i<dir->nchild; i++)
20180ee5cbfSDavid du Colombier 		assert(dir->child[i].nchild == 0);
20280ee5cbfSDavid du Colombier 
20380ee5cbfSDavid du Colombier 	free(dir->child);
20480ee5cbfSDavid du Colombier 	dir->child = nil;
20580ee5cbfSDavid du Colombier 	dir->nchild = 0;
20680ee5cbfSDavid du Colombier }
20780ee5cbfSDavid du Colombier 
20880ee5cbfSDavid du Colombier /*
20980ee5cbfSDavid du Colombier  * Add a whole directory and all its children to our binary tree.
21080ee5cbfSDavid du Colombier  */
21180ee5cbfSDavid du Colombier static void
adddir(Cdimg * cd,Dump * d,Direc * dir)21280ee5cbfSDavid du Colombier adddir(Cdimg *cd, Dump *d, Direc *dir)
21380ee5cbfSDavid du Colombier {
21480ee5cbfSDavid du Colombier 	int i;
21580ee5cbfSDavid du Colombier 
21680ee5cbfSDavid du Colombier 	readkids(cd, dir, isostring);
21780ee5cbfSDavid du Colombier 	for(i=0; i<dir->nchild; i++) {
2189a747e4fSDavid du Colombier 		if(dir->child[i].mode & DMDIR)
21980ee5cbfSDavid du Colombier 			adddir(cd, d, &dir->child[i]);
22080ee5cbfSDavid du Colombier 		else
22180ee5cbfSDavid du Colombier 			addfile(cd, d, atom(dir->name), &dir->child[i]);
22280ee5cbfSDavid du Colombier 	}
22380ee5cbfSDavid du Colombier 	freekids(dir);
22480ee5cbfSDavid du Colombier }
22580ee5cbfSDavid du Colombier 
22680ee5cbfSDavid du Colombier Dumpdir*
lookupmd5(Dump * d,uchar * md5)22780ee5cbfSDavid du Colombier lookupmd5(Dump *d, uchar *md5)
22880ee5cbfSDavid du Colombier {
22980ee5cbfSDavid du Colombier 	return *ltreewalkmd5(&d->md5root, md5);
23080ee5cbfSDavid du Colombier }
23180ee5cbfSDavid du Colombier 
23280ee5cbfSDavid du Colombier void
adddirx(Cdimg * cd,Dump * d,Direc * dir,int lev)23380ee5cbfSDavid du Colombier adddirx(Cdimg *cd, Dump *d, Direc *dir, int lev)
23480ee5cbfSDavid du Colombier {
23580ee5cbfSDavid du Colombier 	int i;
23680ee5cbfSDavid du Colombier 	Direc dd;
23780ee5cbfSDavid du Colombier 
23880ee5cbfSDavid du Colombier 	if(lev == 2){
23980ee5cbfSDavid du Colombier 		dd = *dir;
24080ee5cbfSDavid du Colombier 		adddir(cd, d, &dd);
24180ee5cbfSDavid du Colombier 		return;
24280ee5cbfSDavid du Colombier 	}
24380ee5cbfSDavid du Colombier 	for(i=0; i<dir->nchild; i++)
24480ee5cbfSDavid du Colombier 		adddirx(cd, d, &dir->child[i], lev+1);
24580ee5cbfSDavid du Colombier }
24680ee5cbfSDavid du Colombier 
24780ee5cbfSDavid du Colombier Dump*
dumpcd(Cdimg * cd,Direc * dir)24880ee5cbfSDavid du Colombier dumpcd(Cdimg *cd, Direc *dir)
24980ee5cbfSDavid du Colombier {
25080ee5cbfSDavid du Colombier 	Dump *d;
25180ee5cbfSDavid du Colombier 
25280ee5cbfSDavid du Colombier 	d = emalloc(sizeof *d);
25380ee5cbfSDavid du Colombier 	d->cd = cd;
25480ee5cbfSDavid du Colombier 	adddirx(cd, d, dir, 0);
25580ee5cbfSDavid du Colombier 	return d;
25680ee5cbfSDavid du Colombier }
25780ee5cbfSDavid du Colombier 
25880ee5cbfSDavid du Colombier /*
25980ee5cbfSDavid du Colombier static ulong
26080ee5cbfSDavid du Colombier minblock(Direc *root, int lev)
26180ee5cbfSDavid du Colombier {
26280ee5cbfSDavid du Colombier 	int i;
26380ee5cbfSDavid du Colombier 	ulong m, n;
26480ee5cbfSDavid du Colombier 
26580ee5cbfSDavid du Colombier 	m = root->block;
26680ee5cbfSDavid du Colombier 	for(i=0; i<root->nchild; i++) {
26780ee5cbfSDavid du Colombier 		n = minblock(&root->child[i], lev-1);
26880ee5cbfSDavid du Colombier 		if(m > n)
26980ee5cbfSDavid du Colombier 			m = n;
27080ee5cbfSDavid du Colombier 	}
27180ee5cbfSDavid du Colombier 	return m;
27280ee5cbfSDavid du Colombier }
27380ee5cbfSDavid du Colombier */
27480ee5cbfSDavid du Colombier 
27580ee5cbfSDavid du Colombier void
copybutname(Direc * d,Direc * s)27680ee5cbfSDavid du Colombier copybutname(Direc *d, Direc *s)
27780ee5cbfSDavid du Colombier {
27880ee5cbfSDavid du Colombier 	Direc x;
27980ee5cbfSDavid du Colombier 
28080ee5cbfSDavid du Colombier 	x = *d;
28180ee5cbfSDavid du Colombier 	*d = *s;
28280ee5cbfSDavid du Colombier 	d->name = x.name;
28380ee5cbfSDavid du Colombier 	d->confname = x.confname;
28480ee5cbfSDavid du Colombier }
28580ee5cbfSDavid du Colombier 
28680ee5cbfSDavid du Colombier Direc*
createdumpdir(Direc * root,XDir * dir,char * utfname)28780ee5cbfSDavid du Colombier createdumpdir(Direc *root, XDir *dir, char *utfname)
28880ee5cbfSDavid du Colombier {
28980ee5cbfSDavid du Colombier 	char *p;
29080ee5cbfSDavid du Colombier 	Direc *d;
29180ee5cbfSDavid du Colombier 
29280ee5cbfSDavid du Colombier 	if(utfname[0]=='/')
29380ee5cbfSDavid du Colombier 		sysfatal("bad dump name '%s'", utfname);
29480ee5cbfSDavid du Colombier 	p = strchr(utfname, '/');
29580ee5cbfSDavid du Colombier 	if(p == nil || strchr(p+1, '/'))
29680ee5cbfSDavid du Colombier 		sysfatal("bad dump name '%s'", utfname);
29780ee5cbfSDavid du Colombier 	*p++ = '\0';
29880ee5cbfSDavid du Colombier 	if((d = walkdirec(root, utfname)) == nil)
29980ee5cbfSDavid du Colombier 		d = adddirec(root, utfname, dir);
30080ee5cbfSDavid du Colombier 	if(walkdirec(d, p))
30180ee5cbfSDavid du Colombier 		sysfatal("duplicate dump name '%s/%s'", utfname, p);
30280ee5cbfSDavid du Colombier 	d = adddirec(d, p, dir);
30380ee5cbfSDavid du Colombier 	return d;
30480ee5cbfSDavid du Colombier }
30580ee5cbfSDavid du Colombier 
30680ee5cbfSDavid du Colombier static void
rmdirec(Direc * d,Direc * kid)30780ee5cbfSDavid du Colombier rmdirec(Direc *d, Direc *kid)
30880ee5cbfSDavid du Colombier {
30980ee5cbfSDavid du Colombier 	Direc *ekid;
31080ee5cbfSDavid du Colombier 
31180ee5cbfSDavid du Colombier 	ekid = d->child+d->nchild;
31280ee5cbfSDavid du Colombier 	assert(d->child <= kid && kid < ekid);
31380ee5cbfSDavid du Colombier 	if(ekid != kid+1)
31480ee5cbfSDavid du Colombier 		memmove(kid, kid+1, (ekid-(kid+1))*sizeof(*kid));
31580ee5cbfSDavid du Colombier 	d->nchild--;
31680ee5cbfSDavid du Colombier }
31780ee5cbfSDavid du Colombier 
31880ee5cbfSDavid du Colombier void
rmdumpdir(Direc * root,char * utfname)31980ee5cbfSDavid du Colombier rmdumpdir(Direc *root, char *utfname)
32080ee5cbfSDavid du Colombier {
32180ee5cbfSDavid du Colombier 	char *p;
32280ee5cbfSDavid du Colombier 	Direc *d, *dd;
32380ee5cbfSDavid du Colombier 
32480ee5cbfSDavid du Colombier 	if(utfname[0]=='/')
32580ee5cbfSDavid du Colombier 		sysfatal("bad dump name '%s'", utfname);
32680ee5cbfSDavid du Colombier 	p = strchr(utfname, '/');
32780ee5cbfSDavid du Colombier 	if(p == nil || strchr(p+1, '/'))
32880ee5cbfSDavid du Colombier 		sysfatal("bad dump name '%s'", utfname);
32980ee5cbfSDavid du Colombier 	*p++ = '\0';
33080ee5cbfSDavid du Colombier 	if((d = walkdirec(root, utfname)) == nil)
33180ee5cbfSDavid du Colombier 		sysfatal("cannot remove %s/%s: %s does not exist", utfname, p, utfname);
33280ee5cbfSDavid du Colombier 	p[-1] = '/';
33380ee5cbfSDavid du Colombier 
33480ee5cbfSDavid du Colombier 	if((dd = walkdirec(d, p)) == nil)
33580ee5cbfSDavid du Colombier 		sysfatal("cannot remove %s: does not exist", utfname);
33680ee5cbfSDavid du Colombier 
33780ee5cbfSDavid du Colombier 	rmdirec(d, dd);
33880ee5cbfSDavid du Colombier 	if(d->nchild == 0)
33980ee5cbfSDavid du Colombier 		rmdirec(root, d);
34080ee5cbfSDavid du Colombier }
34180ee5cbfSDavid du Colombier 
34280ee5cbfSDavid du Colombier char*
adddumpdir(Direc * root,ulong now,XDir * dir)34380ee5cbfSDavid du Colombier adddumpdir(Direc *root, ulong now, XDir *dir)
34480ee5cbfSDavid du Colombier {
34580ee5cbfSDavid du Colombier 	char buf[40], *p;
34680ee5cbfSDavid du Colombier 	int n;
34780ee5cbfSDavid du Colombier 	Direc *dday, *dyear;
34880ee5cbfSDavid du Colombier 	Tm tm;
34980ee5cbfSDavid du Colombier 
35080ee5cbfSDavid du Colombier 	tm = *localtime(now);
35180ee5cbfSDavid du Colombier 
35280ee5cbfSDavid du Colombier 	sprint(buf, "%d", tm.year+1900);
35380ee5cbfSDavid du Colombier 	if((dyear = walkdirec(root, buf)) == nil) {
35480ee5cbfSDavid du Colombier 		dyear = adddirec(root, buf, dir);
35580ee5cbfSDavid du Colombier 		assert(dyear != nil);
35680ee5cbfSDavid du Colombier 	}
35780ee5cbfSDavid du Colombier 
35880ee5cbfSDavid du Colombier 	n = 0;
35980ee5cbfSDavid du Colombier 	sprint(buf, "%.2d%.2d", tm.mon+1, tm.mday);
36080ee5cbfSDavid du Colombier 	p = buf+strlen(buf);
36180ee5cbfSDavid du Colombier 	while(walkdirec(dyear, buf))
36280ee5cbfSDavid du Colombier 		sprint(p, "%d", ++n);
36380ee5cbfSDavid du Colombier 
36480ee5cbfSDavid du Colombier 	dday = adddirec(dyear, buf, dir);
36580ee5cbfSDavid du Colombier 	assert(dday != nil);
36680ee5cbfSDavid du Colombier 
36780ee5cbfSDavid du Colombier 	sprint(buf, "%s/%s", dyear->name, dday->name);
36880ee5cbfSDavid du Colombier assert(walkdirec(root, buf)==dday);
36980ee5cbfSDavid du Colombier 	return atom(buf);
37080ee5cbfSDavid du Colombier }
37180ee5cbfSDavid du Colombier 
37280ee5cbfSDavid du Colombier /*
37380ee5cbfSDavid du Colombier  * The dump directory tree is inferred from a linked list of special blocks.
37480ee5cbfSDavid du Colombier  * One block is written at the end of each dump.
37580ee5cbfSDavid du Colombier  * The blocks have the form
37680ee5cbfSDavid du Colombier  *
37780ee5cbfSDavid du Colombier  * plan 9 dump cd
37880ee5cbfSDavid du Colombier  * <dump-name> <dump-time> <next-block> <conform-block> <conform-length> \
37980ee5cbfSDavid du Colombier  *	<iroot-block> <iroot-length> <jroot-block> <jroot-length>
38080ee5cbfSDavid du Colombier  *
38180ee5cbfSDavid du Colombier  * If only the first line is present, this is the end of the chain.
38280ee5cbfSDavid du Colombier  */
38380ee5cbfSDavid du Colombier static char magic[] = "plan 9 dump cd\n";
38480ee5cbfSDavid du Colombier ulong
Cputdumpblock(Cdimg * cd)38580ee5cbfSDavid du Colombier Cputdumpblock(Cdimg *cd)
38680ee5cbfSDavid du Colombier {
387*73ee67a1SDavid du Colombier 	uvlong x;
38880ee5cbfSDavid du Colombier 
389*73ee67a1SDavid du Colombier 	Cwseek(cd, (vlong)cd->nextblock * Blocksize);
39080ee5cbfSDavid du Colombier 	x = Cwoffset(cd);
39180ee5cbfSDavid du Colombier 	Cwrite(cd, magic, sizeof(magic)-1);
39280ee5cbfSDavid du Colombier 	Cpadblock(cd);
39380ee5cbfSDavid du Colombier 	return x/Blocksize;
39480ee5cbfSDavid du Colombier }
39580ee5cbfSDavid du Colombier 
39680ee5cbfSDavid du Colombier int
hasdump(Cdimg * cd)39780ee5cbfSDavid du Colombier hasdump(Cdimg *cd)
39880ee5cbfSDavid du Colombier {
39980ee5cbfSDavid du Colombier 	int i;
40080ee5cbfSDavid du Colombier 	char buf[128];
40180ee5cbfSDavid du Colombier 
40280ee5cbfSDavid du Colombier 	for(i=16; i<24; i++) {
40380ee5cbfSDavid du Colombier 		Creadblock(cd, buf, i, sizeof buf);
40480ee5cbfSDavid du Colombier 		if(memcmp(buf, magic, sizeof(magic)-1) == 0)
40580ee5cbfSDavid du Colombier 			return i;
40680ee5cbfSDavid du Colombier 	}
40780ee5cbfSDavid du Colombier 	return 0;
40880ee5cbfSDavid du Colombier }
40980ee5cbfSDavid du Colombier 
41080ee5cbfSDavid du Colombier Direc
readdumpdirs(Cdimg * cd,XDir * dir,char * (* cvt)(uchar *,int))41180ee5cbfSDavid du Colombier readdumpdirs(Cdimg *cd, XDir *dir, char *(*cvt)(uchar*, int))
41280ee5cbfSDavid du Colombier {
41380ee5cbfSDavid du Colombier 	char buf[Blocksize];
41480ee5cbfSDavid du Colombier 	char *p, *q, *f[16];
41580ee5cbfSDavid du Colombier 	int i, nf;
41680ee5cbfSDavid du Colombier 	ulong db, t;
41780ee5cbfSDavid du Colombier 	Direc *nr, root;
41880ee5cbfSDavid du Colombier 	XDir xd;
41980ee5cbfSDavid du Colombier 
42080ee5cbfSDavid du Colombier 	mkdirec(&root, dir);
42180ee5cbfSDavid du Colombier 	db = hasdump(cd);
42280ee5cbfSDavid du Colombier 	xd = *dir;
42380ee5cbfSDavid du Colombier 	for(;;){
42480ee5cbfSDavid du Colombier 		if(db == 0)
42580ee5cbfSDavid du Colombier 			sysfatal("error in dump blocks");
42680ee5cbfSDavid du Colombier 
42780ee5cbfSDavid du Colombier 		Creadblock(cd, buf, db, sizeof buf);
42880ee5cbfSDavid du Colombier 		if(memcmp(buf, magic, sizeof(magic)-1) != 0)
42980ee5cbfSDavid du Colombier 			break;
43080ee5cbfSDavid du Colombier 		p = buf+sizeof(magic)-1;
43180ee5cbfSDavid du Colombier 		if(p[0] == '\0')
43280ee5cbfSDavid du Colombier 			break;
43380ee5cbfSDavid du Colombier 		if((q = strchr(p, '\n')) != nil)
43480ee5cbfSDavid du Colombier 			*q = '\0';
43580ee5cbfSDavid du Colombier 
43680ee5cbfSDavid du Colombier 		nf = tokenize(p, f, nelem(f));
43780ee5cbfSDavid du Colombier 		i = 5;
43880ee5cbfSDavid du Colombier 		if(nf < i || (cvt==jolietstring && nf < i+2))
43980ee5cbfSDavid du Colombier 			sysfatal("error in dump block %lud: nf=%d; p='%s'", db, nf, p);
44080ee5cbfSDavid du Colombier 		nr = createdumpdir(&root, &xd, f[0]);
44180ee5cbfSDavid du Colombier 		t = strtoul(f[1], 0, 0);
44280ee5cbfSDavid du Colombier 		xd.mtime = xd.ctime = xd.atime = t;
44380ee5cbfSDavid du Colombier 		db = strtoul(f[2], 0, 0);
44480ee5cbfSDavid du Colombier 		if(cvt == jolietstring)
44580ee5cbfSDavid du Colombier 			i += 2;
44680ee5cbfSDavid du Colombier 		nr->block = strtoul(f[i], 0, 0);
44780ee5cbfSDavid du Colombier 		nr->length = strtoul(f[i+1], 0, 0);
44880ee5cbfSDavid du Colombier 	}
44980ee5cbfSDavid du Colombier 	cd->nulldump = db;
45080ee5cbfSDavid du Colombier 	return root;
45180ee5cbfSDavid du Colombier }
45280ee5cbfSDavid du Colombier 
45380ee5cbfSDavid du Colombier extern void addtx(char*, char*);
45480ee5cbfSDavid du Colombier 
45580ee5cbfSDavid du Colombier static int
isalldigit(char * s)45680ee5cbfSDavid du Colombier isalldigit(char *s)
45780ee5cbfSDavid du Colombier {
45880ee5cbfSDavid du Colombier 	while(*s)
45980ee5cbfSDavid du Colombier 		if(!isdigit(*s++))
46080ee5cbfSDavid du Colombier 			return 0;
46180ee5cbfSDavid du Colombier 	return 1;
46280ee5cbfSDavid du Colombier }
46380ee5cbfSDavid du Colombier 
46480ee5cbfSDavid du Colombier void
readdumpconform(Cdimg * cd)46580ee5cbfSDavid du Colombier readdumpconform(Cdimg *cd)
46680ee5cbfSDavid du Colombier {
46780ee5cbfSDavid du Colombier 	char buf[Blocksize];
46880ee5cbfSDavid du Colombier 	char *p, *q, *f[10];
46980ee5cbfSDavid du Colombier 	int nf;
470*73ee67a1SDavid du Colombier 	ulong cb, nc, db;
471*73ee67a1SDavid du Colombier 	uvlong m;
47280ee5cbfSDavid du Colombier 
47380ee5cbfSDavid du Colombier 	db = hasdump(cd);
47480ee5cbfSDavid du Colombier 	assert(map==nil || map->nt == 0);
47580ee5cbfSDavid du Colombier 
47680ee5cbfSDavid du Colombier 	for(;;){
47780ee5cbfSDavid du Colombier 		if(db == 0)
47880ee5cbfSDavid du Colombier 			sysfatal("error0 in dump blocks");
47980ee5cbfSDavid du Colombier 
48080ee5cbfSDavid du Colombier 		Creadblock(cd, buf, db, sizeof buf);
48180ee5cbfSDavid du Colombier 		if(memcmp(buf, magic, sizeof(magic)-1) != 0)
48280ee5cbfSDavid du Colombier 			break;
48380ee5cbfSDavid du Colombier 		p = buf+sizeof(magic)-1;
48480ee5cbfSDavid du Colombier 		if(p[0] == '\0')
48580ee5cbfSDavid du Colombier 			break;
48680ee5cbfSDavid du Colombier 		if((q = strchr(p, '\n')) != nil)
48780ee5cbfSDavid du Colombier 			*q = '\0';
48880ee5cbfSDavid du Colombier 
48980ee5cbfSDavid du Colombier 		nf = tokenize(p, f, nelem(f));
49080ee5cbfSDavid du Colombier 		if(nf < 5)
49180ee5cbfSDavid du Colombier 			sysfatal("error0 in dump block %lud", db);
49280ee5cbfSDavid du Colombier 
49380ee5cbfSDavid du Colombier 		db = strtoul(f[2], 0, 0);
49480ee5cbfSDavid du Colombier 		cb = strtoul(f[3], 0, 0);
49580ee5cbfSDavid du Colombier 		nc = strtoul(f[4], 0, 0);
49680ee5cbfSDavid du Colombier 
497*73ee67a1SDavid du Colombier 		Crseek(cd, (vlong)cb * Blocksize);
498*73ee67a1SDavid du Colombier 		m = (vlong)cb * Blocksize + nc;
49980ee5cbfSDavid du Colombier 		while(Croffset(cd) < m && (p = Crdline(cd, '\n')) != nil){
50080ee5cbfSDavid du Colombier 			p[Clinelen(cd)-1] = '\0';
50180ee5cbfSDavid du Colombier 			if(tokenize(p, f, 2) != 2 || (f[0][0] != 'D' && f[0][0] != 'F')
50280ee5cbfSDavid du Colombier 			|| strlen(f[0]) != 7 || !isalldigit(f[0]+1))
50380ee5cbfSDavid du Colombier 				break;
50480ee5cbfSDavid du Colombier 
50580ee5cbfSDavid du Colombier 			addtx(atom(f[1]), atom(f[0]));
50680ee5cbfSDavid du Colombier 		}
50780ee5cbfSDavid du Colombier 	}
50880ee5cbfSDavid du Colombier 	if(map)
50980ee5cbfSDavid du Colombier 		cd->nconform = map->nt;
51080ee5cbfSDavid du Colombier 	else
51180ee5cbfSDavid du Colombier 		cd->nconform = 0;
51280ee5cbfSDavid du Colombier }
513