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