]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Ensure a database file is not truncated without an exclusive lock.
authordanielk1977 <danielk1977@noemail.net>
Tue, 15 Feb 2005 03:38:05 +0000 (03:38 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 15 Feb 2005 03:38:05 +0000 (03:38 +0000)
Fix for ticket #1114. (CVS 2332)

FossilOrigin-Name: dcbc983355d3207615b52b0724405a024a1a5955

manifest
manifest.uuid
src/pager.c

index 7aa1fa980966abfd368f2e7a819e72c046a8e4cc..37e083d78c1e9208e9c1defb1e078f634f1cf38c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Check\sthat\sread-only\spages\sare\snot\sbeing\smodified\s(disabled\sby\sdefault).\s(CVS\s2331)
-D 2005-02-15T02:54:15
+C Ensure\sa\sdatabase\sfile\sis\snot\struncated\swithout\san\sexclusive\slock.\r\nFix\sfor\sticket\s#1114.\s(CVS\s2332)
+D 2005-02-15T03:38:06
 F Makefile.in d928187101fa3d78426cf48ca30e39d0fb714e57
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -51,7 +51,7 @@ F src/os_unix.c 68d3d32937eee90fe1f50d500d1a4ee826cbe790
 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
 F src/os_win.c bddeae1c3299be0fbe47077dd4e98b786a067f71
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 69efe972d6034d8d5603f5b2a768e43e25dad0c0
+F src/pager.c 835028769569971c7dbd63d11d3517392f1cdae0
 F src/pager.h 70d496f372163abb6340f474288c4bb9ea962cf7
 F src/parse.y 450fc9c4d5a737be6fdba6e4b2e3de5800d4d750
 F src/pragma.c 7e65c5545d83909238adf231e2a6eee6eb43e0d5
@@ -271,7 +271,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd
-P cbed92f397ec13b57771ab8b5be74c0cacf35dfd
-R f5e0bf334bc8ca4771ae6f5140466932
+P 8514a4feb2a86e93c4251c491d394e861bb65edb
+R 68447a9e1a1587fdc5cb563c6b34ab1f
 U danielk1977
-Z 79138fc5bf3ab18977a8db63dd8b495b
+Z 2caaa7f8c9b8fb759f5bcfb478549a3f
index d68eba3a8c2b26c194b97391c7e3313a02dd4322..3ef30be8bca581632555c9f7eceb17ea0a798477 100644 (file)
@@ -1 +1 @@
-8514a4feb2a86e93c4251c491d394e861bb65edb
\ No newline at end of file
+dcbc983355d3207615b52b0724405a024a1a5955
\ No newline at end of file
index ab6490fb9d55c40390259eab83cf1ef4735e5596..4a65af72c17d0b7454f19260bc6f426ca4ce8162 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.189 2005/02/15 02:54:15 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.190 2005/02/15 03:38:06 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1137,6 +1137,7 @@ static int pager_reload_cache(Pager *pPager){
 ** indicated.
 */
 static int pager_truncate(Pager *pPager, int nPage){
+  assert( pPager->state>=PAGER_EXCLUSIVE );
   return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(i64)nPage);
 }
 
@@ -1256,7 +1257,8 @@ static int pager_playback(Pager *pPager){
     /* If this is the first header read from the journal, truncate the
     ** database file back to it's original size.
     */
-    if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
+    if( pPager->state>=PAGER_EXCLUSIVE && 
+        pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
       assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg );
       rc = pager_truncate(pPager, mxPg);
       if( rc!=SQLITE_OK ){
@@ -1354,10 +1356,11 @@ static int pager_stmt_playback(Pager *pPager){
     hdrOff = szJ;
   }
   
-
   /* Truncate the database back to its original size.
   */
-  rc = pager_truncate(pPager, pPager->stmtSize);
+  if( pPager->state>=PAGER_EXCLUSIVE ){
+    rc = pager_truncate(pPager, pPager->stmtSize);
+  }
   pPager->dbSize = pPager->stmtSize;
 
   /* Figure out how many records are in the statement journal.
@@ -1804,6 +1807,37 @@ static void memoryTruncate(Pager *pPager){
 #define memoryTruncate(p)
 #endif
 
+/*
+** Try to obtain a lock on a file.  Invoke the busy callback if the lock
+** is currently not available.  Repeate until the busy callback returns
+** false or until the lock succeeds.
+**
+** Return SQLITE_OK on success and an error code if we cannot obtain
+** the lock.
+*/
+static int pager_wait_on_lock(Pager *pPager, int locktype){
+  int rc;
+  assert( PAGER_SHARED==SHARED_LOCK );
+  assert( PAGER_RESERVED==RESERVED_LOCK );
+  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
+  if( pPager->state>=locktype ){
+    rc = SQLITE_OK;
+  }else{
+    int busy = 1;
+    do {
+      rc = sqlite3OsLock(&pPager->fd, locktype);
+    }while( rc==SQLITE_BUSY && 
+        pPager->pBusyHandler && 
+        pPager->pBusyHandler->xFunc && 
+        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
+    );
+    if( rc==SQLITE_OK ){
+      pPager->state = locktype;
+    }
+  }
+  return rc;
+}
+
 /*
 ** Truncate the file to the number of pages specified.
 */
@@ -1826,6 +1860,13 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){
   if( rc!=SQLITE_OK ){
     return rc;
   }
+
+  /* Get an exclusive lock on the database before truncating. */
+  rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+  if( rc!=SQLITE_OK ){
+    return rc;
+  }
+
   rc = pager_truncate(pPager, nPage);
   if( rc==SQLITE_OK ){
     pPager->dbSize = nPage;
@@ -2057,37 +2098,6 @@ static int syncJournal(Pager *pPager){
   return rc;
 }
 
-/*
-** Try to obtain a lock on a file.  Invoke the busy callback if the lock
-** is currently not available.  Repeate until the busy callback returns
-** false or until the lock succeeds.
-**
-** Return SQLITE_OK on success and an error code if we cannot obtain
-** the lock.
-*/
-static int pager_wait_on_lock(Pager *pPager, int locktype){
-  int rc;
-  assert( PAGER_SHARED==SHARED_LOCK );
-  assert( PAGER_RESERVED==RESERVED_LOCK );
-  assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
-  if( pPager->state>=locktype ){
-    rc = SQLITE_OK;
-  }else{
-    int busy = 1;
-    do {
-      rc = sqlite3OsLock(&pPager->fd, locktype);
-    }while( rc==SQLITE_BUSY && 
-        pPager->pBusyHandler && 
-        pPager->pBusyHandler->xFunc && 
-        pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, busy++)
-    );
-    if( rc==SQLITE_OK ){
-      pPager->state = locktype;
-    }
-  }
-  return rc;
-}
-
 /*
 ** Given a list of pages (connected by the PgHdr.pDirty pointer) write
 ** every one of those pages out to the database file and mark them all
@@ -3072,13 +3082,11 @@ int sqlite3pager_rollback(Pager *pPager){
     return pager_errcode(pPager);
   }
   if( pPager->state==PAGER_RESERVED ){
-    int rc2, rc3;
+    int rc2;
     rc = pager_reload_cache(pPager);
-    rc2 = pager_truncate(pPager, pPager->origDbSize);
-    rc3 = pager_unwritelock(pPager);
+    rc2 = pager_unwritelock(pPager);
     if( rc==SQLITE_OK ){
       rc = rc2;
-      if( rc3 ) rc = rc3;
     }
   }else{
     rc = pager_playback(pPager);