/ Check-in [e238dcf9]
Login

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

Overview
Comment: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.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e238dcf9189c029fbdcf89339e21d9cdd8fbf2c5
User & Date: drh 2013-04-11 01:16:15
Context
2013-04-11
11:53
Show the process-id on log messages from mptester. check-in: 6748a83d user: drh tags: trunk
01:16
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. check-in: e238dcf9 user: drh tags: trunk
00:09
Enhance multi-process tester integration with the Win32 API. check-in: 0fdc7435 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/os_unix.c.

   276    276   #else
   277    277   # define UNIXFILE_DIRSYNC    0x00
   278    278   #endif
   279    279   #define UNIXFILE_PSOW        0x10     /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
   280    280   #define UNIXFILE_DELETE      0x20     /* Delete on close */
   281    281   #define UNIXFILE_URI         0x40     /* Filename might have query parameters */
   282    282   #define UNIXFILE_NOLOCK      0x80     /* Do no file locking */
          283  +#define UNIXFILE_WARNED    0x0100     /* verifyDbFile() warnings have been issued */
   283    284   
   284    285   /*
   285    286   ** Include code that is common to all os_*.c files
   286    287   */
   287    288   #include "os_common.h"
   288    289   
   289    290   /*
................................................................................
   795    796       
   796    797     default: 
   797    798       return sqliteIOErr;
   798    799     }
   799    800   }
   800    801   
   801    802   
   802         -
   803    803   /******************************************************************************
   804    804   ****************** Begin Unique File ID Utility Used By VxWorks ***************
   805    805   **
   806    806   ** On most versions of unix, we can get a unique ID for a file by concatenating
   807    807   ** the device number and the inode number.  But this does not work on VxWorks.
   808    808   ** On VxWorks, a unique file id must be based on the canonical filename.
   809    809   **
................................................................................
  1295   1295     }else{
  1296   1296       pInode->nRef++;
  1297   1297     }
  1298   1298     *ppInode = pInode;
  1299   1299     return SQLITE_OK;
  1300   1300   }
  1301   1301   
         1302  +
         1303  +/*
         1304  +** Check a unixFile that is a database.  Verify the following:
         1305  +**
         1306  +** (1) There is exactly one hard link on the file
         1307  +** (2) The file is not a symbolic link
         1308  +** (3) The file has not been renamed or unlinked
         1309  +**
         1310  +** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
         1311  +*/
         1312  +static void verifyDbFile(unixFile *pFile){
         1313  +  struct stat buf;
         1314  +  int rc;
         1315  +  if( pFile->ctrlFlags & UNIXFILE_WARNED ){
         1316  +    /* One or more of the following warnings have already been issued.  Do not
         1317  +    ** repeat them so as not to clutter the error log */
         1318  +    return;
         1319  +  }
         1320  +  rc = osFstat(pFile->h, &buf);
         1321  +  if( rc!=0 ){
         1322  +    sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
         1323  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1324  +    return;
         1325  +  }
         1326  +  if( buf.st_nlink==0 && (pFile->ctrlFlags & UNIXFILE_DELETE)==0 ){
         1327  +    sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
         1328  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1329  +    return;
         1330  +  }
         1331  +  if( buf.st_nlink>1 ){
         1332  +    sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
         1333  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1334  +    return;
         1335  +  }
         1336  +  if( pFile->pInode!=0
         1337  +   && ((rc = osStat(pFile->zPath, &buf))!=0
         1338  +       || buf.st_ino!=pFile->pInode->fileId.ino)
         1339  +  ){
         1340  +    sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
         1341  +    pFile->ctrlFlags |= UNIXFILE_WARNED;
         1342  +    return;
         1343  +  }
         1344  +}
         1345  +
  1302   1346   
  1303   1347   /*
  1304   1348   ** This routine checks if there is a RESERVED lock held on the specified
  1305   1349   ** file by this or any other process. If such a lock is held, set *pResOut
  1306   1350   ** to a non-zero value otherwise *pResOut is set to zero.  The return value
  1307   1351   ** is set to SQLITE_OK unless an I/O error occurs during lock checking.
  1308   1352   */
