#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
static int allZero(unsigned char *aLine){
int i;
for(i=0; i<16 && aLine[i]==0; i++){}
return i==16;
}
int main(int argc, char **argv){
int pgsz = 0;
int forCli = 0;
int bSQL = 0;
long szFile;
FILE *in;
int nSQL;
int i, j;
int nErr = 0;
const char *zInputFile = 0;
const char *zBaseName = 0;
int lastPage = 0;
int iPage;
unsigned char *aData = 0;
unsigned char *aLine;
unsigned char *aHdr;
unsigned char bShow[256];
memset(bShow, '.', sizeof(bShow));
for(i=' '; i<='~'; i++){
if( i!='{' && i!='}' && i!='"' && i!='\\' ) bShow[i] = (unsigned char)i;
}
for(i=1; i<argc; i++){
if( argv[i][0]=='-' ){
const char *z = argv[i];
z++;
if( z[0]=='-' ) z++;
if( strcmp(z,"pagesize")==0 ){
i++;
pgsz = atoi(argv[i]);
if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
fprintf(stderr, "Page size must be a power of two between"
" 512 and 65536.\n");
nErr++;
}
continue;
}else if( strcmp(z,"for-cli")==0 ){
forCli = 1;
continue;
}else if( strcmp(z,"script")==0 ){
forCli = 1;
bSQL = 1;
continue;
}
fprintf(stderr, "Unknown option: %s\n", argv[i]);
nErr++;
}else if( zInputFile ){
fprintf(stderr, "Already using a different input file: [%s]\n", argv[i]);
nErr++;
}else{
zInputFile = argv[i];
}
}
if( zInputFile==0 ){
fprintf(stderr, "No input file specified.\n");
nErr++;
}
if( nErr ){
fprintf(stderr,
"Usage: %s [--pagesize N] [--script] [--for-cli] FILENAME\n", argv[0]);
exit(1);
}
in = fopen(zInputFile, "rb");
if( in==0 ){
fprintf(stderr, "Cannot open input file [%s]\n", zInputFile);
exit(1);
}
fseek(in, 0, SEEK_END);
szFile = ftell(in);
rewind(in);
if( szFile<100 ){
fprintf(stderr, "File too short. Minimum size is 100 bytes.\n");
exit(1);
}
aData = malloc( szFile+16 );
if( aData==0 ){
fprintf(stderr, "Failed to allocate %ld bytes\n", szFile);
exit(1);
}
if( fread(aData, szFile, 1, in)!=1 ){
fprintf(stderr, "Cannot read file info memory\n");
exit(1);
}
memset(aData+szFile, 0, 16);
fclose(in);
if( bSQL ){
for(i=0; i<szFile && aData[i]!=0; i++){}
if( i==szFile ){
fprintf(stderr, "No zero terminator on SQL script\n");
exit(1);
}
nSQL = i+1;
if( szFile - nSQL<100 ){
fprintf(stderr, "Less than 100 bytes in the database\n");
exit(1);
}
}else{
nSQL = 0;
}
aHdr = aData + nSQL;
if( pgsz==0 ){
pgsz = (aHdr[16]<<8) | aHdr[17];
if( pgsz==1 ) pgsz = 65536;
if( pgsz<512 || (pgsz&(pgsz-1))!=0 ){
fprintf(stderr, "Invalid page size in header: %d\n", pgsz);
exit(1);
}
}
zBaseName = zInputFile;
for(i=0; zInputFile[i]; i++){
if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+i+1;
}
if( forCli ){
printf(".open --hexdb\n");
}
printf("| size %d pagesize %d filename %s\n",(int)szFile,pgsz,zBaseName);
for(i=nSQL; i<szFile; i+=16){
aLine = aData+i;
if( allZero(aLine) ) continue;
iPage = i/pgsz + 1;
if( lastPage!=iPage ){
printf("| page %d offset %d\n", iPage, (iPage-1)*pgsz);
lastPage = iPage;
}
printf("| %5d:", i-(iPage-1)*pgsz);
for(j=0; j<16; j++) printf(" %02x", aLine[j]);
printf(" ");
for(j=0; j<16; j++){
unsigned char c = (unsigned char)aLine[j];
fputc( bShow[c], stdout);
}
fputc('\n', stdout);
}
printf("| end %s\n", zBaseName);
if( nSQL>0 ){
printf("%s\n", aData);
}
free( aData );
return 0;
}