93 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| ** 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;
 | |
| }
 | 
