/* ** 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; }