summaryrefslogtreecommitdiff
path: root/tool/showjournal.c
blob: 19220f5196af37b939c4c92f40574f28aa162f70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
** A utility for printing an SQLite database journal.
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

/*
** state information
*/
static int pageSize = 1024;
static int sectorSize = 512;
static FILE *db = 0;
static int fileSize = 0;
static unsigned cksumNonce = 0;

/* Report a memory allocation error */
static void out_of_memory(void){
  fprintf(stderr,"Out of memory...\n");
  exit(1);
}

/*
** Read N bytes of memory starting at iOfst into space obtained
** from malloc().
*/
static unsigned char *read_content(int N, int iOfst){
  int got;
  unsigned char *pBuf = malloc(N);
  if( pBuf==0 ) out_of_memory();
  fseek(db, iOfst, SEEK_SET);
  got = fread(pBuf, 1, N, db);
  if( got<0 ){
    fprintf(stderr, "I/O error reading %d bytes from %d\n", N, iOfst);
    memset(pBuf, 0, N);
  }else if( got<N ){
    fprintf(stderr, "Short read: got only %d of %d bytes from %d\n",
                     got, N, iOfst);
    memset(&pBuf[got], 0, N-got);
  }
  return pBuf;
}

/* Print a line of decode output showing a 4-byte integer.
*/
static unsigned print_decode_line(
  const unsigned char *aData,  /* Content being decoded */
  int ofst, int nByte,         /* Start and size of decode */
  const char *zMsg             /* Message to append */
){
  int i, j;
  unsigned val = aData[ofst];
  char zBuf[100];
  sprintf(zBuf, " %05x: %02x", ofst, aData[ofst]);
  i = strlen(zBuf);
  for(j=1; j<4; j++){
    if( j>=nByte ){
      sprintf(&zBuf[i], "   ");
    }else{
      sprintf(&zBuf[i], " %02x", aData[ofst+j]);
      val = val*256 + aData[ofst+j];
    }
    i += strlen(&zBuf[i]);
  }
  sprintf(&zBuf[i], "   %10u", val);
  printf("%s  %s\n", zBuf, zMsg);
  return val;
}

/*
** Read and print a journal header.  Store key information (page size, etc)
** in global variables.
*/
static unsigned decode_journal_header(int iOfst){
  unsigned char *pHdr = read_content(64, iOfst);
  unsigned nPage;
  printf("Header at offset %d:\n", iOfst);
  print_decode_line(pHdr, 0, 4, "Header part 1 (3654616569)");
  print_decode_line(pHdr, 4, 4, "Header part 2 (547447767)");
  nPage =
  print_decode_line(pHdr, 8, 4, "page count");
  cksumNonce =
  print_decode_line(pHdr, 12, 4, "chksum nonce");
  print_decode_line(pHdr, 16, 4, "initial database size in pages");
  sectorSize =
  print_decode_line(pHdr, 20, 4, "sector size");
  pageSize =
  print_decode_line(pHdr, 24, 4, "page size");
  print_decode_line(pHdr, 28, 4, "zero");
  print_decode_line(pHdr, 32, 4, "zero");
  print_decode_line(pHdr, 36, 4, "zero");
  print_decode_line(pHdr, 40, 4, "zero");
  free(pHdr);
  return nPage;
}

static void print_page(int iOfst){
  unsigned char *aData;
  char zTitle[50];
  aData = read_content(pageSize+8, iOfst);
  sprintf(zTitle, "page number for page at offset %d", iOfst);
  print_decode_line(aData-iOfst, iOfst, 4, zTitle);
  free(aData);
}

int main(int argc, char **argv){
  int nPage, cnt;
  int iOfst;
  if( argc!=2 ){
    fprintf(stderr,"Usage: %s FILENAME\n", argv[0]);
    exit(1);
  }
  db = fopen(argv[1], "rb");
  if( db==0 ){
    fprintf(stderr,"%s: can't open %s\n", argv[0], argv[1]);
    exit(1);
  }
  fseek(db, 0, SEEK_END);
  fileSize = ftell(db);
  printf("journal file size: %d bytes\n", fileSize);
  fseek(db, 0, SEEK_SET);
  iOfst = 0;
  while( iOfst<fileSize ){
    cnt = nPage = (int)decode_journal_header(iOfst);
    if( cnt==0 ){
      cnt = (fileSize - sectorSize)/(pageSize+8);
    }
    iOfst += sectorSize;
    while( cnt && iOfst<fileSize ){
      print_page(iOfst);
      iOfst += pageSize+8;
    }
    iOfst = (iOfst/sectorSize + 1)*sectorSize;
  }
  fclose(db);
  return 0;
}