1*5e96a66cSDavid du Colombier #include "stdinc.h" 2*5e96a66cSDavid du Colombier #include "dat.h" 3*5e96a66cSDavid du Colombier #include "fns.h" 4*5e96a66cSDavid du Colombier #include <draw.h> 5*5e96a66cSDavid du Colombier #include <event.h> 6*5e96a66cSDavid du Colombier 7*5e96a66cSDavid du Colombier /* --- tree.h */ 8*5e96a66cSDavid du Colombier typedef struct Tree Tree; 9*5e96a66cSDavid du Colombier typedef struct Tnode Tnode; 10*5e96a66cSDavid du Colombier 11*5e96a66cSDavid du Colombier struct Tree 12*5e96a66cSDavid du Colombier { 13*5e96a66cSDavid du Colombier Tnode *root; 14*5e96a66cSDavid du Colombier Point offset; 15*5e96a66cSDavid du Colombier Image *clipr; 16*5e96a66cSDavid du Colombier }; 17*5e96a66cSDavid du Colombier 18*5e96a66cSDavid du Colombier struct Tnode 19*5e96a66cSDavid du Colombier { 20*5e96a66cSDavid du Colombier Point offset; 21*5e96a66cSDavid du Colombier 22*5e96a66cSDavid du Colombier char *str; 23*5e96a66cSDavid du Colombier // char *(*strfn)(Tnode*); 24*5e96a66cSDavid du Colombier // uint (*draw)(Tnode*, Image*, Image*, Point); 25*5e96a66cSDavid du Colombier void (*expand)(Tnode*); 26*5e96a66cSDavid du Colombier void (*collapse)(Tnode*); 27*5e96a66cSDavid du Colombier 28*5e96a66cSDavid du Colombier uint expanded; 29*5e96a66cSDavid du Colombier Tnode **kid; 30*5e96a66cSDavid du Colombier int nkid; 31*5e96a66cSDavid du Colombier void *aux; 32*5e96a66cSDavid du Colombier }; 33*5e96a66cSDavid du Colombier 34*5e96a66cSDavid du Colombier typedef struct Atree Atree; 35*5e96a66cSDavid du Colombier struct Atree 36*5e96a66cSDavid du Colombier { 37*5e96a66cSDavid du Colombier int resizefd; 38*5e96a66cSDavid du Colombier Tnode *root; 39*5e96a66cSDavid du Colombier }; 40*5e96a66cSDavid du Colombier 41*5e96a66cSDavid du Colombier Atree *atreeinit(char*); 42*5e96a66cSDavid du Colombier 43*5e96a66cSDavid du Colombier /* --- visfossil.c */ 44*5e96a66cSDavid du Colombier Tnode *initxheader(void); 45*5e96a66cSDavid du Colombier Tnode *initxcache(char *name); 46*5e96a66cSDavid du Colombier Tnode *initxsuper(void); 47*5e96a66cSDavid du Colombier Tnode *initxlocalroot(char *name, u32int addr); 48*5e96a66cSDavid du Colombier Tnode *initxentry(Entry); 49*5e96a66cSDavid du Colombier Tnode *initxsource(Entry, int); 50*5e96a66cSDavid du Colombier Tnode *initxentryblock(Block*, Entry*); 51*5e96a66cSDavid du Colombier Tnode *initxdatablock(Block*, uint); 52*5e96a66cSDavid du Colombier Tnode *initxroot(char *name, uchar[VtScoreSize]); 53*5e96a66cSDavid du Colombier 54*5e96a66cSDavid du Colombier int fd; 55*5e96a66cSDavid du Colombier Header h; 56*5e96a66cSDavid du Colombier Super super; 57*5e96a66cSDavid du Colombier VtSession *z; 58*5e96a66cSDavid du Colombier VtRoot vac; 59*5e96a66cSDavid du Colombier int showinactive; 60*5e96a66cSDavid du Colombier 61*5e96a66cSDavid du Colombier /* 62*5e96a66cSDavid du Colombier * dumbed down versions of fossil routines 63*5e96a66cSDavid du Colombier */ 64*5e96a66cSDavid du Colombier char* 65*5e96a66cSDavid du Colombier bsStr(int state) 66*5e96a66cSDavid du Colombier { 67*5e96a66cSDavid du Colombier static char s[100]; 68*5e96a66cSDavid du Colombier 69*5e96a66cSDavid du Colombier if(state == BsFree) 70*5e96a66cSDavid du Colombier return "Free"; 71*5e96a66cSDavid du Colombier if(state == BsBad) 72*5e96a66cSDavid du Colombier return "Bad"; 73*5e96a66cSDavid du Colombier 74*5e96a66cSDavid du Colombier sprint(s, "%x", state); 75*5e96a66cSDavid du Colombier if(!(state&BsAlloc)) 76*5e96a66cSDavid du Colombier strcat(s, ",Free"); /* should not happen */ 77*5e96a66cSDavid du Colombier if(state&BsCopied) 78*5e96a66cSDavid du Colombier strcat(s, ",Copied"); 79*5e96a66cSDavid du Colombier if(state&BsVenti) 80*5e96a66cSDavid du Colombier strcat(s, ",Venti"); 81*5e96a66cSDavid du Colombier if(state&BsClosed) 82*5e96a66cSDavid du Colombier strcat(s, ",Closed"); 83*5e96a66cSDavid du Colombier return s; 84*5e96a66cSDavid du Colombier } 85*5e96a66cSDavid du Colombier 86*5e96a66cSDavid du Colombier char *bttab[] = { 87*5e96a66cSDavid du Colombier "BtData", 88*5e96a66cSDavid du Colombier "BtData+1", 89*5e96a66cSDavid du Colombier "BtData+2", 90*5e96a66cSDavid du Colombier "BtData+3", 91*5e96a66cSDavid du Colombier "BtData+4", 92*5e96a66cSDavid du Colombier "BtData+5", 93*5e96a66cSDavid du Colombier "BtData+6", 94*5e96a66cSDavid du Colombier "BtData+7", 95*5e96a66cSDavid du Colombier "BtDir", 96*5e96a66cSDavid du Colombier "BtDir+1", 97*5e96a66cSDavid du Colombier "BtDir+2", 98*5e96a66cSDavid du Colombier "BtDir+3", 99*5e96a66cSDavid du Colombier "BtDir+4", 100*5e96a66cSDavid du Colombier "BtDir+5", 101*5e96a66cSDavid du Colombier "BtDir+6", 102*5e96a66cSDavid du Colombier "BtDir+7", 103*5e96a66cSDavid du Colombier }; 104*5e96a66cSDavid du Colombier 105*5e96a66cSDavid du Colombier char* 106*5e96a66cSDavid du Colombier btStr(int type) 107*5e96a66cSDavid du Colombier { 108*5e96a66cSDavid du Colombier if(type < nelem(bttab)) 109*5e96a66cSDavid du Colombier return bttab[type]; 110*5e96a66cSDavid du Colombier return "unknown"; 111*5e96a66cSDavid du Colombier } 112*5e96a66cSDavid du Colombier #pragma varargck argpos stringnode 1 113*5e96a66cSDavid du Colombier 114*5e96a66cSDavid du Colombier Block* 115*5e96a66cSDavid du Colombier allocBlock(void) 116*5e96a66cSDavid du Colombier { 117*5e96a66cSDavid du Colombier Block *b; 118*5e96a66cSDavid du Colombier 119*5e96a66cSDavid du Colombier b = mallocz(sizeof(Block)+h.blockSize, 1); 120*5e96a66cSDavid du Colombier b->data = (void*)&b[1]; 121*5e96a66cSDavid du Colombier return b; 122*5e96a66cSDavid du Colombier } 123*5e96a66cSDavid du Colombier 124*5e96a66cSDavid du Colombier void 125*5e96a66cSDavid du Colombier blockPut(Block *b) 126*5e96a66cSDavid du Colombier { 127*5e96a66cSDavid du Colombier free(b); 128*5e96a66cSDavid du Colombier } 129*5e96a66cSDavid du Colombier 130*5e96a66cSDavid du Colombier static u32int 131*5e96a66cSDavid du Colombier partStart(int part) 132*5e96a66cSDavid du Colombier { 133*5e96a66cSDavid du Colombier switch(part){ 134*5e96a66cSDavid du Colombier default: 135*5e96a66cSDavid du Colombier assert(0); 136*5e96a66cSDavid du Colombier case PartSuper: 137*5e96a66cSDavid du Colombier return h.super; 138*5e96a66cSDavid du Colombier case PartLabel: 139*5e96a66cSDavid du Colombier return h.label; 140*5e96a66cSDavid du Colombier case PartData: 141*5e96a66cSDavid du Colombier return h.data; 142*5e96a66cSDavid du Colombier } 143*5e96a66cSDavid du Colombier } 144*5e96a66cSDavid du Colombier 145*5e96a66cSDavid du Colombier 146*5e96a66cSDavid du Colombier static u32int 147*5e96a66cSDavid du Colombier partEnd(int part) 148*5e96a66cSDavid du Colombier { 149*5e96a66cSDavid du Colombier switch(part){ 150*5e96a66cSDavid du Colombier default: 151*5e96a66cSDavid du Colombier assert(0); 152*5e96a66cSDavid du Colombier case PartSuper: 153*5e96a66cSDavid du Colombier return h.super+1; 154*5e96a66cSDavid du Colombier case PartLabel: 155*5e96a66cSDavid du Colombier return h.data; 156*5e96a66cSDavid du Colombier case PartData: 157*5e96a66cSDavid du Colombier return h.end; 158*5e96a66cSDavid du Colombier } 159*5e96a66cSDavid du Colombier } 160*5e96a66cSDavid du Colombier 161*5e96a66cSDavid du Colombier Block* 162*5e96a66cSDavid du Colombier readBlock(int part, u32int addr) 163*5e96a66cSDavid du Colombier { 164*5e96a66cSDavid du Colombier u32int start, end; 165*5e96a66cSDavid du Colombier u64int offset; 166*5e96a66cSDavid du Colombier int n, nn; 167*5e96a66cSDavid du Colombier Block *b; 168*5e96a66cSDavid du Colombier uchar *buf; 169*5e96a66cSDavid du Colombier 170*5e96a66cSDavid du Colombier start = partStart(part); 171*5e96a66cSDavid du Colombier end = partEnd(part); 172*5e96a66cSDavid du Colombier if(addr >= end-start){ 173*5e96a66cSDavid du Colombier werrstr("bad addr 0x%.8ux; wanted 0x%.8ux - 0x%.8ux", addr, start, end); 174*5e96a66cSDavid du Colombier return nil; 175*5e96a66cSDavid du Colombier } 176*5e96a66cSDavid du Colombier 177*5e96a66cSDavid du Colombier b = allocBlock(); 178*5e96a66cSDavid du Colombier b->addr = addr; 179*5e96a66cSDavid du Colombier buf = b->data; 180*5e96a66cSDavid du Colombier offset = ((u64int)(addr+start))*h.blockSize; 181*5e96a66cSDavid du Colombier n = h.blockSize; 182*5e96a66cSDavid du Colombier while(n > 0){ 183*5e96a66cSDavid du Colombier nn = pread(fd, buf, n, offset); 184*5e96a66cSDavid du Colombier if(nn < 0){ 185*5e96a66cSDavid du Colombier blockPut(b); 186*5e96a66cSDavid du Colombier return nil; 187*5e96a66cSDavid du Colombier } 188*5e96a66cSDavid du Colombier if(nn == 0){ 189*5e96a66cSDavid du Colombier werrstr("short read"); 190*5e96a66cSDavid du Colombier blockPut(b); 191*5e96a66cSDavid du Colombier return nil; 192*5e96a66cSDavid du Colombier } 193*5e96a66cSDavid du Colombier n -= nn; 194*5e96a66cSDavid du Colombier offset += nn; 195*5e96a66cSDavid du Colombier buf += nn; 196*5e96a66cSDavid du Colombier } 197*5e96a66cSDavid du Colombier return b; 198*5e96a66cSDavid du Colombier } 199*5e96a66cSDavid du Colombier 200*5e96a66cSDavid du Colombier int vtType[BtMax] = { 201*5e96a66cSDavid du Colombier VtDataType, /* BtData | 0 */ 202*5e96a66cSDavid du Colombier VtPointerType0, /* BtData | 1 */ 203*5e96a66cSDavid du Colombier VtPointerType1, /* BtData | 2 */ 204*5e96a66cSDavid du Colombier VtPointerType2, /* BtData | 3 */ 205*5e96a66cSDavid du Colombier VtPointerType3, /* BtData | 4 */ 206*5e96a66cSDavid du Colombier VtPointerType4, /* BtData | 5 */ 207*5e96a66cSDavid du Colombier VtPointerType5, /* BtData | 6 */ 208*5e96a66cSDavid du Colombier VtPointerType6, /* BtData | 7 */ 209*5e96a66cSDavid du Colombier VtDirType, /* BtDir | 0 */ 210*5e96a66cSDavid du Colombier VtPointerType0, /* BtDir | 1 */ 211*5e96a66cSDavid du Colombier VtPointerType1, /* BtDir | 2 */ 212*5e96a66cSDavid du Colombier VtPointerType2, /* BtDir | 3 */ 213*5e96a66cSDavid du Colombier VtPointerType3, /* BtDir | 4 */ 214*5e96a66cSDavid du Colombier VtPointerType4, /* BtDir | 5 */ 215*5e96a66cSDavid du Colombier VtPointerType5, /* BtDir | 6 */ 216*5e96a66cSDavid du Colombier VtPointerType6, /* BtDir | 7 */ 217*5e96a66cSDavid du Colombier }; 218*5e96a66cSDavid du Colombier 219*5e96a66cSDavid du Colombier Block* 220*5e96a66cSDavid du Colombier ventiBlock(uchar score[VtScoreSize], uint type) 221*5e96a66cSDavid du Colombier { 222*5e96a66cSDavid du Colombier int n; 223*5e96a66cSDavid du Colombier Block *b; 224*5e96a66cSDavid du Colombier 225*5e96a66cSDavid du Colombier b = allocBlock(); 226*5e96a66cSDavid du Colombier memmove(b->score, score, VtScoreSize); 227*5e96a66cSDavid du Colombier b->addr = NilBlock; 228*5e96a66cSDavid du Colombier 229*5e96a66cSDavid du Colombier n = vtRead(z, b->score, vtType[type], b->data, h.blockSize); 230*5e96a66cSDavid du Colombier if(n < 0){ 231*5e96a66cSDavid du Colombier fprint(2, "vtRead returns %d: %R\n", n); 232*5e96a66cSDavid du Colombier blockPut(b); 233*5e96a66cSDavid du Colombier return nil; 234*5e96a66cSDavid du Colombier } 235*5e96a66cSDavid du Colombier vtZeroExtend(vtType[type], b->data, n, h.blockSize); 236*5e96a66cSDavid du Colombier b->l.type = type; 237*5e96a66cSDavid du Colombier b->l.state = 0; 238*5e96a66cSDavid du Colombier b->l.tag = 0; 239*5e96a66cSDavid du Colombier b->l.epoch = 0; 240*5e96a66cSDavid du Colombier return b; 241*5e96a66cSDavid du Colombier } 242*5e96a66cSDavid du Colombier 243*5e96a66cSDavid du Colombier Block* 244*5e96a66cSDavid du Colombier dataBlock(uchar score[VtScoreSize], uint type, uint tag) 245*5e96a66cSDavid du Colombier { 246*5e96a66cSDavid du Colombier Block *b, *bl; 247*5e96a66cSDavid du Colombier int lpb; 248*5e96a66cSDavid du Colombier Label l; 249*5e96a66cSDavid du Colombier u32int addr; 250*5e96a66cSDavid du Colombier 251*5e96a66cSDavid du Colombier addr = globalToLocal(score); 252*5e96a66cSDavid du Colombier if(addr == NilBlock) 253*5e96a66cSDavid du Colombier return ventiBlock(score, type); 254*5e96a66cSDavid du Colombier 255*5e96a66cSDavid du Colombier lpb = h.blockSize/LabelSize; 256*5e96a66cSDavid du Colombier bl = readBlock(PartLabel, addr/lpb); 257*5e96a66cSDavid du Colombier if(bl == nil) 258*5e96a66cSDavid du Colombier return nil; 259*5e96a66cSDavid du Colombier if(!labelUnpack(&l, bl->data, addr%lpb)){ 260*5e96a66cSDavid du Colombier werrstr("%R"); 261*5e96a66cSDavid du Colombier blockPut(bl); 262*5e96a66cSDavid du Colombier return nil; 263*5e96a66cSDavid du Colombier } 264*5e96a66cSDavid du Colombier blockPut(bl); 265*5e96a66cSDavid du Colombier if(l.type != type){ 266*5e96a66cSDavid du Colombier werrstr("type mismatch; got %d (%s) wanted %d (%s)", 267*5e96a66cSDavid du Colombier l.type, btStr(l.type), type, btStr(type)); 268*5e96a66cSDavid du Colombier return nil; 269*5e96a66cSDavid du Colombier } 270*5e96a66cSDavid du Colombier if(tag && l.tag != tag){ 271*5e96a66cSDavid du Colombier werrstr("tag mismatch; got 0x%.8ux wanted 0x%.8ux", 272*5e96a66cSDavid du Colombier l.tag, tag); 273*5e96a66cSDavid du Colombier return nil; 274*5e96a66cSDavid du Colombier } 275*5e96a66cSDavid du Colombier b = readBlock(PartData, addr); 276*5e96a66cSDavid du Colombier if(b == nil) 277*5e96a66cSDavid du Colombier return nil; 278*5e96a66cSDavid du Colombier b->l = l; 279*5e96a66cSDavid du Colombier return b; 280*5e96a66cSDavid du Colombier } 281*5e96a66cSDavid du Colombier 282*5e96a66cSDavid du Colombier Entry* 283*5e96a66cSDavid du Colombier copyEntry(Entry e) 284*5e96a66cSDavid du Colombier { 285*5e96a66cSDavid du Colombier Entry *p; 286*5e96a66cSDavid du Colombier 287*5e96a66cSDavid du Colombier p = mallocz(sizeof *p, 1); 288*5e96a66cSDavid du Colombier *p = e; 289*5e96a66cSDavid du Colombier return p; 290*5e96a66cSDavid du Colombier } 291*5e96a66cSDavid du Colombier 292*5e96a66cSDavid du Colombier MetaBlock* 293*5e96a66cSDavid du Colombier copyMetaBlock(MetaBlock mb) 294*5e96a66cSDavid du Colombier { 295*5e96a66cSDavid du Colombier MetaBlock *p; 296*5e96a66cSDavid du Colombier 297*5e96a66cSDavid du Colombier p = mallocz(sizeof mb, 1); 298*5e96a66cSDavid du Colombier *p = mb; 299*5e96a66cSDavid du Colombier return p; 300*5e96a66cSDavid du Colombier } 301*5e96a66cSDavid du Colombier 302*5e96a66cSDavid du Colombier /* 303*5e96a66cSDavid du Colombier * visualizer 304*5e96a66cSDavid du Colombier */ 305*5e96a66cSDavid du Colombier 306*5e96a66cSDavid du Colombier Tnode* 307*5e96a66cSDavid du Colombier stringnode(char *fmt, ...) 308*5e96a66cSDavid du Colombier { 309*5e96a66cSDavid du Colombier va_list arg; 310*5e96a66cSDavid du Colombier Tnode *t; 311*5e96a66cSDavid du Colombier 312*5e96a66cSDavid du Colombier t = mallocz(sizeof(Tnode), 1); 313*5e96a66cSDavid du Colombier va_start(arg, fmt); 314*5e96a66cSDavid du Colombier t->str = vsmprint(fmt, arg); 315*5e96a66cSDavid du Colombier va_end(arg); 316*5e96a66cSDavid du Colombier t->nkid = -1; 317*5e96a66cSDavid du Colombier return t; 318*5e96a66cSDavid du Colombier } 319*5e96a66cSDavid du Colombier 320*5e96a66cSDavid du Colombier void 321*5e96a66cSDavid du Colombier xcacheexpand(Tnode *t) 322*5e96a66cSDavid du Colombier { 323*5e96a66cSDavid du Colombier if(t->nkid >= 0) 324*5e96a66cSDavid du Colombier return; 325*5e96a66cSDavid du Colombier 326*5e96a66cSDavid du Colombier t->nkid = 1; 327*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1); 328*5e96a66cSDavid du Colombier t->kid[0] = initxheader(); 329*5e96a66cSDavid du Colombier } 330*5e96a66cSDavid du Colombier 331*5e96a66cSDavid du Colombier Tnode* 332*5e96a66cSDavid du Colombier initxcache(char *name) 333*5e96a66cSDavid du Colombier { 334*5e96a66cSDavid du Colombier Tnode *t; 335*5e96a66cSDavid du Colombier 336*5e96a66cSDavid du Colombier if((fd = open(name, OREAD)) < 0) 337*5e96a66cSDavid du Colombier sysfatal("cannot open %s: %r", name); 338*5e96a66cSDavid du Colombier 339*5e96a66cSDavid du Colombier t = stringnode("%s", name); 340*5e96a66cSDavid du Colombier t->expand = xcacheexpand; 341*5e96a66cSDavid du Colombier return t; 342*5e96a66cSDavid du Colombier } 343*5e96a66cSDavid du Colombier 344*5e96a66cSDavid du Colombier void 345*5e96a66cSDavid du Colombier xheaderexpand(Tnode *t) 346*5e96a66cSDavid du Colombier { 347*5e96a66cSDavid du Colombier if(t->nkid >= 0) 348*5e96a66cSDavid du Colombier return; 349*5e96a66cSDavid du Colombier 350*5e96a66cSDavid du Colombier t->nkid = 1; 351*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1); 352*5e96a66cSDavid du Colombier t->kid[0] = initxsuper(); 353*5e96a66cSDavid du Colombier //t->kid[1] = initxlabel(h.label); 354*5e96a66cSDavid du Colombier //t->kid[2] = initxdata(h.data); 355*5e96a66cSDavid du Colombier } 356*5e96a66cSDavid du Colombier 357*5e96a66cSDavid du Colombier Tnode* 358*5e96a66cSDavid du Colombier initxheader(void) 359*5e96a66cSDavid du Colombier { 360*5e96a66cSDavid du Colombier u8int buf[HeaderSize]; 361*5e96a66cSDavid du Colombier Tnode *t; 362*5e96a66cSDavid du Colombier 363*5e96a66cSDavid du Colombier if(pread(fd, buf, HeaderSize, HeaderOffset) < HeaderSize) 364*5e96a66cSDavid du Colombier return stringnode("error reading header: %r"); 365*5e96a66cSDavid du Colombier if(!headerUnpack(&h, buf)) 366*5e96a66cSDavid du Colombier return stringnode("error unpacking header: %R"); 367*5e96a66cSDavid du Colombier 368*5e96a66cSDavid du Colombier t = stringnode("header " 369*5e96a66cSDavid du Colombier "version=%#ux (%d) " 370*5e96a66cSDavid du Colombier "blockSize=%#ux (%d) " 371*5e96a66cSDavid du Colombier "super=%#lux (%ld) " 372*5e96a66cSDavid du Colombier "label=%#lux (%ld) " 373*5e96a66cSDavid du Colombier "data=%#lux (%ld) " 374*5e96a66cSDavid du Colombier "end=%#lux (%ld)", 375*5e96a66cSDavid du Colombier h.version, h.version, h.blockSize, h.blockSize, 376*5e96a66cSDavid du Colombier h.super, h.super, 377*5e96a66cSDavid du Colombier h.label, h.label, h.data, h.data, h.end, h.end); 378*5e96a66cSDavid du Colombier t->expand = xheaderexpand; 379*5e96a66cSDavid du Colombier return t; 380*5e96a66cSDavid du Colombier } 381*5e96a66cSDavid du Colombier 382*5e96a66cSDavid du Colombier void 383*5e96a66cSDavid du Colombier xsuperexpand(Tnode *t) 384*5e96a66cSDavid du Colombier { 385*5e96a66cSDavid du Colombier if(t->nkid >= 0) 386*5e96a66cSDavid du Colombier return; 387*5e96a66cSDavid du Colombier 388*5e96a66cSDavid du Colombier t->nkid = 1; 389*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1); 390*5e96a66cSDavid du Colombier t->kid[0] = initxlocalroot("active", super.active); 391*5e96a66cSDavid du Colombier // t->kid[1] = initxlocalroot("next", super.next); 392*5e96a66cSDavid du Colombier // t->kid[2] = initxlocalroot("current", super.current); 393*5e96a66cSDavid du Colombier } 394*5e96a66cSDavid du Colombier 395*5e96a66cSDavid du Colombier Tnode* 396*5e96a66cSDavid du Colombier initxsuper(void) 397*5e96a66cSDavid du Colombier { 398*5e96a66cSDavid du Colombier Block *b; 399*5e96a66cSDavid du Colombier Tnode *t; 400*5e96a66cSDavid du Colombier 401*5e96a66cSDavid du Colombier b = readBlock(PartSuper, 0); 402*5e96a66cSDavid du Colombier if(b == nil) 403*5e96a66cSDavid du Colombier return stringnode("reading super: %r"); 404*5e96a66cSDavid du Colombier if(!superUnpack(&super, b->data)){ 405*5e96a66cSDavid du Colombier blockPut(b); 406*5e96a66cSDavid du Colombier return stringnode("unpacking super: %R"); 407*5e96a66cSDavid du Colombier } 408*5e96a66cSDavid du Colombier blockPut(b); 409*5e96a66cSDavid du Colombier t = stringnode("super " 410*5e96a66cSDavid du Colombier "version=%#ux " 411*5e96a66cSDavid du Colombier "epoch=[%#ux,%#ux) " 412*5e96a66cSDavid du Colombier "qid=%#llux " 413*5e96a66cSDavid du Colombier "active=%#x " 414*5e96a66cSDavid du Colombier "next=%#x " 415*5e96a66cSDavid du Colombier "current=%#x " 416*5e96a66cSDavid du Colombier "last=%V " 417*5e96a66cSDavid du Colombier "name=%s", 418*5e96a66cSDavid du Colombier super.version, super.epochLow, super.epochHigh, 419*5e96a66cSDavid du Colombier super.qid, super.active, super.next, super.current, 420*5e96a66cSDavid du Colombier super.last, super.name); 421*5e96a66cSDavid du Colombier t->expand = xsuperexpand; 422*5e96a66cSDavid du Colombier return t; 423*5e96a66cSDavid du Colombier } 424*5e96a66cSDavid du Colombier 425*5e96a66cSDavid du Colombier void 426*5e96a66cSDavid du Colombier xvacrootexpand(Tnode *t) 427*5e96a66cSDavid du Colombier { 428*5e96a66cSDavid du Colombier if(t->nkid >= 0) 429*5e96a66cSDavid du Colombier return; 430*5e96a66cSDavid du Colombier 431*5e96a66cSDavid du Colombier t->nkid = 1; 432*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1); 433*5e96a66cSDavid du Colombier t->kid[0] = initxroot("root", vac.score); 434*5e96a66cSDavid du Colombier } 435*5e96a66cSDavid du Colombier 436*5e96a66cSDavid du Colombier Tnode* 437*5e96a66cSDavid du Colombier initxvacroot(uchar score[VtScoreSize]) 438*5e96a66cSDavid du Colombier { 439*5e96a66cSDavid du Colombier Tnode *t; 440*5e96a66cSDavid du Colombier uchar buf[VtRootSize]; 441*5e96a66cSDavid du Colombier int n; 442*5e96a66cSDavid du Colombier 443*5e96a66cSDavid du Colombier if((n = vtRead(z, score, VtRootType, buf, VtRootSize)) < 0) 444*5e96a66cSDavid du Colombier return stringnode("reading root %V: %R", score); 445*5e96a66cSDavid du Colombier 446*5e96a66cSDavid du Colombier if(!vtRootUnpack(&vac, buf)) 447*5e96a66cSDavid du Colombier return stringnode("unpack %d-byte root: %R", n); 448*5e96a66cSDavid du Colombier 449*5e96a66cSDavid du Colombier h.blockSize = vac.blockSize; 450*5e96a66cSDavid du Colombier t = stringnode("vac version=%#ux name=%s type=%s blockSize=%ud score=%V prev=%V", 451*5e96a66cSDavid du Colombier vac.version, vac.name, vac.type, vac.blockSize, vac.score, vac.prev); 452*5e96a66cSDavid du Colombier t->expand = xvacrootexpand; 453*5e96a66cSDavid du Colombier return t; 454*5e96a66cSDavid du Colombier } 455*5e96a66cSDavid du Colombier 456*5e96a66cSDavid du Colombier Tnode* 457*5e96a66cSDavid du Colombier initxlabel(Label l) 458*5e96a66cSDavid du Colombier { 459*5e96a66cSDavid du Colombier return stringnode("label type=%s state=%s epoch=%#ux tag=%#ux", 460*5e96a66cSDavid du Colombier btStr(l.type), bsStr(l.state), l.epoch, l.tag); 461*5e96a66cSDavid du Colombier } 462*5e96a66cSDavid du Colombier 463*5e96a66cSDavid du Colombier typedef struct Xblock Xblock; 464*5e96a66cSDavid du Colombier struct Xblock 465*5e96a66cSDavid du Colombier { 466*5e96a66cSDavid du Colombier Tnode; 467*5e96a66cSDavid du Colombier Block *b; 468*5e96a66cSDavid du Colombier int (*gen)(void*, Block*, int, Tnode**); 469*5e96a66cSDavid du Colombier void *arg; 470*5e96a66cSDavid du Colombier int printlabel; 471*5e96a66cSDavid du Colombier }; 472*5e96a66cSDavid du Colombier 473*5e96a66cSDavid du Colombier void 474*5e96a66cSDavid du Colombier xblockexpand(Tnode *tt) 475*5e96a66cSDavid du Colombier { 476*5e96a66cSDavid du Colombier int i, j; 477*5e96a66cSDavid du Colombier enum { Q = 32 }; 478*5e96a66cSDavid du Colombier Xblock *t = (Xblock*)tt; 479*5e96a66cSDavid du Colombier Tnode *nn; 480*5e96a66cSDavid du Colombier 481*5e96a66cSDavid du Colombier if(t->nkid >= 0) 482*5e96a66cSDavid du Colombier return; 483*5e96a66cSDavid du Colombier 484*5e96a66cSDavid du Colombier j = 0; 485*5e96a66cSDavid du Colombier if(t->printlabel){ 486*5e96a66cSDavid du Colombier t->kid = mallocz(Q*sizeof(t->kid[0]), 1); 487*5e96a66cSDavid du Colombier t->kid[0] = initxlabel(t->b->l); 488*5e96a66cSDavid du Colombier j = 1; 489*5e96a66cSDavid du Colombier } 490*5e96a66cSDavid du Colombier 491*5e96a66cSDavid du Colombier for(i=0;; i++){ 492*5e96a66cSDavid du Colombier switch((*t->gen)(t->arg, t->b, i, &nn)){ 493*5e96a66cSDavid du Colombier case -1: 494*5e96a66cSDavid du Colombier t->nkid = j; 495*5e96a66cSDavid du Colombier return; 496*5e96a66cSDavid du Colombier case 0: 497*5e96a66cSDavid du Colombier break; 498*5e96a66cSDavid du Colombier case 1: 499*5e96a66cSDavid du Colombier if(j%Q == 0) 500*5e96a66cSDavid du Colombier t->kid = realloc(t->kid, (j+Q)*sizeof(t->kid[0])); 501*5e96a66cSDavid du Colombier t->kid[j++] = nn; 502*5e96a66cSDavid du Colombier break; 503*5e96a66cSDavid du Colombier } 504*5e96a66cSDavid du Colombier } 505*5e96a66cSDavid du Colombier } 506*5e96a66cSDavid du Colombier 507*5e96a66cSDavid du Colombier int 508*5e96a66cSDavid du Colombier nilgen(void*, Block*, int, Tnode**) 509*5e96a66cSDavid du Colombier { 510*5e96a66cSDavid du Colombier return -1; 511*5e96a66cSDavid du Colombier } 512*5e96a66cSDavid du Colombier 513*5e96a66cSDavid du Colombier Tnode* 514*5e96a66cSDavid du Colombier initxblock(Block *b, char *s, int (*gen)(void*, Block*, int, Tnode**), void *arg) 515*5e96a66cSDavid du Colombier { 516*5e96a66cSDavid du Colombier Xblock *t; 517*5e96a66cSDavid du Colombier 518*5e96a66cSDavid du Colombier if(gen == nil) 519*5e96a66cSDavid du Colombier gen = nilgen; 520*5e96a66cSDavid du Colombier t = mallocz(sizeof(Xblock), 1); 521*5e96a66cSDavid du Colombier t->b = b; 522*5e96a66cSDavid du Colombier t->gen = gen; 523*5e96a66cSDavid du Colombier t->arg = arg; 524*5e96a66cSDavid du Colombier if(b->addr == NilBlock) 525*5e96a66cSDavid du Colombier t->str = smprint("Block %V: %s", b->score, s); 526*5e96a66cSDavid du Colombier else 527*5e96a66cSDavid du Colombier t->str = smprint("Block %#ux: %s", b->addr, s); 528*5e96a66cSDavid du Colombier t->printlabel = 1; 529*5e96a66cSDavid du Colombier t->nkid = -1; 530*5e96a66cSDavid du Colombier t->expand = xblockexpand; 531*5e96a66cSDavid du Colombier return t; 532*5e96a66cSDavid du Colombier } 533*5e96a66cSDavid du Colombier 534*5e96a66cSDavid du Colombier int 535*5e96a66cSDavid du Colombier xentrygen(void *v, Block *b, int o, Tnode **tp) 536*5e96a66cSDavid du Colombier { 537*5e96a66cSDavid du Colombier Entry e; 538*5e96a66cSDavid du Colombier Entry *ed; 539*5e96a66cSDavid du Colombier 540*5e96a66cSDavid du Colombier ed = v; 541*5e96a66cSDavid du Colombier if(o >= ed->dsize/VtEntrySize) 542*5e96a66cSDavid du Colombier return -1; 543*5e96a66cSDavid du Colombier 544*5e96a66cSDavid du Colombier entryUnpack(&e, b->data, o); 545*5e96a66cSDavid du Colombier if(!showinactive && !(e.flags & VtEntryActive)) 546*5e96a66cSDavid du Colombier return 0; 547*5e96a66cSDavid du Colombier *tp = initxentry(e); 548*5e96a66cSDavid du Colombier return 1; 549*5e96a66cSDavid du Colombier } 550*5e96a66cSDavid du Colombier 551*5e96a66cSDavid du Colombier Tnode* 552*5e96a66cSDavid du Colombier initxentryblock(Block *b, Entry *ed) 553*5e96a66cSDavid du Colombier { 554*5e96a66cSDavid du Colombier return initxblock(b, "entry", xentrygen, ed); 555*5e96a66cSDavid du Colombier } 556*5e96a66cSDavid du Colombier 557*5e96a66cSDavid du Colombier typedef struct Xentry Xentry; 558*5e96a66cSDavid du Colombier struct Xentry 559*5e96a66cSDavid du Colombier { 560*5e96a66cSDavid du Colombier Tnode; 561*5e96a66cSDavid du Colombier Entry e; 562*5e96a66cSDavid du Colombier }; 563*5e96a66cSDavid du Colombier 564*5e96a66cSDavid du Colombier void 565*5e96a66cSDavid du Colombier xentryexpand(Tnode *tt) 566*5e96a66cSDavid du Colombier { 567*5e96a66cSDavid du Colombier Xentry *t = (Xentry*)tt; 568*5e96a66cSDavid du Colombier 569*5e96a66cSDavid du Colombier if(t->nkid >= 0) 570*5e96a66cSDavid du Colombier return; 571*5e96a66cSDavid du Colombier 572*5e96a66cSDavid du Colombier t->nkid = 1; 573*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1); 574*5e96a66cSDavid du Colombier t->kid[0] = initxsource(t->e, 1); 575*5e96a66cSDavid du Colombier } 576*5e96a66cSDavid du Colombier 577*5e96a66cSDavid du Colombier Tnode* 578*5e96a66cSDavid du Colombier initxentry(Entry e) 579*5e96a66cSDavid du Colombier { 580*5e96a66cSDavid du Colombier Xentry *t; 581*5e96a66cSDavid du Colombier 582*5e96a66cSDavid du Colombier t = mallocz(sizeof *t, 1); 583*5e96a66cSDavid du Colombier t->nkid = -1; 584*5e96a66cSDavid du Colombier t->str = smprint("Entry gen=%#ux psize=%d dsize=%d depth=%d flags=%#ux size=%lld score=%V", 585*5e96a66cSDavid du Colombier e.gen, e.psize, e.dsize, e.depth, e.flags, e.size, e.score); 586*5e96a66cSDavid du Colombier if(e.flags & VtEntryLocal) 587*5e96a66cSDavid du Colombier t->str = smprint("%s archive=%d snap=%d tag=%#ux", t->str, e.archive, e.snap, e.tag); 588*5e96a66cSDavid du Colombier t->expand = xentryexpand; 589*5e96a66cSDavid du Colombier t->e = e; 590*5e96a66cSDavid du Colombier return t; 591*5e96a66cSDavid du Colombier } 592*5e96a66cSDavid du Colombier 593*5e96a66cSDavid du Colombier int 594*5e96a66cSDavid du Colombier ptrgen(void *v, Block *b, int o, Tnode **tp) 595*5e96a66cSDavid du Colombier { 596*5e96a66cSDavid du Colombier Entry *ed; 597*5e96a66cSDavid du Colombier Entry e; 598*5e96a66cSDavid du Colombier 599*5e96a66cSDavid du Colombier ed = v; 600*5e96a66cSDavid du Colombier if(o >= ed->psize/VtScoreSize) 601*5e96a66cSDavid du Colombier return -1; 602*5e96a66cSDavid du Colombier 603*5e96a66cSDavid du Colombier e = *ed; 604*5e96a66cSDavid du Colombier e.depth--; 605*5e96a66cSDavid du Colombier memmove(e.score, b->data+o*VtScoreSize, VtScoreSize); 606*5e96a66cSDavid du Colombier if(memcmp(e.score, vtZeroScore, VtScoreSize) == 0) 607*5e96a66cSDavid du Colombier return 0; 608*5e96a66cSDavid du Colombier *tp = initxsource(e, 0); 609*5e96a66cSDavid du Colombier return 1; 610*5e96a66cSDavid du Colombier } 611*5e96a66cSDavid du Colombier 612*5e96a66cSDavid du Colombier static int 613*5e96a66cSDavid du Colombier etype(int flags, int depth) 614*5e96a66cSDavid du Colombier { 615*5e96a66cSDavid du Colombier uint t; 616*5e96a66cSDavid du Colombier 617*5e96a66cSDavid du Colombier if(flags&VtEntryDir) 618*5e96a66cSDavid du Colombier t = BtDir; 619*5e96a66cSDavid du Colombier else 620*5e96a66cSDavid du Colombier t = BtData; 621*5e96a66cSDavid du Colombier return t+depth; 622*5e96a66cSDavid du Colombier } 623*5e96a66cSDavid du Colombier 624*5e96a66cSDavid du Colombier Tnode* 625*5e96a66cSDavid du Colombier initxsource(Entry e, int dowrap) 626*5e96a66cSDavid du Colombier { 627*5e96a66cSDavid du Colombier Block *b; 628*5e96a66cSDavid du Colombier Tnode *t, *tt; 629*5e96a66cSDavid du Colombier 630*5e96a66cSDavid du Colombier b = dataBlock(e.score, etype(e.flags, e.depth), e.tag); 631*5e96a66cSDavid du Colombier if(b == nil) 632*5e96a66cSDavid du Colombier return stringnode("dataBlock: %r"); 633*5e96a66cSDavid du Colombier 634*5e96a66cSDavid du Colombier if((e.flags & VtEntryActive) == 0) 635*5e96a66cSDavid du Colombier return stringnode("inactive Entry"); 636*5e96a66cSDavid du Colombier 637*5e96a66cSDavid du Colombier if(e.depth == 0){ 638*5e96a66cSDavid du Colombier if(e.flags & VtEntryDir) 639*5e96a66cSDavid du Colombier tt = initxentryblock(b, copyEntry(e)); 640*5e96a66cSDavid du Colombier else 641*5e96a66cSDavid du Colombier tt = initxdatablock(b, e.dsize); 642*5e96a66cSDavid du Colombier }else{ 643*5e96a66cSDavid du Colombier tt = initxblock(b, smprint("%s+%d pointer", (e.flags & VtEntryDir) ? "BtDir" : "BtData", e.depth), 644*5e96a66cSDavid du Colombier ptrgen, copyEntry(e)); 645*5e96a66cSDavid du Colombier } 646*5e96a66cSDavid du Colombier 647*5e96a66cSDavid du Colombier /* 648*5e96a66cSDavid du Colombier * wrap the contents of the Source in a Source node, 649*5e96a66cSDavid du Colombier * just so it's closer to what you see in the code. 650*5e96a66cSDavid du Colombier */ 651*5e96a66cSDavid du Colombier if(dowrap){ 652*5e96a66cSDavid du Colombier t = stringnode("Source"); 653*5e96a66cSDavid du Colombier t->nkid = 1; 654*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(Tnode*)*1, 1); 655*5e96a66cSDavid du Colombier t->kid[0] = tt; 656*5e96a66cSDavid du Colombier tt = t; 657*5e96a66cSDavid du Colombier } 658*5e96a66cSDavid du Colombier return tt; 659*5e96a66cSDavid du Colombier } 660*5e96a66cSDavid du Colombier 661*5e96a66cSDavid du Colombier int 662*5e96a66cSDavid du Colombier xlocalrootgen(void*, Block *b, int o, Tnode **tp) 663*5e96a66cSDavid du Colombier { 664*5e96a66cSDavid du Colombier Entry e; 665*5e96a66cSDavid du Colombier 666*5e96a66cSDavid du Colombier if(o >= 1) 667*5e96a66cSDavid du Colombier return -1; 668*5e96a66cSDavid du Colombier entryUnpack(&e, b->data, o); 669*5e96a66cSDavid du Colombier *tp = initxentry(e); 670*5e96a66cSDavid du Colombier return 1; 671*5e96a66cSDavid du Colombier } 672*5e96a66cSDavid du Colombier 673*5e96a66cSDavid du Colombier Tnode* 674*5e96a66cSDavid du Colombier initxlocalroot(char *name, u32int addr) 675*5e96a66cSDavid du Colombier { 676*5e96a66cSDavid du Colombier uchar score[VtScoreSize]; 677*5e96a66cSDavid du Colombier Block *b; 678*5e96a66cSDavid du Colombier 679*5e96a66cSDavid du Colombier localToGlobal(addr, score); 680*5e96a66cSDavid du Colombier b = dataBlock(score, BtDir, RootTag); 681*5e96a66cSDavid du Colombier if(b == nil) 682*5e96a66cSDavid du Colombier return stringnode("read data block %#ux: %R", addr); 683*5e96a66cSDavid du Colombier return initxblock(b, smprint("'%s' fs root", name), xlocalrootgen, nil); 684*5e96a66cSDavid du Colombier } 685*5e96a66cSDavid du Colombier 686*5e96a66cSDavid du Colombier int 687*5e96a66cSDavid du Colombier xvacrootgen(void*, Block *b, int o, Tnode **tp) 688*5e96a66cSDavid du Colombier { 689*5e96a66cSDavid du Colombier Entry e; 690*5e96a66cSDavid du Colombier 691*5e96a66cSDavid du Colombier if(o >= 3) 692*5e96a66cSDavid du Colombier return -1; 693*5e96a66cSDavid du Colombier entryUnpack(&e, b->data, o); 694*5e96a66cSDavid du Colombier *tp = initxentry(e); 695*5e96a66cSDavid du Colombier return 1; 696*5e96a66cSDavid du Colombier } 697*5e96a66cSDavid du Colombier 698*5e96a66cSDavid du Colombier Tnode* 699*5e96a66cSDavid du Colombier initxroot(char *name, uchar score[VtScoreSize]) 700*5e96a66cSDavid du Colombier { 701*5e96a66cSDavid du Colombier Block *b; 702*5e96a66cSDavid du Colombier 703*5e96a66cSDavid du Colombier b = dataBlock(score, BtDir, RootTag); 704*5e96a66cSDavid du Colombier if(b == nil) 705*5e96a66cSDavid du Colombier return stringnode("read data block %V: %R", score); 706*5e96a66cSDavid du Colombier return initxblock(b, smprint("'%s' fs root", name), xvacrootgen, nil); 707*5e96a66cSDavid du Colombier } 708*5e96a66cSDavid du Colombier Tnode* 709*5e96a66cSDavid du Colombier initxdirentry(MetaEntry *me) 710*5e96a66cSDavid du Colombier { 711*5e96a66cSDavid du Colombier DirEntry dir; 712*5e96a66cSDavid du Colombier Tnode *t; 713*5e96a66cSDavid du Colombier 714*5e96a66cSDavid du Colombier if(!deUnpack(&dir, me)) 715*5e96a66cSDavid du Colombier return stringnode("deUnpack: %R"); 716*5e96a66cSDavid du Colombier 717*5e96a66cSDavid du Colombier t = stringnode("dirEntry elem=%s size=%llud data=%#lux/%#lux meta=%#lux/%#lux", dir.elem, dir.size, dir.entry, dir.gen, dir.mentry, dir.mgen); 718*5e96a66cSDavid du Colombier t->nkid = 1; 719*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*1, 1); 720*5e96a66cSDavid du Colombier t->kid[0] = stringnode( 721*5e96a66cSDavid du Colombier "qid=%#llux\n" 722*5e96a66cSDavid du Colombier "uid=%s gid=%s mid=%s\n" 723*5e96a66cSDavid du Colombier "mtime=%lud mcount=%lud ctime=%lud atime=%lud\n" 724*5e96a66cSDavid du Colombier "mode=%luo\n" 725*5e96a66cSDavid du Colombier "plan9 %d p9path %#llux p9version %lud\n" 726*5e96a66cSDavid du Colombier "qidSpace %d offset %#llux max %#llux", 727*5e96a66cSDavid du Colombier dir.qid, 728*5e96a66cSDavid du Colombier dir.uid, dir.gid, dir.mid, 729*5e96a66cSDavid du Colombier dir.mtime, dir.mcount, dir.ctime, dir.atime, 730*5e96a66cSDavid du Colombier dir.mode, 731*5e96a66cSDavid du Colombier dir.plan9, dir.p9path, dir.p9version, 732*5e96a66cSDavid du Colombier dir.qidSpace, dir.qidOffset, dir.qidMax); 733*5e96a66cSDavid du Colombier return t; 734*5e96a66cSDavid du Colombier } 735*5e96a66cSDavid du Colombier 736*5e96a66cSDavid du Colombier int 737*5e96a66cSDavid du Colombier metaentrygen(void *v, Block*, int o, Tnode **tp) 738*5e96a66cSDavid du Colombier { 739*5e96a66cSDavid du Colombier Tnode *t; 740*5e96a66cSDavid du Colombier MetaBlock *mb; 741*5e96a66cSDavid du Colombier MetaEntry me; 742*5e96a66cSDavid du Colombier 743*5e96a66cSDavid du Colombier mb = v; 744*5e96a66cSDavid du Colombier if(o >= mb->nindex) 745*5e96a66cSDavid du Colombier return -1; 746*5e96a66cSDavid du Colombier meUnpack(&me, mb, o); 747*5e96a66cSDavid du Colombier 748*5e96a66cSDavid du Colombier t = stringnode("MetaEntry %d bytes", mb->size); 749*5e96a66cSDavid du Colombier t->kid = mallocz(sizeof(t->kid[0])*1, 1); 750*5e96a66cSDavid du Colombier t->kid[0] = initxdirentry(&me); 751*5e96a66cSDavid du Colombier t->nkid = 1; 752*5e96a66cSDavid du Colombier *tp = t; 753*5e96a66cSDavid du Colombier return 1; 754*5e96a66cSDavid du Colombier } 755*5e96a66cSDavid du Colombier 756*5e96a66cSDavid du Colombier int 757*5e96a66cSDavid du Colombier metablockgen(void *v, Block *b, int o, Tnode **tp) 758*5e96a66cSDavid du Colombier { 759*5e96a66cSDavid du Colombier Xblock *t; 760*5e96a66cSDavid du Colombier MetaBlock *mb; 761*5e96a66cSDavid du Colombier 762*5e96a66cSDavid du Colombier if(o >= 1) 763*5e96a66cSDavid du Colombier return -1; 764*5e96a66cSDavid du Colombier 765*5e96a66cSDavid du Colombier /* hack: reuse initxblock as a generic iterator */ 766*5e96a66cSDavid du Colombier mb = v; 767*5e96a66cSDavid du Colombier t = (Xblock*)initxblock(b, "", metaentrygen, mb); 768*5e96a66cSDavid du Colombier t->str = smprint("MetaBlock %d/%d space used, %d add'l free %d/%d table used%s", 769*5e96a66cSDavid du Colombier mb->size, mb->maxsize, mb->free, mb->nindex, mb->maxindex, 770*5e96a66cSDavid du Colombier mb->botch ? " [BOTCH]" : ""); 771*5e96a66cSDavid du Colombier t->printlabel = 0; 772*5e96a66cSDavid du Colombier *tp = t; 773*5e96a66cSDavid du Colombier return 1; 774*5e96a66cSDavid du Colombier } 775*5e96a66cSDavid du Colombier 776*5e96a66cSDavid du Colombier /* 777*5e96a66cSDavid du Colombier * attempt to guess at the type of data in the block. 778*5e96a66cSDavid du Colombier * it could just be data from a file, but we're hoping it's MetaBlocks. 779*5e96a66cSDavid du Colombier */ 780*5e96a66cSDavid du Colombier Tnode* 781*5e96a66cSDavid du Colombier initxdatablock(Block *b, uint n) 782*5e96a66cSDavid du Colombier { 783*5e96a66cSDavid du Colombier MetaBlock mb; 784*5e96a66cSDavid du Colombier 785*5e96a66cSDavid du Colombier if(n > h.blockSize) 786*5e96a66cSDavid du Colombier n = h.blockSize; 787*5e96a66cSDavid du Colombier 788*5e96a66cSDavid du Colombier if(mbUnpack(&mb, b->data, n)) 789*5e96a66cSDavid du Colombier return initxblock(b, "metadata", metablockgen, copyMetaBlock(mb)); 790*5e96a66cSDavid du Colombier 791*5e96a66cSDavid du Colombier return initxblock(b, "data", nil, nil); 792*5e96a66cSDavid du Colombier } 793*5e96a66cSDavid du Colombier 794*5e96a66cSDavid du Colombier int 795*5e96a66cSDavid du Colombier parseScore(uchar *score, char *buf, int n) 796*5e96a66cSDavid du Colombier { 797*5e96a66cSDavid du Colombier int i, c; 798*5e96a66cSDavid du Colombier 799*5e96a66cSDavid du Colombier memset(score, 0, VtScoreSize); 800*5e96a66cSDavid du Colombier 801*5e96a66cSDavid du Colombier if(n < VtScoreSize*2) 802*5e96a66cSDavid du Colombier return 0; 803*5e96a66cSDavid du Colombier for(i=0; i<VtScoreSize*2; i++){ 804*5e96a66cSDavid du Colombier if(buf[i] >= '0' && buf[i] <= '9') 805*5e96a66cSDavid du Colombier c = buf[i] - '0'; 806*5e96a66cSDavid du Colombier else if(buf[i] >= 'a' && buf[i] <= 'f') 807*5e96a66cSDavid du Colombier c = buf[i] - 'a' + 10; 808*5e96a66cSDavid du Colombier else if(buf[i] >= 'A' && buf[i] <= 'F') 809*5e96a66cSDavid du Colombier c = buf[i] - 'A' + 10; 810*5e96a66cSDavid du Colombier else{ 811*5e96a66cSDavid du Colombier return 0; 812*5e96a66cSDavid du Colombier } 813*5e96a66cSDavid du Colombier 814*5e96a66cSDavid du Colombier if((i & 1) == 0) 815*5e96a66cSDavid du Colombier c <<= 4; 816*5e96a66cSDavid du Colombier 817*5e96a66cSDavid du Colombier score[i>>1] |= c; 818*5e96a66cSDavid du Colombier } 819*5e96a66cSDavid du Colombier return 1; 820*5e96a66cSDavid du Colombier } 821*5e96a66cSDavid du Colombier 822*5e96a66cSDavid du Colombier int 823*5e96a66cSDavid du Colombier scoreFmt(Fmt *f) 824*5e96a66cSDavid du Colombier { 825*5e96a66cSDavid du Colombier uchar *v; 826*5e96a66cSDavid du Colombier int i; 827*5e96a66cSDavid du Colombier u32int addr; 828*5e96a66cSDavid du Colombier 829*5e96a66cSDavid du Colombier v = va_arg(f->args, uchar*); 830*5e96a66cSDavid du Colombier if(v == nil){ 831*5e96a66cSDavid du Colombier fmtprint(f, "*"); 832*5e96a66cSDavid du Colombier }else if((addr = globalToLocal(v)) != NilBlock) 833*5e96a66cSDavid du Colombier fmtprint(f, "0x%.8ux", addr); 834*5e96a66cSDavid du Colombier else{ 835*5e96a66cSDavid du Colombier for(i = 0; i < VtScoreSize; i++) 836*5e96a66cSDavid du Colombier fmtprint(f, "%2.2ux", v[i]); 837*5e96a66cSDavid du Colombier } 838*5e96a66cSDavid du Colombier 839*5e96a66cSDavid du Colombier return 0; 840*5e96a66cSDavid du Colombier } 841*5e96a66cSDavid du Colombier 842*5e96a66cSDavid du Colombier Atree* 843*5e96a66cSDavid du Colombier atreeinit(char *arg) 844*5e96a66cSDavid du Colombier { 845*5e96a66cSDavid du Colombier Atree *a; 846*5e96a66cSDavid du Colombier uchar score[VtScoreSize]; 847*5e96a66cSDavid du Colombier 848*5e96a66cSDavid du Colombier vtAttach(); 849*5e96a66cSDavid du Colombier 850*5e96a66cSDavid du Colombier fmtinstall('V', scoreFmt); 851*5e96a66cSDavid du Colombier fmtinstall('R', vtErrFmt); 852*5e96a66cSDavid du Colombier 853*5e96a66cSDavid du Colombier z = vtDial(nil, 1); 854*5e96a66cSDavid du Colombier if(z == nil) 855*5e96a66cSDavid du Colombier fprint(2, "warning: cannot dial venti: %R\n"); 856*5e96a66cSDavid du Colombier if(!vtConnect(z, 0)){ 857*5e96a66cSDavid du Colombier fprint(2, "warning: cannot connect to venti: %R\n"); 858*5e96a66cSDavid du Colombier z = nil; 859*5e96a66cSDavid du Colombier } 860*5e96a66cSDavid du Colombier a = mallocz(sizeof(Atree), 1); 861*5e96a66cSDavid du Colombier if(strncmp(arg, "vac:", 4) == 0){ 862*5e96a66cSDavid du Colombier if(!parseScore(score, arg+4, strlen(arg+4))){ 863*5e96a66cSDavid du Colombier fprint(2, "cannot parse score\n"); 864*5e96a66cSDavid du Colombier return nil; 865*5e96a66cSDavid du Colombier } 866*5e96a66cSDavid du Colombier a->root = initxvacroot(score); 867*5e96a66cSDavid du Colombier }else 868*5e96a66cSDavid du Colombier a->root = initxcache(arg); 869*5e96a66cSDavid du Colombier a->resizefd = -1; 870*5e96a66cSDavid du Colombier return a; 871*5e96a66cSDavid du Colombier } 872*5e96a66cSDavid du Colombier 873*5e96a66cSDavid du Colombier /* --- tree.c */ 874*5e96a66cSDavid du Colombier enum 875*5e96a66cSDavid du Colombier { 876*5e96a66cSDavid du Colombier Nubwidth = 11, 877*5e96a66cSDavid du Colombier Nubheight = 11, 878*5e96a66cSDavid du Colombier Linewidth = Nubwidth*2+4, 879*5e96a66cSDavid du Colombier }; 880*5e96a66cSDavid du Colombier 881*5e96a66cSDavid du Colombier uint 882*5e96a66cSDavid du Colombier drawtext(char *s, Image *m, Image *clipr, Point o) 883*5e96a66cSDavid du Colombier { 884*5e96a66cSDavid du Colombier char *t, *nt, *e; 885*5e96a66cSDavid du Colombier uint dy; 886*5e96a66cSDavid du Colombier 887*5e96a66cSDavid du Colombier if(s == nil) 888*5e96a66cSDavid du Colombier s = "???"; 889*5e96a66cSDavid du Colombier 890*5e96a66cSDavid du Colombier dy = 0; 891*5e96a66cSDavid du Colombier for(t=s; t&&*t; t=nt){ 892*5e96a66cSDavid du Colombier if(nt = strchr(t, '\n')){ 893*5e96a66cSDavid du Colombier e = nt; 894*5e96a66cSDavid du Colombier nt++; 895*5e96a66cSDavid du Colombier }else 896*5e96a66cSDavid du Colombier e = t+strlen(t); 897*5e96a66cSDavid du Colombier 898*5e96a66cSDavid du Colombier _string(m, Pt(o.x, o.y+dy), display->black, ZP, display->defaultfont, 899*5e96a66cSDavid du Colombier t, nil, e-t, clipr->clipr, nil, ZP, SoverD); 900*5e96a66cSDavid du Colombier dy += display->defaultfont->height; 901*5e96a66cSDavid du Colombier } 902*5e96a66cSDavid du Colombier return dy; 903*5e96a66cSDavid du Colombier } 904*5e96a66cSDavid du Colombier 905*5e96a66cSDavid du Colombier void 906*5e96a66cSDavid du Colombier drawnub(Image *m, Image *clipr, Point o, Tnode *t) 907*5e96a66cSDavid du Colombier { 908*5e96a66cSDavid du Colombier clipr = nil; 909*5e96a66cSDavid du Colombier 910*5e96a66cSDavid du Colombier if(t->nkid == 0) 911*5e96a66cSDavid du Colombier return; 912*5e96a66cSDavid du Colombier if(t->nkid == -1 && t->expand == nil) 913*5e96a66cSDavid du Colombier return; 914*5e96a66cSDavid du Colombier 915*5e96a66cSDavid du Colombier o.y += (display->defaultfont->height-Nubheight)/2; 916*5e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0,0,1,Nubheight), o), display->black, clipr, ZP); 917*5e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0,0,Nubwidth,1), o), display->black, clipr, o); 918*5e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(Nubwidth-1,0,Nubwidth,Nubheight), o), 919*5e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(Nubwidth-1, 0))); 920*5e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0, Nubheight-1, Nubwidth, Nubheight), o), 921*5e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(0, Nubheight-1))); 922*5e96a66cSDavid du Colombier 923*5e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(0, Nubheight/2, Nubwidth, Nubheight/2+1), o), 924*5e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(0, Nubheight/2))); 925*5e96a66cSDavid du Colombier if(!t->expanded) 926*5e96a66cSDavid du Colombier draw(m, rectaddpt(Rect(Nubwidth/2, 0, Nubwidth/2+1, Nubheight), o), 927*5e96a66cSDavid du Colombier display->black, clipr, addpt(o, Pt(Nubwidth/2, 0))); 928*5e96a66cSDavid du Colombier 929*5e96a66cSDavid du Colombier } 930*5e96a66cSDavid du Colombier 931*5e96a66cSDavid du Colombier uint 932*5e96a66cSDavid du Colombier drawnode(Tnode *t, Image *m, Image *clipr, Point o) 933*5e96a66cSDavid du Colombier { 934*5e96a66cSDavid du Colombier int i; 935*5e96a66cSDavid du Colombier char *fs, *s; 936*5e96a66cSDavid du Colombier uint dy; 937*5e96a66cSDavid du Colombier Point oo; 938*5e96a66cSDavid du Colombier 939*5e96a66cSDavid du Colombier if(t == nil) 940*5e96a66cSDavid du Colombier return 0; 941*5e96a66cSDavid du Colombier 942*5e96a66cSDavid du Colombier t->offset = o; 943*5e96a66cSDavid du Colombier 944*5e96a66cSDavid du Colombier oo = Pt(o.x+Nubwidth+2, o.y); 945*5e96a66cSDavid du Colombier // if(t->draw) 946*5e96a66cSDavid du Colombier // dy = (*t->draw)(t, m, clipr, oo); 947*5e96a66cSDavid du Colombier // else{ 948*5e96a66cSDavid du Colombier fs = nil; 949*5e96a66cSDavid du Colombier if(t->str) 950*5e96a66cSDavid du Colombier s = t->str; 951*5e96a66cSDavid du Colombier // else if(t->strfn) 952*5e96a66cSDavid du Colombier // fs = s = (*t->strfn)(t); 953*5e96a66cSDavid du Colombier else 954*5e96a66cSDavid du Colombier s = "???"; 955*5e96a66cSDavid du Colombier dy = drawtext(s, m, clipr, oo); 956*5e96a66cSDavid du Colombier free(fs); 957*5e96a66cSDavid du Colombier // } 958*5e96a66cSDavid du Colombier 959*5e96a66cSDavid du Colombier if(t->expanded){ 960*5e96a66cSDavid du Colombier if(t->nkid == -1 && t->expand) 961*5e96a66cSDavid du Colombier (*t->expand)(t); 962*5e96a66cSDavid du Colombier oo = Pt(o.x+Nubwidth+(Linewidth-Nubwidth)/2, o.y+dy); 963*5e96a66cSDavid du Colombier for(i=0; i<t->nkid; i++) 964*5e96a66cSDavid du Colombier oo.y += drawnode(t->kid[i], m, clipr, oo); 965*5e96a66cSDavid du Colombier dy = oo.y - o.y; 966*5e96a66cSDavid du Colombier } 967*5e96a66cSDavid du Colombier drawnub(m, clipr, o, t); 968*5e96a66cSDavid du Colombier return dy; 969*5e96a66cSDavid du Colombier } 970*5e96a66cSDavid du Colombier 971*5e96a66cSDavid du Colombier void 972*5e96a66cSDavid du Colombier drawtree(Tree *t, Image *m, Rectangle r) 973*5e96a66cSDavid du Colombier { 974*5e96a66cSDavid du Colombier Point p; 975*5e96a66cSDavid du Colombier 976*5e96a66cSDavid du Colombier draw(m, r, display->white, nil, ZP); 977*5e96a66cSDavid du Colombier 978*5e96a66cSDavid du Colombier replclipr(t->clipr, 1, r); 979*5e96a66cSDavid du Colombier p = addpt(t->offset, r.min); 980*5e96a66cSDavid du Colombier drawnode(t->root, m, t->clipr, p); 981*5e96a66cSDavid du Colombier } 982*5e96a66cSDavid du Colombier 983*5e96a66cSDavid du Colombier Tnode* 984*5e96a66cSDavid du Colombier findnode(Tnode *t, Point p) 985*5e96a66cSDavid du Colombier { 986*5e96a66cSDavid du Colombier int i; 987*5e96a66cSDavid du Colombier Tnode *tt; 988*5e96a66cSDavid du Colombier 989*5e96a66cSDavid du Colombier if(ptinrect(p, rectaddpt(Rect(0,0,Nubwidth, Nubheight), t->offset))) 990*5e96a66cSDavid du Colombier return t; 991*5e96a66cSDavid du Colombier if(!t->expanded) 992*5e96a66cSDavid du Colombier return nil; 993*5e96a66cSDavid du Colombier for(i=0; i<t->nkid; i++) 994*5e96a66cSDavid du Colombier if(tt = findnode(t->kid[i], p)) 995*5e96a66cSDavid du Colombier return tt; 996*5e96a66cSDavid du Colombier return nil; 997*5e96a66cSDavid du Colombier } 998*5e96a66cSDavid du Colombier 999*5e96a66cSDavid du Colombier void 1000*5e96a66cSDavid du Colombier usage(void) 1001*5e96a66cSDavid du Colombier { 1002*5e96a66cSDavid du Colombier fprint(2, "usage: vtree /dev/sdC0/fossil\n"); 1003*5e96a66cSDavid du Colombier exits("usage"); 1004*5e96a66cSDavid du Colombier } 1005*5e96a66cSDavid du Colombier 1006*5e96a66cSDavid du Colombier Tree t; 1007*5e96a66cSDavid du Colombier 1008*5e96a66cSDavid du Colombier void 1009*5e96a66cSDavid du Colombier eresized(int new) 1010*5e96a66cSDavid du Colombier { 1011*5e96a66cSDavid du Colombier Rectangle r; 1012*5e96a66cSDavid du Colombier r = screen->r; 1013*5e96a66cSDavid du Colombier if(new && getwindow(display, Refnone) < 0) 1014*5e96a66cSDavid du Colombier fprint(2,"can't reattach to window"); 1015*5e96a66cSDavid du Colombier drawtree(&t, screen, screen->r); 1016*5e96a66cSDavid du Colombier } 1017*5e96a66cSDavid du Colombier 1018*5e96a66cSDavid du Colombier enum 1019*5e96a66cSDavid du Colombier { 1020*5e96a66cSDavid du Colombier Left = 1<<0, 1021*5e96a66cSDavid du Colombier Middle = 1<<1, 1022*5e96a66cSDavid du Colombier Right = 1<<2, 1023*5e96a66cSDavid du Colombier 1024*5e96a66cSDavid du Colombier MMenu = 2, 1025*5e96a66cSDavid du Colombier }; 1026*5e96a66cSDavid du Colombier 1027*5e96a66cSDavid du Colombier char *items[] = { "exit", 0 }; 1028*5e96a66cSDavid du Colombier enum { IExit, }; 1029*5e96a66cSDavid du Colombier 1030*5e96a66cSDavid du Colombier Menu menu; 1031*5e96a66cSDavid du Colombier 1032*5e96a66cSDavid du Colombier void 1033*5e96a66cSDavid du Colombier main(int argc, char **argv) 1034*5e96a66cSDavid du Colombier { 1035*5e96a66cSDavid du Colombier int n; 1036*5e96a66cSDavid du Colombier char *dir; 1037*5e96a66cSDavid du Colombier Event e; 1038*5e96a66cSDavid du Colombier Point op, p; 1039*5e96a66cSDavid du Colombier Tnode *tn; 1040*5e96a66cSDavid du Colombier Mouse m; 1041*5e96a66cSDavid du Colombier int Eready; 1042*5e96a66cSDavid du Colombier Atree *fs; 1043*5e96a66cSDavid du Colombier 1044*5e96a66cSDavid du Colombier ARGBEGIN{ 1045*5e96a66cSDavid du Colombier case 'a': 1046*5e96a66cSDavid du Colombier showinactive = 1; 1047*5e96a66cSDavid du Colombier break; 1048*5e96a66cSDavid du Colombier default: 1049*5e96a66cSDavid du Colombier usage(); 1050*5e96a66cSDavid du Colombier }ARGEND 1051*5e96a66cSDavid du Colombier 1052*5e96a66cSDavid du Colombier switch(argc){ 1053*5e96a66cSDavid du Colombier default: 1054*5e96a66cSDavid du Colombier usage(); 1055*5e96a66cSDavid du Colombier case 1: 1056*5e96a66cSDavid du Colombier dir = argv[0]; 1057*5e96a66cSDavid du Colombier break; 1058*5e96a66cSDavid du Colombier } 1059*5e96a66cSDavid du Colombier 1060*5e96a66cSDavid du Colombier fs = atreeinit(dir); 1061*5e96a66cSDavid du Colombier initdraw(0, "/lib/font/bit/lucidasans/unicode.8.font", "tree"); 1062*5e96a66cSDavid du Colombier t.root = fs->root; 1063*5e96a66cSDavid du Colombier t.offset = ZP; 1064*5e96a66cSDavid du Colombier t.clipr = allocimage(display, Rect(0,0,1,1), GREY1, 1, DOpaque); 1065*5e96a66cSDavid du Colombier 1066*5e96a66cSDavid du Colombier eresized(0); 1067*5e96a66cSDavid du Colombier flushimage(display, 1); 1068*5e96a66cSDavid du Colombier 1069*5e96a66cSDavid du Colombier einit(Emouse); 1070*5e96a66cSDavid du Colombier 1071*5e96a66cSDavid du Colombier menu.item = items; 1072*5e96a66cSDavid du Colombier menu.gen = 0; 1073*5e96a66cSDavid du Colombier menu.lasthit = 0; 1074*5e96a66cSDavid du Colombier if(fs->resizefd > 0){ 1075*5e96a66cSDavid du Colombier Eready = 1<<3; 1076*5e96a66cSDavid du Colombier estart(Eready, fs->resizefd, 1); 1077*5e96a66cSDavid du Colombier }else 1078*5e96a66cSDavid du Colombier Eready = 0; 1079*5e96a66cSDavid du Colombier 1080*5e96a66cSDavid du Colombier for(;;){ 1081*5e96a66cSDavid du Colombier switch(n=eread(Emouse|Eready, &e)){ 1082*5e96a66cSDavid du Colombier default: 1083*5e96a66cSDavid du Colombier if(Eready && n==Eready) 1084*5e96a66cSDavid du Colombier eresized(0); 1085*5e96a66cSDavid du Colombier break; 1086*5e96a66cSDavid du Colombier case Emouse: 1087*5e96a66cSDavid du Colombier m = e.mouse; 1088*5e96a66cSDavid du Colombier switch(m.buttons){ 1089*5e96a66cSDavid du Colombier case Left: 1090*5e96a66cSDavid du Colombier op = t.offset; 1091*5e96a66cSDavid du Colombier p = m.xy; 1092*5e96a66cSDavid du Colombier do { 1093*5e96a66cSDavid du Colombier t.offset = addpt(t.offset, subpt(m.xy, p)); 1094*5e96a66cSDavid du Colombier p = m.xy; 1095*5e96a66cSDavid du Colombier eresized(0); 1096*5e96a66cSDavid du Colombier m = emouse(); 1097*5e96a66cSDavid du Colombier }while(m.buttons == Left); 1098*5e96a66cSDavid du Colombier if(m.buttons){ 1099*5e96a66cSDavid du Colombier t.offset = op; 1100*5e96a66cSDavid du Colombier eresized(0); 1101*5e96a66cSDavid du Colombier } 1102*5e96a66cSDavid du Colombier break; 1103*5e96a66cSDavid du Colombier case Middle: 1104*5e96a66cSDavid du Colombier n = emenuhit(MMenu, &m, &menu); 1105*5e96a66cSDavid du Colombier if(n == -1) 1106*5e96a66cSDavid du Colombier break; 1107*5e96a66cSDavid du Colombier switch(n){ 1108*5e96a66cSDavid du Colombier case IExit: 1109*5e96a66cSDavid du Colombier exits(nil); 1110*5e96a66cSDavid du Colombier } 1111*5e96a66cSDavid du Colombier break; 1112*5e96a66cSDavid du Colombier case Right: 1113*5e96a66cSDavid du Colombier do 1114*5e96a66cSDavid du Colombier m = emouse(); 1115*5e96a66cSDavid du Colombier while(m.buttons == Right); 1116*5e96a66cSDavid du Colombier if(m.buttons) 1117*5e96a66cSDavid du Colombier break; 1118*5e96a66cSDavid du Colombier tn = findnode(t.root, m.xy); 1119*5e96a66cSDavid du Colombier if(tn){ 1120*5e96a66cSDavid du Colombier tn->expanded = !tn->expanded; 1121*5e96a66cSDavid du Colombier eresized(0); 1122*5e96a66cSDavid du Colombier } 1123*5e96a66cSDavid du Colombier break; 1124*5e96a66cSDavid du Colombier } 1125*5e96a66cSDavid du Colombier } 1126*5e96a66cSDavid du Colombier } 1127*5e96a66cSDavid du Colombier } 1128