123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #include "stdinc.h"
- #include <bio.h>
- typedef struct Source Source;
- struct Source
- {
- ulong gen;
- int psize;
- int dsize;
- int dir;
- int active;
- int depth;
- uvlong size;
- uchar score[VtScoreSize];
- int reserved;
- };
- int bsize;
- Biobuf *bout;
- VtRoot root;
- int ver;
- int cmp;
- int all;
- int find;
- uchar fscore[VtScoreSize];
- VtSession *z;
- int vtGetUint16(uchar *p);
- ulong vtGetUint32(uchar *p);
- uvlong vtGetUint48(uchar *p);
- void usage(void);
- int parseScore(uchar *score, char *buf, int n);
- void readRoot(VtRoot*, uchar *score, char *file);
- int dumpDir(Source*, int indent);
- void
- main(int argc, char *argv[])
- {
- char *host = nil;
- uchar score[VtScoreSize];
- Source source;
- uchar buf[VtMaxLumpSize];
- char *p;
- int n;
- ARGBEGIN{
- case 'h':
- host = ARGF();
- break;
- case 'c':
- cmp++;
- break;
- case 'f':
- find++;
- p = ARGF();
- if(p == nil || !parseScore(fscore, p, strlen(p)))
- usage();
- break;
- case 'a':
- all = 1;
- break;
- }ARGEND
- vtAttach();
- bout = vtMemAllocZ(sizeof(Biobuf));
- Binit(bout, 1, OWRITE);
- if(argc > 1)
- usage();
- vtAttach();
- fmtinstall('V', vtScoreFmt);
- fmtinstall('R', vtErrFmt);
- z = vtDial(host, 0);
- if(z == nil)
- vtFatal("could not connect to server: %s", vtGetError());
- if(!vtConnect(z, 0))
- sysfatal("vtConnect: %r");
- readRoot(&root, score, argv[0]);
- ver = root.version;
- bsize = root.blockSize;
- if(!find) {
- Bprint(bout, "score: %V\n", score);
- Bprint(bout, "version: %d\n", ver);
- Bprint(bout, "name: %s\n", root.name);
- Bprint(bout, "type: %s\n", root.type);
- Bprint(bout, "bsize: %d\n", bsize);
- Bprint(bout, "prev: %V\n", root.prev);
- }
- switch(ver) {
- default:
- sysfatal("unknown version");
- case VtRootVersion:
- break;
- }
- n = vtRead(z, root.score, VtDirType, buf, bsize);
- if(n < 0)
- sysfatal("could not read root dir");
- /* fake up top level source */
- memset(&source, 0, sizeof(source));
- memmove(source.score, root.score, VtScoreSize);
- source.psize = bsize;
- source.dsize = bsize;
- source.dir = 1;
- source.active = 1;
- source.depth = 0;
- source.size = n;
- dumpDir(&source, 0);
- Bterm(bout);
- vtClose(z);
- vtDetach();
- exits(0);
- }
- void
- sourcePrint(Source *s, int indent, int entry)
- {
- int i;
- uvlong size;
- int ne;
- for(i=0; i<indent; i++)
- Bprint(bout, " ");
- Bprint(bout, "%4d", entry);
- if(s->active) {
- /* dir size in directory entries */
- if(s->dir) {
- ne = s->dsize/VtEntrySize;
- size = ne*(s->size/s->dsize) + (s->size%s->dsize)/VtEntrySize;
- } else
- size = s->size;
- if(cmp) {
- Bprint(bout, ": gen: %lud size: %llud",
- s->gen, size);
- if(!s->dir)
- Bprint(bout, ": %V", s->score);
- } else {
- Bprint(bout, ": gen: %lud psize: %d dsize: %d",
- s->gen, s->psize, s->dsize);
- Bprint(bout, " depth: %d size: %llud: %V",
- s->depth, size, s->score);
- }
-
- if(s->reserved)
- Bprint(bout, ": reserved not emtpy");
- }
- Bprint(bout, "\n");
- }
- int
- parse(Source *s, uchar *p)
- {
- VtEntry dir;
- memset(s, 0, sizeof(*s));
- if(!vtEntryUnpack(&dir, p, 0))
- return 0;
- if(!(dir.flags & VtEntryActive))
- return 1;
- s->active = 1;
- s->gen = dir.gen;
- s->psize = dir.psize;
- s->dsize = dir.size;
- s->size = dir.size;
- memmove(s->score, dir.score, VtScoreSize);
- if(dir.flags & VtEntryDir)
- s->dir = 1;
- s->depth = dir.depth;
- return 1;
- }
- int
- sourceRead(Source *s, ulong block, uchar *p, int n)
- {
- uchar buf[VtMaxLumpSize];
- uchar score[VtScoreSize];
- int i, nn, np, type;
- int elem[VtPointerDepth];
- memmove(score, s->score, VtScoreSize);
- np = s->psize/VtScoreSize;
- for(i=0; i<s->depth; i++) {
- elem[i] = block % np;
- block /= np;
- }
- assert(block == 0);
- for(i=s->depth-1; i>=0; i--) {
- nn = vtRead(z, score, VtPointerType0+i, buf, s->psize);
- if(nn < 0)
- return -1;
- if(!vtSha1Check(score, buf, nn)) {
- vtSetError("vtSha1Check failed on root block");
- return -1;
- }
- if((elem[i]+1)*VtScoreSize > nn)
- return 0;
- memmove(score, buf + elem[i]*VtScoreSize, VtScoreSize);
- }
- if(s->dir)
- type = VtDirType;
- else
- type = VtDataType;
- nn = vtRead(z, score, type, p, n);
- if(nn < 0)
- return -1;
- if(!vtSha1Check(score, p, nn)) {
- vtSetError("vtSha1Check failed on root block");
- return -1;
- }
-
- return nn;
- }
- void
- dumpFileContents(Source *s)
- {
- int nb, lb, i, n;
- uchar buf[VtMaxLumpSize];
- nb = (s->size + s->dsize - 1)/s->dsize;
- lb = s->size%s->dsize;
- for(i=0; i<nb; i++) {
- memset(buf, 0, s->dsize);
- n = sourceRead(s, i, buf, s->dsize);
- if(n < 0) {
- fprint(2, "could not read block: %d: %s\n", i, vtGetError());
- continue;
- }
- if(i < nb-1)
- Bwrite(bout, buf, s->dsize);
- else
- Bwrite(bout, buf, lb);
- }
- }
- void
- dumpFile(Source *s, int indent)
- {
- int nb, i, j, n;
- uchar buf[VtMaxLumpSize];
- uchar score[VtScoreSize];
- nb = (s->size + s->dsize - 1)/s->dsize;
- for(i=0; i<nb; i++) {
- memset(buf, 0, s->dsize);
- n = sourceRead(s, i, buf, s->dsize);
- if(n < 0) {
- fprint(2, "could not read block: %d: %s\n", i, vtGetError());
- continue;
- }
- for(j=0; j<indent; j++)
- Bprint(bout, " ");
- vtSha1(score, buf, n);
- Bprint(bout, "%4d: size: %ud: %V\n", i, n, score);
- }
- }
- int
- dumpDir(Source *s, int indent)
- {
- int pb, ne, nb, i, j, n, entry;
- uchar buf[VtMaxLumpSize];
- Source ss;
- pb = s->dsize/VtEntrySize;
- ne = pb*(s->size/s->dsize) + (s->size%s->dsize)/VtEntrySize;
- nb = (s->size + s->dsize - 1)/s->dsize;
- for(i=0; i<nb; i++) {
- memset(buf, 0, s->dsize);
- n = sourceRead(s, i, buf, s->dsize);
- if(n < 0) {
- fprint(2, "could not read block: %d: %s\n", i, vtGetError());
- continue;
- }
- for(j=0; j<pb; j++) {
- entry = i*pb + j;
- if(entry >= ne)
- break;
- parse(&ss, buf + j * VtEntrySize);
- if(!find)
- sourcePrint(&ss, indent, entry);
- else if(memcmp(ss.score, fscore, VtScoreSize) == 0) {
- dumpFileContents(&ss);
- return 0;
- }
- if(ss.dir) {
- if(!dumpDir(&ss, indent+1))
- return 0;
- } else if(all)
- dumpFile(&ss, indent+1);
- }
- }
- return 1;
- }
- void
- usage(void)
- {
- fprint(2, "%s: [file]\n", argv0);
- exits("usage");
- }
- int
- parseScore(uchar *score, char *buf, int n)
- {
- int i, c;
- memset(score, 0, VtScoreSize);
- if(n < VtScoreSize*2)
- return 0;
- for(i=0; i<VtScoreSize*2; i++) {
- if(buf[i] >= '0' && buf[i] <= '9')
- c = buf[i] - '0';
- else if(buf[i] >= 'a' && buf[i] <= 'f')
- c = buf[i] - 'a' + 10;
- else if(buf[i] >= 'A' && buf[i] <= 'F')
- c = buf[i] - 'A' + 10;
- else {
- return 0;
- }
- if((i & 1) == 0)
- c <<= 4;
-
- score[i>>1] |= c;
- }
- return 1;
- }
- void
- readRoot(VtRoot *root, uchar *score, char *file)
- {
- int fd;
- uchar buf[VtRootSize];
- int i, n, nn;
- if(file == 0)
- fd = 0;
- else {
- fd = open(file, OREAD);
- if(fd < 0)
- sysfatal("could not open file: %s: %r\n", file);
- }
- n = readn(fd, buf, sizeof(buf)-1);
- if(n < 0)
- sysfatal("read failed: %r\n");
- buf[n] = 0;
- close(fd);
- for(i=0; i<n; i++) {
- if(!parseScore(score, (char*)(buf+i), n-i))
- continue;
- nn = vtRead(z, score, VtRootType, buf, VtRootSize);
- if(nn >= 0) {
- if(nn != VtRootSize)
- sysfatal("vtRead on root too short");
- if(!vtSha1Check(score, buf, VtRootSize))
- sysfatal("vtSha1Check failed on root block");
- if(!vtRootUnpack(root, buf))
- sysfatal("could not parse root: %r");
- return;
- }
- }
- sysfatal("could not find root");
- }
|