xref: /sqlite-3.40.0/tool/pagesig.c (revision 919e3b39)
1 /*
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 */
vlogSignature(unsigned char * p,int n,char * zCksum)31 static 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]);
45     sprintf(zCksum+i*2, "-%08x%08x", s0, s1);
46   }
47 }
48 
49 /*
50 ** Open a file.  Find its page size.  Read each page, and compute and
51 ** display the page signature.
52 */
computeSigs(const char * zFilename)53 static 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 
81 endComputeSigs:
82   fclose(in);
83 }
84 
85 /*
86 ** Find page signatures for all named files.
87 */
main(int argc,char ** argv)88 int main(int argc, char **argv){
89   int i;
90   for(i=1; i<argc; i++) computeSigs(argv[i]);
91   return 0;
92 }
93