diff options
Diffstat (limited to 'tool/pagesig.c')
-rw-r--r-- | tool/pagesig.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/tool/pagesig.c b/tool/pagesig.c new file mode 100644 index 0000000..540c9d7 --- /dev/null +++ b/tool/pagesig.c @@ -0,0 +1,92 @@ +/* +** 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; +} |