#include "stdinc.h" #include "dat.h" #include "fns.h" static int verbose; void usage(void) { fprint(2, "usage: verifyarena [-v]\n"); threadexitsall(0); } static void readblock(uchar *buf, int n) { int nr, m; for(nr = 0; nr < n; nr += m){ m = n - nr; m = read(0, &buf[nr], m); if(m <= 0) sysfatal("can't read arena from standard input: %r"); } } static void verifyarena(void) { Arena arena; ArenaHead head; ZBlock *b; DigestState s; u64int n, e; u32int bs; u8int score[VtScoreSize]; fprint(2, "verify arena from standard input\n"); memset(&arena, 0, sizeof arena); memset(&s, 0, sizeof s); /* * read the little bit, which will included the header */ bs = MaxIoSize; b = alloczblock(bs, 0, 0); readblock(b->data, HeadSize); sha1(b->data, HeadSize, nil, &s); if(unpackarenahead(&head, b->data) < 0) sysfatal("corrupted arena header: %r"); if(head.version != ArenaVersion4 && head.version != ArenaVersion5) fprint(2, "warning: unknown arena version %d\n", head.version); /* * now we know how much to read * read everything but the last block, which is special */ e = head.size - head.blocksize; for(n = HeadSize; n < e; n += bs){ if(n + bs > e) bs = e - n; readblock(b->data, bs); sha1(b->data, bs, nil, &s); } /* * read the last block update the sum. * the sum is calculated assuming the slot for the sum is zero. */ bs = head.blocksize; readblock(b->data, bs); sha1(b->data, bs-VtScoreSize, nil, &s); sha1(zeroscore, VtScoreSize, nil, &s); sha1(nil, 0, score, &s); /* * validity check on the trailer */ arena.blocksize = head.blocksize; if(unpackarena(&arena, b->data) < 0) sysfatal("corrupted arena trailer: %r"); scorecp(arena.score, &b->data[arena.blocksize - VtScoreSize]); if(namecmp(arena.name, head.name) != 0) sysfatal("arena header and trailer names clash: %s vs. %s\n", head.name, arena.name); if(arena.version != head.version) sysfatal("arena header and trailer versions clash: %d vs. %d\n", head.version, arena.version); arena.size = head.size - 2 * head.blocksize; /* * check for no checksum or the same */ if(scorecmp(score, arena.score) != 0){ if(scorecmp(zeroscore, arena.score) != 0) fprint(2, "warning: mismatched checksums for arena=%s, found=%V calculated=%V", arena.name, arena.score, score); scorecp(arena.score, score); }else fprint(2, "matched score\n"); printarena(2, &arena); } void threadmain(int argc, char *argv[]) { ventifmtinstall(); statsinit(); ARGBEGIN{ case 'v': verbose++; break; default: usage(); break; }ARGEND readonly = 1; if(argc != 0) usage(); verifyarena(); threadexitsall(0); }