/ Check-in [f5c26547]
Login

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

Overview
Comment:Fix for ticket #146: Correctly handle reads of unused disk blocks at the end of the file. (CVS 743)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:f5c2654768a6201fc554b59f1b2f56bcce738bc4
User & Date: drh 2002-09-05 16:08:27
Context
2002-09-05
19:10
Rewind the checkpoint journal after each statement to avoid allowing the file to become too large. (CVS 744) check-in: f4288520 user: drh tags: trunk
16:08
Fix for ticket #146: Correctly handle reads of unused disk blocks at the end of the file. (CVS 743) check-in: f5c26547 user: drh tags: trunk
2002-09-03
19:43
Always fill in the 5th parameter to sqlite_exec if there is an error. (CVS 742) check-in: 7f8fd5c7 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os.c.

475
476
477
478
479
480
481
482



483

484
485
486
487
488
489
490



491

492
493
494
495
496
497
498
499
500
501
502
503
504




505

506
507
508

509
510
511




512
513
514
515
516
517
518
...
533
534
535
536
537
538
539
540




541
542
543




544
545
546
547
548
549
550
*/
int sqliteOsRead(OsFile *id, void *pBuf, int amt){
#if OS_UNIX
  int got;
  SimulateIOError(SQLITE_IOERR);
  TRACE2("READ %d\n", last_page);
  got = read(id->fd, pBuf, amt);
  if( got<0 ) got = 0;



  return got==amt ? SQLITE_OK : SQLITE_IOERR;

#endif
#if OS_WIN
  DWORD got;
  SimulateIOError(SQLITE_IOERR);
  if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
    got = 0;
  }



  return got==amt ? SQLITE_OK : SQLITE_IOERR;

#endif
}

/*
** Write data from a buffer into a file.  Return SQLITE_OK on success
** or some other error code on failure.
*/
int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
#if OS_UNIX
  int wrote;
  SimulateIOError(SQLITE_IOERR);
  TRACE2("WRITE %d\n", last_page);
  wrote = write(id->fd, pBuf, amt);




  if( wrote<amt ) return SQLITE_FULL;

  return SQLITE_OK;
#endif
#if OS_WIN

  DWORD wrote;
  SimulateIOError(SQLITE_IOERR);
  if( !WriteFile(id->h, pBuf, amt, &wrote, 0) || (int)wrote<amt ){




    return SQLITE_FULL;
  }
  return SQLITE_OK;
#endif
}

/*
................................................................................
/*
** Make sure all writes to a particular file are committed to disk.
*/
int sqliteOsSync(OsFile *id){
  SimulateIOError(SQLITE_IOERR);
  TRACE1("SYNC\n");
#if OS_UNIX
  return fsync(id->fd)==0 ? SQLITE_OK : SQLITE_IOERR;




#endif
#if OS_WIN
  return FlushFileBuffers(id->h) ? SQLITE_OK : SQLITE_IOERR;




#endif
}

/*
** Truncate an open file to a specified size
*/
int sqliteOsTruncate(OsFile *id, int nByte){







|
>
>
>
|
>







>
>
>
|
>









|


|
>
>
>
>
|
>



>


|
>
>
>
>







 







|
>
>
>
>


|
>
>
>
>







475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
*/
int sqliteOsRead(OsFile *id, void *pBuf, int amt){
#if OS_UNIX
  int got;
  SimulateIOError(SQLITE_IOERR);
  TRACE2("READ %d\n", last_page);
  got = read(id->fd, pBuf, amt);
  /* if( got<0 ) got = 0; */
  if( got==amt ){
    return SQLITE_OK;
  }else{
    return SQLITE_IOERR;
  }
#endif
#if OS_WIN
  DWORD got;
  SimulateIOError(SQLITE_IOERR);
  if( !ReadFile(id->h, pBuf, amt, &got, 0) ){
    got = 0;
  }
  if( got==amt ){
    return SQLITE_OK;
  }else{
    return SQLITE_IOERR;
  }
#endif
}

/*
** Write data from a buffer into a file.  Return SQLITE_OK on success
** or some other error code on failure.
*/
int sqliteOsWrite(OsFile *id, const void *pBuf, int amt){
#if OS_UNIX
  int wrote = 0;
  SimulateIOError(SQLITE_IOERR);
  TRACE2("WRITE %d\n", last_page);
  while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){
    amt -= wrote;
    pBuf = &((char*)pBuf)[wrote];
  }
  if( amt>0 ){
    return SQLITE_FULL;
  }
  return SQLITE_OK;
#endif
#if OS_WIN
  int rc;
  DWORD wrote;
  SimulateIOError(SQLITE_IOERR);
  while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){
    amt -= wrote;
    pBuf = &((char*)pBuf)[wrote];
  }
  if( !rc || amt>(int)wrote ){
    return SQLITE_FULL;
  }
  return SQLITE_OK;
