view.c 19 KB

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