/ Check-in [b34bde80]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a problem in backup.c causing OsTruncate() to be called with an argument larger than the current file-size. (CVS 6271)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b34bde80c7e2028baf7ba2ff26e587a63a170f3d
User & Date: danielk1977 2009-02-09 18:55:46
Context
2009-02-10
05:45
Fix a bug in test file misc7.test. No code changes. (CVS 6272) check-in: d919d2a1 user: danielk1977 tags: trunk
2009-02-09
18:55
Fix a problem in backup.c causing OsTruncate() to be called with an argument larger than the current file-size. (CVS 6271) check-in: b34bde80 user: danielk1977 tags: trunk
17:34
Add assert() statements to os_unix.c which fire if there is a read or write for the locking region of a database file. (CVS 6270) check-in: 93e792ff user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/backup.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains the implementation of the sqlite3_backup_XXX() 
    13     13   ** API functions and the related features.
    14     14   **
    15         -** $Id: backup.c,v 1.8 2009/02/06 05:59:44 danielk1977 Exp $
           15  +** $Id: backup.c,v 1.9 2009/02/09 18:55:46 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include "btreeInt.h"
    19     19   
    20     20   /* Macro to find the minimum of two numeric values.
    21     21   */
    22     22   #ifndef MIN
................................................................................
   249    249         ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
   250    250       }
   251    251       sqlite3PagerUnref(pDestPg);
   252    252     }
   253    253   
   254    254     return rc;
   255    255   }
          256  +
          257  +/*
          258  +** If pFile is currently larger than iSize bytes, then truncate it to
          259  +** exactly iSize bytes. If pFile is not larger than iSize bytes, then
          260  +** this function is a no-op.
          261  +**
          262  +** Return SQLITE_OK if everything is successful, or an SQLite error 
          263  +** code if an error occurs.
          264  +*/
          265  +static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
          266  +  i64 iCurrent;
          267  +  int rc = sqlite3OsFileSize(pFile, &iCurrent);
          268  +  if( rc==SQLITE_OK && iCurrent>iSize ){
          269  +    rc = sqlite3OsTruncate(pFile, iSize);
          270  +  }
          271  +  return rc;
          272  +}
   256    273   
   257    274   /*
   258    275   ** Copy nPage pages from the source b-tree to the destination.
   259    276   */
   260    277   int sqlite3_backup_step(sqlite3_backup *p, int nPage){
   261    278     int rc;
   262    279   
................................................................................
   326    343         }
   327    344       }
   328    345     
   329    346       if( rc==SQLITE_DONE ){
   330    347         const int nSrcPagesize = sqlite3BtreeGetPageSize(p->pSrc);
   331    348         const int nDestPagesize = sqlite3BtreeGetPageSize(p->pDest);
   332    349         int nDestTruncate;
   333         -      sqlite3_file *pFile = 0;
   334         -      i64 iSize;
   335    350     
   336    351         /* Update the schema version field in the destination database. This
   337    352         ** is to make sure that the schema-version really does change in
   338    353         ** the case where the source and destination databases have the
   339    354         ** same schema version.
   340    355         */
   341    356         sqlite3BtreeUpdateMeta(p->pDest, 1, p->iDestSchema+1);
................................................................................
   369    384           **
   370    385           **   * The destination may need to be truncated, and
   371    386           **
   372    387           **   * Data stored on the pages immediately following the 
   373    388           **     pending-byte page in the source database may need to be
   374    389           **     copied into the destination database.
   375    390           */
   376         -        iSize = (i64)nSrcPagesize * (i64)nSrcPage;
   377         -        pFile = sqlite3PagerFile(pDestPager);
          391  +        const i64 iSize = (i64)nSrcPagesize * (i64)nSrcPage;
          392  +        sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
          393  +
   378    394           assert( pFile );
          395  +        assert( (i64)nDestTruncate*(i64)nDestPagesize >= iSize );
   379    396           if( SQLITE_OK==(rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1))
   380         -         && SQLITE_OK==(rc = sqlite3OsTruncate(pFile, iSize))
          397  +         && SQLITE_OK==(rc = backupTruncateFile(pFile, iSize))
   381    398            && SQLITE_OK==(rc = sqlite3PagerSync(pDestPager))
   382    399           ){
   383    400             i64 iOff;
   384    401             i64 iEnd = MIN(PENDING_BYTE + nDestPagesize, iSize);
   385    402             for(
   386    403               iOff=PENDING_BYTE+nSrcPagesize; 
   387    404               rc==SQLITE_OK && iOff<iEnd; 

Changes to test/backup.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the sqlite3_backup_XXX API.
    13     13   #
    14         -# $Id: backup.test,v 1.4 2009/02/06 05:59:45 danielk1977 Exp $
           14  +# $Id: backup.test,v 1.5 2009/02/09 18:55:46 danielk1977 Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   #---------------------------------------------------------------------
    20     20   # Test organization:
    21     21   #
................................................................................
   259    259   #   * Target database does not include pending-byte page.
   260    260   #
   261    261   #   * Target database page-size is the same as the source, OR
   262    262   #   * Target database page-size is larger than the source, OR
   263    263   #   * Target database page-size is smaller than the source.
   264    264   #
   265    265   set iTest 1
   266         -foreach nSrcRow {10 100} {
          266  +foreach nSrcPg {10 64 65 66 100} {
   267    267   foreach nDestRow {10 100} {
   268    268   foreach nDestPgsz {512 1024 2048 4096} {
   269    269   
   270    270     catch { file delete test.db }
   271    271     catch { file delete test2.db }
   272    272     sqlite3 db test.db
   273    273     sqlite3 db2 test2.db
   274    274   
   275    275     # Set up the content of the two databases.
   276    276     #
   277         -  foreach {db nRow} [list db $nSrcRow db2 $nDestRow] {
          277  +  execsql { PRAGMA page_size = 1024 }
          278  +  execsql "PRAGMA page_size = $nDestPgsz" db2
          279  +  foreach db {db db2} {
   278    280       execsql {
   279    281         BEGIN; 
   280    282         CREATE TABLE t1(a, b);
   281    283         CREATE INDEX i1 ON t1(a, b);
          284  +      COMMIT;
   282    285       } $db
   283         -    for {set ii 0} {$ii < $nSrcRow} {incr ii} {
   284         -      execsql { INSERT INTO t1 VALUES($ii, randstr(1000,1000)) } $db
   285         -    }
   286         -    execsql COMMIT $db
          286  +  }
          287  +  while {[file size test.db]/1024 < $nSrcPg} {
          288  +    execsql { INSERT INTO t1 VALUES($ii, randstr(200,200)) }
          289  +  }
          290  +
          291  +  for {set ii 0} {$ii < $nDestRow} {incr ii} {
          292  +    execsql { INSERT INTO t1 VALUES($ii, randstr(1000,1000)) } db2
   287    293     }
   288         -    
          294  +
   289    295     # Backup the source database.
   290    296     do_test backup-3.$iTest.1 {
   291    297       sqlite3_backup B db main db2 main
   292    298       while {[B step 10]=="SQLITE_OK"} {}
   293    299       B finish
   294    300     } {SQLITE_OK}
   295    301