1 7763a61a 2003-11-23 devnull #include "stdinc.h"
2 7763a61a 2003-11-23 devnull #include <bio.h>
4 7763a61a 2003-11-23 devnull typedef struct Source Source;
6 7763a61a 2003-11-23 devnull struct Source
8 7763a61a 2003-11-23 devnull ulong gen;
9 7763a61a 2003-11-23 devnull int psize;
10 7763a61a 2003-11-23 devnull int dsize;
12 7763a61a 2003-11-23 devnull int active;
13 7763a61a 2003-11-23 devnull int depth;
14 7763a61a 2003-11-23 devnull uvlong size;
15 7763a61a 2003-11-23 devnull uchar score[VtScoreSize];
16 7763a61a 2003-11-23 devnull int reserved;
19 7763a61a 2003-11-23 devnull int bsize;
20 7763a61a 2003-11-23 devnull Biobuf *bout;
21 7763a61a 2003-11-23 devnull VtRoot root;
25 7763a61a 2003-11-23 devnull int find;
26 7763a61a 2003-11-23 devnull uchar fscore[VtScoreSize];
27 7763a61a 2003-11-23 devnull VtSession *z;
29 7763a61a 2003-11-23 devnull int vtGetUint16(uchar *p);
30 7763a61a 2003-11-23 devnull ulong vtGetUint32(uchar *p);
31 7763a61a 2003-11-23 devnull uvlong vtGetUint48(uchar *p);
32 7763a61a 2003-11-23 devnull void usage(void);
33 7763a61a 2003-11-23 devnull int parseScore(uchar *score, char *buf, int n);
34 7763a61a 2003-11-23 devnull void readRoot(VtRoot*, uchar *score, char *file);
35 7763a61a 2003-11-23 devnull int dumpDir(Source*, int indent);
38 7763a61a 2003-11-23 devnull main(int argc, char *argv[])
40 7763a61a 2003-11-23 devnull char *host = nil;
41 7763a61a 2003-11-23 devnull uchar score[VtScoreSize];
42 7763a61a 2003-11-23 devnull Source source;
43 7763a61a 2003-11-23 devnull uchar buf[VtMaxLumpSize];
47 7763a61a 2003-11-23 devnull ARGBEGIN{
48 7763a61a 2003-11-23 devnull case 'h':
49 7763a61a 2003-11-23 devnull host = ARGF();
51 7763a61a 2003-11-23 devnull case 'c':
54 7763a61a 2003-11-23 devnull case 'f':
56 7763a61a 2003-11-23 devnull p = ARGF();
57 7763a61a 2003-11-23 devnull if(p == nil || !parseScore(fscore, p, strlen(p)))
60 7763a61a 2003-11-23 devnull case 'a':
65 7763a61a 2003-11-23 devnull vtAttach();
67 7763a61a 2003-11-23 devnull bout = vtMemAllocZ(sizeof(Biobuf));
68 7763a61a 2003-11-23 devnull Binit(bout, 1, OWRITE);
70 7763a61a 2003-11-23 devnull if(argc > 1)
73 7763a61a 2003-11-23 devnull vtAttach();
75 7763a61a 2003-11-23 devnull fmtinstall('V', vtScoreFmt);
76 7763a61a 2003-11-23 devnull fmtinstall('R', vtErrFmt);
78 7763a61a 2003-11-23 devnull z = vtDial(host, 0);
79 7763a61a 2003-11-23 devnull if(z == nil)
80 7763a61a 2003-11-23 devnull vtFatal("could not connect to server: %s", vtGetError());
82 7763a61a 2003-11-23 devnull if(!vtConnect(z, 0))
83 7763a61a 2003-11-23 devnull sysfatal("vtConnect: %r");
85 7763a61a 2003-11-23 devnull readRoot(&root, score, argv[0]);
86 7763a61a 2003-11-23 devnull ver = root.version;
87 7763a61a 2003-11-23 devnull bsize = root.blockSize;
88 7763a61a 2003-11-23 devnull if(!find) {
89 7763a61a 2003-11-23 devnull Bprint(bout, "score: %V\n", score);
90 7763a61a 2003-11-23 devnull Bprint(bout, "version: %d\n", ver);
91 7763a61a 2003-11-23 devnull Bprint(bout, "name: %s\n", root.name);
92 7763a61a 2003-11-23 devnull Bprint(bout, "type: %s\n", root.type);
93 7763a61a 2003-11-23 devnull Bprint(bout, "bsize: %d\n", bsize);
94 7763a61a 2003-11-23 devnull Bprint(bout, "prev: %V\n", root.prev);
97 7763a61a 2003-11-23 devnull switch(ver) {
99 7763a61a 2003-11-23 devnull sysfatal("unknown version");
100 7763a61a 2003-11-23 devnull case VtRootVersion:
104 7763a61a 2003-11-23 devnull n = vtRead(z, root.score, VtDirType, buf, bsize);
105 7763a61a 2003-11-23 devnull if(n < 0)
106 7763a61a 2003-11-23 devnull sysfatal("could not read root dir");
108 7763a61a 2003-11-23 devnull /* fake up top level source */
109 7763a61a 2003-11-23 devnull memset(&source, 0, sizeof(source));
110 7763a61a 2003-11-23 devnull memmove(source.score, root.score, VtScoreSize);
111 7763a61a 2003-11-23 devnull source.psize = bsize;
112 7763a61a 2003-11-23 devnull source.dsize = bsize;
113 7763a61a 2003-11-23 devnull source.dir = 1;
114 7763a61a 2003-11-23 devnull source.active = 1;
115 7763a61a 2003-11-23 devnull source.depth = 0;
116 7763a61a 2003-11-23 devnull source.size = n;
118 7763a61a 2003-11-23 devnull dumpDir(&source, 0);
120 7763a61a 2003-11-23 devnull Bterm(bout);
122 7763a61a 2003-11-23 devnull vtClose(z);
123 7763a61a 2003-11-23 devnull vtDetach();
124 7763a61a 2003-11-23 devnull exits(0);
128 7763a61a 2003-11-23 devnull sourcePrint(Source *s, int indent, int entry)
131 7763a61a 2003-11-23 devnull uvlong size;
134 7763a61a 2003-11-23 devnull for(i=0; i<indent; i++)
135 7763a61a 2003-11-23 devnull Bprint(bout, " ");
136 7763a61a 2003-11-23 devnull Bprint(bout, "%4d", entry);
137 7763a61a 2003-11-23 devnull if(s->active) {
138 7763a61a 2003-11-23 devnull /* dir size in directory entries */
139 7763a61a 2003-11-23 devnull if(s->dir) {
140 7763a61a 2003-11-23 devnull ne = s->dsize/VtEntrySize;
141 7763a61a 2003-11-23 devnull size = ne*(s->size/s->dsize) + (s->size%s->dsize)/VtEntrySize;
143 7763a61a 2003-11-23 devnull size = s->size;
144 7763a61a 2003-11-23 devnull if(cmp) {
145 7763a61a 2003-11-23 devnull Bprint(bout, ": gen: %lud size: %llud",
146 7763a61a 2003-11-23 devnull s->gen, size);
147 7763a61a 2003-11-23 devnull if(!s->dir)
148 7763a61a 2003-11-23 devnull Bprint(bout, ": %V", s->score);
149 7763a61a 2003-11-23 devnull } else {
150 7763a61a 2003-11-23 devnull Bprint(bout, ": gen: %lud psize: %d dsize: %d",
151 7763a61a 2003-11-23 devnull s->gen, s->psize, s->dsize);
152 7763a61a 2003-11-23 devnull Bprint(bout, " depth: %d size: %llud: %V",
153 7763a61a 2003-11-23 devnull s->depth, size, s->score);
156 7763a61a 2003-11-23 devnull if(s->reserved)
157 7763a61a 2003-11-23 devnull Bprint(bout, ": reserved not emtpy");
159 7763a61a 2003-11-23 devnull Bprint(bout, "\n");
163 7763a61a 2003-11-23 devnull parse(Source *s, uchar *p)
165 7763a61a 2003-11-23 devnull VtEntry dir;
167 7763a61a 2003-11-23 devnull memset(s, 0, sizeof(*s));
168 7763a61a 2003-11-23 devnull if(!vtEntryUnpack(&dir, p, 0))
169 7763a61a 2003-11-23 devnull return 0;
171 7763a61a 2003-11-23 devnull if(!(dir.flags & VtEntryActive))
172 7763a61a 2003-11-23 devnull return 1;
174 7763a61a 2003-11-23 devnull s->active = 1;
175 7763a61a 2003-11-23 devnull s->gen = dir.gen;
176 7763a61a 2003-11-23 devnull s->psize = dir.psize;
177 7763a61a 2003-11-23 devnull s->dsize = dir.size;
178 7763a61a 2003-11-23 devnull s->size = dir.size;
179 7763a61a 2003-11-23 devnull memmove(s->score, dir.score, VtScoreSize);
180 7763a61a 2003-11-23 devnull if(dir.flags & VtEntryDir)
181 7763a61a 2003-11-23 devnull s->dir = 1;
182 7763a61a 2003-11-23 devnull s->depth = dir.depth;
183 7763a61a 2003-11-23 devnull return 1;
188 7763a61a 2003-11-23 devnull sourceRead(Source *s, ulong block, uchar *p, int n)
190 7763a61a 2003-11-23 devnull uchar buf[VtMaxLumpSize];
191 7763a61a 2003-11-23 devnull uchar score[VtScoreSize];
192 7763a61a 2003-11-23 devnull int i, nn, np, type;
193 7763a61a 2003-11-23 devnull int elem[VtPointerDepth];
195 7763a61a 2003-11-23 devnull memmove(score, s->score, VtScoreSize);
197 7763a61a 2003-11-23 devnull np = s->psize/VtScoreSize;
198 7763a61a 2003-11-23 devnull for(i=0; i<s->depth; i++) {
199 7763a61a 2003-11-23 devnull elem[i] = block % np;
200 7763a61a 2003-11-23 devnull block /= np;
202 7763a61a 2003-11-23 devnull assert(block == 0);
204 7763a61a 2003-11-23 devnull for(i=s->depth-1; i>=0; i--) {
205 7763a61a 2003-11-23 devnull nn = vtRead(z, score, VtPointerType0+i, buf, s->psize);
206 7763a61a 2003-11-23 devnull if(nn < 0)
207 7763a61a 2003-11-23 devnull return -1;
209 7763a61a 2003-11-23 devnull if(!vtSha1Check(score, buf, nn)) {
210 7763a61a 2003-11-23 devnull vtSetError("vtSha1Check failed on root block");
211 7763a61a 2003-11-23 devnull return -1;
214 7763a61a 2003-11-23 devnull if((elem[i]+1)*VtScoreSize > nn)
215 7763a61a 2003-11-23 devnull return 0;
216 7763a61a 2003-11-23 devnull memmove(score, buf + elem[i]*VtScoreSize, VtScoreSize);
219 7763a61a 2003-11-23 devnull if(s->dir)
220 7763a61a 2003-11-23 devnull type = VtDirType;
222 7763a61a 2003-11-23 devnull type = VtDataType;
224 7763a61a 2003-11-23 devnull nn = vtRead(z, score, type, p, n);
225 7763a61a 2003-11-23 devnull if(nn < 0)
226 7763a61a 2003-11-23 devnull return -1;
228 7763a61a 2003-11-23 devnull if(!vtSha1Check(score, p, nn)) {
229 7763a61a 2003-11-23 devnull vtSetError("vtSha1Check failed on root block");
230 7763a61a 2003-11-23 devnull return -1;
233 7763a61a 2003-11-23 devnull return nn;
237 7763a61a 2003-11-23 devnull dumpFileContents(Source *s)
239 7763a61a 2003-11-23 devnull int nb, lb, i, n;
240 7763a61a 2003-11-23 devnull uchar buf[VtMaxLumpSize];
242 7763a61a 2003-11-23 devnull nb = (s->size + s->dsize - 1)/s->dsize;
243 7763a61a 2003-11-23 devnull lb = s->size%s->dsize;
244 7763a61a 2003-11-23 devnull for(i=0; i<nb; i++) {
245 7763a61a 2003-11-23 devnull memset(buf, 0, s->dsize);
246 7763a61a 2003-11-23 devnull n = sourceRead(s, i, buf, s->dsize);
247 7763a61a 2003-11-23 devnull if(n < 0) {
248 7763a61a 2003-11-23 devnull fprint(2, "could not read block: %d: %s\n", i, vtGetError());
249 7763a61a 2003-11-23 devnull continue;
251 7763a61a 2003-11-23 devnull if(i < nb-1)
252 7763a61a 2003-11-23 devnull Bwrite(bout, buf, s->dsize);
254 7763a61a 2003-11-23 devnull Bwrite(bout, buf, lb);
259 7763a61a 2003-11-23 devnull dumpFile(Source *s, int indent)
261 7763a61a 2003-11-23 devnull int nb, i, j, n;
262 7763a61a 2003-11-23 devnull uchar buf[VtMaxLumpSize];
263 7763a61a 2003-11-23 devnull uchar score[VtScoreSize];
265 7763a61a 2003-11-23 devnull nb = (s->size + s->dsize - 1)/s->dsize;
266 7763a61a 2003-11-23 devnull for(i=0; i<nb; i++) {
267 7763a61a 2003-11-23 devnull memset(buf, 0, s->dsize);
268 7763a61a 2003-11-23 devnull n = sourceRead(s, i, buf, s->dsize);
269 7763a61a 2003-11-23 devnull if(n < 0) {
270 7763a61a 2003-11-23 devnull fprint(2, "could not read block: %d: %s\n", i, vtGetError());
271 7763a61a 2003-11-23 devnull continue;
273 7763a61a 2003-11-23 devnull for(j=0; j<indent; j++)
274 7763a61a 2003-11-23 devnull Bprint(bout, " ");
275 7763a61a 2003-11-23 devnull vtSha1(score, buf, n);
276 7763a61a 2003-11-23 devnull Bprint(bout, "%4d: size: %ud: %V\n", i, n, score);
281 7763a61a 2003-11-23 devnull dumpDir(Source *s, int indent)
283 7763a61a 2003-11-23 devnull int pb, ne, nb, i, j, n, entry;
284 7763a61a 2003-11-23 devnull uchar buf[VtMaxLumpSize];
285 7763a61a 2003-11-23 devnull Source ss;
287 7763a61a 2003-11-23 devnull pb = s->dsize/VtEntrySize;
288 7763a61a 2003-11-23 devnull ne = pb*(s->size/s->dsize) + (s->size%s->dsize)/VtEntrySize;
289 7763a61a 2003-11-23 devnull nb = (s->size + s->dsize - 1)/s->dsize;
290 7763a61a 2003-11-23 devnull for(i=0; i<nb; i++) {
291 7763a61a 2003-11-23 devnull memset(buf, 0, s->dsize);
292 7763a61a 2003-11-23 devnull n = sourceRead(s, i, buf, s->dsize);
293 7763a61a 2003-11-23 devnull if(n < 0) {
294 7763a61a 2003-11-23 devnull fprint(2, "could not read block: %d: %s\n", i, vtGetError());
295 7763a61a 2003-11-23 devnull continue;
297 7763a61a 2003-11-23 devnull for(j=0; j<pb; j++) {
298 7763a61a 2003-11-23 devnull entry = i*pb + j;
299 7763a61a 2003-11-23 devnull if(entry >= ne)
301 7763a61a 2003-11-23 devnull parse(&ss, buf + j * VtEntrySize);
303 7763a61a 2003-11-23 devnull if(!find)
304 7763a61a 2003-11-23 devnull sourcePrint(&ss, indent, entry);
305 7763a61a 2003-11-23 devnull else if(memcmp(ss.score, fscore, VtScoreSize) == 0) {
306 7763a61a 2003-11-23 devnull dumpFileContents(&ss);
307 7763a61a 2003-11-23 devnull return 0;
310 7763a61a 2003-11-23 devnull if(ss.dir) {
311 7763a61a 2003-11-23 devnull if(!dumpDir(&ss, indent+1))
312 7763a61a 2003-11-23 devnull return 0;
313 7763a61a 2003-11-23 devnull } else if(all)
314 7763a61a 2003-11-23 devnull dumpFile(&ss, indent+1);
317 7763a61a 2003-11-23 devnull return 1;
321 7763a61a 2003-11-23 devnull usage(void)
323 7763a61a 2003-11-23 devnull fprint(2, "%s: [file]\n", argv0);
324 7763a61a 2003-11-23 devnull exits("usage");
328 7763a61a 2003-11-23 devnull parseScore(uchar *score, char *buf, int n)
330 7763a61a 2003-11-23 devnull int i, c;
332 7763a61a 2003-11-23 devnull memset(score, 0, VtScoreSize);
334 7763a61a 2003-11-23 devnull if(n < VtScoreSize*2)
335 7763a61a 2003-11-23 devnull return 0;
336 7763a61a 2003-11-23 devnull for(i=0; i<VtScoreSize*2; i++) {
337 7763a61a 2003-11-23 devnull if(buf[i] >= '0' && buf[i] <= '9')
338 7763a61a 2003-11-23 devnull c = buf[i] - '0';
339 7763a61a 2003-11-23 devnull else if(buf[i] >= 'a' && buf[i] <= 'f')
340 7763a61a 2003-11-23 devnull c = buf[i] - 'a' + 10;
341 7763a61a 2003-11-23 devnull else if(buf[i] >= 'A' && buf[i] <= 'F')
342 7763a61a 2003-11-23 devnull c = buf[i] - 'A' + 10;
344 7763a61a 2003-11-23 devnull return 0;
347 7763a61a 2003-11-23 devnull if((i & 1) == 0)
348 7763a61a 2003-11-23 devnull c <<= 4;
350 7763a61a 2003-11-23 devnull score[i>>1] |= c;
352 7763a61a 2003-11-23 devnull return 1;
356 7763a61a 2003-11-23 devnull readRoot(VtRoot *root, uchar *score, char *file)
359 7763a61a 2003-11-23 devnull uchar buf[VtRootSize];
360 7763a61a 2003-11-23 devnull int i, n, nn;
362 7763a61a 2003-11-23 devnull if(file == 0)
365 7763a61a 2003-11-23 devnull fd = open(file, OREAD);
366 7763a61a 2003-11-23 devnull if(fd < 0)
367 7763a61a 2003-11-23 devnull sysfatal("could not open file: %s: %r\n", file);
369 7763a61a 2003-11-23 devnull n = readn(fd, buf, sizeof(buf)-1);
370 7763a61a 2003-11-23 devnull if(n < 0)
371 7763a61a 2003-11-23 devnull sysfatal("read failed: %r\n");
372 7763a61a 2003-11-23 devnull buf[n] = 0;
373 7763a61a 2003-11-23 devnull close(fd);
375 7763a61a 2003-11-23 devnull for(i=0; i<n; i++) {
376 7763a61a 2003-11-23 devnull if(!parseScore(score, (char*)(buf+i), n-i))
377 7763a61a 2003-11-23 devnull continue;
378 7763a61a 2003-11-23 devnull nn = vtRead(z, score, VtRootType, buf, VtRootSize);
379 7763a61a 2003-11-23 devnull if(nn >= 0) {
380 7763a61a 2003-11-23 devnull if(nn != VtRootSize)
381 7763a61a 2003-11-23 devnull sysfatal("vtRead on root too short");
382 7763a61a 2003-11-23 devnull if(!vtSha1Check(score, buf, VtRootSize))
383 7763a61a 2003-11-23 devnull sysfatal("vtSha1Check failed on root block");
384 7763a61a 2003-11-23 devnull if(!vtRootUnpack(root, buf))
385 7763a61a 2003-11-23 devnull sysfatal("could not parse root: %r");
390 7763a61a 2003-11-23 devnull sysfatal("could not find root");