drh | 7cd84ff | 2013-10-10 13:38:51 +0000 | [diff] [blame] | 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 | */ |
| 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]); |
drh | 919e3b3 | 2013-10-10 13:41:04 +0000 | [diff] [blame] | 45 | sprintf(zCksum+i*2, "-%08x%08x", s0, s1); |
drh | 7cd84ff | 2013-10-10 13:38:51 +0000 | [diff] [blame] | 46 | } |
| 47 | } |
| 48 | |
| 49 | /* |
| 50 | ** Open a file. Find its page size. Read each page, and compute and |
| 51 | ** display the page signature. |
| 52 | */ |
| 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 | */ |
| 88 | int main(int argc, char **argv){ |
| 89 | int i; |
| 90 | for(i=1; i<argc; i++) computeSigs(argv[i]); |
| 91 | return 0; |
| 92 | } |