]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove the untested and undocumented "scrub" utility program. It was written
authordrh <>
Sat, 30 May 2026 10:09:33 +0000 (10:09 +0000)
committerdrh <>
Sat, 30 May 2026 10:09:33 +0000 (10:09 +0000)
in 2016, but made obsolete by the [VACUUM INTO] command in 2019.

FossilOrigin-Name: 27d67fb175e839f6e7450f54166b52e0a6137c075758511da32fd82c57c310c4

Makefile.msc
ext/misc/scrub.c [deleted file]
main.mk
manifest
manifest.uuid

index dd4f86d593f4903eb86fe795aee16e97a9fb421a..e14cf0227c982bfbfe1dd6b149f02e4ddac2ca26 100644 (file)
@@ -1897,9 +1897,6 @@ RSYNC_OPT = \
 sqlite3_rsync.exe:     $(RSYNC_SRC) $(LIBRESOBJS)
        $(LTLINK) $(RSYNC_OPT) $(NO_WARN) $(RSYNC_SRC) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
 
-scrub.exe:     $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
-       $(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
-
 srcck1.exe:    $(TOP)\tool\srcck1.c
        $(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\srcck1.c
 
diff --git a/ext/misc/scrub.c b/ext/misc/scrub.c
deleted file mode 100644 (file)
index 2406d39..0000000
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
-** 2016-05-05
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file implements a utility function (and a utility program) that
-** makes a copy of an SQLite database while simultaneously zeroing out all
-** deleted content.
-**
-** Normally (when PRAGMA secure_delete=OFF, which is the default) when SQLite
-** deletes content, it does not overwrite the deleted content but rather marks
-** the region of the file that held that content as being reusable.  This can
-** cause deleted content to recoverable from the database file.  This stale
-** content is removed by the VACUUM command, but VACUUM can be expensive for
-** large databases.  When in PRAGMA secure_delete=ON mode, the deleted content
-** is zeroed, but secure_delete=ON has overhead as well.
-**
-** This utility attempts to make a copy of a complete SQLite database where
-** all of the deleted content is zeroed out in the copy, and it attempts to
-** do so while being faster than running VACUUM.
-**
-** Usage:
-**
-**   int sqlite3_scrub_backup(
-**       const char *zSourceFile,   // Source database filename
-**       const char *zDestFile,     // Destination database filename
-**       char **pzErrMsg            // Write error message here
-**   );
-**
-** Simply call the API above specifying the filename of the source database
-** and the name of the backup copy.  The source database must already exist
-** and can be in active use. (A read lock is held during the backup.)  The
-** destination file should not previously exist.  If the pzErrMsg parameter
-** is non-NULL and if an error occurs, then an error message might be written
-** into memory obtained from sqlite3_malloc() and *pzErrMsg made to point to
-** that error message.  But if the error is an OOM, the error might not be
-** reported.  The routine always returns non-zero if there is an error.
-**
-** If compiled with -DSCRUB_STANDALONE then a main() procedure is added and
-** this file becomes a standalone program that can be run as follows:
-**
-**      ./sqlite3scrub SOURCE DEST
-*/
-#include "sqlite3.h"
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-typedef struct ScrubState ScrubState;
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-
-/* State information for a scrub-and-backup operation */
-struct ScrubState {
-  const char *zSrcFile;    /* Name of the source file */
-  const char *zDestFile;   /* Name of the destination file */
-  int rcErr;               /* Error code */
-  char *zErr;              /* Error message text */
-  sqlite3 *dbSrc;          /* Source database connection */
-  sqlite3_file *pSrc;      /* Source file handle */
-  sqlite3 *dbDest;         /* Destination database connection */
-  sqlite3_file *pDest;     /* Destination file handle */
-  u32 szPage;              /* Page size */
-  u32 szUsable;            /* Usable bytes on each page */
-  u32 nPage;               /* Number of pages */
-  u32 iLastPage;           /* Page number of last page written so far*/
-  u8 *page1;               /* Content of page 1 */
-};
-
-/* Store an error message */
-static void scrubBackupErr(ScrubState *p, const char *zFormat, ...){
-  va_list ap;
-  sqlite3_free(p->zErr);
-  va_start(ap, zFormat);
-  p->zErr = sqlite3_vmprintf(zFormat, ap);
-  va_end(ap);
-  if( p->rcErr==0 ) p->rcErr = SQLITE_ERROR;
-}
-
-/* Allocate memory to hold a single page of content */
-static u8 *scrubBackupAllocPage(ScrubState *p){
-  u8 *pPage;
-  if( p->rcErr ) return 0;
-  pPage = sqlite3_malloc64( p->szPage );
-  if( pPage==0 ) p->rcErr = SQLITE_NOMEM;
-  return pPage;
-}
-
-/* Read a page from the source database into memory.  Use the memory
-** provided by pBuf if not NULL or allocate a new page if pBuf==NULL.
-*/
-static u8 *scrubBackupRead(ScrubState *p, int pgno, u8 *pBuf){
-  int rc;
-  sqlite3_int64 iOff;
-  u8 *pOut = pBuf;
-  if( p->rcErr ) return 0;
-  if( pOut==0 ){
-    pOut = scrubBackupAllocPage(p);
-    if( pOut==0 ) return 0;
-  }
-  iOff = (pgno-1)*(sqlite3_int64)p->szPage;
-  rc = p->pSrc->pMethods->xRead(p->pSrc, pOut, p->szPage, iOff);
-  if( rc!=SQLITE_OK ){
-    if( pBuf==0 ) sqlite3_free(pOut);
-    pOut = 0;
-    scrubBackupErr(p, "read failed for page %d", pgno);
-    p->rcErr = SQLITE_IOERR;
-  }
-  return pOut;  
-}
-
-/* Write a page to the destination database */
-static void scrubBackupWrite(ScrubState *p, int pgno, const u8 *pData){
-  int rc;
-  sqlite3_int64 iOff;
-  if( p->rcErr ) return;
-  iOff = (pgno-1)*(sqlite3_int64)p->szPage;
-  rc = p->pDest->pMethods->xWrite(p->pDest, pData, p->szPage, iOff);
-  if( rc!=SQLITE_OK ){
-    scrubBackupErr(p, "write failed for page %d", pgno);
-    p->rcErr = SQLITE_IOERR;
-  }
-  if( (u32)pgno>p->iLastPage ) p->iLastPage = pgno;
-}
-
-/* Prepare a statement against the "db" database. */
-static sqlite3_stmt *scrubBackupPrepare(
-  ScrubState *p,      /* Backup context */
-  sqlite3 *db,        /* Database to prepare against */
-  const char *zSql    /* SQL statement */
-){
-  sqlite3_stmt *pStmt;
-  if( p->rcErr ) return 0;
-  p->rcErr = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
-  if( p->rcErr ){
-    scrubBackupErr(p, "SQL error \"%s\" on \"%s\"",
-                   sqlite3_errmsg(db), zSql);
-    sqlite3_finalize(pStmt);
-    return 0;
-  }
-  return pStmt;
-}
-
-
-/* Open the source database file */
-static void scrubBackupOpenSrc(ScrubState *p){
-  sqlite3_stmt *pStmt;
-  int rc;
-  /* Open the source database file */
-  p->rcErr = sqlite3_open_v2(p->zSrcFile, &p->dbSrc,
-                 SQLITE_OPEN_READWRITE |
-                 SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
-  if( p->rcErr ){
-    scrubBackupErr(p, "cannot open source database: %s",
-                      sqlite3_errmsg(p->dbSrc));
-    return;
-  }
-  p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_schema; BEGIN;",
-                          0, 0, 0);
-  if( p->rcErr ){
-    scrubBackupErr(p,
-       "cannot start a read transaction on the source database: %s",
-       sqlite3_errmsg(p->dbSrc));
-    return;
-  }
-  rc = sqlite3_wal_checkpoint_v2(p->dbSrc, "main", SQLITE_CHECKPOINT_FULL,
-                                 0, 0);
-  if( rc ){
-    scrubBackupErr(p, "cannot checkpoint the source database");
-    return;
-  }
-  pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_size");
-  if( pStmt==0 ) return;
-  rc = sqlite3_step(pStmt);
-  if( rc==SQLITE_ROW ){
-    p->szPage = sqlite3_column_int(pStmt, 0);
-  }else{
-    scrubBackupErr(p, "unable to determine the page size");
-  }
-  sqlite3_finalize(pStmt);
-  if( p->rcErr ) return;
-  pStmt = scrubBackupPrepare(p, p->dbSrc, "PRAGMA page_count");
-  if( pStmt==0 ) return;
-  rc = sqlite3_step(pStmt);
-  if( rc==SQLITE_ROW ){
-    p->nPage = sqlite3_column_int(pStmt, 0);
-  }else{
-    scrubBackupErr(p, "unable to determine the size of the source database");
-  }
-  sqlite3_finalize(pStmt);
-  sqlite3_file_control(p->dbSrc, "main", SQLITE_FCNTL_FILE_POINTER, &p->pSrc);
-  if( p->pSrc==0 || p->pSrc->pMethods==0 ){
-    scrubBackupErr(p, "cannot get the source file handle");
-    p->rcErr = SQLITE_ERROR;
-  }
-}
-
-/* Create and open the destination file */
-static void scrubBackupOpenDest(ScrubState *p){
-  sqlite3_stmt *pStmt;
-  int rc;
-  char *zSql;
-  if( p->rcErr ) return;
-  p->rcErr = sqlite3_open_v2(p->zDestFile, &p->dbDest,
-                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
-                 SQLITE_OPEN_URI | SQLITE_OPEN_PRIVATECACHE, 0);
-  if( p->rcErr ){
-    scrubBackupErr(p, "cannot open destination database: %s",
-                      sqlite3_errmsg(p->dbDest));
-    return;
-  }
-  zSql = sqlite3_mprintf("PRAGMA page_size(%u);", p->szPage);
-  if( zSql==0 ){
-    p->rcErr = SQLITE_NOMEM;
-    return;
-  }
-  p->rcErr = sqlite3_exec(p->dbDest, zSql, 0, 0, 0);
-  sqlite3_free(zSql);
-  if( p->rcErr ){
-    scrubBackupErr(p,
-       "cannot set the page size on the destination database: %s",
-       sqlite3_errmsg(p->dbDest));
-    return;
-  }
-  sqlite3_exec(p->dbDest, "PRAGMA journal_mode=OFF;", 0, 0, 0);
-  p->rcErr = sqlite3_exec(p->dbDest, "BEGIN EXCLUSIVE;", 0, 0, 0);
-  if( p->rcErr ){
-    scrubBackupErr(p,
-       "cannot start a write transaction on the destination database: %s",
-       sqlite3_errmsg(p->dbDest));
-    return;
-  }
-  pStmt = scrubBackupPrepare(p, p->dbDest, "PRAGMA page_count;");
-  if( pStmt==0 ) return;
-  rc = sqlite3_step(pStmt);
-  if( rc!=SQLITE_ROW ){
-    scrubBackupErr(p, "cannot measure the size of the destination");
-  }else if( sqlite3_column_int(pStmt, 0)>1 ){
-    scrubBackupErr(p, "destination database is not empty - holds %d pages",
-                   sqlite3_column_int(pStmt, 0));
-  }
-  sqlite3_finalize(pStmt);
-  sqlite3_file_control(p->dbDest, "main", SQLITE_FCNTL_FILE_POINTER, &p->pDest);
-  if( p->pDest==0 || p->pDest->pMethods==0 ){
-    scrubBackupErr(p, "cannot get the destination file handle");
-    p->rcErr = SQLITE_ERROR;
-  }
-}
-
-/* Read a 32-bit big-endian integer */
-static u32 scrubBackupInt32(const u8 *a){
-  u32 v = a[3];
-  v += ((u32)a[2])<<8;
-  v += ((u32)a[1])<<16;
-  v += ((u32)a[0])<<24;
-  return v;
-}
-
-/* Read a 16-bit big-endian integer */
-static u32 scrubBackupInt16(const u8 *a){
-  return (a[0]<<8) + a[1];
-}
-
-/*
-** Read a varint.  Put the value in *pVal and return the number of bytes.
-*/
-static int scrubBackupVarint(const u8 *z, sqlite3_int64 *pVal){
-  sqlite3_int64 v = 0;
-  int i;
-  for(i=0; i<8; i++){
-    v = (v<<7) + (z[i]&0x7f);
-    if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
-  }
-  v = (v<<8) + (z[i]&0xff);
-  *pVal = v;
-  return 9;
-}
-
-/*
-** Return the number of bytes in a varint.
-*/
-static int scrubBackupVarintSize(const u8 *z){
-  int i;
-  for(i=0; i<8; i++){
-    if( (z[i]&0x80)==0 ){ return i+1; }
-  }
-  return 9;
-}
-
-/*
-** Copy the freelist trunk page given, and all its descendents,
-** zeroing out as much as possible in the process.
-*/
-static void scrubBackupFreelist(ScrubState *p, int pgno, u32 nFree){
-  u8 *a, *aBuf;
-  u32 n, mx;
-
-  if( p->rcErr ) return;
-  aBuf = scrubBackupAllocPage(p);
-  if( aBuf==0 ) return;
-  while( pgno && nFree){
-    a = scrubBackupRead(p, pgno, aBuf);
-    if( a==0 ) break;
-    n = scrubBackupInt32(&a[4]);
-    mx = p->szUsable/4 - 2;
-    if( n<mx ){
-      memset(&a[n*4+8], 0, 4*(mx-n));
-    }
-    scrubBackupWrite(p, pgno, a);
-    pgno = scrubBackupInt32(a);
-#if 0
-    /* There is really no point in copying the freelist leaf pages.
-    ** Simply leave them uninitialized in the destination database.  The
-    ** OS filesystem should zero those pages for us automatically.
-    */
-    for(i=0; i<n && nFree; i++){
-      u32 iLeaf = scrubBackupInt32(&a[i*4+8]);
-      if( aZero==0 ){
-        aZero = scrubBackupAllocPage(p);
-        if( aZero==0 ){ pgno = 0; break; }
-        memset(aZero, 0, p->szPage);
-      }
-      scrubBackupWrite(p, iLeaf, aZero);
-      nFree--;
-    }
-#endif
-  }
-  sqlite3_free(aBuf);
-}
-
-/*
-** Copy an overflow chain from source to destination.  Zero out any
-** unused tail at the end of the overflow chain.
-*/
-static void scrubBackupOverflow(ScrubState *p, int pgno, u32 nByte){
-  u8 *a, *aBuf;
-
-  aBuf = scrubBackupAllocPage(p);
-  if( aBuf==0 ) return;
-  while( nByte>0 && pgno!=0 ){
-    a = scrubBackupRead(p, pgno, aBuf);
-    if( a==0 ) break;
-    if( nByte >= (p->szUsable)-4 ){
-      nByte -= (p->szUsable) - 4;
-    }else{
-      u32 x = (p->szUsable - 4) - nByte;
-      u32 i = p->szUsable - x;
-      memset(&a[i], 0, x);
-      nByte = 0;
-    }
-    scrubBackupWrite(p, pgno, a);
-    pgno = scrubBackupInt32(a);
-  }
-  sqlite3_free(aBuf);      
-}
-   
-
-/*
-** Copy B-Tree page pgno, and all of its children, from source to destination.
-** Zero out deleted content during the copy.
-*/
-static void scrubBackupBtree(ScrubState *p, int pgno, int iDepth){
-  u8 *a;
-  u32 i, n, pc;
-  u32 nCell;
-  u32 nPrefix;
-  u32 szHdr;
-  u32 iChild;
-  u8 *aTop;
-  u8 *aCell;
-  u32 x, y;
-  int ln = 0;
-
-  
-  if( p->rcErr ) return;
-  if( iDepth>50 ){
-    scrubBackupErr(p, "corrupt: b-tree too deep at page %d", pgno);
-    return;
-  }
-  if( pgno==1 ){
-    a = p->page1;
-  }else{
-    a = scrubBackupRead(p, pgno, 0);
-    if( a==0 ) return;
-  }
-  nPrefix = pgno==1 ? 100 : 0;
-  aTop = &a[nPrefix];
-  szHdr = 8 + 4*(aTop[0]==0x02 || aTop[0]==0x05);
-  aCell = aTop + szHdr;
-  nCell = scrubBackupInt16(&aTop[3]);
-
-  /* Zero out the gap between the cell index and the start of the
-  ** cell content area */
-  x = scrubBackupInt16(&aTop[5]);  /* First byte of cell content area */
-  if( x>p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
-  y = szHdr + nPrefix + nCell*2;
-  if( y>x ){ ln=__LINE__; goto btree_corrupt; }
-  if( y<x ) memset(a+y, 0, x-y);  /* Zero the gap */
-
-  /* Zero out all the free blocks */  
-  pc = scrubBackupInt16(&aTop[1]);
-  if( pc>0 && pc<x ){ ln=__LINE__; goto btree_corrupt; }
-  while( pc ){
-    if( pc>(p->szUsable)-4 ){ ln=__LINE__; goto btree_corrupt; }
-    n = scrubBackupInt16(&a[pc+2]);
-    if( pc+n>(p->szUsable) ){ ln=__LINE__; goto btree_corrupt; }
-    if( n>4 ) memset(&a[pc+4], 0, n-4);
-    x = scrubBackupInt16(&a[pc]);
-    if( x<pc+4 && x>0 ){ ln=__LINE__; goto btree_corrupt; }
-    pc = x;
-  }
-
-  /* Write this one page */
-  scrubBackupWrite(p, pgno, a);
-
-  /* Walk the tree and process child pages */
-  for(i=0; i<nCell; i++){
-    u32 X, M, K, nLocal;
-    sqlite3_int64 P;
-    pc = scrubBackupInt16(&aCell[i*2]);
-    if( pc <= szHdr ){ ln=__LINE__; goto btree_corrupt; }
-    if( pc > p->szUsable-3 ){ ln=__LINE__; goto btree_corrupt; }
-    if( aTop[0]==0x05 || aTop[0]==0x02 ){
-      if( pc+4 > p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
-      iChild = scrubBackupInt32(&a[pc]);
-      pc += 4;
-      scrubBackupBtree(p, iChild, iDepth+1);
-      if( aTop[0]==0x05 ) continue;
-    }
-    pc += scrubBackupVarint(&a[pc], &P);
-    if( pc >= p->szUsable ){ ln=__LINE__; goto btree_corrupt; }
-    if( aTop[0]==0x0d ){
-      X = p->szUsable - 35;
-    }else{
-      X = ((p->szUsable - 12)*64/255) - 23;
-    }
-    if( P<=X ){
-      /* All content is local.  No overflow */
-      continue;
-    }
-    M = ((p->szUsable - 12)*32/255)-23;
-    K = M + ((P-M)%(p->szUsable-4));
-    if( aTop[0]==0x0d ){
-      pc += scrubBackupVarintSize(&a[pc]);
-      if( pc > (p->szUsable-4) ){ ln=__LINE__; goto btree_corrupt; }
-    }
-    nLocal = K<=X ? K : M;
-    if( pc+nLocal > p->szUsable-4 ){ ln=__LINE__; goto btree_corrupt; }
-    iChild = scrubBackupInt32(&a[pc+nLocal]);
-    scrubBackupOverflow(p, iChild, (u32)(P-nLocal));
-  }
-
-  /* Walk the right-most tree */
-  if( aTop[0]==0x05 || aTop[0]==0x02 ){
-    iChild = scrubBackupInt32(&aTop[8]);
-    scrubBackupBtree(p, iChild, iDepth+1);
-  }
-
-  /* All done */
-  if( pgno>1 ) sqlite3_free(a);
-  return;
-
-btree_corrupt:
-  scrubBackupErr(p, "corruption on page %d of source database (errid=%d)",
-                 pgno, ln);
-  if( pgno>1 ) sqlite3_free(a);  
-}
-
-/*
-** Copy all ptrmap pages from source to destination.
-** This routine is only called if the source database is in autovacuum
-** or incremental vacuum mode.
-*/
-static void scrubBackupPtrmap(ScrubState *p){
-  u32 pgno = 2;
-  u32 J = p->szUsable/5;
-  u32 iLock = (1073742335/p->szPage)+1;
-  u8 *a, *pBuf;
-  if( p->rcErr ) return;
-  pBuf = scrubBackupAllocPage(p);
-  if( pBuf==0 ) return;
-  while( pgno<=p->nPage ){
-    a = scrubBackupRead(p, pgno, pBuf);
-    if( a==0 ) break;
-    scrubBackupWrite(p, pgno, a);
-    pgno += J+1;
-    if( pgno==iLock ) pgno++;
-  }
-  sqlite3_free(pBuf);
-}
-
-int sqlite3_scrub_backup(
-  const char *zSrcFile,    /* Source file */
-  const char *zDestFile,   /* Destination file */
-  char **pzErr             /* Write error here if non-NULL */
-){
-  ScrubState s;
-  u32 n, i;
-  sqlite3_stmt *pStmt;
-
-  memset(&s, 0, sizeof(s));
-  s.zSrcFile = zSrcFile;
-  s.zDestFile = zDestFile;
-
-  /* Open both source and destination databases */
-  scrubBackupOpenSrc(&s);
-  scrubBackupOpenDest(&s);
-
-  /* Read in page 1 */
-  s.page1 = scrubBackupRead(&s, 1, 0);
-  if( s.page1==0 ) goto scrub_abort;
-  s.szUsable = s.szPage - s.page1[20];
-
-  /* Copy the freelist */    
-  n = scrubBackupInt32(&s.page1[36]);
-  i = scrubBackupInt32(&s.page1[32]);
-  if( n ) scrubBackupFreelist(&s, i, n);
-
-  /* Copy ptrmap pages */
-  n = scrubBackupInt32(&s.page1[52]);
-  if( n ) scrubBackupPtrmap(&s);
-
-  /* Copy all of the btrees */
-  scrubBackupBtree(&s, 1, 0);
-  pStmt = scrubBackupPrepare(&s, s.dbSrc,
-       "SELECT rootpage FROM sqlite_schema WHERE coalesce(rootpage,0)>0");
-  if( pStmt==0 ) goto scrub_abort;
-  while( sqlite3_step(pStmt)==SQLITE_ROW ){
-    i = (u32)sqlite3_column_int(pStmt, 0);
-    scrubBackupBtree(&s, i, 0);
-  }
-  sqlite3_finalize(pStmt);
-
-  /* If the last page of the input db file is a free-list leaf, then the
-  ** backup file on disk is still smaller than the size indicated within 
-  ** the database header. In this case, write a page of zeroes to the 
-  ** last page of the backup database so that SQLite does not mistakenly
-  ** think the db is corrupt.  */
-  if( s.iLastPage<s.nPage ){
-    u8 *aZero = scrubBackupAllocPage(&s);
-    if( aZero ){
-      memset(aZero, 0, s.szPage);
-      scrubBackupWrite(&s, s.nPage, aZero);
-      sqlite3_free(aZero);
-    }
-  }
-
-scrub_abort:    
-  /* Close the destination database without closing the transaction. If we
-  ** commit, page zero will be overwritten. */
-  sqlite3_close(s.dbDest);
-
-  /* But do close out the read-transaction on the source database */
-  sqlite3_exec(s.dbSrc, "COMMIT;", 0, 0, 0);
-  sqlite3_close(s.dbSrc);
-  sqlite3_free(s.page1);
-  if( pzErr ){
-    *pzErr = s.zErr;
-  }else{
-    sqlite3_free(s.zErr);
-  }
-  return s.rcErr;
-}   
-
-#ifdef SCRUB_STANDALONE
-/* Error and warning log */
-static void errorLogCallback(void *pNotUsed, int iErr, const char *zMsg){
-  const char *zType;
-  switch( iErr&0xff ){
-    case SQLITE_WARNING: zType = "WARNING";  break;
-    case SQLITE_NOTICE:  zType = "NOTICE";   break;
-    default:             zType = "ERROR";    break;
-  }
-  fprintf(stderr, "%s: %s\n", zType, zMsg);
-}
-
-/* The main() routine when this utility is run as a stand-alone program */
-int main(int argc, char **argv){
-  char *zErr = 0;
-  int rc;
-  if( argc!=3 ){
-    fprintf(stderr,"Usage: %s SOURCE DESTINATION\n", argv[0]);
-    exit(1);
-  }
-  sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, 0);
-  rc = sqlite3_scrub_backup(argv[1], argv[2], &zErr);
-  if( rc==SQLITE_NOMEM ){
-    fprintf(stderr, "%s: out of memory\n", argv[0]);
-    exit(1);
-  }
-  if( zErr ){
-    fprintf(stderr, "%s: %s\n", argv[0], zErr);
-    sqlite3_free(zErr);
-    exit(1);
-  }
-  return 0;
-}
-#endif
diff --git a/main.mk b/main.mk
index 337a754d9230603f97b5fe1f7bf7e4f508aad31c..7d01b3eed0d570ece4dc5ba078d34180c6ff740f 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -2236,11 +2236,6 @@ install: install-man1
 install-pc: sqlite3.pc $(install-dir.pkgconfig)
        $(INSTALL.noexec) sqlite3.pc "$(install-dir.pkgconfig)"
 
-scrub$(T.exe): $(TOP)/ext/misc/scrub.c sqlite3.o
-       $(T.link) -o $@ -I. -DSCRUB_STANDALONE \
-               $(TOP)/ext/misc/scrub.c sqlite3.o $(LDFLAGS.libsqlite3)
-xbin: scrub$(T.exe)
-
 srcck1$(B.exe):        $(TOP)/tool/srcck1.c
        $(B.cc) -o srcck1$(B.exe) $(TOP)/tool/srcck1.c
 xbin: srcck1$(B.exe)
index a436121a7cb125c1da6d63dd00390514bf9985ca..63ea87624343e614498a2ab14ae1b94e37ce56da 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Be\ssure\sto\sdo\sfloating-point\sto\stext\sconversions\sin\sJSON\sto\sthe\sfull\n17-digits.
-D 2026-05-29T23:14:22.751
+C Remove\sthe\suntested\sand\sundocumented\s"scrub"\sutility\sprogram.\s\sIt\swas\swritten\nin\s2016,\sbut\smade\sobsolete\sby\sthe\s[VACUUM\sINTO]\scommand\sin\s2019.
+D 2026-05-30T10:09:33.845
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -7,7 +7,7 @@ F AGENTS.md 44ddfb38ef23e277888bd70ae378e6cbf5f5cab0e2a4420bd21d89b6caff7a4a
 F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
 F Makefile.in 5fda086f33b144da08119255da1d2557f983d0764a13707f05acf0159fd89ba5
 F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
-F Makefile.msc 3b2129c90e15ea734682c8769b567012200ac30d7ff1e73c4717e23edbe1bb4b
+F Makefile.msc 46ff6560f0046d92017ccafc91a3cd6cb2b54fbd25c56b2b6890cd84ed268159
 F README.md f00091ffb5c6379b783afb57ca5f443a5742e119082f37c407f64a5e16c56346
 F VERSION 99cf3be5f13d091183e4314b7fc2e0c0e69accfbe64608b45a313338bbdd7b62
 F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -395,7 +395,6 @@ F ext/misc/randomjson.c ef835fc64289e76ac4873b85fe12f9463a036168d7683cf2b773e36e
 F ext/misc/regexp.c 378e6e84516952a4b9f3f4df88927f20e6538e2609f55b773ed78899dab8206e
 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
 F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
-F ext/misc/scrub.c df54e202887e480bf9cd73168c9ac829e3b0211381b68b9809e0cb5bc1bdc2cf
 F ext/misc/series.c 496f43bac9bad2ee2cea63fb5212036f30ad3003b4cd317d5c2d6f3ad7c7d264
 F ext/misc/sha1.c 9a11826db885e8afd997c0a1b28bb799a43e462ef770ac33f19e744887c9c6fa
 F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
@@ -660,7 +659,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
 F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
 F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
 F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk 0bbfd0c3d2d3ac908b2a6ab4017bd650be0e694291b7f97490877b7c28a147e4
+F main.mk 77e33a16a795abd4a07a55f7eb2e11136326998db597b67c8655d5d2d9b98054
 F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -2208,8 +2207,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P c7839f7a1749b38f8a36c06d93a7b59095e91ce753e8dd020de273ca8f73a239
-R 98e56ce237be73746fac763491f7390f
+P 61a776650cdc3fe632bdb1dc39f50f542b00a9e5b468180eb54b69750d0cd70c
+R 9c2fc9974fe8017282e58f1c910cfd7a
 U drh
-Z 387ede1c1d94fbfd8f5814bf5cc8fe24
+Z 51c91ccc61b1424ccb83e3d868932c40
 # Remove this line to create a well-formed Fossil manifest.
index 4d6faa82fb465852af8e29a6626a69a278a39985..7b470bcb8a791d06fe63eb4dbcd854e9f8597341 100644 (file)
@@ -1 +1 @@
-61a776650cdc3fe632bdb1dc39f50f542b00a9e5b468180eb54b69750d0cd70c
+27d67fb175e839f6e7450f54166b52e0a6137c075758511da32fd82c57c310c4