view.c 19 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  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. #pragma varargck argpos stringnode 1
  269. Tnode*
  270. stringnode(char *fmt, ...)
  271. {
  272. va_list arg;
  273. Tnode *t;
  274. t = mallocz(sizeof(Tnode), 1);
  275. va_start(arg, fmt);
  276. t->str = vsmprint(fmt, arg);
  277. va_end(arg);
  278. t->nkid = -1;
  279. return t;
  280. }
  281. void
  282. xcacheexpand(Tnode *t)
  283. {
  284. if(t->nkid >= 0)
  285. return;
  286. t->nkid = 1;
  287. t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
  288. t->kid[0] = initxheader();
  289. }
  290. Tnode*
  291. initxcache(char *name)
  292. {
  293. Tnode *t;
  294. if((fd = open(name, OREAD)) < 0)
  295. sysfatal("cannot open %s: %r", name);
  296. t = stringnode("%s", name);
  297. t->expand = xcacheexpand;
  298. return t;
  299. }
  300. void
  301. xheaderexpand(Tnode *t)
  302. {
  303. if(t->nkid >= 0)
  304. return;
  305. t->nkid = 1;
  306. t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
  307. t->kid[0] = initxsuper();
  308. //t->kid[1] = initxlabel(h.label);
  309. //t->kid[2] = initxdata(h.data);
  310. }
  311. Tnode*
  312. initxheader(void)
  313. {
  314. u8int buf[HeaderSize];
  315. Tnode *t;
  316. if(pread(fd, buf, HeaderSize, HeaderOffset) < HeaderSize)
  317. return stringnode("error reading header: %r");
  318. if(!headerUnpack(&h, buf))
  319. return stringnode("error unpacking header: %R");
  320. t = stringnode("header "
  321. "version=%#ux (%d) "
  322. "blockSize=%#ux (%d) "
  323. "super=%#lux (%ld) "
  324. "label=%#lux (%ld) "
  325. "data=%#lux (%ld) "
  326. "end=%#lux (%ld)",
  327. h.version, h.version, h.blockSize, h.blockSize,
  328. h.super, h.super,
  329. h.label, h.label, h.data, h.data, h.end, h.end);
  330. t->expand = xheaderexpand;
  331. return t;
  332. }
  333. void
  334. xsuperexpand(Tnode *t)
  335. {
  336. if(t->nkid >= 0)
  337. return;
  338. t->nkid = 1;
  339. t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
  340. t->kid[0] = initxlocalroot("active", super.active);
  341. // t->kid[1] = initxlocalroot("next", super.next);
  342. // t->kid[2] = initxlocalroot("current", super.current);
  343. }
  344. Tnode*
  345. initxsuper(void)
  346. {
  347. Block *b;
  348. Tnode *t;
  349. b = readBlock(PartSuper, 0);
  350. if(b == nil)
  351. return stringnode("reading super: %r");
  352. if(!superUnpack(&super, b->data)){
  353. blockPut(b);
  354. return stringnode("unpacking super: %R");
  355. }
  356. blockPut(b);
  357. t = stringnode("super "
  358. "version=%#ux "
  359. "epoch=[%#ux,%#ux) "
  360. "qid=%#llux "
  361. "active=%#x "
  362. "next=%#x "
  363. "current=%#x "
  364. "last=%V "
  365. "name=%s",
  366. super.version, super.epochLow, super.epochHigh,
  367. super.qid, super.active, super.next, super.current,
  368. super.last, super.name);
  369. t->expand = xsuperexpand;
  370. return t;
  371. }
  372. void
  373. xvacrootexpand(Tnode *t)
  374. {
  375. if(t->nkid >= 0)
  376. return;
  377. t->nkid = 1;
  378. t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
  379. t->kid[0] = initxroot("root", vac.score);
  380. }
  381. Tnode*
  382. initxvacroot(uchar score[VtScoreSize])
  383. {
  384. Tnode *t;
  385. uchar buf[VtRootSize];
  386. int n;
  387. if((n = vtRead(z, score, VtRootType, buf, VtRootSize)) < 0)
  388. return stringnode("reading root %V: %R", score);
  389. if(!vtRootUnpack(&vac, buf))
  390. return stringnode("unpack %d-byte root: %R", n);
  391. h.blockSize = vac.blockSize;
  392. t = stringnode("vac version=%#ux name=%s type=%s blockSize=%ud score=%V prev=%V",
  393. vac.version, vac.name, vac.type, vac.blockSize, vac.score, vac.prev);
  394. t->expand = xvacrootexpand;
  395. return t;
  396. }
  397. Tnode*
  398. initxlabel(Label l)
  399. {
  400. return stringnode("label type=%s state=%s epoch=%#ux tag=%#ux",
  401. btStr(l.type), bsStr(l.state), l.epoch, l.tag);
  402. }
  403. typedef struct Xblock Xblock;
  404. struct Xblock
  405. {
  406. Tnode;
  407. Block *b;
  408. int (*gen)(void*, Block*, int, Tnode**);
  409. void *arg;
  410. int printlabel;
  411. };
  412. void
  413. xblockexpand(Tnode *tt)
  414. {
  415. int i, j;
  416. enum { Q = 32 };
  417. Xblock *t = (Xblock*)tt;
  418. Tnode *nn;
  419. if(t->nkid >= 0)
  420. return;
  421. j = 0;
  422. if(t->printlabel){
  423. t->kid = mallocz(Q*sizeof(t->kid[0]), 1);
  424. t->kid[0] = initxlabel(t->b->l);
  425. j = 1;
  426. }
  427. for(i=0;; i++){
  428. switch((*t->gen)(t->arg, t->b, i, &nn)){
  429. case -1:
  430. t->nkid = j;
  431. return;
  432. case 0:
  433. break;
  434. case 1:
  435. if(j%Q == 0)
  436. t->kid = realloc(t->kid, (j+Q)*sizeof(t->kid[0]));
  437. t->kid[j++] = nn;
  438. break;
  439. }
  440. }
  441. }
  442. int
  443. nilgen(void*, Block*, int, Tnode**)
  444. {
  445. return -1;
  446. }
  447. Tnode*
  448. initxblock(Block *b, char *s, int (*gen)(void*, Block*, int, Tnode**), void *arg)
  449. {
  450. Xblock *t;
  451. if(gen == nil)
  452. gen = nilgen;
  453. t = mallocz(sizeof(Xblock), 1);
  454. t->b = b;
  455. t->gen = gen;
  456. t->arg = arg;
  457. if(b->addr == NilBlock)
  458. t->str = smprint("Block %V: %s", b->score, s);
  459. else
  460. t->str = smprint("Block %#ux: %s", b->addr, s);
  461. t->printlabel = 1;
  462. t->nkid = -1;
  463. t->expand = xblockexpand;
  464. return t;
  465. }
  466. int
  467. xentrygen(void *v, Block *b, int o, Tnode **tp)
  468. {
  469. Entry e;
  470. Entry *ed;
  471. ed = v;
  472. if(o >= ed->dsize/VtEntrySize)
  473. return -1;
  474. entryUnpack(&e, b->data, o);
  475. if(!showinactive && !(e.flags & VtEntryActive))
  476. return 0;
  477. *tp = initxentry(e);
  478. return 1;
  479. }
  480. Tnode*
  481. initxentryblock(Block *b, Entry *ed)
  482. {
  483. return initxblock(b, "entry", xentrygen, ed);
  484. }
  485. typedef struct Xentry Xentry;
  486. struct Xentry
  487. {
  488. Tnode;
  489. Entry e;
  490. };
  491. void
  492. xentryexpand(Tnode *tt)
  493. {
  494. Xentry *t = (Xentry*)tt;
  495. if(t->nkid >= 0)
  496. return;
  497. t->nkid = 1;
  498. t->kid = mallocz(sizeof(t->kid[0])*t->nkid, 1);
  499. t->kid[0] = initxsource(t->e, 1);
  500. }
  501. Tnode*
  502. initxentry(Entry e)
  503. {
  504. Xentry *t;
  505. t = mallocz(sizeof *t, 1);
  506. t->nkid = -1;
  507. t->str = smprint("Entry gen=%#ux psize=%d dsize=%d depth=%d flags=%#ux size=%lld score=%V",
  508. e.gen, e.psize, e.dsize, e.depth, e.flags, e.size, e.score);
  509. if(e.flags & VtEntryLocal)
  510. t->str = smprint("%s archive=%d snap=%d tag=%#ux", t->str, e.archive, e.snap, e.tag);
  511. t->expand = xentryexpand;
  512. t->e = e;
  513. return t;
  514. }
  515. int
  516. ptrgen(void *v, Block *b, int o, Tnode **tp)
  517. {
  518. Entry *ed;
  519. Entry e;
  520. ed = v;
  521. if(o >= ed->psize/VtScoreSize)
  522. return -1;
  523. e = *ed;
  524. e.depth--;
  525. memmove(e.score, b->data+o*VtScoreSize, VtScoreSize);
  526. if(memcmp(e.score, vtZeroScore, VtScoreSize) == 0)
  527. return 0;
  528. *tp = initxsource(e, 0);
  529. return 1;
  530. }
  531. static int
  532. etype(int flags, int depth)
  533. {
  534. uint t;
  535. if(flags&VtEntryDir)
  536. t = BtDir;
  537. else
  538. t = BtData;
  539. return t+depth;
  540. }
  541. Tnode*
  542. initxsource(Entry e, int dowrap)
  543. {
  544. Block *b;
  545. Tnode *t, *tt;
  546. b = dataBlock(e.score, etype(e.flags, e.depth), e.tag);
  547. if(b == nil)
  548. return stringnode("dataBlock: %r");
  549. if((e.flags & VtEntryActive) == 0)
  550. return stringnode("inactive Entry");
  551. if(e.depth == 0){
  552. if(e.flags & VtEntryDir)
  553. tt = initxentryblock(b, copyEntry(e));
  554. else
  555. tt = initxdatablock(b, e.dsize);
  556. }else{
  557. tt = initxblock(b, smprint("%s+%d pointer", (e.flags & VtEntryDir) ? "BtDir" : "BtData", e.depth),
  558. ptrgen, copyEntry(e));
  559. }
  560. /*
  561. * wrap the contents of the Source in a Source node,
  562. * just so it's closer to what you see in the code.
  563. */
  564. if(dowrap){
  565. t = stringnode("Source");
  566. t->nkid = 1;
  567. t->kid = mallocz(sizeof(Tnode*)*1, 1);
  568. t->kid[0] = tt;
  569. tt = t;
  570. }
  571. return tt;
  572. }
  573. int
  574. xlocalrootgen(void*, Block *b, int o, Tnode **tp)
  575. {
  576. Entry e;
  577. if(o >= 1)
  578. return -1;
  579. entryUnpack(&e, b->data, o);
  580. *tp = initxentry(e);
  581. return 1;
  582. }
  583. Tnode*
  584. initxlocalroot(char *name, u32int addr)
  585. {
  586. uchar score[VtScoreSize];
  587. Block *b;
  588. localToGlobal(addr, score);
  589. b = dataBlock(score, BtDir, RootTag);
  590. if(b == nil)
  591. return stringnode("read data block %#ux: %R", addr);
  592. return initxblock(b, smprint("'%s' fs root", name), xlocalrootgen, nil);
  593. }
  594. int
  595. xvacrootgen(void*, Block *b, int o, Tnode **tp)
  596. {
  597. Entry e;
  598. if(o >= 3)
  599. return -1;
  600. entryUnpack(&e, b->data, o);
  601. *tp = initxentry(e);
  602. return 1;
  603. }
  604. Tnode*
  605. initxroot(char *name, uchar score[VtScoreSize])
  606. {
  607. Block *b;
  608. b = dataBlock(score, BtDir, RootTag);
  609. if(b == nil)
  610. return stringnode("read data block %V: %R", score);
  611. return initxblock(b, smprint("'%s' fs root", name), xvacrootgen, nil);
  612. }
  613. Tnode*
  614. initxdirentry(MetaEntry *me)
  615. {
  616. DirEntry dir;
  617. Tnode *t;
  618. if(!deUnpack(&dir, me))
  619. return stringnode("deUnpack: %R");
  620. 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);
  621. t->nkid = 1;
  622. t->kid = mallocz(sizeof(t->kid[0])*1, 1);
  623. t->kid[0] = stringnode(
  624. "qid=%#llux\n"
  625. "uid=%s gid=%s mid=%s\n"
  626. "mtime=%lud mcount=%lud ctime=%lud atime=%lud\n"
  627. "mode=%luo\n"
  628. "plan9 %d p9path %#llux p9version %lud\n"
  629. "qidSpace %d offset %#llux max %#llux",
  630. dir.qid,
  631. dir.uid, dir.gid, dir.mid,
  632. dir.mtime, dir.mcount, dir.ctime, dir.atime,
  633. dir.mode,
  634. dir.plan9, dir.p9path, dir.p9version,
  635. dir.qidSpace, dir.qidOffset, dir.qidMax);
  636. return t;
  637. }
  638. int
  639. metaentrygen(void *v, Block*, int o, Tnode **tp)
  640. {
  641. Tnode *t;
  642. MetaBlock *mb;
  643. MetaEntry me;
  644. mb = v;
  645. if(o >= mb->nindex)
  646. return -1;
  647. meUnpack(&me, mb, o);
  648. t = stringnode("MetaEntry %d bytes", mb->size);
  649. t->kid = mallocz(sizeof(t->kid[0])*1, 1);
  650. t->kid[0] = initxdirentry(&me);
  651. t->nkid = 1;
  652. *tp = t;
  653. return 1;
  654. }
  655. int
  656. metablockgen(void *v, Block *b, int o, Tnode **tp)
  657. {
  658. Xblock *t;
  659. MetaBlock *mb;
  660. if(o >= 1)
  661. return -1;
  662. /* hack: reuse initxblock as a generic iterator */
  663. mb = v;
  664. t = (Xblock*)initxblock(b, "", metaentrygen, mb);
  665. t->str = smprint("MetaBlock %d/%d space used, %d add'l free %d/%d table used%s",
  666. mb->size, mb->maxsize, mb->free, mb->nindex, mb->maxindex,
  667. mb->botch ? " [BOTCH]" : "");
  668. t->printlabel = 0;
  669. *tp = t;
  670. return 1;
  671. }
  672. /*
  673. * attempt to guess at the type of data in the block.
  674. * it could just be data from a file, but we're hoping it's MetaBlocks.
  675. */
  676. Tnode*
  677. initxdatablock(Block *b, uint n)
  678. {
  679. MetaBlock mb;
  680. if(n > h.blockSize)
  681. n = h.blockSize;
  682. if(mbUnpack(&mb, b->data, n))
  683. return initxblock(b, "metadata", metablockgen, copyMetaBlock(mb));
  684. return initxblock(b, "data", nil, nil);
  685. }
  686. int
  687. parseScore(uchar *score, char *buf, int n)
  688. {
  689. int i, c;
  690. memset(score, 0, VtScoreSize);
  691. if(n < VtScoreSize*2)
  692. return 0;
  693. for(i=0; i<VtScoreSize*2; i++){
  694. if(buf[i] >= '0' && buf[i] <= '9')
  695. c = buf[i] - '0';
  696. else if(buf[i] >= 'a' && buf[i] <= 'f')
  697. c = buf[i] - 'a' + 10;
  698. else if(buf[i] >= 'A' && buf[i] <= 'F')
  699. c = buf[i] - 'A' + 10;
  700. else{
  701. return 0;
  702. }
  703. if((i & 1) == 0)
  704. c <<= 4;
  705. score[i>>1] |= c;
  706. }
  707. return 1;
  708. }
  709. int
  710. scoreFmt(Fmt *f)
  711. {
  712. uchar *v;
  713. int i;
  714. u32int addr;
  715. v = va_arg(f->args, uchar*);
  716. if(v == nil){
  717. fmtprint(f, "*");
  718. }else if((addr = globalToLocal(v)) != NilBlock)
  719. fmtprint(f, "0x%.8ux", addr);
  720. else{
  721. for(i = 0; i < VtScoreSize; i++)
  722. fmtprint(f, "%2.2ux", v[i]);
  723. }
  724. return 0;
  725. }
  726. Atree*
  727. atreeinit(char *arg)
  728. {
  729. Atree *a;
  730. uchar score[VtScoreSize];
  731. vtAttach();
  732. fmtinstall('V', scoreFmt);
  733. fmtinstall('R', vtErrFmt);
  734. z = vtDial(nil, 1);
  735. if(z == nil)
  736. fprint(2, "warning: cannot dial venti: %R\n");
  737. if(!vtConnect(z, 0)){
  738. fprint(2, "warning: cannot connect to venti: %R\n");
  739. z = nil;
  740. }
  741. a = mallocz(sizeof(Atree), 1);
  742. if(strncmp(arg, "vac:", 4) == 0){
  743. if(!parseScore(score, arg+4, strlen(arg+4))){
  744. fprint(2, "cannot parse score\n");
  745. return nil;
  746. }
  747. a->root = initxvacroot(score);
  748. }else
  749. a->root = initxcache(arg);
  750. a->resizefd = -1;
  751. return a;
  752. }
  753. /* --- tree.c */
  754. enum
  755. {
  756. Nubwidth = 11,
  757. Nubheight = 11,
  758. Linewidth = Nubwidth*2+4,
  759. };
  760. uint
  761. drawtext(char *s, Image *m, Image *clipr, Point o)
  762. {
  763. char *t, *nt, *e;
  764. uint dy;
  765. if(s == nil)
  766. s = "???";
  767. dy = 0;
  768. for(t=s; t&&*t; t=nt){
  769. if(nt = strchr(t, '\n')){
  770. e = nt;
  771. nt++;
  772. }else
  773. e = t+strlen(t);
  774. _string(m, Pt(o.x, o.y+dy), display->black, ZP, display->defaultfont,
  775. t, nil, e-t, clipr->clipr, nil, ZP, SoverD);
  776. dy += display->defaultfont->height;
  777. }
  778. return dy;
  779. }
  780. void
  781. drawnub(Image *m, Image *clipr, Point o, Tnode *t)
  782. {
  783. clipr = nil;
  784. if(t->nkid == 0)
  785. return;
  786. if(t->nkid == -1 && t->expand == nil)
  787. return;
  788. o.y += (display->defaultfont->height-Nubheight)/2;
  789. draw(m, rectaddpt(Rect(0,0,1,Nubheight), o), display->black, clipr, ZP);
  790. draw(m, rectaddpt(Rect(0,0,Nubwidth,1), o), display->black, clipr, o);
  791. draw(m, rectaddpt(Rect(Nubwidth-1,0,Nubwidth,Nubheight), o),
  792. display->black, clipr, addpt(o, Pt(Nubwidth-1, 0)));
  793. draw(m, rectaddpt(Rect(0, Nubheight-1, Nubwidth, Nubheight), o),
  794. display->black, clipr, addpt(o, Pt(0, Nubheight-1)));
  795. draw(m, rectaddpt(Rect(0, Nubheight/2, Nubwidth, Nubheight/2+1), o),
  796. display->black, clipr, addpt(o, Pt(0, Nubheight/2)));
  797. if(!t->expanded)
  798. draw(m, rectaddpt(Rect(Nubwidth/2, 0, Nubwidth/2+1, Nubheight), o),
  799. display->black, clipr, addpt(o, Pt(Nubwidth/2, 0)));
  800. }
  801. uint
  802. drawnode(Tnode *t, Image *m, Image *clipr, Point o)
  803. {
  804. int i;
  805. char *fs, *s;
  806. uint dy;
  807. Point oo;
  808. if(t == nil)
  809. return 0;
  810. t->offset = o;
  811. oo = Pt(o.x+Nubwidth+2, o.y);
  812. // if(t->draw)
  813. // dy = (*t->draw)(t, m, clipr, oo);
  814. // else{
  815. fs = nil;
  816. if(t->str)
  817. s = t->str;
  818. // else if(t->strfn)
  819. // fs = s = (*t->strfn)(t);
  820. else
  821. s = "???";
  822. dy = drawtext(s, m, clipr, oo);
  823. free(fs);
  824. // }
  825. if(t->expanded){
  826. if(t->nkid == -1 && t->expand)
  827. (*t->expand)(t);
  828. oo = Pt(o.x+Nubwidth+(Linewidth-Nubwidth)/2, o.y+dy);
  829. for(i=0; i<t->nkid; i++)
  830. oo.y += drawnode(t->kid[i], m, clipr, oo);
  831. dy = oo.y - o.y;
  832. }
  833. drawnub(m, clipr, o, t);
  834. return dy;
  835. }
  836. void
  837. drawtree(Tree *t, Image *m, Rectangle r)
  838. {
  839. Point p;
  840. draw(m, r, display->white, nil, ZP);
  841. replclipr(t->clipr, 1, r);
  842. p = addpt(t->offset, r.min);
  843. drawnode(t->root, m, t->clipr, p);
  844. }
  845. Tnode*
  846. findnode(Tnode *t, Point p)
  847. {
  848. int i;
  849. Tnode *tt;
  850. if(ptinrect(p, rectaddpt(Rect(0,0,Nubwidth, Nubheight), t->offset)))
  851. return t;
  852. if(!t->expanded)
  853. return nil;
  854. for(i=0; i<t->nkid; i++)
  855. if(tt = findnode(t->kid[i], p))
  856. return tt;
  857. return nil;
  858. }
  859. void
  860. usage(void)
  861. {
  862. fprint(2, "usage: vtree /dev/sdC0/fossil\n");
  863. exits("usage");
  864. }
  865. Tree t;
  866. void
  867. eresized(int new)
  868. {
  869. Rectangle r;
  870. r = screen->r;
  871. if(new && getwindow(display, Refnone) < 0)
  872. fprint(2,"can't reattach to window");
  873. drawtree(&t, screen, screen->r);
  874. }
  875. enum
  876. {
  877. Left = 1<<0,
  878. Middle = 1<<1,
  879. Right = 1<<2,
  880. MMenu = 2,
  881. };
  882. char *items[] = { "exit", 0 };
  883. enum { IExit, };
  884. Menu menu;
  885. void
  886. main(int argc, char **argv)
  887. {
  888. int n;
  889. char *dir;
  890. Event e;
  891. Point op, p;
  892. Tnode *tn;
  893. Mouse m;
  894. int Eready;
  895. Atree *fs;
  896. ARGBEGIN{
  897. case 'a':
  898. showinactive = 1;
  899. break;
  900. default:
  901. usage();
  902. }ARGEND
  903. switch(argc){
  904. default:
  905. usage();
  906. case 1:
  907. dir = argv[0];
  908. break;
  909. }
  910. fs = atreeinit(dir);
  911. initdraw(0, "/lib/font/bit/lucidasans/unicode.8.font", "tree");
  912. t.root = fs->root;
  913. t.offset = ZP;
  914. t.clipr = allocimage(display, Rect(0,0,1,1), GREY1, 1, DOpaque);
  915. eresized(0);
  916. flushimage(display, 1);
  917. einit(Emouse);
  918. menu.item = items;
  919. menu.gen = 0;
  920. menu.lasthit = 0;
  921. if(fs->resizefd > 0){
  922. Eready = 1<<3;
  923. estart(Eready, fs->resizefd, 1);
  924. }else
  925. Eready = 0;
  926. for(;;){
  927. switch(n=eread(Emouse|Eready, &e)){
  928. default:
  929. if(Eready && n==Eready)
  930. eresized(0);
  931. break;
  932. case Emouse:
  933. m = e.mouse;
  934. switch(m.buttons){
  935. case Left:
  936. op = t.offset;
  937. p = m.xy;
  938. do {
  939. t.offset = addpt(t.offset, subpt(m.xy, p));
  940. p = m.xy;
  941. eresized(0);
  942. m = emouse();
  943. }while(m.buttons == Left);
  944. if(m.buttons){
  945. t.offset = op;
  946. eresized(0);
  947. }
  948. break;
  949. case Middle:
  950. n = emenuhit(MMenu, &m, &menu);
  951. if(n == -1)
  952. break;
  953. switch(n){
  954. case IExit:
  955. exits(nil);
  956. }
  957. break;
  958. case Right:
  959. do
  960. m = emouse();
  961. while(m.buttons == Right);
  962. if(m.buttons)
  963. break;
  964. tn = findnode(t.root, m.xy);
  965. if(tn){
  966. tn->expanded = !tn->expanded;
  967. eresized(0);
  968. }
  969. break;
  970. }
  971. }
  972. }
  973. }