1 /* 2 ** Try to enlarge an SQLite database by appending many unused pages. 3 ** The resulting database will fail PRAGMA integrity_check due to the 4 ** appended unused pages, but it should work otherwise. 5 ** 6 ** Usage: 7 ** 8 ** enlargedb DATABASE N 9 ** 10 ** Adds N blank pages onto the end of DATABASE. N can be decimal 11 ** or hex. The total number of pages after adding must be no greater 12 ** than 4294967297 13 */ 14 #include <stdio.h> 15 #include <string.h> 16 #include <stdlib.h> 17 18 int main(int argc, char **argv){ 19 char *zEnd; 20 long long int toAppend; 21 long long int currentSz; 22 long long int newSz; 23 FILE *f; 24 size_t got; 25 int pgsz; 26 char zero = 0; 27 unsigned char buf[100]; 28 29 if( argc!=3 ) goto usage_error; 30 toAppend = strtoll(argv[2], &zEnd, 0); 31 if( zEnd==argv[2] || zEnd[0] ) goto usage_error; 32 if( toAppend<1 ){ 33 fprintf(stderr, "N must be at least 1\n"); 34 exit(1); 35 } 36 f = fopen(argv[1], "r+b"); 37 if( f==0 ){ 38 fprintf(stderr, "cannot open \"%s\" for reading and writing\n", argv[1]); 39 exit(1); 40 } 41 got = fread(buf, 1, sizeof(buf), f); 42 if( got!=sizeof(buf) ) goto not_valid_db; 43 if( strcmp((char*)buf,"SQLite format 3")!=0 ) goto not_valid_db; 44 pgsz = (buf[16]<<8) + buf[17]; 45 if( pgsz==1 ) pgsz = 65536; 46 if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto not_valid_db; 47 currentSz = (buf[28]<<24) + (buf[29]<<16) + (buf[30]<<8) + buf[31]; 48 newSz = currentSz + toAppend; 49 if( newSz > 0xffffffff ) newSz = 0xffffffff; 50 buf[28] = (newSz>>24) & 0xff; 51 buf[29] = (newSz>>16) & 0xff; 52 buf[30] = (newSz>>8) & 0xff; 53 buf[31] = newSz & 0xff; 54 fseek(f, 28, SEEK_SET); 55 fwrite(&buf[28],4,1,f); 56 fseek(f, (long)(newSz*pgsz - 1), SEEK_SET); 57 fwrite(&zero,1,1,f); 58 fclose(f); 59 return 0; 60 61 not_valid_db: 62 fprintf(stderr,"not a valid database: %s\n", argv[1]); 63 exit(1); 64 65 usage_error: 66 fprintf(stderr,"Usage: %s DATABASE N\n", argv[0]); 67 exit(1); 68 } 69