blob: 540c9d722668cccdd348e348bb96ce4208dfe1da [file] [log] [blame]
drh7cd84ff2013-10-10 13:38:51 +00001/*
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*/
31static 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]);
drh919e3b32013-10-10 13:41:04 +000045 sprintf(zCksum+i*2, "-%08x%08x", s0, s1);
drh7cd84ff2013-10-10 13:38:51 +000046 }
47}
48
49/*
50** Open a file. Find its page size. Read each page, and compute and
51** display the page signature.
52*/
53static 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
81endComputeSigs:
82 fclose(in);
83}
84
85/*
86** Find page signatures for all named files.
87*/
88int main(int argc, char **argv){
89 int i;
90 for(i=1; i<argc; i++) computeSigs(argv[i]);
91 return 0;
92}