................................................................................
  1872   1916   
  1873   1917   /*
  1874   1918   ** Close a file.
  1875   1919   */
  1876   1920   static int unixClose(sqlite3_file *id){
  1877   1921     int rc = SQLITE_OK;
  1878   1922     unixFile *pFile = (unixFile *)id;
         1923  +  verifyDbFile(pFile);
  1879   1924     unixUnlock(id, NO_LOCK);
  1880   1925     unixEnterMutex();
  1881   1926   
  1882   1927     /* unixFile.pInode is always valid here. Otherwise, a different close
  1883   1928     ** routine (e.g. nolockClose()) would be called instead.
  1884   1929     */
  1885   1930     assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
................................................................................
  4535   4580       pFd->pMapRegion = 0;
  4536   4581       pFd->mmapSize = 0;
  4537   4582       pFd->mmapOrigsize = 0;
  4538   4583     }
  4539   4584   #endif
  4540   4585   }
  4541   4586   
         4587  +#ifndef SQLITE_DISABLE_MMAP
  4542   4588   /*
  4543   4589   ** Return the system page size.
  4544   4590   */
  4545   4591   static int unixGetPagesize(void){
  4546   4592   #if HAVE_MREMAP
  4547   4593     return 512;
  4548   4594   #elif defined(_BSD_SOURCE)
  4549   4595     return getpagesize();
  4550   4596   #else
  4551   4597     return (int)sysconf(_SC_PAGESIZE);
  4552   4598   #endif
  4553   4599   }
         4600  +#endif /* SQLITE_DISABLE_MMAP */
  4554   4601   
  4555   4602   #ifndef SQLITE_DISABLE_MMAP
  4556   4603   /*
  4557   4604   ** Attempt to set the size of the memory mapping maintained by file 
  4558   4605   ** descriptor pFd to nNew bytes. Any existing mapping is discarded.
  4559   4606   **
  4560   4607   ** If successful, this function sets the following variables:
................................................................................
  4652   4699   ** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
  4653   4700   **
  4654   4701   ** SQLITE_OK is returned if no error occurs (even if the mapping is not
  4655   4702   ** recreated as a result of outstanding references) or an SQLite error
  4656   4703   ** code otherwise.
  4657   4704   */
  4658   4705   static int unixMapfile(unixFile *pFd, i64 nByte){
         4706  +#ifndef SQLITE_DISABLE_MMAP
  4659   4707     i64 nMap = nByte;
  4660   4708     int rc;
  4661   4709   
  4662         -#ifndef SQLITE_DISABLE_MMAP
  4663   4710     assert( nMap>=0 || pFd->nFetchOut==0 );
  4664   4711     if( pFd->nFetchOut>0 ) return SQLITE_OK;
  4665   4712   
  4666   4713     if( nMap<0 ){
  4667   4714       struct stat statbuf;          /* Low-level file information */
  4668   4715       rc = osFstat(pFd->h, &statbuf);
  4669   4716       if( rc!=SQLITE_OK ){
................................................................................
  4696   4743   ** Finally, if an error does occur, return an SQLite error code. The final
  4697   4744   ** value of *pp is undefined in this case.
  4698   4745   **
  4699   4746   ** If this function does return a pointer, the caller must eventually 
  4700   4747   ** release the reference by calling unixUnfetch().
  4701   4748   */
  4702   4749   static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
         4750  +#ifndef SQLITE_DISABLE_MMAP
  4703   4751     unixFile *pFd = (unixFile *)fd;   /* The underlying database file */
         4752  +#endif
  4704   4753     *pp = 0;
  4705   4754   
  4706   4755   #ifndef SQLITE_DISABLE_MMAP
  4707   4756     if( pFd->mmapLimit>0 ){
  4708   4757       if( pFd->pMapRegion==0 ){
  4709   4758         int rc = unixMapfile(pFd, -1);
  4710   4759         if( rc!=SQLITE_OK ) return rc;
................................................................................
  5218   5267     if( isDelete ) pNew->ctrlFlags |= UNIXFILE_DELETE;
  5219   5268   #endif
  5220   5269     if( rc!=SQLITE_OK ){
  5221   5270       if( h>=0 ) robust_close(pNew, h, __LINE__);
  5222   5271     }else{
  5223   5272       pNew->pMethod = pLockingStyle;
  5224   5273       OpenCounter(+1);
         5274  +    verifyDbFile(pNew);
  5225   5275     }
  5226   5276     return rc;
  5227   5277   }
  5228   5278   
  5229   5279   /*
  5230   5280   ** Return the name of a directory in which to put temporary files.
  5231   5281   ** If no suitable temporary file directory can be found, return NULL.