diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/os_win.c | 1 | ||||
-rw-r--r-- | src/pager.c | 25 | ||||
-rw-r--r-- | src/sqlite.h.in | 6 | ||||
-rw-r--r-- | src/test_vfstrace.c | 5 |
4 files changed, 36 insertions, 1 deletions
diff --git a/src/os_win.c b/src/os_win.c index 22052a3fe..56b546fb4 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -3192,6 +3192,7 @@ static int winSectorSize(sqlite3_file *id){ static int winDeviceCharacteristics(sqlite3_file *id){ winFile *p = (winFile*)id; return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | + SQLITE_IOCAP_UNMOVABLE_WHEN_OPEN | ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); } diff --git a/src/pager.c b/src/pager.c index d675b8582..78cb78ab2 100644 --- a/src/pager.c +++ b/src/pager.c @@ -4797,6 +4797,27 @@ int sqlite3PagerOpen( } +/* Verify that the database file has not be deleted or renamed out from +** under the pager. Return SQLITE_OK if the database is still were it ought +** to be on disk. Return non-zero (SQLITE_IOERR_NODB or some other error +** code from sqlite3OsAccess()) if the database has gone missing. +*/ +static int databaseIsUnmoved(Pager *pPager){ + const int fixedFlags = SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | + SQLITE_IOCAP_UNMOVABLE_WHEN_OPEN; + int dc; + int x = 0, rc; + + if( pPager->tempFile ) return SQLITE_OK; + if( pPager->dbSize==0 ) return SQLITE_OK; + assert( pPager->zFilename && pPager->zFilename[0] ); + dc = sqlite3OsDeviceCharacteristics(pPager->fd); + if( (dc&fixedFlags)==fixedFlags ) return SQLITE_OK; + rc = sqlite3OsAccess(pPager->pVfs, pPager->zFilename, SQLITE_ACCESS_EXISTS, &x); + if( rc==SQLITE_OK && !x ) rc = SQLITE_IOERR_NODB; + return rc; +} + /* ** This function is called after transitioning from PAGER_UNLOCK to @@ -4970,6 +4991,10 @@ int sqlite3PagerSharedLock(Pager *pPager){ goto failed; } + /* Verify that the database is unmoved and undeleted */ + rc = databaseIsUnmoved(pPager); + if( rc ) goto failed; + /* If a journal file exists, and there is no RESERVED lock on the ** database file, then it either needs to be played back or deleted. */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 98c89da32..de6b59b0b 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -475,6 +475,7 @@ int sqlite3_exec( #define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8)) #define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8)) #define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8)) +#define SQLITE_IOERR_NODB (SQLITE_IOERR | (27<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) @@ -553,7 +554,9 @@ int sqlite3_exec( ** after reboot following a crash or power loss, the only bytes in a ** file that were written at the application level might have changed ** and that adjacent bytes, even bytes within the same sector are -** guaranteed to be unchanged. +** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN +** and SQLITE_IOCAP_UNMOVABLE_WHEN_OPEN flags indicate that a file +** cannot be deleted or renamed when open, respectively. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 @@ -568,6 +571,7 @@ int sqlite3_exec( #define SQLITE_IOCAP_SEQUENTIAL 0x00000400 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 +#define SQLITE_IOCAP_UNMOVABLE_WHEN_OPEN 0x00002000 /* ** CAPI3REF: File Locking Levels diff --git a/src/test_vfstrace.c b/src/test_vfstrace.c index 0aacc01fe..8d56cf894 100644 --- a/src/test_vfstrace.c +++ b/src/test_vfstrace.c @@ -258,6 +258,11 @@ static void vfstrace_print_errcode( case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break; case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break; case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break; + case SQLITE_IOERR_SHMMAP: zVal = "SQLITE_IOERR_SHMMAP"; break; + case SQLITE_IOERR_SEEK: zVal = "SQLITE_IOERR_SEEK"; break; + case SQLITE_IOERR_GETTEMPPATH: zVal = "SQLITE_IOERR_GETTEMPPATH"; break; + case SQLITE_IOERR_CONVPATH: zVal = "SQLITE_IOERR_CONVPATH"; break; + case SQLITE_IOERR_NODB: zVal = "SQLITE_IOERR_NODB"; break; case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break; case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break; case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break; |