#endif
}

/*
................................................................................
/*
** Make sure all writes to a particular file are committed to disk.
*/
int sqliteOsSync(OsFile *id){
  SimulateIOError(SQLITE_IOERR);
  TRACE1("SYNC\n");
#if OS_UNIX
  if( fsync(id->fd) ){
    return SQLITE_IOERR;
  }else{
    return SQLITE_OK;
  }
#endif
#if OS_WIN
  if( FlushFileBuffers(id->h) ){
    return SQLITE_OK;
  }else{
    return SQLITE_IOERR;
  }
#endif
}

/*
** Truncate an open file to a specified size
*/
int sqliteOsTruncate(OsFile *id, int nByte){

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
999
1000
1001
1002
1003
1004
1005



1006



1007
1008
1009
1010
1011
1012
1013
....
1151
1152
1153
1154
1155
1156
1157
1158


1159
1160
1161
1162
1163
1164
1165
....
1359
1360
1361
1362
1363
1364
1365
1366


1367
1368
1369
1370
1371
1372
1373
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.51 2002/08/13 00:01:17 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "os.h"
#include <assert.h>
#include <string.h>

................................................................................
    if( pPager->dbSize<(int)pgno ){
      memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
    }else{
      int rc;
      sqliteOsSeek(&pPager->fd, (pgno-1)*SQLITE_PAGE_SIZE);
      rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
      if( rc!=SQLITE_OK ){



        return rc;



      }
    }
    if( pPager->nExtra>0 ){
      memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
    }
  }else{
    /* The requested page is in the page cache. */
................................................................................
      rc = sqliteOsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
    }
    if( rc==SQLITE_OK ){
      rc = write32bits(&pPager->jfd, pPager->dbSize);
    }
    if( rc!=SQLITE_OK ){
      rc = pager_unwritelock(pPager);
      if( rc==SQLITE_OK ) rc = SQLITE_FULL;


    }
  }
  return rc;
}

/*
** Mark a data page as writeable.  The page is written into the journal 
................................................................................
*/
int sqlitepager_commit(Pager *pPager){
  int rc;
  PgHdr *pPg;

  if( pPager->errMask==PAGER_ERR_FULL ){
    rc = sqlitepager_rollback(pPager);
    if( rc==SQLITE_OK ) rc = SQLITE_FULL;


    return rc;
  }
  if( pPager->errMask!=0 ){
    rc = pager_errcode(pPager);
    return rc;
  }
  if( pPager->state!=SQLITE_WRITELOCK ){







|







 







>
>
>
|
>
>
>







 







|
>
>







 







|
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
....
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
....
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.52 2002/09/05 16:08:27 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "os.h"
#include <assert.h>
#include <string.h>

................................................................................
    if( pPager->dbSize<(int)pgno ){
      memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
    }else{
      int rc;
      sqliteOsSeek(&pPager->fd, (pgno-1)*SQLITE_PAGE_SIZE);
      rc = sqliteOsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
      if( rc!=SQLITE_OK ){
        int fileSize;
        if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
               || fileSize>=pgno*SQLITE_PAGE_SIZE ){
          return rc;
        }else{
          memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
        }
      }
    }
    if( pPager->nExtra>0 ){
      memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
    }
  }else{
    /* The requested page is in the page cache. */
................................................................................
      rc = sqliteOsWrite(&pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
    }
    if( rc==SQLITE_OK ){
      rc = write32bits(&pPager->jfd, pPager->dbSize);
    }
    if( rc!=SQLITE_OK ){
      rc = pager_unwritelock(pPager);
      if( rc==SQLITE_OK ){
        rc = SQLITE_FULL;
      }
    }
  }
  return rc;
}

/*
** Mark a data page as writeable.  The page is written into the journal 
................................................................................
*/
int sqlitepager_commit(Pager *pPager){
  int rc;
  PgHdr *pPg;

  if( pPager->errMask==PAGER_ERR_FULL ){
    rc = sqlitepager_rollback(pPager);
    if( rc==SQLITE_OK ){
      rc = SQLITE_FULL;
    }
    return rc;
  }
  if( pPager->errMask!=0 ){
    rc = pager_errcode(pPager);
    return rc;
  }
  if( pPager->state!=SQLITE_WRITELOCK ){