pagesig.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. ** Compute signature for a block of content.
  23. **
  24. ** For blocks of 16 or fewer bytes, the signature is just a hex dump of
  25. ** the entire block.
  26. **
  27. ** For blocks of more than 16 bytes, the signature is a hex dump of the
  28. ** first 8 bytes followed by a 64-bit hash of the entire block.
  29. */
  30. static void vlogSignature(unsigned char *p, int n, char *zCksum){
  31. unsigned int s0 = 0, s1 = 0;
  32. unsigned int *pI;
  33. int i;
  34. if( n<=16 ){
  35. for(i=0; i<n; i++) sprintf(zCksum+i*2, "%02x", p[i]);
  36. }else{
  37. pI = (unsigned int*)p;
  38. for(i=0; i<n-7; i+=8){
  39. s0 += pI[0] + s1;
  40. s1 += pI[1] + s0;
  41. pI += 2;
  42. }
  43. for(i=0; i<8; i++) sprintf(zCksum+i*2, "%02x", p[i]);
  44. sprintf(zCksum+i*2, "-%08x%08x", s0, s1);
  45. }
  46. }
  47. /*
  48. ** Open a file. Find its page size. Read each page, and compute and
  49. ** display the page signature.
  50. */
  51. static void computeSigs(const char *zFilename){
  52. FILE *in = fopen(zFilename, "rb");
  53. unsigned pgsz;
  54. size_t got;
  55. unsigned n;
  56. unsigned char aBuf[50];
  57. unsigned char aPage[65536];
  58. if( in==0 ){
  59. fprintf(stderr, "cannot open \"%s\"\n", zFilename);
  60. return;
  61. }
  62. got = fread(aBuf, 1, sizeof(aBuf), in);
  63. if( got!=sizeof(aBuf) ){
  64. goto endComputeSigs;
  65. }
  66. pgsz = aBuf[16]*256 + aBuf[17];
  67. if( pgsz==1 ) pgsz = 65536;
  68. if( (pgsz & (pgsz-1))!=0 ){
  69. fprintf(stderr, "invalid page size: %02x%02x\n", aBuf[16], aBuf[17]);
  70. goto endComputeSigs;
  71. }
  72. rewind(in);
  73. for(n=1; (got=fread(aPage, 1, pgsz, in))==pgsz; n++){
  74. vlogSignature(aPage, pgsz, aBuf);
  75. printf("%4d: %s\n", n, aBuf);
  76. }
  77. endComputeSigs:
  78. fclose(in);
  79. }
  80. /*
  81. ** Find page signatures for all named files.
  82. */
  83. int main(int argc, char **argv){
  84. int i;
  85. for(i=1; i<argc; i++) computeSigs(argv[i]);
  86. return 0;
  87. }