view.c 20 KB

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