modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/misc/scrub.c (about)

     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