URI: 
       tverifyarena.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tverifyarena.c (5993B)
       ---
            1 #include "stdinc.h"
            2 #include "dat.h"
            3 #include "fns.h"
            4 
            5 static int        verbose;
            6 static int        fd;
            7 static uchar        *data;
            8 static int        blocksize;
            9 static int        sleepms;
           10 static vlong offset0;
           11 
           12 void
           13 usage(void)
           14 {
           15         fprint(2, "usage: verifyarena [-b blocksize] [-s ms] [-v] [arenapart [name...]]\n");
           16         threadexitsall(0);
           17 }
           18 
           19 static int
           20 preadblock(uchar *buf, int n, vlong off)
           21 {
           22         int nr, m;
           23 
           24         for(nr = 0; nr < n; nr += m){
           25                 m = n - nr;
           26                 m = pread(fd, &buf[nr], m, offset0+off+nr);
           27                 if(m <= 0){
           28                         if(m == 0)
           29                                 werrstr("early eof");
           30                         return -1;
           31                 }
           32         }
           33         return 0;
           34 }
           35 
           36 static int
           37 readblock(uchar *buf, int n)
           38 {
           39         int nr, m;
           40 
           41         for(nr = 0; nr < n; nr += m){
           42                 m = n - nr;
           43                 m = read(fd, &buf[nr], m);
           44                 if(m <= 0){
           45                         if(m == 0)
           46                                 werrstr("early eof");
           47                         return -1;
           48                 }
           49         }
           50         return 0;
           51 }
           52 
           53 static void
           54 verifyarena(char *name, vlong len)
           55 {
           56         Arena arena;
           57         ArenaHead head;
           58         DigestState s;
           59         u64int n, e;
           60         u32int bs;
           61         u8int score[VtScoreSize];
           62 
           63         if(verbose)
           64                 fprint(2, "%T verify %s\n", name);
           65 
           66         memset(&arena, 0, sizeof arena);
           67         memset(&s, 0, sizeof s);
           68 
           69         /*
           70          * read a little bit, which will include the header
           71          */
           72         if(readblock(data, HeadSize) < 0){
           73                 fprint(2, "%T %s: reading header: %r\n", name);
           74                 return;
           75         }
           76         sha1(data, HeadSize, nil, &s);
           77         if(unpackarenahead(&head, data) < 0){
           78                 fprint(2, "%T %s: corrupt arena header: %r\n", name);
           79                 return;
           80         }
           81         if(head.version != ArenaVersion4 && head.version != ArenaVersion5)
           82                 fprint(2, "%T %s: warning: unknown arena version %d\n", name, head.version);
           83         if(len != 0 && len != head.size)
           84                 fprint(2, "%T %s: warning: unexpected length %lld != %lld\n", name, head.size, len);
           85         if(strcmp(name, "<stdin>") != 0 && strcmp(head.name, name) != 0)
           86                 fprint(2, "%T %s: warning: unexpected name %s\n", name, head.name);
           87 
           88         /*
           89          * now we know how much to read
           90          * read everything but the last block, which is special
           91          */
           92         e = head.size - head.blocksize;
           93         bs = blocksize;
           94         for(n = HeadSize; n < e; n += bs){
           95                 if(n + bs > e)
           96                         bs = e - n;
           97                 if(readblock(data, bs) < 0){
           98                         fprint(2, "%T %s: read data: %r\n", name);
           99                         return;
          100                 }
          101                 sha1(data, bs, nil, &s);
          102                 if(sleepms)
          103                         sleep(sleepms);
          104         }
          105 
          106         /*
          107          * read the last block update the sum.
          108          * the sum is calculated assuming the slot for the sum is zero.
          109          */
          110         bs = head.blocksize;
          111         if(readblock(data, bs) < 0){
          112                 fprint(2, "%T %s: read last block: %r\n", name);
          113                 return;
          114         }
          115         sha1(data, bs-VtScoreSize, nil, &s);
          116         sha1(zeroscore, VtScoreSize, nil, &s);
          117         sha1(nil, 0, score, &s);
          118 
          119         /*
          120          * validity check on the trailer
          121          */
          122         arena.blocksize = head.blocksize;
          123         if(unpackarena(&arena, data) < 0){
          124                 fprint(2, "%T %s: corrupt arena trailer: %r\n", name);
          125                 return;
          126         }
          127         scorecp(arena.score, &data[arena.blocksize - VtScoreSize]);
          128 
          129         if(namecmp(arena.name, head.name) != 0){
          130                 fprint(2, "%T %s: wrong name in trailer: %s vs. %s\n",
          131                         name, head.name, arena.name);
          132                 return;
          133         }
          134         if(arena.version != head.version){
          135                 fprint(2, "%T %s: wrong version in trailer: %d vs. %d\n",
          136                         name, head.version, arena.version);
          137                 return;
          138         }
          139         arena.size = head.size - 2 * head.blocksize;
          140 
          141         /*
          142          * check for no checksum or the same
          143          */
          144         if(scorecmp(score, arena.score) == 0) {
          145                 if(verbose)
          146                         fprint(2, "%T %s: verified score\n", name);
          147         } else if(scorecmp(zeroscore, arena.score) == 0) {
          148                 if(verbose || arena.diskstats.used > 0)
          149                         fprint(2, "%T %s: unsealed %,lld bytes\n", name, arena.diskstats.used);
          150         } else{
          151                 fprint(2, "%T %s: mismatch checksum - found=%V calculated=%V\n",
          152                         name, arena.score, score);
          153                 return;
          154         }
          155         if(verbose > 1)
          156                 printarena(2, &arena);
          157 }
          158 
          159 static int
          160 shouldcheck(char *name, char **s, int n)
          161 {
          162         int i;
          163 
          164         if(n == 0)
          165                 return 1;
          166 
          167         for(i=0; i<n; i++){
          168                 if(s[i] && strcmp(name, s[i]) == 0){
          169                         s[i] = nil;
          170                         return 1;
          171                 }
          172         }
          173         return 0;
          174 }
          175 
          176 void
          177 threadmain(int argc, char *argv[])
          178 {
          179         int i, nline;
          180         char *p, *q, *table, *f[10], line[256];
          181         vlong start, stop;
          182         ArenaPart ap;
          183         Part *part;
          184 
          185         needzeroscore();
          186         ventifmtinstall();
          187         blocksize = MaxIoSize;
          188         ARGBEGIN{
          189         case 'b':
          190                 blocksize = unittoull(EARGF(usage()));
          191                 break;
          192         case 's':
          193                 sleepms = atoi(EARGF(usage()));
          194                 break;
          195         case 'v':
          196                 verbose++;
          197                 break;
          198         default:
          199                 usage();
          200                 break;
          201         }ARGEND
          202 
          203         data = vtmalloc(MaxIo + blocksize);
          204         if((uintptr)data % MaxIo)
          205                 data += MaxIo - (uintptr)data%MaxIo;
          206 
          207         if(argc == 0){
          208                 fd = 0;
          209                 verifyarena("<stdin>", 0);
          210                 threadexitsall(nil);
          211         }
          212 
          213         if((part = initpart(argv[0], OREAD)) == nil)
          214                 sysfatal("open partition %s: %r", argv[0]);
          215         fd = part->fd;
          216         offset0 = part->offset;
          217 
          218         if(preadblock(data, 8192, PartBlank) < 0)
          219                 sysfatal("read arena part header: %r");
          220         if(unpackarenapart(&ap, data) < 0)
          221                 sysfatal("corrupted arena part header: %r");
          222         if(verbose)
          223                 fprint(2, "%T # arena part version=%d blocksize=%d arenabase=%d\n",
          224                         ap.version, ap.blocksize, ap.arenabase);
          225         ap.tabbase = (PartBlank+HeadSize+ap.blocksize-1)&~(ap.blocksize-1);
          226         ap.tabsize = ap.arenabase - ap.tabbase;
          227         table = malloc(ap.tabsize+1);
          228         if(preadblock((uchar*)table, ap.tabsize, ap.tabbase) < 0)
          229                 sysfatal("reading arena part directory: %r");
          230         table[ap.tabsize] = 0;
          231 
          232         nline = atoi(table);
          233         p = strchr(table, '\n');
          234         if(p)
          235                 p++;
          236         for(i=0; i<nline; i++){
          237                 if(p == nil){
          238                         fprint(2, "%T warning: unexpected arena table end\n");
          239                         break;
          240                 }
          241                 q = strchr(p, '\n');
          242                 if(q)
          243                         *q++ = 0;
          244                 if(strlen(p) >= sizeof line){
          245                         fprint(2, "%T warning: long arena table line: %s\n", p);
          246                         p = q;
          247                         continue;
          248                 }
          249                 strcpy(line, p);
          250                 memset(f, 0, sizeof f);
          251                 if(tokenize(line, f, nelem(f)) < 3){
          252                         fprint(2, "%T warning: bad arena table line: %s\n", p);
          253                         p = q;
          254                         continue;
          255                 }
          256                 p = q;
          257                 if(shouldcheck(f[0], argv+1, argc-1)){
          258                         start = strtoull(f[1], 0, 0);
          259                         stop = strtoull(f[2], 0, 0);
          260                         if(stop <= start){
          261                                 fprint(2, "%T %s: bad start,stop %lld,%lld\n", f[0], stop, start);
          262                                 continue;
          263                         }
          264                         if(seek(fd, offset0+start, 0) < 0)
          265                                 fprint(2, "%T %s: seek to start: %r\n", f[0]);
          266                         verifyarena(f[0], stop - start);
          267                 }
          268         }
          269         for(i=1; i<argc; i++)
          270                 if(argv[i] != 0)
          271                         fprint(2, "%T %s: did not find arena\n", argv[i]);
          272 
          273         threadexitsall(nil);
          274 }