xref: /sqlite-3.40.0/ext/misc/scrub.c (revision dfe4e6bb)
1 /*
2 ** 2016-05-05
3 **
4 ** The author disclaims copyright to this source code.  In place of
5 ** a legal notice, here is a blessing:
6 **
7 **    May you do good and not evil.
8 **    May you find forgiveness for yourself and forgive others.
9 **    May you share freely, never taking more than you give.
10 **
11 ******************************************************************************
12 **
13 ** This file implements a utility function (and a utility program) that
14 ** makes a copy of an SQLite database while simultaneously zeroing out all
15 ** deleted content.
16 **
17 ** Normally (when PRAGMA secure_delete=OFF, which is the default) when SQLite
18 ** deletes content, it does not overwrite the deleted content but rather marks
19 ** the region of the file that held that content as being reusable.  This can
20 ** cause deleted content to recoverable from the database file.  This stale
21 ** content is removed by the VACUUM command, but VACUUM can be expensive for
22 ** large databases.  When in PRAGMA secure_delete=ON mode, the deleted content
23 ** is zeroed, but secure_delete=ON has overhead as well.
24 **
25 ** This utility attempts to make a copy of a complete SQLite database where
26 ** all of the deleted content is zeroed out in the copy, and it attempts to
27 ** do so while being faster than running VACUUM.
28 **
29 ** Usage:
30 **
31 **   int sqlite3_scrub_backup(
32 **       const char *zSourceFile,   // Source database filename
33 **       const char *zDestFile,     // Destination database filename
34 **       char **pzErrMsg            // Write error message here
35 **   );
36 **
37 ** Simply call the API above specifying the filename of the source database
38 ** and the name of the backup copy.  The source database must already exist
39 ** and can be in active use. (A read lock is held during the backup.)  The
40 ** destination file should not previously exist.  If the pzErrMsg parameter
41 ** is non-NULL and if an error occurs, then an error message might be written
42 ** into memory obtained from sqlite3_malloc() and *pzErrMsg made to point to
43 ** that error message.  But if the error is an OOM, the error might not be
44 ** reported.  The routine always returns non-zero if there is an error.
45 **
46 ** If compiled with -DSCRUB_STANDALONE then a main() procedure is added and
47 ** this file becomes a standalone program that can be run as follows:
48 **
49 **      ./sqlite3scrub SOURCE DEST
50 */
51 #include "sqlite3.h"
52 #include <assert.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <stdarg.h>
56 #include <string.h>
57 
58 typedef struct ScrubState ScrubState;
59 typedef unsigned char u8;
60 typedef unsigned short u16;
61 typedef unsigned int u32;
62 
63 
64 /* State information for a scrub-and-backup operation */
65 struct ScrubState {
66   const char *zSrcFile;    /* Name of the source file */
67   const char *zDestFile;   /* Name of the destination file */
68   int rcErr;               /* Error code */
69   char *zErr;              /* Error message text */
70   sqlite3 *dbSrc;          /* Source database connection */
71   sqlite3_file *pSrc;      /* Source file handle */
72   sqlite3 *dbDest;         /* Destination database connection */
73   sqlite3_file *pDest;     /* Destination file handle */
74   u32 szPage;              /* Page size */
75   u32 szUsable;            /* Usable bytes on each page */
76   u32 nPage;               /* Number of pages */
77   u32 iLastPage;           /* Page number of last page written so far*/
78   u8 *page1;               /* Content of page 1 */
79 };
80 
81 /* Store an error message */
82 static void scrubBackupErr(ScrubState *p, const char *zFormat, ...){
83   va_list ap;
84   sqlite3_free(p->zErr);
85   va_start(ap, zFormat);
86   p->zErr = sqlite3_vmprintf(zFormat, ap);
87   va_end(ap);
88   if( p->rcErr==0 ) p->rcErr = SQLITE_ERROR;
89 }
90 
91 /* Allocate memory to hold a single page of content */
92 static u8 *scrubBackupAllocPage(ScrubState *p){
93   u8 *pPage;
94   if( p->rcErr ) return 0;
95   pPage = sqlite3_malloc( p->szPage );
96   if( pPage==0 ) p->rcErr = SQLITE_NOMEM;
97   return pPage;
98 }
99 
100 /* Read a page from the source database into memory.  Use the memory
101 ** provided by pBuf if not NULL or allocate a new page if pBuf==NULL.
102 */
103 static u8 *scrubBackupRead(ScrubState *p, int pgno, u8 *pBuf){
104   int rc;
105   sqlite3_int64 iOff;
106   u8 *pOut = pBuf;
107   if( p->rcErr ) return 0;
108   if( pOut==0 ){
109     pOut = scrubBackupAllocPage(p);
110     if( pOut==0 ) return 0;
111   }
112   iOff = (pgno-1)*(sqlite3_int64)p->szPage;
113   rc = p->pSrc->pMethods->xRead(p->pSrc, pOut, p->szPage, iOff);
114   if( rc!=SQLITE_OK ){
115     if( pBuf==0 ) sqlite3_free(pOut);
116     pOut = 0;
117     scrubBackupErr(p, "read failed for page %d", pgno);
118     p->rcErr = SQLITE_IOERR;
119   }
120   return pOut;
121 }
122 
123 /* Write a page to the destination database */
124 static void scrubBackupWrite(ScrubState *p, int pgno, const u8 *pData){
125   int rc;
126   sqlite3_int64 iOff;
127   if( p->rcErr ) return;
128   iOff = (pgno-1)*(sqlite3_int64)p->szPage;
129   rc = p->pDest->pMethods->xWrite(p->pDest, pData, p->szPage, iOff);
130   if( rc!=SQLITE_OK ){
131     scrubBackupErr(p, "write failed for page %d", pgno);
132     p->rcErr = SQLITE_IOERR;
133   }
134   if( pgno>p->iLastPage ) p->iLastPage = pgno;
135 }
136 
137 /* Prepare a statement against the "db" database. */
138 static sqlite3_stmt *scrubBackupPrepare(
139   ScrubState *p,      /* Backup context */
140   sqlite3 *db,        /* Database to prepare against */
141   const char *zSql    /* SQL statement */
142 ){
143   sqlite3_stmt *pStmt;
144   if( p->rcErr ) return 0;
145   p->rcErr = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
146   if( p->rcErr ){
147     scrubBackupErr(p, "SQL error \"%s\" on \"%s\"",
148                    sqlite3_errmsg(db), zSql);
149     sqlite3_finalize(pStmt);
150     return 0;
151   }
152   return pStmt;
153 }
154 
155 
156 /* Open the source database file */
157 static void scrubBackupOpenSrc(ScrubState *p){
158   sqlite3_stmt *pStmt;
159   int rc;
160   /* Open the source database file */
161   p->rcErr = sqlite3_open_v2(p->zSrcFile, &p->dbSrc,
162                  SQLITE_OPEN_READWRITE |
163                  SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
164   if( p->rcErr ){
165     scrubBackupErr(p, "cannot open source database: %s",
166                       sqlite3_errmsg(p->dbSrc));
167     return;
168   }
169   p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_master; BEGIN;",
170                           0, 0, 0);
171   if( p->rcErr ){
172     scrubBackupErr(p,
173        "cannot start a read transaction on the source database: %s",
174        sqlite3_errmsg(p->dbSrc));
175     return;
176   }
177   rc = sqlite3_wal_checkpoint_v2(p->dbSrc, "main", SQLITE_CHECKPOINT_FULL,
178                                  0, 0);
179   if( rc ){
180     scrubBackupErr(p, "cannot checkpoint the source database");
181     return;
182   }
183   pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_size");
184   if( pStmt==0 ) return;
185   rc = sqlite3_step(pStmt);
186   if( rc==SQLITE_ROW ){
187     p->szPage = sqlite3_column_int(pStmt, 0);
188   }else{
189     scrubBackupErr(p, "unable to determine the page size");
190   }
191   sqlite3_finalize(pStmt);
192   if( p->rcErr ) return;
193   pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_count");
194   if( pStmt==0 ) return;
195   rc = sqlite3_step(pStmt);
196   if( rc==SQLITE_ROW ){
197     p->nPage = sqlite3_column_int(pStmt, 0);
198   }else{
199     scrubBackupErr(p, "unable to determine the size of the source database");
200   }
201   sqlite3_finalize(pStmt);
202   sqlite3_file_control(p->dbSrc, "main", SQLITE_FCNTL_FILE_POINTER, &p->pSrc);
203   if( p->pSrc==0 || p->pSrc->pMethods==0 ){
204     scrubBackupErr(p, "cannot get the source file handle");
205     p->rcErr = SQLITE_ERROR;
206   }
207 }
208 
209 /* Create and open the destination file */
210 static void scrubBackupOpenDest(ScrubState *p){
211   sqlite3_stmt *pStmt;
212   int rc;
213   char *zSql;
214   if( p->rcErr ) return;
215   p->rcErr = sqlite3_open_v2(p->zDestFile, &p->dbDest,
216                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
217                  SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
218   if( p->rcErr ){
219     scrubBackupErr(p, "cannot open destination database: %s",
220                       sqlite3_errmsg(p->dbDest));
221     return;
222   }
223   zSql = sqlite3_mprintf("PRAGMA page_size(%u);", p->szPage);
224   if( zSql==0 ){
225     p->rcErr = SQLITE_NOMEM;
226     return;
227   }
228   p->rcErr = sqlite3_exec(p->dbDest, zSql, 0, 0, 0);
229   sqlite3_free(zSql);
230   if( p->rcErr ){
231     scrubBackupErr(p,
232        "cannot set the page size on the destination database: %s",
233        sqlite3_errmsg(p->dbDest));
234     return;
235   }
236   sqlite3_exec(p->dbDest, "PRAGMA journal_mode=OFF;", 0, 0, 0);
237   p->rcErr = sqlite3_exec(p->dbDest, "BEGIN EXCLUSIVE;", 0, 0, 0);
238   if( p->rcErr ){
239     scrubBackupErr(p,
240        "cannot start a write transaction on the destination database: %s",
241        sqlite3_errmsg(p->dbDest));
242     return;
243   }
244   pStmt = scrubBackupPrepare(p, p->dbDest, "PRAGMA page_count;");
245   if( pStmt==0 ) return;
246   rc = sqlite3_step(pStmt);
247   if( rc!=SQLITE_ROW ){
248     scrubBackupErr(p, "cannot measure the size of the destination");
249   }else if( sqlite3_column_int(pStmt, 0)>1 ){
250     scrubBackupErr(p, "destination database is not empty - holds %d pages",
251                    sqlite3_column_int(pStmt, 0));
252   }
253   sqlite3_finalize(pStmt);
254   sqlite3_file_control(p->dbDest, "main", SQLITE_FCNTL_FILE_POINTER, &p->pDest);
255   if( p->pDest==0 || p->pDest->pMethods==0 ){
256     scrubBackupErr(p, "cannot get the destination file handle");
257     p->rcErr = SQLITE_ERROR;
258   }
259 }
260 
261 /* Read a 32-bit big-endian integer */
262 static u32 scrubBackupInt32(const u8 *a){
263   u32 v = a[3];
264   v += ((u32)a[2])<<8;
265   v += ((u32)a[1])<<16;
266   v += ((u32)a[0])<<24;
267   return v;
268 }
269 
270 /* Read a 16-bit big-endian integer */
271 static u32 scrubBackupInt16(const u8 *a){
272   return (a[0]<<8) + a[1];
273 }
274 
275 /*
276 ** Read a varint.  Put the value in *pVal and return the number of bytes.
277 */
278 static int scrubBackupVarint(const u8 *z, sqlite3_int64 *pVal){
279   sqlite3_int64 v = 0;
280   int i;
281   for(i=0; i<8; i++){
282     v = (v<<7) + (z[i]&0x7f);
283     if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
284   }
285   v = (v<<8) + (z[i]&0xff);
286   *pVal = v;
287   return 9;
288 }
289 
290 /*
291 ** Return the number of bytes in a varint.
292 */
293 static int scrubBackupVarintSize(const u8 *z){
294   int i;
295   for(i=0; i<8; i++){
296     if( (z[i]&0x80)==0 ){ return i+1; }
297   }
298   return 9;
299 }
300 
301 /*
302 ** Copy the freelist trunk page given, and all its descendents,
303 ** zeroing out as much as possible in the process.
304 */
305 static void scrubBackupFreelist(ScrubState *p, int pgno, u32 nFree){
306   u8 *a, *aBuf;
307   u32 n, mx;
308 
309   if( p->rcErr ) return;
310   aBuf = scrubBackupAllocPage(p);
311   if( aBuf==0 ) return;
312 
313   while( pgno && nFree){
314     a = scrubBackupRead(p, pgno, aBuf);
315     if( a==0 ) break;
316     n = scrubBackupInt32(&a[4]);
317     mx = p->szUsable/4 - 2;
318     if( n<mx ){
319       memset(&a[n*4+8], 0, 4*(mx-n));
320     }
321     scrubBackupWrite(p, pgno, a);
322     pgno = scrubBackupInt32(a);
323 #if 0
324     /* There is really no point in copying the freelist leaf pages.
325     ** Simply leave them uninitialized in the destination database.  The
326     ** OS filesystem should zero those pages for us automatically.
327     */
328     for(i=0; i<n && nFree; i++){
329       u32 iLeaf = scrubBackupInt32(&a[i*4+8]);
330       if( aZero==0 ){
331         aZero = scrubBackupAllocPage(p);
332         if( aZero==0 ){ pgno = 0; break; }
333         memset(aZero, 0, p->szPage);
334       }
335       scrubBackupWrite(p, iLeaf, aZero);
336       nFree--;
337     }
338 #endif
339   }
340   sqlite3_free(aBuf);
341 }
342 
343 /*
344 ** Copy an overflow chain from source to destination.  Zero out any
345 ** unused tail at the end of the overflow chain.
346 */
347 static void scrubBackupOverflow(ScrubState *p, int pgno, u32 nByte){
348   u8 *a, *aBuf;
349 
350   aBuf = scrubBackupAllocPage(p);
351   if( aBuf==0 ) return;
352   while( nByte>0 && pgno!=0 ){
353     a = scrubBackupRead(p, pgno, aBuf);
354     if( a==0 ) break;
355     if( nByte >= (p->szUsable)-4 ){
356       nByte -= (p->szUsable) - 4;
357     }else{
358       u32 x = (p->szUsable - 4) - nByte;
359       u32 i = p->szUsable - x;
360       memset(&a[i], 0, x);
361       nByte = 0;
362     }
363     scrubBackupWrite(p, pgno, a);
364     pgno = scrubBackupInt32(a);
365   }
366   sqlite3_free(aBuf);
367 }
368 
369 
370 /*
371 ** Copy B-Tree page pgno, and all of its children, from source to destination.
372 ** Zero out deleted content during the copy.
373 */
374 static void scrubBackupBtree(ScrubState *p, int pgno, int iDepth){
375   u8 *a;
376   u32 i, n, pc;
377   u32 nCell;
378   u32 nPrefix;
379   u32 szHdr;
380   u32 iChild;
381   u8 *aTop;
382   u8 *aCell;
383   u32 x, y;
384   int ln = 0;
385 
386 
387   if( p->rcErr ) return;
388   if( iDepth>50 ){
389     scrubBackupErr(p, "corrupt: b-tree too deep at page %d", pgno);
390     return;
391   }
392   if( pgno==1 ){
393     a = p->page1;
394   }else{
395     a = scrubBackupRead(p, pgno, 0);
396     if( a==0 ) return;
397   }
398   nPrefix = pgno==1 ? 100 : 0;
399   aTop = &a[nPrefix];
400   szHdr = 8 + 4*(aTop[0]==0x02 || aTop[0]==0x05);
401   aCell = aTop + szHdr;
402   nCell = scrubBackupInt16(&aTop[3]);
403 
404   /* Zero out the gap between the cell index and the start of the
405   ** cell content area */
406   x = scrubBackupInt16(&aTop[5]);  /* First byte of cell content area */
407   if( x>p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
408   y = szHdr + nPrefix + nCell*2;
409   if( y>x ){ ln=__LINE__; goto btree_corrupt; }
410   if( y<x ) memset(a+y, 0, x-y);  /* Zero the gap */
411 
412   /* Zero out all the free blocks */
413   pc = scrubBackupInt16(&aTop[1]);
414   if( pc>0 && pc<x ){ ln=__LINE__; goto btree_corrupt; }
415   while( pc ){
416     if( pc>(p->szUsable)-4 ){ ln=__LINE__; goto btree_corrupt; }
417     n = scrubBackupInt16(&a[pc+2]);
418     if( pc+n>(p->szUsable) ){ ln=__LINE__; goto btree_corrupt; }
419     if( n>4 ) memset(&a[pc+4], 0, n-4);
420     x = scrubBackupInt16(&a[pc]);
421     if( x<pc+4 && x>0 ){ ln=__LINE__; goto btree_corrupt; }
422     pc = x;
423   }
424 
425   /* Write this one page */
426   scrubBackupWrite(p, pgno, a);
427 
428   /* Walk the tree and process child pages */
429   for(i=0; i<nCell; i++){
430     u32 X, M, K, nLocal;
431     sqlite3_int64 P;
432     pc = scrubBackupInt16(&aCell[i*2]);
433     if( pc <= szHdr ){ ln=__LINE__; goto btree_corrupt; }
434     if( pc > p->szUsable-3 ){ ln=__LINE__; goto btree_corrupt; }
435     if( aTop[0]==0x05 || aTop[0]==0x02 ){
436       if( pc+4 > p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
437       iChild = scrubBackupInt32(&a[pc]);
438       pc += 4;
439       scrubBackupBtree(p, iChild, iDepth+1);
440       if( aTop[0]==0x05 ) continue;
441     }
442     pc += scrubBackupVarint(&a[pc], &P);
443     if( pc >= p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
444     if( aTop[0]==0x0d ){
445       X = p->szUsable - 35;
446     }else{
447       X = ((p->szUsable - 12)*64/255) - 23;
448     }
449     if( P<=X ){
450       /* All content is local.  No overflow */
451       continue;
452     }
453     M = ((p->szUsable - 12)*32/255)-23;
454     K = M + ((P-M)%(p->szUsable-4));
455     if( aTop[0]==0x0d ){
456       pc += scrubBackupVarintSize(&a[pc]);
457       if( pc > (p->szUsable-4) ){ ln=__LINE__; goto btree_corrupt; }
458     }
459     nLocal = K<=X ? K : M;
460     if( pc+nLocal > p->szUsable-4 ){ ln=__LINE__; goto btree_corrupt; }
461     iChild = scrubBackupInt32(&a[pc+nLocal]);
462     scrubBackupOverflow(p, iChild, P-nLocal);
463   }
464 
465   /* Walk the right-most tree */
466   if( aTop[0]==0x05 || aTop[0]==0x02 ){
467     iChild = scrubBackupInt32(&aTop[8]);
468     scrubBackupBtree(p, iChild, iDepth+1);
469   }
470 
471   /* All done */
472   if( pgno>1 ) sqlite3_free(a);
473   return;
474 
475 btree_corrupt:
476   scrubBackupErr(p, "corruption on page %d of source database (errid=%d)",
477                  pgno, ln);
478   if( pgno>1 ) sqlite3_free(a);
479 }
480 
481 /*
482 ** Copy all ptrmap pages from source to destination.
483 ** This routine is only called if the source database is in autovacuum
484 ** or incremental vacuum mode.
485 */
486 static void scrubBackupPtrmap(ScrubState *p){
487   u32 pgno = 2;
488   u32 J = p->szUsable/5;
489   u32 iLock = (1073742335/p->szPage)+1;
490   u8 *a, *pBuf;
491   if( p->rcErr ) return;
492   pBuf = scrubBackupAllocPage(p);
493   if( pBuf==0 ) return;
494   while( pgno<=p->nPage ){
495     a = scrubBackupRead(p, pgno, pBuf);
496     if( a==0 ) break;
497     scrubBackupWrite(p, pgno, a);
498     pgno += J+1;
499     if( pgno==iLock ) pgno++;
500   }
501   sqlite3_free(pBuf);
502 }
503 
504 int sqlite3_scrub_backup(
505   const char *zSrcFile,    /* Source file */
506   const char *zDestFile,   /* Destination file */
507   char **pzErr             /* Write error here if non-NULL */
508 ){
509   ScrubState s;
510   u32 n, i;
511   sqlite3_stmt *pStmt;
512 
513   memset(&s, 0, sizeof(s));
514   s.zSrcFile = zSrcFile;
515   s.zDestFile = zDestFile;
516 
517   /* Open both source and destination databases */
518   scrubBackupOpenSrc(&s);
519   scrubBackupOpenDest(&s);
520 
521   /* Read in page 1 */
522   s.page1 = scrubBackupRead(&s, 1, 0);
523   if( s.page1==0 ) goto scrub_abort;
524   s.szUsable = s.szPage - s.page1[20];
525 
526   /* Copy the freelist */
527   n = scrubBackupInt32(&s.page1[36]);
528   i = scrubBackupInt32(&s.page1[32]);
529   if( n ) scrubBackupFreelist(&s, i, n);
530 
531   /* Copy ptrmap pages */
532   n = scrubBackupInt32(&s.page1[52]);
533   if( n ) scrubBackupPtrmap(&s);
534 
535   /* Copy all of the btrees */
536   scrubBackupBtree(&s, 1, 0);
537   pStmt = scrubBackupPrepare(&s, s.dbSrc,
538        "SELECT rootpage FROM sqlite_master WHERE coalesce(rootpage,0)>0");
539   if( pStmt==0 ) goto scrub_abort;
540   while( sqlite3_step(pStmt)==SQLITE_ROW ){
541     i = (u32)sqlite3_column_int(pStmt, 0);
542     scrubBackupBtree(&s, i, 0);
543   }
544   sqlite3_finalize(pStmt);
545 
546   /* If the last page of the input db file is a free-list leaf, then the
547   ** backup file on disk is still smaller than the size indicated within
548   ** the database header. In this case, write a page of zeroes to the
549   ** last page of the backup database so that SQLite does not mistakenly
550   ** think the db is corrupt.  */
551   if( s.iLastPage<s.nPage ){
552     u8 *aZero = scrubBackupAllocPage(&s);
553     if( aZero ){
554       memset(aZero, 0, s.szPage);
555       scrubBackupWrite(&s, s.nPage, aZero);
556       sqlite3_free(aZero);
557     }
558   }
559 
560 scrub_abort:
561   /* Close the destination database without closing the transaction. If we
562   ** commit, page zero will be overwritten. */
563   sqlite3_close(s.dbDest);
564 
565   /* But do close out the read-transaction on the source database */
566   sqlite3_exec(s.dbSrc, "COMMIT;", 0, 0, 0);
567   sqlite3_close(s.dbSrc);
568   sqlite3_free(s.page1);
569   if( pzErr ){
570     *pzErr = s.zErr;
571   }else{
572     sqlite3_free(s.zErr);
573   }
574   return s.rcErr;
575 }
576 
577 #ifdef SCRUB_STANDALONE
578 /* Error and warning log */
579 static void errorLogCallback(void *pNotUsed, int iErr, const char *zMsg){
580   const char *zType;
581   switch( iErr&0xff ){
582     case SQLITE_WARNING: zType = "WARNING";  break;
583     case SQLITE_NOTICE:  zType = "NOTICE";   break;
584     default:             zType = "ERROR";    break;
585   }
586   fprintf(stderr, "%s: %s\n", zType, zMsg);
587 }
588 
589 /* The main() routine when this utility is run as a stand-alone program */
590 int main(int argc, char **argv){
591   char *zErr = 0;
592   int rc;
593   if( argc!=3 ){
594     fprintf(stderr,"Usage: %s SOURCE DESTINATION\n", argv[0]);
595     exit(1);
596   }
597   sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, 0);
598   rc = sqlite3_scrub_backup(argv[1], argv[2], &zErr);
599   if( rc==SQLITE_NOMEM ){
600     fprintf(stderr, "%s: out of memory\n", argv[0]);
601     exit(1);
602   }
603   if( zErr ){
604     fprintf(stderr, "%s: %s\n", argv[0], zErr);
605     sqlite3_free(zErr);
606     exit(1);
607   }
608   return 0;
609 }
610 #endif
611