1 /* 2 ** 2013-10-01 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ****************************************************************************** 12 ** 13 ** Compute hash signatures for every page of a database file. This utility 14 ** program is useful for analyzing the output logs generated by the 15 ** ext/misc/vfslog.c extension. 16 */ 17 #include <stdio.h> 18 #include <string.h> 19 #include <assert.h> 20 #include <stdlib.h> 21 22 /* 23 ** Compute signature for a block of content. 24 ** 25 ** For blocks of 16 or fewer bytes, the signature is just a hex dump of 26 ** the entire block. 27 ** 28 ** For blocks of more than 16 bytes, the signature is a hex dump of the 29 ** first 8 bytes followed by a 64-bit has of the entire block. 30 */ 31 static void vlogSignature(unsigned char *p, int n, char *zCksum){ 32 unsigned int s0 = 0, s1 = 0; 33 unsigned int *pI; 34 int i; 35 if( n<=16 ){ 36 for(i=0; i<n; i++) sprintf(zCksum+i*2, "%02x", p[i]); 37 }else{ 38 pI = (unsigned int*)p; 39 for(i=0; i<n-7; i+=8){ 40 s0 += pI[0] + s1; 41 s1 += pI[1] + s0; 42 pI += 2; 43 } 44 for(i=0; i<8; i++) sprintf(zCksum+i*2, "%02x", p[i]); 45 sprintf(zCksum+i*2, "-%08x%08x", s0, s1); 46 } 47 } 48 49 /* 50 ** Open a file. Find its page size. Read each page, and compute and 51 ** display the page signature. 52 */ 53 static void computeSigs(const char *zFilename){ 54 FILE *in = fopen(zFilename, "rb"); 55 unsigned pgsz; 56 size_t got; 57 unsigned n; 58 unsigned char aBuf[50]; 59 unsigned char aPage[65536]; 60 61 if( in==0 ){ 62 fprintf(stderr, "cannot open \"%s\"\n", zFilename); 63 return; 64 } 65 got = fread(aBuf, 1, sizeof(aBuf), in); 66 if( got!=sizeof(aBuf) ){ 67 goto endComputeSigs; 68 } 69 pgsz = aBuf[16]*256 + aBuf[17]; 70 if( pgsz==1 ) pgsz = 65536; 71 if( (pgsz & (pgsz-1))!=0 ){ 72 fprintf(stderr, "invalid page size: %02x%02x\n", aBuf[16], aBuf[17]); 73 goto endComputeSigs; 74 } 75 rewind(in); 76 for(n=1; (got=fread(aPage, 1, pgsz, in))==pgsz; n++){ 77 vlogSignature(aPage, pgsz, aBuf); 78 printf("%4d: %s\n", n, aBuf); 79 } 80 81 endComputeSigs: 82 fclose(in); 83 } 84 85 /* 86 ** Find page signatures for all named files. 87 */ 88 int main(int argc, char **argv){ 89 int i; 90 for(i=1; i<argc; i++) computeSigs(argv[i]); 91 return 0; 92 } 93