Index: third_party/sqlite/src/src/backup.c |
diff --git a/third_party/sqlite/src/src/backup.c b/third_party/sqlite/src/src/backup.c |
index 9fcb669106dd3bfff953d50d4e653ab453cc4722..1c282242d7a578822602ab6726409e7acac6fe71 100644 |
--- a/third_party/sqlite/src/src/backup.c |
+++ b/third_party/sqlite/src/src/backup.c |
@@ -123,6 +123,20 @@ static int setDestPgsz(sqlite3_backup *p){ |
} |
/* |
+** Check that there is no open read-transaction on the b-tree passed as the |
+** second argument. If there is not, return SQLITE_OK. Otherwise, if there |
+** is an open read-transaction, return SQLITE_ERROR and leave an error |
+** message in database handle db. |
+*/ |
+static int checkReadTransaction(sqlite3 *db, Btree *p){ |
+ if( sqlite3BtreeIsInReadTrans(p) ){ |
+ sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); |
+ return SQLITE_ERROR; |
+ } |
+ return SQLITE_OK; |
+} |
+ |
+/* |
** Create an sqlite3_backup process to copy the contents of zSrcDb from |
** connection handle pSrcDb to zDestDb in pDestDb. If successful, return |
** a pointer to the new sqlite3_backup object. |
@@ -138,6 +152,13 @@ sqlite3_backup *sqlite3_backup_init( |
){ |
sqlite3_backup *p; /* Value to return */ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
+ |
/* Lock the source database handle. The destination database |
** handle is not locked in this routine, but it is locked in |
** sqlite3_backup_step(). The user is required to ensure that no |
@@ -174,12 +195,15 @@ sqlite3_backup *sqlite3_backup_init( |
p->iNext = 1; |
p->isAttached = 0; |
- if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){ |
+ if( 0==p->pSrc || 0==p->pDest |
+ || setDestPgsz(p)==SQLITE_NOMEM |
+ || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK |
+ ){ |
/* One (or both) of the named databases did not exist or an OOM |
- ** error was hit. The error has already been written into the |
- ** pDestDb handle. All that is left to do here is free the |
- ** sqlite3_backup structure. |
- */ |
+ ** error was hit. Or there is a transaction open on the destination |
+ ** database. The error has already been written into the pDestDb |
+ ** handle. All that is left to do here is free the sqlite3_backup |
+ ** structure. */ |
sqlite3_free(p); |
p = 0; |
} |
@@ -223,7 +247,7 @@ static int backupOnePage( |
** guaranteed that the shared-mutex is held by this thread, handle |
** p->pSrc may not actually be the owner. */ |
int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); |
- int nDestReserve = sqlite3BtreeGetReserve(p->pDest); |
+ int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); |
#endif |
int rc = SQLITE_OK; |
i64 iOff; |
@@ -269,7 +293,7 @@ static int backupOnePage( |
DbPage *pDestPg = 0; |
Pgno iDest = (Pgno)(iOff/nDestPgsz)+1; |
if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue; |
- if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg)) |
+ if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0)) |
&& SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg)) |
){ |
const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; |
@@ -334,6 +358,9 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ |
int pgszSrc = 0; /* Source page size */ |
int pgszDest = 0; /* Destination page size */ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( p==0 ) return SQLITE_MISUSE_BKPT; |
+#endif |
sqlite3_mutex_enter(p->pSrcDb->mutex); |
sqlite3BtreeEnter(p->pSrc); |
if( p->pDestDb ){ |
@@ -392,8 +419,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ |
const Pgno iSrcPg = p->iNext; /* Source page number */ |
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ |
DbPage *pSrcPg; /* Source page object */ |
- rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg, |
- PAGER_GET_READONLY); |
+ rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY); |
if( rc==SQLITE_OK ){ |
rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); |
sqlite3PagerUnref(pSrcPg); |
@@ -493,7 +519,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ |
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ |
if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ |
DbPage *pPg; |
- rc = sqlite3PagerGet(pDestPager, iPg, &pPg); |
+ rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0); |
if( rc==SQLITE_OK ){ |
rc = sqlite3PagerWrite(pPg); |
sqlite3PagerUnref(pPg); |
@@ -513,7 +539,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ |
){ |
PgHdr *pSrcPg = 0; |
const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1); |
- rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg); |
+ rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0); |
if( rc==SQLITE_OK ){ |
u8 *zData = sqlite3PagerGetData(pSrcPg); |
rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff); |
@@ -623,6 +649,12 @@ int sqlite3_backup_finish(sqlite3_backup *p){ |
** call to sqlite3_backup_step(). |
*/ |
int sqlite3_backup_remaining(sqlite3_backup *p){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( p==0 ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
return p->nRemaining; |
} |
@@ -631,6 +663,12 @@ int sqlite3_backup_remaining(sqlite3_backup *p){ |
** recent call to sqlite3_backup_step(). |
*/ |
int sqlite3_backup_pagecount(sqlite3_backup *p){ |
+#ifdef SQLITE_ENABLE_API_ARMOR |
+ if( p==0 ){ |
+ (void)SQLITE_MISUSE_BKPT; |
+ return 0; |
+ } |
+#endif |
return p->nPagecount; |
} |
@@ -646,9 +684,13 @@ int sqlite3_backup_pagecount(sqlite3_backup *p){ |
** corresponding to the source database is held when this function is |
** called. |
*/ |
-void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ |
- sqlite3_backup *p; /* Iterator variable */ |
- for(p=pBackup; p; p=p->pNext){ |
+static SQLITE_NOINLINE void backupUpdate( |
+ sqlite3_backup *p, |
+ Pgno iPage, |
+ const u8 *aData |
+){ |
+ assert( p!=0 ); |
+ do{ |
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); |
if( !isFatalError(p->rc) && iPage<p->iNext ){ |
/* The backup process p has already copied page iPage. But now it |
@@ -665,7 +707,10 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ |
p->rc = rc; |
} |
} |
- } |
+ }while( (p = p->pNext)!=0 ); |
+} |
+void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ |
+ if( pBackup ) backupUpdate(pBackup, iPage, aData); |
} |
/* |
@@ -723,6 +768,10 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ |
b.pDest = pTo; |
b.iNext = 1; |
+#ifdef SQLITE_HAS_CODEC |
+ sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); |
+#endif |
+ |
/* 0x7FFFFFFF is the hard limit for the number of pages in a database |
** file. By passing this as the number of pages to copy to |
** sqlite3_backup_step(), we can guarantee that the copy finishes |