update version to 4.3.0
[sqlcipher.git] / tool / dbtotxt.c
blob8b0600fa51496c031f6d1f0fbd1efb8226ca2178
1 /*
2 ** Copyright 2008 D. Richard Hipp and Hipp, Wyrick & Company, Inc.
3 ** All Rights Reserved
4 **
5 ******************************************************************************
6 **
7 ** This file implements a stand-alone utility program that converts
8 ** a binary file (usually an SQLite database) into a text format that
9 ** is compact and friendly to human-readers.
11 ** Usage:
13 ** dbtotxt [--pagesize N] FILENAME
15 ** The translation of the database appears on standard output. If the
16 ** --pagesize command-line option is omitted, then the page size is taken
17 ** from the database header.
19 ** Compactness is achieved by suppressing lines of all zero bytes. This
20 ** works well at compressing test databases that are mostly empty. But
21 ** the output will probably be lengthy for a real database containing lots
22 ** of real content. For maximum compactness, it is suggested that test
23 ** databases be constructed with "zeroblob()" rather than "randomblob()"
24 ** used for filler content and with "PRAGMA secure_delete=ON" selected to
25 ** zero-out deleted content.
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <ctype.h>
32 /* Return true if the line is all zeros */
33 static int allZero(unsigned char *aLine){
34 int i;
35 for(i=0; i<16 && aLine[i]==0; i++){}
36 return i==16;
39 int main(int argc, char **argv){
40 int pgsz = 0; /* page size */
41 long szFile; /* Size of the input file in bytes */
42 FILE *in; /* Input file */
43 int i, j; /* Loop counters */
44 int nErr = 0; /* Number of errors */
45 const char *zInputFile = 0; /* Name of the input file */
46 const char *zBaseName = 0; /* Base name of the file */
47 int lastPage = 0; /* Last page number shown */
48 int iPage; /* Current page number */
49 unsigned char aLine[16]; /* A single line of the file */
50 unsigned char aHdr[100]; /* File header */
51 unsigned char bShow[256]; /* Characters ok to display */
52 memset(bShow, '.', sizeof(bShow));
53 for(i=' '; i<='~'; i++){
54 if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = (unsigned char)i;
56 for(i=1; i<argc; i++){
57 if( argv[i][0]=='-' ){
58 const char *z = argv[i];
59 z++;
60 if( z[0]=='-' ) z++;
61 if( strcmp(z,"pagesize")==0 ){
62 i++;
63 pgsz = atoi(argv[i]);
64 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
65 fprintf(stderr, "Page size must be a power of two between"
66 " 512 and 65536.\n");
67 nErr++;
69 continue;
71 fprintf(stderr, "Unknown option: %s\n", argv[i]);
72 nErr++;
73 }else if( zInputFile ){
74 fprintf(stderr, "Already using a different input file: [%s]\n", argv[i]);
75 nErr++;
76 }else{
77 zInputFile = argv[i];
80 if( zInputFile==0 ){
81 fprintf(stderr, "No input file specified.\n");
82 nErr++;
84 if( nErr ){
85 fprintf(stderr, "Usage: %s [--pagesize N] FILENAME\n", argv[0]);
86 exit(1);
88 in = fopen(zInputFile, "rb");
89 if( in==0 ){
90 fprintf(stderr, "Cannot open input file [%s]\n", zInputFile);
91 exit(1);
93 fseek(in, 0, SEEK_END);
94 szFile = ftell(in);
95 rewind(in);
96 if( szFile<100 ){
97 fprintf(stderr, "File too short. Minimum size is 100 bytes.\n");
98 exit(1);
100 if( fread(aHdr, 100, 1, in)!=1 ){
101 fprintf(stderr, "Cannot read file header\n");
102 exit(1);
104 rewind(in);
105 if( pgsz==0 ){
106 pgsz = (aHdr[16]<<8) | aHdr[17];
107 if( pgsz==1 ) pgsz = 65536;
108 if( pgsz<512 || (pgsz&(pgsz-1))!=0 ){
109 fprintf(stderr, "Invalid page size in header: %d\n", pgsz);
110 exit(1);
113 zBaseName = zInputFile;
114 for(i=0; zInputFile[i]; i++){
115 if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+i+1;
117 printf("| size %d pagesize %d filename %s\n",(int)szFile,pgsz,zBaseName);
118 for(i=0; i<szFile; i+=16){
119 int got = (int)fread(aLine, 1, 16, in);
120 if( got!=16 ){
121 static int once = 1;
122 if( once ){
123 fprintf(stderr, "Could not read input file starting at byte %d\n",
124 i+got);
126 memset(aLine+got, 0, 16-got);
128 if( allZero(aLine) ) continue;
129 iPage = i/pgsz + 1;
130 if( lastPage!=iPage ){
131 printf("| page %d offset %d\n", iPage, (iPage-1)*pgsz);
132 lastPage = iPage;
134 printf("| %5d:", i-(iPage-1)*pgsz);
135 for(j=0; j<16; j++) printf(" %02x", aLine[j]);
136 printf(" ");
137 for(j=0; j<16; j++){
138 unsigned char c = (unsigned char)aLine[j];
139 fputc( bShow[c], stdout);
141 fputc('\n', stdout);
143 fclose(in);
144 printf("| end %s\n", zBaseName);
145 return 0;