aboutsummaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2013-04-11 01:16:15 +0000
committerdrh <drh@noemail.net>2013-04-11 01:16:15 +0000
commitfbc7e8845d6c3a0b140306d46c3454ca6ac45288 (patch)
tree1bbe4d602423c8bb7deaa81a0aded37d20eb6cf6 /src/os_unix.c
parent08d418904a124936ff274240795a471cc6c1af77 (diff)
downloadsqlite-fbc7e8845d6c3a0b140306d46c3454ca6ac45288.tar.gz
sqlite-fbc7e8845d6c3a0b140306d46c3454ca6ac45288.zip
Have the UNIX VFS issue warnings via sqlite3_log() if a database file is
renamed or unlinked or linked to more than one name while the file is open. FossilOrigin-Name: e238dcf9189c029fbdcf89339e21d9cdd8fbf2c5
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index a65f894eb..778575f7b 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -280,6 +280,7 @@ struct unixFile {
#define UNIXFILE_DELETE 0x20 /* Delete on close */
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
+#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */
/*
** Include code that is common to all os_*.c files
@@ -799,7 +800,6 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
}
-
/******************************************************************************
****************** Begin Unique File ID Utility Used By VxWorks ***************
**
@@ -1301,6 +1301,50 @@ static int findInodeInfo(
/*
+** Check a unixFile that is a database. Verify the following:
+**
+** (1) There is exactly one hard link on the file
+** (2) The file is not a symbolic link
+** (3) The file has not been renamed or unlinked
+**
+** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
+*/
+static void verifyDbFile(unixFile *pFile){
+ struct stat buf;
+ int rc;
+ if( pFile->ctrlFlags & UNIXFILE_WARNED ){
+ /* One or more of the following warnings have already been issued. Do not
+ ** repeat them so as not to clutter the error log */
+ return;
+ }
+ rc = osFstat(pFile->h, &buf);
+ if( rc!=0 ){
+ sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
+ pFile->ctrlFlags |= UNIXFILE_WARNED;
+ return;
+ }
+ if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
+ sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
+ pFile->ctrlFlags |= UNIXFILE_WARNED;
+ return;
+ }
+ if( buf.st_nlink>1 ){
+ sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
+ pFile->ctrlFlags |= UNIXFILE_WARNED;
+ return;
+ }
+ if( pFile->pInode!=0
+ && ((rc = osStat(pFile->zPath, &buf))!=0
+ || buf.st_ino!=pFile->pInode->fileId.ino)
+ ){
+ sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
+ pFile->ctrlFlags |= UNIXFILE_WARNED;
+ return;
+ }
+}
+
+
+/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero. The return value
@@ -1876,6 +1920,7 @@ static int closeUnixFile(sqlite3_file *id){
static int unixClose(sqlite3_file *id){
int rc = SQLITE_OK;
unixFile *pFile = (unixFile *)id;
+ verifyDbFile(pFile);
unixUnlock(id, NO_LOCK);
unixEnterMutex();
@@ -4539,6 +4584,7 @@ static void unixUnmapfile(unixFile *pFd){
#endif
}
+#ifndef SQLITE_DISABLE_MMAP
/*
** Return the system page size.
*/
@@ -4551,6 +4597,7 @@ static int unixGetPagesize(void){
return (int)sysconf(_SC_PAGESIZE);
#endif
}
+#endif /* SQLITE_DISABLE_MMAP */
#ifndef SQLITE_DISABLE_MMAP
/*
@@ -4656,10 +4703,10 @@ static void unixRemapfile(
** code otherwise.
*/
static int unixMapfile(unixFile *pFd, i64 nByte){
+#ifndef SQLITE_DISABLE_MMAP
i64 nMap = nByte;
int rc;
-#ifndef SQLITE_DISABLE_MMAP
assert( nMap>=0 || pFd->nFetchOut==0 );
if( pFd->nFetchOut>0 ) return SQLITE_OK;
@@ -4700,7 +4747,9 @@ static int unixMapfile(unixFile *pFd, i64 nByte){
** release the reference by calling unixUnfetch().
*/
static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
+#ifndef SQLITE_DISABLE_MMAP
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
+#endif
*pp = 0;
#ifndef SQLITE_DISABLE_MMAP
@@ -5222,6 +5271,7 @@ static int fillInUnixFile(
}else{
pNew->pMethod = pLockingStyle;
OpenCounter(+1);
+ verifyDbFile(pNew);
}
return rc;
}