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