xref: /sqlite-3.40.0/tool/showdb.c (revision dfe4e6bb)
1 /*
2 ** A utility for printing all or part of an SQLite database file.
3 */
4 #include <stdio.h>
5 #include <ctype.h>
6 #define ISDIGIT(X) isdigit((unsigned char)(X))
7 #define ISPRINT(X) isprint((unsigned char)(X))
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 
12 #if !defined(_MSC_VER)
13 #include <unistd.h>
14 #else
15 #include <io.h>
16 #endif
17 
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21 #include "sqlite3.h"
22 
23 
24 static struct GlobalData {
25   int pagesize;                   /* Size of a database page */
26   int dbfd;                       /* File descriptor for reading the DB */
27   int mxPage;                     /* Last page number */
28   int perLine;                    /* HEX elements to print per line */
29   int bRaw;                       /* True to access db file via OS APIs */
30   sqlite3_file *pFd;              /* File descriptor for non-raw mode */
31   sqlite3 *pDb;                   /* Database handle that owns pFd */
32 } g = {1024, -1, 0, 16,   0, 0, 0};
33 
34 
35 typedef long long int i64;      /* Datatype for 64-bit integers */
36 
37 
38 /*
39 ** Convert the var-int format into i64.  Return the number of bytes
40 ** in the var-int.  Write the var-int value into *pVal.
41 */
42 static int decodeVarint(const unsigned char *z, i64 *pVal){
43   i64 v = 0;
44   int i;
45   for(i=0; i<8; i++){
46     v = (v<<7) + (z[i]&0x7f);
47     if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
48   }
49   v = (v<<8) + (z[i]&0xff);
50   *pVal = v;
51   return 9;
52 }
53 
54 /*
55 ** Extract a big-endian 32-bit integer
56 */
57 static unsigned int decodeInt32(const unsigned char *z){
58   return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3];
59 }
60 
61 /* Report an out-of-memory error and die.
62 */
63 static void out_of_memory(void){
64   fprintf(stderr,"Out of memory...\n");
65   exit(1);
66 }
67 
68 /*
69 ** Open a database connection.
70 */
71 static sqlite3 *openDatabase(const char *zPrg, const char *zName){
72   sqlite3 *db = 0;
73   int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI;
74   int rc = sqlite3_open_v2(zName, &db, flags, 0);
75   if( rc!=SQLITE_OK ){
76     const char *zErr = sqlite3_errmsg(db);
77     fprintf(stderr, "%s: can't open %s (%s)\n", zPrg, zName, zErr);
78     sqlite3_close(db);
79     exit(1);
80   }
81   return db;
82 }
83 
84 /**************************************************************************
85 ** Beginning of low-level file access functions.
86 **
87 ** All low-level access to the database file read by this program is
88 ** performed using the following four functions:
89 **
90 **   fileOpen()     - open the db file
91 **   fileClose()    - close the db file
92 **   fileRead()     - read raw data from the db file
93 **   fileGetsize()  - return the size of the db file in bytes
94 */
95 
96 /*
97 ** Open the database file.
98 */
99 static void fileOpen(const char *zPrg, const char *zName){
100   assert( g.dbfd<0 );
101   if( g.bRaw==0 ){
102     int rc;
103     void *pArg = (void *)(&g.pFd);
104     g.pDb = openDatabase(zPrg, zName);
105     rc = sqlite3_file_control(g.pDb, "main", SQLITE_FCNTL_FILE_POINTER, pArg);
106     if( rc!=SQLITE_OK ){
107       fprintf(stderr,
108           "%s: failed to obtain fd for %s (SQLite too old?)\n", zPrg, zName
109       );
110       exit(1);
111     }
112   }else{
113     g.dbfd = open(zName, O_RDONLY);
114     if( g.dbfd<0 ){
115       fprintf(stderr,"%s: can't open %s\n", zPrg, zName);
116       exit(1);
117     }
118   }
119 }
120 
121 /*
122 ** Close the database file opened by fileOpen()
123 */
124 static void fileClose(){
125   if( g.bRaw==0 ){
126     sqlite3_close(g.pDb);
127     g.pDb = 0;
128     g.pFd = 0;
129   }else{
130     close(g.dbfd);
131     g.dbfd = -1;
132   }
133 }
134 
135 /*
136 ** Read content from the file.
137 **
138 ** Space to hold the content is obtained from sqlite3_malloc() and needs
139 ** to be freed by the caller.
140 */
141 static unsigned char *fileRead(sqlite3_int64 ofst, int nByte){
142   unsigned char *aData;
143   int got;
144   aData = sqlite3_malloc(nByte+32);
145   if( aData==0 ) out_of_memory();
146   memset(aData, 0, nByte+32);
147   if( g.bRaw==0 ){
148     int rc = g.pFd->pMethods->xRead(g.pFd, (void*)aData, nByte, ofst);
149     if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
150       fprintf(stderr, "error in xRead() - %d\n", rc);
151       exit(1);
152     }
153   }else{
154     lseek(g.dbfd, (long)ofst, SEEK_SET);
155     got = read(g.dbfd, aData, nByte);
156     if( got>0 && got<nByte ) memset(aData+got, 0, nByte-got);
157   }
158   return aData;
159 }
160 
161 /*
162 ** Return the size of the file in byte.
163 */
164 static sqlite3_int64 fileGetsize(void){
165   sqlite3_int64 res = 0;
166   if( g.bRaw==0 ){
167     int rc = g.pFd->pMethods->xFileSize(g.pFd, &res);
168     if( rc!=SQLITE_OK ){
169       fprintf(stderr, "error in xFileSize() - %d\n", rc);
170       exit(1);
171     }
172   }else{
173     struct stat sbuf;
174     fstat(g.dbfd, &sbuf);
175     res = (sqlite3_int64)(sbuf.st_size);
176   }
177   return res;
178 }
179 
180 /*
181 ** End of low-level file access functions.
182 **************************************************************************/
183 
184 /*
185 ** Print a range of bytes as hex and as ascii.
186 */
187 static unsigned char *print_byte_range(
188   int ofst,          /* First byte in the range of bytes to print */
189   int nByte,         /* Number of bytes to print */
190   int printOfst      /* Add this amount to the index on the left column */
191 ){
192   unsigned char *aData;
193   int i, j;
194   const char *zOfstFmt;
195 
196   if( ((printOfst+nByte)&~0xfff)==0 ){
197     zOfstFmt = " %03x: ";
198   }else if( ((printOfst+nByte)&~0xffff)==0 ){
199     zOfstFmt = " %04x: ";
200   }else if( ((printOfst+nByte)&~0xfffff)==0 ){
201     zOfstFmt = " %05x: ";
202   }else if( ((printOfst+nByte)&~0xffffff)==0 ){
203     zOfstFmt = " %06x: ";
204   }else{
205     zOfstFmt = " %08x: ";
206   }
207 
208   aData = fileRead(ofst, nByte);
209   for(i=0; i<nByte; i += g.perLine){
210     fprintf(stdout, zOfstFmt, i+printOfst);
211     for(j=0; j<g.perLine; j++){
212       if( i+j>nByte ){
213         fprintf(stdout, "   ");
214       }else{
215         fprintf(stdout,"%02x ", aData[i+j]);
216       }
217     }
218     for(j=0; j<g.perLine; j++){
219       if( i+j>nByte ){
220         fprintf(stdout, " ");
221       }else{
222         fprintf(stdout,"%c", ISPRINT(aData[i+j]) ? aData[i+j] : '.');
223       }
224     }
225     fprintf(stdout,"\n");
226   }
227   return aData;
228 }
229 
230 /*
231 ** Print an entire page of content as hex
232 */
233 static void print_page(int iPg){
234   int iStart;
235   unsigned char *aData;
236   iStart = (iPg-1)*g.pagesize;
237   fprintf(stdout, "Page %d:   (offsets 0x%x..0x%x)\n",
238           iPg, iStart, iStart+g.pagesize-1);
239   aData = print_byte_range(iStart, g.pagesize, 0);
240   sqlite3_free(aData);
241 }
242 
243 
244 /* Print a line of decode output showing a 4-byte integer.
245 */
246 static void print_decode_line(
247   unsigned char *aData,      /* Content being decoded */
248   int ofst, int nByte,       /* Start and size of decode */
249   const char *zMsg           /* Message to append */
250 ){
251   int i, j;
252   int val = aData[ofst];
253   char zBuf[100];
254   sprintf(zBuf, " %03x: %02x", ofst, aData[ofst]);
255   i = (int)strlen(zBuf);
256   for(j=1; j<4; j++){
257     if( j>=nByte ){
258       sprintf(&zBuf[i], "   ");
259     }else{
260       sprintf(&zBuf[i], " %02x", aData[ofst+j]);
261       val = val*256 + aData[ofst+j];
262     }
263     i += (int)strlen(&zBuf[i]);
264   }
265   sprintf(&zBuf[i], "   %9d", val);
266   printf("%s  %s\n", zBuf, zMsg);
267 }
268 
269 /*
270 ** Decode the database header.
271 */
272 static void print_db_header(void){
273   unsigned char *aData;
274   aData = print_byte_range(0, 100, 0);
275   printf("Decoded:\n");
276   print_decode_line(aData, 16, 2, "Database page size");
277   print_decode_line(aData, 18, 1, "File format write version");
278   print_decode_line(aData, 19, 1, "File format read version");
279   print_decode_line(aData, 20, 1, "Reserved space at end of page");
280   print_decode_line(aData, 24, 4, "File change counter");
281   print_decode_line(aData, 28, 4, "Size of database in pages");
282   print_decode_line(aData, 32, 4, "Page number of first freelist page");
283   print_decode_line(aData, 36, 4, "Number of freelist pages");
284   print_decode_line(aData, 40, 4, "Schema cookie");
285   print_decode_line(aData, 44, 4, "Schema format version");
286   print_decode_line(aData, 48, 4, "Default page cache size");
287   print_decode_line(aData, 52, 4, "Largest auto-vac root page");
288   print_decode_line(aData, 56, 4, "Text encoding");
289   print_decode_line(aData, 60, 4, "User version");
290   print_decode_line(aData, 64, 4, "Incremental-vacuum mode");
291   print_decode_line(aData, 68, 4, "Application ID");
292   print_decode_line(aData, 72, 4, "meta[8]");
293   print_decode_line(aData, 76, 4, "meta[9]");
294   print_decode_line(aData, 80, 4, "meta[10]");
295   print_decode_line(aData, 84, 4, "meta[11]");
296   print_decode_line(aData, 88, 4, "meta[12]");
297   print_decode_line(aData, 92, 4, "Change counter for version number");
298   print_decode_line(aData, 96, 4, "SQLite version number");
299 }
300 
301 /*
302 ** Describe cell content.
303 */
304 static i64 describeContent(
305   unsigned char *a,       /* Cell content */
306   i64 nLocal,             /* Bytes in a[] */
307   char *zDesc             /* Write description here */
308 ){
309   i64 nDesc = 0;
310   int n, j;
311   i64 i, x, v;
312   const unsigned char *pData;
313   const unsigned char *pLimit;
314   char sep = ' ';
315 
316   pLimit = &a[nLocal];
317   n = decodeVarint(a, &x);
318   pData = &a[x];
319   a += n;
320   i = x - n;
321   while( i>0 && pData<=pLimit ){
322     n = decodeVarint(a, &x);
323     a += n;
324     i -= n;
325     nLocal -= n;
326     zDesc[0] = sep;
327     sep = ',';
328     nDesc++;
329     zDesc++;
330     if( x==0 ){
331       sprintf(zDesc, "*");     /* NULL is a "*" */
332     }else if( x>=1 && x<=6 ){
333       v = (signed char)pData[0];
334       pData++;
335       switch( x ){
336         case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
337         case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
338         case 4:  v = (v<<8) + pData[0];  pData++;
339         case 3:  v = (v<<8) + pData[0];  pData++;
340         case 2:  v = (v<<8) + pData[0];  pData++;
341       }
342       sprintf(zDesc, "%lld", v);
343     }else if( x==7 ){
344       sprintf(zDesc, "real");
345       pData += 8;
346     }else if( x==8 ){
347       sprintf(zDesc, "0");
348     }else if( x==9 ){
349       sprintf(zDesc, "1");
350     }else if( x>=12 ){
351       i64 size = (x-12)/2;
352       if( (x&1)==0 ){
353         sprintf(zDesc, "blob(%lld)", size);
354       }else{
355         sprintf(zDesc, "txt(%lld)", size);
356       }
357       pData += size;
358     }
359     j = (int)strlen(zDesc);
360     zDesc += j;
361     nDesc += j;
362   }
363   return nDesc;
364 }
365 
366 /*
367 ** Compute the local payload size given the total payload size and
368 ** the page size.
369 */
370 static i64 localPayload(i64 nPayload, char cType){
371   i64 maxLocal;
372   i64 minLocal;
373   i64 surplus;
374   i64 nLocal;
375   if( cType==13 ){
376     /* Table leaf */
377     maxLocal = g.pagesize-35;
378     minLocal = (g.pagesize-12)*32/255-23;
379   }else{
380     maxLocal = (g.pagesize-12)*64/255-23;
381     minLocal = (g.pagesize-12)*32/255-23;
382   }
383   if( nPayload>maxLocal ){
384     surplus = minLocal + (nPayload-minLocal)%(g.pagesize-4);
385     if( surplus<=maxLocal ){
386       nLocal = surplus;
387     }else{
388       nLocal = minLocal;
389     }
390   }else{
391     nLocal = nPayload;
392   }
393   return nLocal;
394 }
395 
396 
397 /*
398 ** Create a description for a single cell.
399 **
400 ** The return value is the local cell size.
401 */
402 static i64 describeCell(
403   unsigned char cType,    /* Page type */
404   unsigned char *a,       /* Cell content */
405   int showCellContent,    /* Show cell content if true */
406   char **pzDesc           /* Store description here */
407 ){
408   int i;
409   i64 nDesc = 0;
410   int n = 0;
411   int leftChild;
412   i64 nPayload;
413   i64 rowid;
414   i64 nLocal;
415   static char zDesc[1000];
416   i = 0;
417   if( cType<=5 ){
418     leftChild = ((a[0]*256 + a[1])*256 + a[2])*256 + a[3];
419     a += 4;
420     n += 4;
421     sprintf(zDesc, "lx: %d ", leftChild);
422     nDesc = strlen(zDesc);
423   }
424   if( cType!=5 ){
425     i = decodeVarint(a, &nPayload);
426     a += i;
427     n += i;
428     sprintf(&zDesc[nDesc], "n: %lld ", nPayload);
429     nDesc += strlen(&zDesc[nDesc]);
430     nLocal = localPayload(nPayload, cType);
431   }else{
432     nPayload = nLocal = 0;
433   }
434   if( cType==5 || cType==13 ){
435     i = decodeVarint(a, &rowid);
436     a += i;
437     n += i;
438     sprintf(&zDesc[nDesc], "r: %lld ", rowid);
439     nDesc += strlen(&zDesc[nDesc]);
440   }
441   if( nLocal<nPayload ){
442     int ovfl;
443     unsigned char *b = &a[nLocal];
444     ovfl = ((b[0]*256 + b[1])*256 + b[2])*256 + b[3];
445     sprintf(&zDesc[nDesc], "ov: %d ", ovfl);
446     nDesc += strlen(&zDesc[nDesc]);
447     n += 4;
448   }
449   if( showCellContent && cType!=5 ){
450     nDesc += describeContent(a, nLocal, &zDesc[nDesc-1]);
451   }
452   *pzDesc = zDesc;
453   return nLocal+n;
454 }
455 
456 /* Print an offset followed by nByte bytes.  Add extra white-space
457 ** at the end so that subsequent text is aligned.
458 */
459 static void printBytes(
460   unsigned char *aData,      /* Content being decoded */
461   unsigned char *aStart,     /* Start of content to be printed */
462   int nByte                  /* Number of bytes to print */
463 ){
464   int j;
465   printf(" %03x: ", (int)(aStart-aData));
466   for(j=0; j<9; j++){
467     if( j>=nByte ){
468       printf("   ");
469     }else{
470       printf("%02x ", aStart[j]);
471     }
472   }
473 }
474 
475 
476 /*
477 ** Write a full decode on stdout for the cell at a[ofst].
478 ** Assume the page contains a header of size szPgHdr bytes.
479 */
480 static void decodeCell(
481   unsigned char *a,       /* Page content (without the page-1 header) */
482   unsigned pgno,          /* Page number */
483   int iCell,              /* Cell index */
484   int szPgHdr,            /* Size of the page header.  0 or 100 */
485   int ofst                /* Cell begins at a[ofst] */
486 ){
487   int i, j = 0;
488   int leftChild;
489   i64 k;
490   i64 nPayload;
491   i64 rowid;
492   i64 nHdr;
493   i64 iType;
494   i64 nLocal;
495   unsigned char *x = a + ofst;
496   unsigned char *end;
497   unsigned char cType = a[0];
498   int nCol = 0;
499   int szCol[2000];
500   int ofstCol[2000];
501   int typeCol[2000];
502 
503   printf("Cell[%d]:\n", iCell);
504   if( cType<=5 ){
505     leftChild = ((x[0]*256 + x[1])*256 + x[2])*256 + x[3];
506     printBytes(a, x, 4);
507     printf("left child page:: %d\n", leftChild);
508     x += 4;
509   }
510   if( cType!=5 ){
511     i = decodeVarint(x, &nPayload);
512     printBytes(a, x, i);
513     nLocal = localPayload(nPayload, cType);
514     if( nLocal==nPayload ){
515       printf("payload-size: %lld\n", nPayload);
516     }else{
517       printf("payload-size: %lld (%lld local, %lld overflow)\n",
518              nPayload, nLocal, nPayload-nLocal);
519     }
520     x += i;
521   }else{
522     nPayload = nLocal = 0;
523   }
524   end = x + nLocal;
525   if( cType==5 || cType==13 ){
526     i = decodeVarint(x, &rowid);
527     printBytes(a, x, i);
528     printf("rowid: %lld\n", rowid);
529     x += i;
530   }
531   if( nLocal>0 ){
532     i = decodeVarint(x, &nHdr);
533     printBytes(a, x, i);
534     printf("record-header-size: %d\n", (int)nHdr);
535     j = i;
536     nCol = 0;
537     k = nHdr;
538     while( x+j<end && j<nHdr ){
539        const char *zTypeName;
540        int sz = 0;
541        char zNm[30];
542        i = decodeVarint(x+j, &iType);
543        printBytes(a, x+j, i);
544        printf("typecode[%d]: %d - ", nCol, (int)iType);
545        switch( iType ){
546          case 0:  zTypeName = "NULL";    sz = 0;  break;
547          case 1:  zTypeName = "int8";    sz = 1;  break;
548          case 2:  zTypeName = "int16";   sz = 2;  break;
549          case 3:  zTypeName = "int24";   sz = 3;  break;
550          case 4:  zTypeName = "int32";   sz = 4;  break;
551          case 5:  zTypeName = "int48";   sz = 6;  break;
552          case 6:  zTypeName = "int64";   sz = 8;  break;
553          case 7:  zTypeName = "double";  sz = 8;  break;
554          case 8:  zTypeName = "zero";    sz = 0;  break;
555          case 9:  zTypeName = "one";     sz = 0;  break;
556          case 10:
557          case 11: zTypeName = "error";   sz = 0;  break;
558          default: {
559            sz = (int)(iType-12)/2;
560            sprintf(zNm, (iType&1)==0 ? "blob(%d)" : "text(%d)", sz);
561            zTypeName = zNm;
562            break;
563          }
564        }
565        printf("%s\n", zTypeName);
566        szCol[nCol] = sz;
567        ofstCol[nCol] = (int)k;
568        typeCol[nCol] = (int)iType;
569        k += sz;
570        nCol++;
571        j += i;
572     }
573     for(i=0; i<nCol && ofstCol[i]+szCol[i]<=nLocal; i++){
574        int s = ofstCol[i];
575        i64 v;
576        const unsigned char *pData;
577        if( szCol[i]==0 ) continue;
578        printBytes(a, x+s, szCol[i]);
579        printf("data[%d]: ", i);
580        pData = x+s;
581        if( typeCol[i]<=7 ){
582          v = (signed char)pData[0];
583          for(k=1; k<szCol[i]; k++){
584            v = (v<<8) + pData[k];
585          }
586          if( typeCol[i]==7 ){
587            double r;
588            memcpy(&r, &v, sizeof(r));
589            printf("%#g\n", r);
590          }else{
591            printf("%lld\n", v);
592          }
593        }else{
594          int ii, jj;
595          char zConst[32];
596          if( (typeCol[i]&1)==0 ){
597            zConst[0] = 'x';
598            zConst[1] = '\'';
599            for(ii=2, jj=0; jj<szCol[i] && ii<24; jj++, ii+=2){
600              sprintf(zConst+ii, "%02x", pData[jj]);
601            }
602          }else{
603            zConst[0] = '\'';
604            for(ii=1, jj=0; jj<szCol[i] && ii<24; jj++, ii++){
605              zConst[ii] = ISPRINT(pData[jj]) ? pData[jj] : '.';
606            }
607            zConst[ii] = 0;
608          }
609          if( jj<szCol[i] ){
610            memcpy(zConst+ii, "...'", 5);
611          }else{
612            memcpy(zConst+ii, "'", 2);
613          }
614          printf("%s\n", zConst);
615        }
616        j = ofstCol[i] + szCol[i];
617     }
618   }
619   if( j<nLocal ){
620     printBytes(a, x+j, 0);
621     printf("... %lld bytes of content ...\n", nLocal-j);
622   }
623   if( nLocal<nPayload ){
624     printBytes(a, x+nLocal, 4);
625     printf("overflow-page: %d\n", decodeInt32(x+nLocal));
626   }
627 }
628 
629 
630 /*
631 ** Decode a btree page
632 */
633 static void decode_btree_page(
634   unsigned char *a,   /* Page content */
635   int pgno,           /* Page number */
636   int hdrSize,        /* Size of the page header.  0 or 100 */
637   char *zArgs         /* Flags to control formatting */
638 ){
639   const char *zType = "unknown";
640   int nCell;
641   int i, j;
642   int iCellPtr;
643   int showCellContent = 0;
644   int showMap = 0;
645   int cellToDecode = -2;
646   char *zMap = 0;
647   switch( a[0] ){
648     case 2:  zType = "index interior node";  break;
649     case 5:  zType = "table interior node";  break;
650     case 10: zType = "index leaf";           break;
651     case 13: zType = "table leaf";           break;
652   }
653   while( zArgs[0] ){
654     switch( zArgs[0] ){
655       case 'c': showCellContent = 1;  break;
656       case 'm': showMap = 1;          break;
657       case 'd': {
658         if( !ISDIGIT(zArgs[1]) ){
659           cellToDecode = -1;
660         }else{
661           cellToDecode = 0;
662           while( ISDIGIT(zArgs[1]) ){
663             zArgs++;
664             cellToDecode = cellToDecode*10 + zArgs[0] - '0';
665           }
666         }
667         break;
668       }
669     }
670     zArgs++;
671   }
672   nCell = a[3]*256 + a[4];
673   iCellPtr = (a[0]==2 || a[0]==5) ? 12 : 8;
674   if( cellToDecode>=nCell ){
675     printf("Page %d has only %d cells\n", pgno, nCell);
676     return;
677   }
678   printf("Header on btree page %d:\n", pgno);
679   print_decode_line(a, 0, 1, zType);
680   print_decode_line(a, 1, 2, "Offset to first freeblock");
681   print_decode_line(a, 3, 2, "Number of cells on this page");
682   print_decode_line(a, 5, 2, "Offset to cell content area");
683   print_decode_line(a, 7, 1, "Fragmented byte count");
684   if( a[0]==2 || a[0]==5 ){
685     print_decode_line(a, 8, 4, "Right child");
686   }
687   if( cellToDecode==(-2) && nCell>0 ){
688     printf(" key: lx=left-child n=payload-size r=rowid\n");
689   }
690   if( showMap ){
691     zMap = sqlite3_malloc(g.pagesize);
692     memset(zMap, '.', g.pagesize);
693     memset(zMap, '1', hdrSize);
694     memset(&zMap[hdrSize], 'H', iCellPtr);
695     memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell);
696   }
697   for(i=0; i<nCell; i++){
698     int cofst = iCellPtr + i*2;
699     char *zDesc;
700     i64 n;
701 
702     cofst = a[cofst]*256 + a[cofst+1];
703     n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc);
704     if( showMap ){
705       char zBuf[30];
706       memset(&zMap[cofst], '*', (size_t)n);
707       zMap[cofst] = '[';
708       zMap[cofst+n-1] = ']';
709       sprintf(zBuf, "%d", i);
710       j = (int)strlen(zBuf);
711       if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j);
712     }
713     if( cellToDecode==(-2) ){
714       printf(" %03x: cell[%d] %s\n", cofst, i, zDesc);
715     }else if( cellToDecode==(-1) || cellToDecode==i ){
716       decodeCell(a, pgno, i, hdrSize, cofst-hdrSize);
717     }
718   }
719   if( showMap ){
720     printf("Page map:  (H=header P=cell-index 1=page-1-header .=free-space)\n");
721     for(i=0; i<g.pagesize; i+=64){
722       printf(" %03x: %.64s\n", i, &zMap[i]);
723     }
724     sqlite3_free(zMap);
725   }
726 }
727 
728 /*
729 ** Decode a freelist trunk page.
730 */
731 static void decode_trunk_page(
732   int pgno,             /* The page number */
733   int detail,           /* Show leaf pages if true */
734   int recursive         /* Follow the trunk change if true */
735 ){
736   int n, i;
737   unsigned char *a;
738   while( pgno>0 ){
739     a = fileRead((pgno-1)*g.pagesize, g.pagesize);
740     printf("Decode of freelist trunk page %d:\n", pgno);
741     print_decode_line(a, 0, 4, "Next freelist trunk page");
742     print_decode_line(a, 4, 4, "Number of entries on this page");
743     if( detail ){
744       n = (int)decodeInt32(&a[4]);
745       for(i=0; i<n; i++){
746         unsigned int x = decodeInt32(&a[8+4*i]);
747         char zIdx[10];
748         sprintf(zIdx, "[%d]", i);
749         printf("  %5s %7u", zIdx, x);
750         if( i%5==4 ) printf("\n");
751       }
752       if( i%5!=0 ) printf("\n");
753     }
754     if( !recursive ){
755       pgno = 0;
756     }else{
757       pgno = (int)decodeInt32(&a[0]);
758     }
759     sqlite3_free(a);
760   }
761 }
762 
763 /*
764 ** A short text comment on the use of each page.
765 */
766 static char **zPageUse;
767 
768 /*
769 ** Add a comment on the use of a page.
770 */
771 static void page_usage_msg(int pgno, const char *zFormat, ...){
772   va_list ap;
773   char *zMsg;
774 
775   va_start(ap, zFormat);
776   zMsg = sqlite3_vmprintf(zFormat, ap);
777   va_end(ap);
778   if( pgno<=0 || pgno>g.mxPage ){
779     printf("ERROR: page %d out of range 1..%d: %s\n",
780             pgno, g.mxPage, zMsg);
781     sqlite3_free(zMsg);
782     return;
783   }
784   if( zPageUse[pgno]!=0 ){
785     printf("ERROR: page %d used multiple times:\n", pgno);
786     printf("ERROR:    previous: %s\n", zPageUse[pgno]);
787     printf("ERROR:    current:  %s\n", zMsg);
788     sqlite3_free(zPageUse[pgno]);
789   }
790   zPageUse[pgno] = zMsg;
791 }
792 
793 /*
794 ** Find overflow pages of a cell and describe their usage.
795 */
796 static void page_usage_cell(
797   unsigned char cType,    /* Page type */
798   unsigned char *a,       /* Cell content */
799   int pgno,               /* page containing the cell */
800   int cellno              /* Index of the cell on the page */
801 ){
802   int i;
803   int n = 0;
804   i64 nPayload;
805   i64 rowid;
806   i64 nLocal;
807   i = 0;
808   if( cType<=5 ){
809     a += 4;
810     n += 4;
811   }
812   if( cType!=5 ){
813     i = decodeVarint(a, &nPayload);
814     a += i;
815     n += i;
816     nLocal = localPayload(nPayload, cType);
817   }else{
818     nPayload = nLocal = 0;
819   }
820   if( cType==5 || cType==13 ){
821     i = decodeVarint(a, &rowid);
822     a += i;
823     n += i;
824   }
825   if( nLocal<nPayload ){
826     int ovfl = decodeInt32(a+nLocal);
827     int cnt = 0;
828     while( ovfl && (cnt++)<g.mxPage ){
829       page_usage_msg(ovfl, "overflow %d from cell %d of page %d",
830                      cnt, cellno, pgno);
831       a = fileRead((ovfl-1)*g.pagesize, 4);
832       ovfl = decodeInt32(a);
833       sqlite3_free(a);
834     }
835   }
836 }
837 
838 
839 /*
840 ** Describe the usages of a b-tree page
841 */
842 static void page_usage_btree(
843   int pgno,             /* Page to describe */
844   int parent,           /* Parent of this page.  0 for root pages */
845   int idx,              /* Which child of the parent */
846   const char *zName     /* Name of the table */
847 ){
848   unsigned char *a;
849   const char *zType = "corrupt node";
850   int nCell;
851   int i;
852   int hdr = pgno==1 ? 100 : 0;
853 
854   if( pgno<=0 || pgno>g.mxPage ) return;
855   a = fileRead((pgno-1)*g.pagesize, g.pagesize);
856   switch( a[hdr] ){
857     case 2:  zType = "interior node of index";  break;
858     case 5:  zType = "interior node of table";  break;
859     case 10: zType = "leaf of index";           break;
860     case 13: zType = "leaf of table";           break;
861   }
862   if( parent ){
863     page_usage_msg(pgno, "%s [%s], child %d of page %d",
864                    zType, zName, idx, parent);
865   }else{
866     page_usage_msg(pgno, "root %s [%s]", zType, zName);
867   }
868   nCell = a[hdr+3]*256 + a[hdr+4];
869   if( a[hdr]==2 || a[hdr]==5 ){
870     int cellstart = hdr+12;
871     unsigned int child;
872     for(i=0; i<nCell; i++){
873       int ofst;
874 
875       ofst = cellstart + i*2;
876       ofst = a[ofst]*256 + a[ofst+1];
877       child = decodeInt32(a+ofst);
878       page_usage_btree(child, pgno, i, zName);
879     }
880     child = decodeInt32(a+cellstart-4);
881     page_usage_btree(child, pgno, i, zName);
882   }
883   if( a[hdr]==2 || a[hdr]==10 || a[hdr]==13 ){
884     int cellstart = hdr + 8 + 4*(a[hdr]<=5);
885     for(i=0; i<nCell; i++){
886       int ofst;
887       ofst = cellstart + i*2;
888       ofst = a[ofst]*256 + a[ofst+1];
889       page_usage_cell(a[hdr], a+ofst, pgno, i);
890     }
891   }
892   sqlite3_free(a);
893 }
894 
895 /*
896 ** Determine page usage by the freelist
897 */
898 static void page_usage_freelist(int pgno){
899   unsigned char *a;
900   int cnt = 0;
901   int i;
902   int n;
903   int iNext;
904   int parent = 1;
905 
906   while( pgno>0 && pgno<=g.mxPage && (cnt++)<g.mxPage ){
907     page_usage_msg(pgno, "freelist trunk #%d child of %d", cnt, parent);
908     a = fileRead((pgno-1)*g.pagesize, g.pagesize);
909     iNext = decodeInt32(a);
910     n = decodeInt32(a+4);
911     for(i=0; i<n; i++){
912       int child = decodeInt32(a + (i*4+8));
913       page_usage_msg(child, "freelist leaf, child %d of trunk page %d",
914                      i, pgno);
915     }
916     sqlite3_free(a);
917     parent = pgno;
918     pgno = iNext;
919   }
920 }
921 
922 /*
923 ** Determine pages used as PTRMAP pages
924 */
925 static void page_usage_ptrmap(unsigned char *a){
926   if( a[55] ){
927     int usable = g.pagesize - a[20];
928     int pgno = 2;
929     int perPage = usable/5;
930     while( pgno<=g.mxPage ){
931       page_usage_msg(pgno, "PTRMAP page covering %d..%d",
932                            pgno+1, pgno+perPage);
933       pgno += perPage + 1;
934     }
935   }
936 }
937 
938 /*
939 ** Try to figure out how every page in the database file is being used.
940 */
941 static void page_usage_report(const char *zPrg, const char *zDbName){
942   int i, j;
943   int rc;
944   sqlite3 *db;
945   sqlite3_stmt *pStmt;
946   unsigned char *a;
947   char zQuery[200];
948 
949   /* Avoid the pathological case */
950   if( g.mxPage<1 ){
951     printf("empty database\n");
952     return;
953   }
954 
955   /* Open the database file */
956   db = openDatabase(zPrg, zDbName);
957 
958   /* Set up global variables zPageUse[] and g.mxPage to record page
959   ** usages */
960   zPageUse = sqlite3_malloc( sizeof(zPageUse[0])*(g.mxPage+1) );
961   if( zPageUse==0 ) out_of_memory();
962   memset(zPageUse, 0, sizeof(zPageUse[0])*(g.mxPage+1));
963 
964   /* Discover the usage of each page */
965   a = fileRead(0, 100);
966   page_usage_freelist(decodeInt32(a+32));
967   page_usage_ptrmap(a);
968   sqlite3_free(a);
969   page_usage_btree(1, 0, 0, "sqlite_master");
970   sqlite3_exec(db, "PRAGMA writable_schema=ON", 0, 0, 0);
971   for(j=0; j<2; j++){
972     sqlite3_snprintf(sizeof(zQuery), zQuery,
973              "SELECT type, name, rootpage FROM SQLITE_MASTER WHERE rootpage"
974              " ORDER BY rowid %s", j?"DESC":"");
975     rc = sqlite3_prepare_v2(db, zQuery, -1, &pStmt, 0);
976     if( rc==SQLITE_OK ){
977       while( sqlite3_step(pStmt)==SQLITE_ROW ){
978         int pgno = sqlite3_column_int(pStmt, 2);
979         page_usage_btree(pgno, 0, 0, (const char*)sqlite3_column_text(pStmt,1));
980       }
981     }else{
982       printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
983     }
984     rc = sqlite3_finalize(pStmt);
985     if( rc==SQLITE_OK ) break;
986   }
987   sqlite3_close(db);
988 
989   /* Print the report and free memory used */
990   for(i=1; i<=g.mxPage; i++){
991     printf("%5d: %s\n", i, zPageUse[i] ? zPageUse[i] : "???");
992     sqlite3_free(zPageUse[i]);
993   }
994   sqlite3_free(zPageUse);
995   zPageUse = 0;
996 }
997 
998 /*
999 ** Try to figure out how every page in the database file is being used.
1000 */
1001 static void ptrmap_coverage_report(const char *zDbName){
1002   int pgno;
1003   unsigned char *aHdr;
1004   unsigned char *a;
1005   int usable;
1006   int perPage;
1007   int i;
1008 
1009   /* Avoid the pathological case */
1010   if( g.mxPage<1 ){
1011     printf("empty database\n");
1012     return;
1013   }
1014 
1015   /* Make sure PTRMAPs are used in this database */
1016   aHdr = fileRead(0, 100);
1017   if( aHdr[55]==0 ){
1018     printf("database does not use PTRMAP pages\n");
1019     return;
1020   }
1021   usable = g.pagesize - aHdr[20];
1022   perPage = usable/5;
1023   sqlite3_free(aHdr);
1024   printf("%5d: root of sqlite_master\n", 1);
1025   for(pgno=2; pgno<=g.mxPage; pgno += perPage+1){
1026     printf("%5d: PTRMAP page covering %d..%d\n", pgno,
1027            pgno+1, pgno+perPage);
1028     a = fileRead((pgno-1)*g.pagesize, usable);
1029     for(i=0; i+5<=usable && pgno+1+i/5<=g.mxPage; i+=5){
1030       const char *zType = "???";
1031       unsigned int iFrom = decodeInt32(&a[i+1]);
1032       switch( a[i] ){
1033         case 1:  zType = "b-tree root page";        break;
1034         case 2:  zType = "freelist page";           break;
1035         case 3:  zType = "first page of overflow";  break;
1036         case 4:  zType = "later page of overflow";  break;
1037         case 5:  zType = "b-tree non-root page";    break;
1038       }
1039       printf("%5d: %s, parent=%u\n", pgno+1+i/5, zType, iFrom);
1040     }
1041     sqlite3_free(a);
1042   }
1043 }
1044 
1045 /*
1046 ** Print a usage comment
1047 */
1048 static void usage(const char *argv0){
1049   fprintf(stderr, "Usage %s ?--uri? FILENAME ?args...?\n\n", argv0);
1050   fprintf(stderr,
1051     "switches:\n"
1052     "    --raw           Read db file directly, bypassing SQLite VFS\n"
1053     "args:\n"
1054     "    dbheader        Show database header\n"
1055     "    pgidx           Index of how each page is used\n"
1056     "    ptrmap          Show all PTRMAP page content\n"
1057     "    NNN..MMM        Show hex of pages NNN through MMM\n"
1058     "    NNN..end        Show hex of pages NNN through end of file\n"
1059     "    NNNb            Decode btree page NNN\n"
1060     "    NNNbc           Decode btree page NNN and show content\n"
1061     "    NNNbm           Decode btree page NNN and show a layout map\n"
1062     "    NNNbdCCC        Decode cell CCC on btree page NNN\n"
1063     "    NNNt            Decode freelist trunk page NNN\n"
1064     "    NNNtd           Show leaf freelist pages on the decode\n"
1065     "    NNNtr           Recursively decode freelist starting at NNN\n"
1066   );
1067 }
1068 
1069 int main(int argc, char **argv){
1070   sqlite3_int64 szFile;
1071   unsigned char *zPgSz;
1072   const char *zPrg = argv[0];     /* Name of this executable */
1073   char **azArg = argv;
1074   int nArg = argc;
1075 
1076   /* Check for the "--uri" or "-uri" switch. */
1077   if( nArg>1 ){
1078     if( sqlite3_stricmp("-raw", azArg[1])==0
1079      || sqlite3_stricmp("--raw", azArg[1])==0
1080     ){
1081       g.bRaw = 1;
1082       azArg++;
1083       nArg--;
1084     }
1085   }
1086 
1087   if( nArg<2 ){
1088     usage(zPrg);
1089     exit(1);
1090   }
1091 
1092   fileOpen(zPrg, azArg[1]);
1093   szFile = fileGetsize();
1094 
1095   zPgSz = fileRead(16, 2);
1096   g.pagesize = zPgSz[0]*256 + zPgSz[1]*65536;
1097   if( g.pagesize==0 ) g.pagesize = 1024;
1098   sqlite3_free(zPgSz);
1099 
1100   printf("Pagesize: %d\n", g.pagesize);
1101   g.mxPage = (int)((szFile+g.pagesize-1)/g.pagesize);
1102 
1103   printf("Available pages: 1..%d\n", g.mxPage);
1104   if( nArg==2 ){
1105     int i;
1106     for(i=1; i<=g.mxPage; i++) print_page(i);
1107   }else{
1108     int i;
1109     for(i=2; i<nArg; i++){
1110       int iStart, iEnd;
1111       char *zLeft;
1112       if( strcmp(azArg[i], "dbheader")==0 ){
1113         print_db_header();
1114         continue;
1115       }
1116       if( strcmp(azArg[i], "pgidx")==0 ){
1117         page_usage_report(zPrg, azArg[1]);
1118         continue;
1119       }
1120       if( strcmp(azArg[i], "ptrmap")==0 ){
1121         ptrmap_coverage_report(azArg[1]);
1122         continue;
1123       }
1124       if( strcmp(azArg[i], "help")==0 ){
1125         usage(zPrg);
1126         continue;
1127       }
1128       if( !ISDIGIT(azArg[i][0]) ){
1129         fprintf(stderr, "%s: unknown option: [%s]\n", zPrg, azArg[i]);
1130         continue;
1131       }
1132       iStart = strtol(azArg[i], &zLeft, 0);
1133       if( zLeft && strcmp(zLeft,"..end")==0 ){
1134         iEnd = g.mxPage;
1135       }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){
1136         iEnd = strtol(&zLeft[2], 0, 0);
1137       }else if( zLeft && zLeft[0]=='b' ){
1138         int ofst, nByte, hdrSize;
1139         unsigned char *a;
1140         if( iStart==1 ){
1141           ofst = hdrSize = 100;
1142           nByte = g.pagesize-100;
1143         }else{
1144           hdrSize = 0;
1145           ofst = (iStart-1)*g.pagesize;
1146           nByte = g.pagesize;
1147         }
1148         a = fileRead(ofst, nByte);
1149         decode_btree_page(a, iStart, hdrSize, &zLeft[1]);
1150         sqlite3_free(a);
1151         continue;
1152       }else if( zLeft && zLeft[0]=='t' ){
1153         int detail = 0;
1154         int recursive = 0;
1155         int j;
1156         for(j=1; zLeft[j]; j++){
1157           if( zLeft[j]=='r' ) recursive = 1;
1158           if( zLeft[j]=='d' ) detail = 1;
1159         }
1160         decode_trunk_page(iStart, detail, recursive);
1161         continue;
1162       }else{
1163         iEnd = iStart;
1164       }
1165       if( iStart<1 || iEnd<iStart || iEnd>g.mxPage ){
1166         fprintf(stderr,
1167           "Page argument should be LOWER?..UPPER?.  Range 1 to %d\n",
1168           g.mxPage);
1169         exit(1);
1170       }
1171       while( iStart<=iEnd ){
1172         print_page(iStart);
1173         iStart++;
1174       }
1175     }
1176   }
1177   fileClose();
1178   return 0;
1179 }
1180