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