Home | History | Annotate | Download | only in tool
      1 /*
      2 ** A utility for printing an SQLite database journal.
      3 */
      4 #include <stdio.h>
      5 #include <ctype.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 
      9 /*
     10 ** state information
     11 */
     12 static int pageSize = 1024;
     13 static int sectorSize = 512;
     14 static FILE *db = 0;
     15 static int showPageContent = 0;
     16 static int fileSize = 0;
     17 static unsigned cksumNonce = 0;
     18 
     19 /* Report a memory allocation error */
     20 static void out_of_memory(void){
     21   fprintf(stderr,"Out of memory...\n");
     22   exit(1);
     23 }
     24 
     25 /*
     26 ** Read N bytes of memory starting at iOfst into space obtained
     27 ** from malloc().
     28 */
     29 static char *read_content(int N, int iOfst){
     30   int got;
     31   char *pBuf = malloc(N);
     32   if( pBuf==0 ) out_of_memory();
     33   fseek(db, iOfst, SEEK_SET);
     34   got = fread(pBuf, 1, N, db);
     35   if( got<0 ){
     36     fprintf(stderr, "I/O error reading %d bytes from %d\n", N, iOfst);
     37     memset(pBuf, 0, N);
     38   }else if( got<N ){
     39     fprintf(stderr, "Short read: got only %d of %d bytes from %d\n",
     40                      got, N, iOfst);
     41     memset(&pBuf[got], 0, N-got);
     42   }
     43   return pBuf;
     44 }
     45 
     46 /* Print a line of decode output showing a 4-byte integer.
     47 */
     48 static unsigned print_decode_line(
     49   unsigned char *aData,      /* Content being decoded */
     50   int ofst, int nByte,       /* Start and size of decode */
     51   const char *zMsg           /* Message to append */
     52 ){
     53   int i, j;
     54   unsigned val = aData[ofst];
     55   char zBuf[100];
     56   sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
     57   i = strlen(zBuf);
     58   for(j=1; j<4; j++){
     59     if( j>=nByte ){
     60       sprintf(&zBuf[i], "   ");
     61     }else{
     62       sprintf(&zBuf[i], " %02x", aData[ofst+j]);
     63       val = val*256 + aData[ofst+j];
     64     }
     65     i += strlen(&zBuf[i]);
     66   }
     67   sprintf(&zBuf[i], "   %10u", val);
     68   printf("%s  %s\n", zBuf, zMsg);
     69   return val;
     70 }
     71 
     72 /*
     73 ** Read and print a journal header.  Store key information (page size, etc)
     74 ** in global variables.
     75 */
     76 static unsigned decode_journal_header(int iOfst){
     77   char *pHdr = read_content(64, iOfst);
     78   unsigned nPage;
     79   printf("Header at offset %d:\n", iOfst);
     80   print_decode_line(pHdr, 0, 4, "Header part 1 (3654616569)");
     81   print_decode_line(pHdr, 4, 4, "Header part 2 (547447767)");
     82   nPage =
     83   print_decode_line(pHdr, 8, 4, "page count");
     84   cksumNonce =
     85   print_decode_line(pHdr, 12, 4, "chksum nonce");
     86   print_decode_line(pHdr, 16, 4, "initial database size in pages");
     87   sectorSize =
     88   print_decode_line(pHdr, 20, 4, "sector size");
     89   pageSize =
     90   print_decode_line(pHdr, 24, 4, "page size");
     91   print_decode_line(pHdr, 28, 4, "zero");
     92   print_decode_line(pHdr, 32, 4, "zero");
     93   print_decode_line(pHdr, 36, 4, "zero");
     94   print_decode_line(pHdr, 40, 4, "zero");
     95   free(pHdr);
     96   return nPage;
     97 }
     98 
     99 static void print_page(int iOfst){
    100   unsigned char *aData;
    101   char zTitle[50];
    102   aData = read_content(pageSize+8, iOfst);
    103   sprintf(zTitle, "page number for page at offset %d", iOfst);
    104   print_decode_line(aData, 0, 4, zTitle);
    105   free(aData);
    106 }
    107 
    108 int main(int argc, char **argv){
    109   int rc;
    110   int nPage, cnt;
    111   int iOfst;
    112   if( argc!=2 ){
    113     fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
    114     exit(1);
    115   }
    116   db = fopen(argv[1], "rb");
    117   if( db==0 ){
    118     fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
    119     exit(1);
    120   }
    121   fseek(db, 0, SEEK_END);
    122   fileSize = ftell(db);
    123   printf("journal file size: %d bytes\n", fileSize);
    124   fseek(db, 0, SEEK_SET);
    125   iOfst = 0;
    126   while( iOfst<fileSize ){
    127     cnt = nPage = (int)decode_journal_header(iOfst);
    128     if( cnt==0 ){
    129       cnt = (fileSize - sectorSize)/(pageSize+8);
    130     }
    131     iOfst += sectorSize;
    132     while( cnt && iOfst<fileSize ){
    133       print_page(iOfst);
    134       iOfst += pageSize+8;
    135     }
    136     iOfst = (iOfst/sectorSize + 1)*sectorSize;
    137   }
    138   fclose(db);
    139 }
    140