/* ** Decode a freelist trunk page. */ static void decode_trunk_page( int pgno, /* The page number */ int pagesize, /* Size of each page */ int detail, /* Show leaf pages if true */ int recursive /* Follow the trunk change if true */ ){ int n, i, k; unsigned char *a; while( pgno>0 ){ a = getContent((pgno-1)*pagesize, pagesize); printf("Decode of freelist trunk page %d:\n", pgno); print_decode_line(a, 0, 4, "Next freelist trunk page"); print_decode_line(a, 4, 4, "Number of entries on this page"); if( detail ){ n = (int)decodeInt32(&a[4]); for(i=0; i<n; i++){ unsigned int x = decodeInt32(&a[8+4*i]); char zIdx[10]; sprintf(zIdx, "[%d]", i); printf(" %5s %7u", zIdx, x); if( i%5==4 ) printf("\n"); } if( i%5!=0 ) printf("\n"); } if( !recursive ){ pgno = 0; }else{ pgno = (int)decodeInt32(&a[0]); } free(a); } }
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); }
/* ** Decode a btree page */ static void decode_btree_page( unsigned char *a, /* Page content */ int pgno, /* Page number */ int hdrSize, /* Size of the page header. 0 or 100 */ char *zArgs /* Flags to control formatting */ ){ const char *zType = "unknown"; int nCell; int i, j; int iCellPtr; int showCellContent = 0; int showMap = 0; char *zMap = 0; switch( a[0] ){ case 2: zType = "index interior node"; break; case 5: zType = "table interior node"; break; case 10: zType = "index leaf"; break; case 13: zType = "table leaf"; break; } while( zArgs[0] ){ switch( zArgs[0] ){ case 'c': showCellContent = 1; break; case 'm': showMap = 1; break; } zArgs++; } printf("Decode of btree page %d:\n", pgno); print_decode_line(a, 0, 1, zType); print_decode_line(a, 1, 2, "Offset to first freeblock"); print_decode_line(a, 3, 2, "Number of cells on this page"); nCell = a[3]*256 + a[4]; print_decode_line(a, 5, 2, "Offset to cell content area"); print_decode_line(a, 7, 1, "Fragmented byte count"); if( a[0]==2 || a[0]==5 ){ print_decode_line(a, 8, 4, "Right child"); iCellPtr = 12; }else{ iCellPtr = 8; } if( nCell>0 ){ printf(" key: lx=left-child n=payload-size r=rowid\n"); } if( showMap ){ zMap = malloc(pagesize); memset(zMap, '.', pagesize); memset(zMap, '1', hdrSize); memset(&zMap[hdrSize], 'H', iCellPtr); memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell); } for(i=0; i<nCell; i++){ int cofst = iCellPtr + i*2; char *zDesc; int n; cofst = a[cofst]*256 + a[cofst+1]; n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc); if( showMap ){ char zBuf[30]; memset(&zMap[cofst], '*', n); zMap[cofst] = '['; zMap[cofst+n-1] = ']'; sprintf(zBuf, "%d", i); j = strlen(zBuf); if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j); } printf(" %03x: cell[%d] %s\n", cofst, i, zDesc); } if( showMap ){ for(i=0; i<pagesize; i+=64){ printf(" %03x: %.64s\n", i, &zMap[i]); } free(zMap); } }
/* ** Decode the database header. */ static void print_db_header(void){ unsigned char *aData; aData = print_byte_range(0, 100, 0); printf("Decoded:\n"); print_decode_line(aData, 16, 2, "Database page size"); print_decode_line(aData, 18, 1, "File format write version"); print_decode_line(aData, 19, 1, "File format read version"); print_decode_line(aData, 20, 1, "Reserved space at end of page"); print_decode_line(aData, 24, 4, "File change counter"); print_decode_line(aData, 28, 4, "Size of database in pages"); print_decode_line(aData, 32, 4, "Page number of first freelist page"); print_decode_line(aData, 36, 4, "Number of freelist pages"); print_decode_line(aData, 40, 4, "Schema cookie"); print_decode_line(aData, 44, 4, "Schema format version"); print_decode_line(aData, 48, 4, "Default page cache size"); print_decode_line(aData, 52, 4, "Largest auto-vac root page"); print_decode_line(aData, 56, 4, "Text encoding"); print_decode_line(aData, 60, 4, "User version"); print_decode_line(aData, 64, 4, "Incremental-vacuum mode"); print_decode_line(aData, 68, 4, "meta[7]"); print_decode_line(aData, 72, 4, "meta[8]"); print_decode_line(aData, 76, 4, "meta[9]"); print_decode_line(aData, 80, 4, "meta[10]"); print_decode_line(aData, 84, 4, "meta[11]"); print_decode_line(aData, 88, 4, "meta[12]"); print_decode_line(aData, 92, 4, "Change counter for version number"); print_decode_line(aData, 96, 4, "SQLite version number"); }
/* ** 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; }
/* ** Decode a btree page */ static void decode_btree_page( unsigned char *a, /* Page content */ int pgno, /* Page number */ int hdrSize, /* Size of the page header. 0 or 100 */ char *zArgs /* Flags to control formatting */ ){ const char *zType = "unknown"; int nCell; int i, j; int iCellPtr; int showCellContent = 0; int showMap = 0; int cellToDecode = -2; char *zMap = 0; switch( a[0] ){ case 2: zType = "index interior node"; break; case 5: zType = "table interior node"; break; case 10: zType = "index leaf"; break; case 13: zType = "table leaf"; break; } while( zArgs[0] ){ switch( zArgs[0] ){ case 'c': showCellContent = 1; break; case 'm': showMap = 1; break; case 'd': { if( !ISDIGIT(zArgs[1]) ){ cellToDecode = -1; }else{ cellToDecode = 0; while( ISDIGIT(zArgs[1]) ){ zArgs++; cellToDecode = cellToDecode*10 + zArgs[0] - '0'; } } break; } } zArgs++; } nCell = a[3]*256 + a[4]; iCellPtr = (a[0]==2 || a[0]==5) ? 12 : 8; if( cellToDecode>=nCell ){ printf("Page %d has only %d cells\n", pgno, nCell); return; } printf("Header on btree page %d:\n", pgno); print_decode_line(a, 0, 1, zType); print_decode_line(a, 1, 2, "Offset to first freeblock"); print_decode_line(a, 3, 2, "Number of cells on this page"); print_decode_line(a, 5, 2, "Offset to cell content area"); print_decode_line(a, 7, 1, "Fragmented byte count"); if( a[0]==2 || a[0]==5 ){ print_decode_line(a, 8, 4, "Right child"); } if( cellToDecode==(-2) && nCell>0 ){ printf(" key: lx=left-child n=payload-size r=rowid\n"); } if( showMap ){ zMap = sqlite3_malloc(g.pagesize); memset(zMap, '.', g.pagesize); memset(zMap, '1', hdrSize); memset(&zMap[hdrSize], 'H', iCellPtr); memset(&zMap[hdrSize+iCellPtr], 'P', 2*nCell); } for(i=0; i<nCell; i++){ int cofst = iCellPtr + i*2; char *zDesc; i64 n; cofst = a[cofst]*256 + a[cofst+1]; n = describeCell(a[0], &a[cofst-hdrSize], showCellContent, &zDesc); if( showMap ){ char zBuf[30]; memset(&zMap[cofst], '*', (size_t)n); zMap[cofst] = '['; zMap[cofst+n-1] = ']'; sprintf(zBuf, "%d", i); j = (int)strlen(zBuf); if( j<=n-2 ) memcpy(&zMap[cofst+1], zBuf, j); } if( cellToDecode==(-2) ){ printf(" %03x: cell[%d] %s\n", cofst, i, zDesc); }else if( cellToDecode==(-1) || cellToDecode==i ){ decodeCell(a, pgno, i, hdrSize, cofst-hdrSize); } } if( showMap ){ printf("Page map: (H=header P=cell-index 1=page-1-header .=free-space)\n"); for(i=0; i<g.pagesize; i+=64){ printf(" %03x: %.64s\n", i, &zMap[i]); } sqlite3_free(zMap); } }