dump.c (2909B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <venti.h> 5 #include <libsec.h> 6 #include <thread.h> 7 8 enum 9 { 10 // XXX What to do here? 11 VtMaxLumpSize = 65535, 12 }; 13 14 VtConn *z; 15 char *host; 16 17 void 18 usage(void) 19 { 20 fprint(2, "usage: venti/dump [-h host] score\n"); 21 threadexitsall("usage"); 22 } 23 24 Biobuf bout; 25 char spaces[256]; 26 27 void 28 dump(int indent, uchar *score, int type) 29 { 30 int i, n; 31 uchar *buf; 32 VtEntry e; 33 VtRoot root; 34 35 if(spaces[0] == 0) 36 memset(spaces, ' ', sizeof spaces-1); 37 38 buf = vtmallocz(VtMaxLumpSize); 39 if(memcmp(score, vtzeroscore, VtScoreSize) == 0) 40 n = 0; 41 else 42 n = vtread(z, score, type, buf, VtMaxLumpSize); 43 if(n < 0){ 44 Bprint(&bout, "%.*serror reading %V: %r\n", indent*4, spaces, score); 45 goto out; 46 } 47 switch(type){ 48 case VtRootType: 49 if(vtrootunpack(&root, buf) < 0){ 50 Bprint(&bout, "%.*serror unpacking root %V: %r\n", indent*4, spaces, score); 51 goto out; 52 } 53 Bprint(&bout, "%.*s%V root name=%s type=%s prev=%V bsize=%ld\n", 54 indent*4, spaces, score, root.name, root.type, root.prev, root.blocksize); 55 dump(indent+1, root.score, VtDirType); 56 break; 57 58 case VtDirType: 59 Bprint(&bout, "%.*s%V dir n=%d\n", indent*4, spaces, score, n); 60 for(i=0; i*VtEntrySize<n; i++){ 61 if(vtentryunpack(&e, buf, i) < 0){ 62 Bprint(&bout, "%.*s%d: cannot unpack\n", indent+1, spaces, i); 63 continue; 64 } 65 Bprint(&bout, "%.*s%d: gen=%#lux psize=%ld dsize=%ld type=%d flags=%#x size=%llud score=%V\n", 66 (indent+1)*4, spaces, i, e.gen, e.psize, e.dsize, e.type, e.flags, e.size, e.score); 67 dump(indent+2, e.score, e.type); 68 } 69 break; 70 71 case VtDataType: 72 Bprint(&bout, "%.*s%V data n=%d", indent*4, spaces, score, n); 73 for(i=0; i<n; i++){ 74 if(i%16 == 0) 75 Bprint(&bout, "\n%.*s", (indent+1)*4, spaces); 76 Bprint(&bout, " %02x", buf[i]); 77 } 78 Bprint(&bout, "\n"); 79 break; 80 81 default: 82 if(type >= VtDirType) 83 Bprint(&bout, "%.*s%V dir+%d\n", indent*4, spaces, score, type-VtDirType); 84 else 85 Bprint(&bout, "%.*s%V data+%d\n", indent*4, spaces, score, type-VtDirType); 86 for(i=0; i<n; i+=VtScoreSize) 87 dump(indent+1, buf+i, type-1); 88 break; 89 } 90 out: 91 free(buf); 92 } 93 94 95 void 96 threadmain(int argc, char *argv[]) 97 { 98 int type, n; 99 uchar score[VtScoreSize]; 100 uchar *buf; 101 char *prefix; 102 103 fmtinstall('F', vtfcallfmt); 104 fmtinstall('V', vtscorefmt); 105 106 ARGBEGIN{ 107 case 'h': 108 host = EARGF(usage()); 109 break; 110 default: 111 usage(); 112 }ARGEND 113 114 if(argc != 1) 115 usage(); 116 117 if(vtparsescore(argv[0], &prefix, score) < 0) 118 sysfatal("could not parse score: %r"); 119 120 buf = vtmallocz(VtMaxLumpSize); 121 z = vtdial(host); 122 if(z == nil) 123 sysfatal("dialing venti: %r"); 124 if(vtconnect(z) < 0) 125 sysfatal("vtconnect src: %r"); 126 127 for(type=0; type<VtMaxType; type++){ 128 n = vtread(z, score, type, buf, VtMaxLumpSize); 129 if(n >= 0) 130 goto havetype; 131 } 132 sysfatal("cannot find block %V", score); 133 134 havetype: 135 Binit(&bout, 1, OWRITE); 136 dump(0, score, type); 137 Bflush(&bout); 138 threadexitsall(nil); 139 }