summaryrefslogtreecommitdiff
path: root/tool/pagesig.c
diff options
context:
space:
mode:
Diffstat (limited to 'tool/pagesig.c')
-rw-r--r--tool/pagesig.c92
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;
+}