| /* | 
 | ** 2013-10-01 | 
 | ** | 
 | ** The author disclaims copyright to this source code.  In place of | 
 | ** a legal notice, here is a blessing: | 
 | ** | 
 | **    May you do good and not evil. | 
 | **    May you find forgiveness for yourself and forgive others. | 
 | **    May you share freely, never taking more than you give. | 
 | ** | 
 | ****************************************************************************** | 
 | ** | 
 | ** Compute hash signatures for every page of a database file.  This utility | 
 | ** program is useful for analyzing the output logs generated by the | 
 | ** ext/misc/vfslog.c extension. | 
 | */ | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <assert.h> | 
 | #include <stdlib.h> | 
 |  | 
 | /* | 
 | ** Compute signature for a block of content. | 
 | ** | 
 | ** For blocks of 16 or fewer bytes, the signature is just a hex dump of | 
 | ** the entire block. | 
 | ** | 
 | ** For blocks of more than 16 bytes, the signature is a hex dump of the | 
 | ** first 8 bytes followed by a 64-bit has of the entire block. | 
 | */ | 
 | static void vlogSignature(unsigned char *p, int n, char *zCksum){ | 
 |   unsigned int s0 = 0, s1 = 0; | 
 |   unsigned int *pI; | 
 |   int i; | 
 |   if( n<=16 ){ | 
 |     for(i=0; i<n; i++) sprintf(zCksum+i*2, "%02x", p[i]); | 
 |   }else{  | 
 |     pI = (unsigned int*)p; | 
 |     for(i=0; i<n-7; i+=8){ | 
 |       s0 += pI[0] + s1; | 
 |       s1 += pI[1] + s0; | 
 |       pI += 2; | 
 |     } | 
 |     for(i=0; i<8; i++) sprintf(zCksum+i*2, "%02x", p[i]); | 
 |     sprintf(zCksum+i*2, "-%08x%08x", s0, s1); | 
 |   } | 
 | } | 
 |  | 
 | /* | 
 | ** Open a file.  Find its page size.  Read each page, and compute and | 
 | ** display the page signature. | 
 | */ | 
 | static void computeSigs(const char *zFilename){ | 
 |   FILE *in = fopen(zFilename, "rb"); | 
 |   unsigned pgsz; | 
 |   size_t got; | 
 |   unsigned n; | 
 |   unsigned char aBuf[50]; | 
 |   unsigned char aPage[65536]; | 
 |  | 
 |   if( in==0 ){ | 
 |     fprintf(stderr, "cannot open \"%s\"\n", zFilename); | 
 |     return; | 
 |   } | 
 |   got = fread(aBuf, 1, sizeof(aBuf), in); | 
 |   if( got!=sizeof(aBuf) ){ | 
 |     goto endComputeSigs; | 
 |   } | 
 |   pgsz = aBuf[16]*256 + aBuf[17]; | 
 |   if( pgsz==1 ) pgsz = 65536; | 
 |   if( (pgsz & (pgsz-1))!=0 ){ | 
 |     fprintf(stderr, "invalid page size: %02x%02x\n", aBuf[16], aBuf[17]); | 
 |     goto endComputeSigs; | 
 |   } | 
 |   rewind(in); | 
 |   for(n=1; (got=fread(aPage, 1, pgsz, in))==pgsz; n++){ | 
 |     vlogSignature(aPage, pgsz, aBuf); | 
 |     printf("%4d: %s\n", n, aBuf); | 
 |   } | 
 |  | 
 | endComputeSigs: | 
 |   fclose(in); | 
 | } | 
 |  | 
 | /* | 
 | ** Find page signatures for all named files. | 
 | */ | 
 | int main(int argc, char **argv){ | 
 |   int i; | 
 |   for(i=1; i<argc; i++) computeSigs(argv[i]); | 
 |   return 0; | 
 | } |