/ Check-in [92b5a76a]
Login

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

Overview
Comment:Proof-of-concept prototype for the proposed xSetSystemCall extension method on the VFS.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | syscall-override
Files: files | file ages | folders
SHA1: 92b5a76abc53290e1bb87b6b55bc64bb1b331dfc
User & Date: drh 2011-03-02 15:09:07
Context
2011-03-02
18:01
Add more system calls to the set that can be overridden in os_unix.c. Also merge in recent fixes from trunk. check-in: 80fac2a6 user: drh tags: syscall-override
15:09
Proof-of-concept prototype for the proposed xSetSystemCall extension method on the VFS. check-in: 92b5a76a user: drh tags: syscall-override
02:08
Log all error from close() in os_unix.c to sqlite3_log() but do not attempt to report errors back up to the application. Update the unix error logging to put the most important information earlier in the message. check-in: 7b6e30e6 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

   266    266   #ifndef O_NOFOLLOW
   267    267   # define O_NOFOLLOW 0
   268    268   #endif
   269    269   #ifndef O_BINARY
   270    270   # define O_BINARY 0
   271    271   #endif
   272    272   
   273         -/*
   274         -** The DJGPP compiler environment looks mostly like Unix, but it
   275         -** lacks the fcntl() system call.  So redefine fcntl() to be something
   276         -** that always succeeds.  This means that locking does not occur under
   277         -** DJGPP.  But it is DOS - what did you expect?
   278         -*/
   279         -#ifdef __DJGPP__
   280         -# define fcntl(A,B,C) 0
   281         -#endif
   282         -
   283    273   /*
   284    274   ** The threadid macro resolves to the thread-id or to 0.  Used for
   285    275   ** testing and debugging only.
   286    276   */
   287    277   #if SQLITE_THREADSAFE
   288    278   #define threadid pthread_self()
   289    279   #else
   290    280   #define threadid 0
   291    281   #endif
          282  +
          283  +/*
          284  +** Many system calls are accessed through pointer-to-functions so that
          285  +** they may be overridden at runtime to facilitate fault injection during
          286  +** testing and sandboxing.  The following array holds the names and pointers
          287  +** to all overrideable system calls.
          288  +*/
          289  +static struct unix_syscall {
          290  +  const char *zName;      /* Name of the sytem call */
          291  +  void *pCurrent;         /* Current value of the system call */
          292  +  void *pDefault;         /* Default value */
          293  +} aSyscall[] = {
          294  +  { "open",         (void*)open,       0  },
          295  +#define osOpen      ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
          296  +
          297  +  { "close",        (void*)close,      0  },
          298  +#define osClose     ((int(*)(int))aSyscall[1].pCurrent)
          299  +
          300  +  { "access",       (void*)access,     0  },
          301  +#define osAccess    ((int(*)(const char*,int))aSyscall[2].pCurrent)
          302  +
          303  +  { "getcwd",       (void*)getcwd,     0  },
          304  +#define osGetcwd    ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
          305  +
          306  +  { "stat",         (void*)stat,       0  },
          307  +#define osStat      ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
          308  +
          309  +/*
          310  +** The DJGPP compiler environment looks mostly like Unix, but it
          311  +** lacks the fcntl() system call.  So redefine fcntl() to be something
          312  +** that always succeeds.  This means that locking does not occur under
          313  +** DJGPP.  But it is DOS - what did you expect?
          314  +*/
          315  +#ifdef __DJGPP__
          316  +  { "fstat",        0,                 0  },
          317  +#define osFstat(a,b,c)    0
          318  +#else     
          319  +  { "fstat",        (void*)fstat,      0  },
          320  +#define osFstat     ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
          321  +#endif
          322  +
          323  +  { "ftruncate",    (void*)ftruncate,  0  },
          324  +#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
          325  +
          326  +  { "fcntl",        (void*)fcntl,    0  },
          327  +#define osFcntl     ((int(*)(int,int,...))aSyscall[7].pCurrent)
          328  +};
          329  +
          330  +/*
          331  +** This is the xSetSystemCall() method of sqlite3_vfs for all of the
          332  +** "unix" VFSes.
          333  +*/
          334  +static int unixSetSystemCall(
          335  +  sqlite3_vfs *pNotUsed,     /* The VFS pointer.  Not used */
          336  +  const char *zName,         /* Name of system call to override */
          337  +  void *pNewFunc             /* Pointer to new system call value */
          338  +){
          339  +  int i;
          340  +  int rc = 0;
          341  +  if( zName==0 ){
          342  +    /* If no zName is given, restore all system calls to their default
          343  +    ** settings and return NULL
          344  +    */
          345  +    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
          346  +      if( aSyscall[i].pDefault ){
          347  +        aSyscall[i].pCurrent = aSyscall[i].pDefault;
          348  +        rc = 1;
          349  +      }
          350  +    }
          351  +  }else{
          352  +    /* If zName is specified, operate on only the one system call
          353  +    ** specified.
          354  +    */
          355  +    for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
          356  +      if( strcmp(zName, aSyscall[i].zName)==0 ){
          357  +        if( aSyscall[i].pDefault==0 ){
          358  +          aSyscall[i].pDefault = aSyscall[i].pCurrent;
          359  +        }
          360  +        rc = 1;
          361  +        if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
          362  +        aSyscall[i].pCurrent = pNewFunc;
          363  +        break;
          364  +      }
          365  +    }
          366  +  }
          367  +  return rc;
          368  +}
   292    369   
   293    370   
   294    371   /*
   295    372   ** Helper functions to obtain and relinquish the global mutex. The
   296    373   ** global mutex is used to protect the unixInodeInfo and
   297    374   ** vxworksFileId objects used by this file, all of which may be 
   298    375   ** shared by multiple threads.
................................................................................
   350    427     int s;
   351    428     int savedErrno;
   352    429     if( op==F_GETLK ){
   353    430       zOpName = "GETLK";
   354    431     }else if( op==F_SETLK ){
   355    432       zOpName = "SETLK";
   356    433     }else{
   357         -    s = fcntl(fd, op, p);
          434  +    s = osFcntl(fd, op, p);
   358    435       sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
   359    436       return s;
   360    437     }
   361    438     if( p->l_type==F_RDLCK ){
   362    439       zType = "RDLCK";
   363    440     }else if( p->l_type==F_WRLCK ){
   364    441       zType = "WRLCK";
   365    442     }else if( p->l_type==F_UNLCK ){
   366    443       zType = "UNLCK";
   367    444     }else{
   368    445       assert( 0 );
   369    446     }
   370    447     assert( p->l_whence==SEEK_SET );
   371         -  s = fcntl(fd, op, p);
          448  +  s = osFcntl(fd, op, p);
   372    449     savedErrno = errno;
   373    450     sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
   374    451        threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
   375    452        (int)p->l_pid, s);
   376    453     if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
   377    454       struct flock l2;
   378    455       l2 = *p;
   379         -    fcntl(fd, F_GETLK, &l2);
          456  +    osFcntl(fd, F_GETLK, &l2);
   380    457       if( l2.l_type==F_RDLCK ){
   381    458         zType = "RDLCK";
   382    459       }else if( l2.l_type==F_WRLCK ){
   383    460         zType = "WRLCK";
   384    461       }else if( l2.l_type==F_UNLCK ){
   385    462         zType = "UNLCK";
   386    463       }else{
................................................................................
   388    465       }
   389    466       sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
   390    467          zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
   391    468     }
   392    469     errno = savedErrno;
   393    470     return s;
   394    471   }
   395         -#define fcntl lockTrace
          472  +#undef osFcntl
          473  +#define osFcntl lockTrace
   396    474   #endif /* SQLITE_LOCK_TRACE */
   397    475   
   398    476   
   399    477   /*
   400    478   ** Retry ftruncate() calls that fail due to EINTR
   401    479   */
   402    480   #ifdef EINTR
   403    481   static int robust_ftruncate(int h, sqlite3_int64 sz){
   404    482     int rc;
   405         -  do{ rc = ftruncate(h,sz); }while( rc<0 && errno==EINTR );
          483  +  do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
   406    484     return rc;
   407    485   }
   408    486   #else
   409         -# define robust_ftruncate(a,b) ftruncate(a,b)
          487  +# define robust_ftruncate(a,b) osFtruncate(a,b)
   410    488   #endif 
   411    489   
   412    490   
   413    491   /*
   414    492   ** This routine translates a standard POSIX errno code into something
   415    493   ** useful to the clients of the sqlite3 functions.  Specifically, it is
   416    494   ** intended to translate a variety of "try again" errors into SQLITE_BUSY
................................................................................
   831    909   **
   832    910   ** Note that it is not safe to retry close() after EINTR since the
   833    911   ** file descriptor might have already been reused by another thread.
   834    912   ** So we don't even try to recover from an EINTR.  Just log the error
   835    913   ** and move on.
   836    914   */
   837    915   static void robust_close(unixFile *pFile, int h, int lineno){
   838         -  if( close(h) ){
          916  +  if( osClose(h) ){
   839    917       unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
   840    918                          pFile ? pFile->zPath : 0, lineno);
   841    919     }
   842    920   }
   843    921   
   844    922   /*
   845    923   ** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
................................................................................
   908    986   
   909    987     assert( unixMutexHeld() );
   910    988   
   911    989     /* Get low-level information about the file that we can used to
   912    990     ** create a unique name for the file.
   913    991     */
   914    992     fd = pFile->h;
   915         -  rc = fstat(fd, &statbuf);
          993  +  rc = osFstat(fd, &statbuf);
   916    994     if( rc!=0 ){
   917    995       pFile->lastErrno = errno;
   918    996   #ifdef EOVERFLOW
   919    997       if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
   920    998   #endif
   921    999       return SQLITE_IOERR;
   922   1000     }
................................................................................
   934   1012     */
   935   1013     if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
   936   1014       do{ rc = write(fd, "S", 1); }while( rc<0 && errno==EINTR );
   937   1015       if( rc!=1 ){
   938   1016         pFile->lastErrno = errno;
   939   1017         return SQLITE_IOERR;
   940   1018       }
   941         -    rc = fstat(fd, &statbuf);
         1019  +    rc = osFstat(fd, &statbuf);
   942   1020       if( rc!=0 ){
   943   1021         pFile->lastErrno = errno;
   944   1022         return SQLITE_IOERR;
   945   1023       }
   946   1024     }
   947   1025   #endif
   948   1026   
................................................................................
  1003   1081   #ifndef __DJGPP__
  1004   1082     if( !reserved ){
  1005   1083       struct flock lock;
  1006   1084       lock.l_whence = SEEK_SET;
  1007   1085       lock.l_start = RESERVED_BYTE;
  1008   1086       lock.l_len = 1;
  1009   1087       lock.l_type = F_WRLCK;
  1010         -    if (-1 == fcntl(pFile->h, F_GETLK, &lock)) {
         1088  +    if (-1 == osFcntl(pFile->h, F_GETLK, &lock)) {
  1011   1089         int tErrno = errno;
  1012   1090         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
  1013   1091         pFile->lastErrno = tErrno;
  1014   1092       } else if( lock.l_type!=F_UNLCK ){
  1015   1093         reserved = 1;
  1016   1094       }
  1017   1095     }
................................................................................
  1156   1234     lock.l_len = 1L;
  1157   1235     lock.l_whence = SEEK_SET;
  1158   1236     if( eFileLock==SHARED_LOCK 
  1159   1237         || (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
  1160   1238     ){
  1161   1239       lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
  1162   1240       lock.l_start = PENDING_BYTE;
  1163         -    s = fcntl(pFile->h, F_SETLK, &lock);
         1241  +    s = osFcntl(pFile->h, F_SETLK, &lock);
  1164   1242       if( s==(-1) ){
  1165   1243         tErrno = errno;
  1166   1244         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1167   1245         if( IS_LOCK_ERROR(rc) ){
  1168   1246           pFile->lastErrno = tErrno;
  1169   1247         }
  1170   1248         goto end_lock;
................................................................................
  1178   1256     if( eFileLock==SHARED_LOCK ){
  1179   1257       assert( pInode->nShared==0 );
  1180   1258       assert( pInode->eFileLock==0 );
  1181   1259   
  1182   1260       /* Now get the read-lock */
  1183   1261       lock.l_start = SHARED_FIRST;
  1184   1262       lock.l_len = SHARED_SIZE;
  1185         -    if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
         1263  +    if( (s = osFcntl(pFile->h, F_SETLK, &lock))==(-1) ){
  1186   1264         tErrno = errno;
  1187   1265       }
  1188   1266       /* Drop the temporary PENDING lock */
  1189   1267       lock.l_start = PENDING_BYTE;
  1190   1268       lock.l_len = 1L;
  1191   1269       lock.l_type = F_UNLCK;
  1192         -    if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
         1270  +    if( osFcntl(pFile->h, F_SETLK, &lock)!=0 ){
  1193   1271         if( s != -1 ){
  1194   1272           /* This could happen with a network mount */
  1195   1273           tErrno = errno; 
  1196   1274           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK); 
  1197   1275           if( IS_LOCK_ERROR(rc) ){
  1198   1276             pFile->lastErrno = tErrno;
  1199   1277           }
................................................................................
  1228   1306         case EXCLUSIVE_LOCK:
  1229   1307           lock.l_start = SHARED_FIRST;
  1230   1308           lock.l_len = SHARED_SIZE;
  1231   1309           break;
  1232   1310         default:
  1233   1311           assert(0);
  1234   1312       }
  1235         -    s = fcntl(pFile->h, F_SETLK, &lock);
         1313  +    s = osFcntl(pFile->h, F_SETLK, &lock);
  1236   1314       if( s==(-1) ){
  1237   1315         tErrno = errno;
  1238   1316         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
  1239   1317         if( IS_LOCK_ERROR(rc) ){
  1240   1318           pFile->lastErrno = tErrno;
  1241   1319         }
  1242   1320       }
................................................................................
  1363   1441         if( handleNFSUnlock ){
  1364   1442           off_t divSize = SHARED_SIZE - 1;
  1365   1443           
  1366   1444           lock.l_type = F_UNLCK;
  1367   1445           lock.l_whence = SEEK_SET;
  1368   1446           lock.l_start = SHARED_FIRST;
  1369   1447           lock.l_len = divSize;
  1370         -        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1448  +        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
  1371   1449             tErrno = errno;
  1372   1450             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1373   1451             if( IS_LOCK_ERROR(rc) ){
  1374   1452               pFile->lastErrno = tErrno;
  1375   1453             }
  1376   1454             goto end_unlock;
  1377   1455           }
  1378   1456           lock.l_type = F_RDLCK;
  1379   1457           lock.l_whence = SEEK_SET;
  1380   1458           lock.l_start = SHARED_FIRST;
  1381   1459           lock.l_len = divSize;
  1382         -        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1460  +        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
  1383   1461             tErrno = errno;
  1384   1462             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1385   1463             if( IS_LOCK_ERROR(rc) ){
  1386   1464               pFile->lastErrno = tErrno;
  1387   1465             }
  1388   1466             goto end_unlock;
  1389   1467           }
  1390   1468           lock.l_type = F_UNLCK;
  1391   1469           lock.l_whence = SEEK_SET;
  1392   1470           lock.l_start = SHARED_FIRST+divSize;
  1393   1471           lock.l_len = SHARED_SIZE-divSize;
  1394         -        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1472  +        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
  1395   1473             tErrno = errno;
  1396   1474             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1397   1475             if( IS_LOCK_ERROR(rc) ){
  1398   1476               pFile->lastErrno = tErrno;
  1399   1477             }
  1400   1478             goto end_unlock;
  1401   1479           }
................................................................................
  1402   1480         }else
  1403   1481   #endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
  1404   1482         {
  1405   1483           lock.l_type = F_RDLCK;
  1406   1484           lock.l_whence = SEEK_SET;
  1407   1485           lock.l_start = SHARED_FIRST;
  1408   1486           lock.l_len = SHARED_SIZE;
  1409         -        if( fcntl(h, F_SETLK, &lock)==(-1) ){
         1487  +        if( osFcntl(h, F_SETLK, &lock)==(-1) ){
  1410   1488             tErrno = errno;
  1411   1489             rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
  1412   1490             if( IS_LOCK_ERROR(rc) ){
  1413   1491               pFile->lastErrno = tErrno;
  1414   1492             }
  1415   1493             goto end_unlock;
  1416   1494           }
  1417   1495         }
  1418   1496       }
  1419   1497       lock.l_type = F_UNLCK;
  1420   1498       lock.l_whence = SEEK_SET;
  1421   1499       lock.l_start = PENDING_BYTE;
  1422   1500       lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
  1423         -    if( fcntl(h, F_SETLK, &lock)!=(-1) ){
         1501  +    if( osFcntl(h, F_SETLK, &lock)!=(-1) ){
  1424   1502         pInode->eFileLock = SHARED_LOCK;
  1425   1503       }else{
  1426   1504         tErrno = errno;
  1427   1505         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1428   1506         if( IS_LOCK_ERROR(rc) ){
  1429   1507           pFile->lastErrno = tErrno;
  1430   1508         }
................................................................................
  1440   1518       if( pInode->nShared==0 ){
  1441   1519         lock.l_type = F_UNLCK;
  1442   1520         lock.l_whence = SEEK_SET;
  1443   1521         lock.l_start = lock.l_len = 0L;
  1444   1522         SimulateIOErrorBenign(1);
  1445   1523         SimulateIOError( h=(-1) )
  1446   1524         SimulateIOErrorBenign(0);
  1447         -      if( fcntl(h, F_SETLK, &lock)!=(-1) ){
         1525  +      if( osFcntl(h, F_SETLK, &lock)!=(-1) ){
  1448   1526           pInode->eFileLock = NO_LOCK;
  1449   1527         }else{
  1450   1528           tErrno = errno;
  1451   1529           rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
  1452   1530           if( IS_LOCK_ERROR(rc) ){
  1453   1531             pFile->lastErrno = tErrno;
  1454   1532           }
................................................................................
  1642   1720     if( pFile->eFileLock>SHARED_LOCK ){
  1643   1721       /* Either this connection or some other connection in the same process
  1644   1722       ** holds a lock on the file.  No need to check further. */
  1645   1723       reserved = 1;
  1646   1724     }else{
  1647   1725       /* The lock is held if and only if the lockfile exists */
  1648   1726       const char *zLockFile = (const char*)pFile->lockingContext;
  1649         -    reserved = access(zLockFile, 0)==0;
         1727  +    reserved = osAccess(zLockFile, 0)==0;
  1650   1728     }
  1651   1729     OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
  1652   1730     *pResOut = reserved;
  1653   1731     return rc;
  1654   1732   }
  1655   1733   
  1656   1734   /*
................................................................................
  1696   1774       /* Always update the timestamp on the old file */
  1697   1775       utimes(zLockFile, NULL);
  1698   1776   #endif
  1699   1777       return SQLITE_OK;
  1700   1778     }
  1701   1779     
  1702   1780     /* grab an exclusive lock */
  1703         -  fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
         1781  +  fd = osOpen(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
  1704   1782     if( fd<0 ){
  1705   1783       /* failed to open/create the file, someone else may have stolen the lock */
  1706   1784       int tErrno = errno;
  1707   1785       if( EEXIST == tErrno ){
  1708   1786         rc = SQLITE_BUSY;
  1709   1787       } else {
  1710   1788         rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
................................................................................
  2960   3038     /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
  2961   3039     ** no-op
  2962   3040     */
  2963   3041   #ifdef SQLITE_NO_SYNC
  2964   3042     rc = SQLITE_OK;
  2965   3043   #elif HAVE_FULLFSYNC
  2966   3044     if( fullSync ){
  2967         -    rc = fcntl(fd, F_FULLFSYNC, 0);
         3045  +    rc = osFcntl(fd, F_FULLFSYNC, 0);
  2968   3046     }else{
  2969   3047       rc = 1;
  2970   3048     }
  2971   3049     /* If the FULLFSYNC failed, fall back to attempting an fsync().
  2972   3050     ** It shouldn't be possible for fullfsync to fail on the local 
  2973   3051     ** file system (on OSX), so failure indicates that FULLFSYNC
  2974   3052     ** isn't supported for this file system. So, attempt an fsync 
................................................................................
  3107   3185   /*
  3108   3186   ** Determine the current size of a file in bytes
  3109   3187   */
  3110   3188   static int unixFileSize(sqlite3_file *id, i64 *pSize){
  3111   3189     int rc;
  3112   3190     struct stat buf;
  3113   3191     assert( id );
  3114         -  rc = fstat(((unixFile*)id)->h, &buf);
         3192  +  rc = osFstat(((unixFile*)id)->h, &buf);
  3115   3193     SimulateIOError( rc=1 );
  3116   3194     if( rc!=0 ){
  3117   3195       ((unixFile*)id)->lastErrno = errno;
  3118   3196       return SQLITE_IOERR_FSTAT;
  3119   3197     }
  3120   3198     *pSize = buf.st_size;
  3121   3199   
................................................................................
  3148   3226   ** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
  3149   3227   */
  3150   3228   static int fcntlSizeHint(unixFile *pFile, i64 nByte){
  3151   3229     if( pFile->szChunk ){
  3152   3230       i64 nSize;                    /* Required file size */
  3153   3231       struct stat buf;              /* Used to hold return values of fstat() */
  3154   3232      
  3155         -    if( fstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
         3233  +    if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
  3156   3234   
  3157   3235       nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
  3158   3236       if( nSize>(i64)buf.st_size ){
  3159   3237   #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
  3160   3238         int rc;
  3161   3239         do{
  3162   3240           rc = posix_fallocate(pFile-.h, buf.st_size, nSize-buf.st_size;
................................................................................
  3363   3441     /* Initialize the locking parameters */
  3364   3442     memset(&f, 0, sizeof(f));
  3365   3443     f.l_type = lockType;
  3366   3444     f.l_whence = SEEK_SET;
  3367   3445     f.l_start = ofst;
  3368   3446     f.l_len = n;
  3369   3447   
  3370         -  rc = fcntl(pShmNode->h, F_SETLK, &f);
         3448  +  rc = osFcntl(pShmNode->h, F_SETLK, &f);
  3371   3449     rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
  3372   3450   
  3373   3451     /* Update the global lock state and do debug tracing */
  3374   3452   #ifdef SQLITE_DEBUG
  3375   3453     { u16 mask;
  3376   3454     OSTRACE(("SHM-LOCK "));
  3377   3455     mask = (1<<(ofst+n)) - (1<<ofst);
................................................................................
  3488   3566       struct stat sStat;                 /* fstat() info for database file */
  3489   3567   
  3490   3568       /* Call fstat() to figure out the permissions on the database file. If
  3491   3569       ** a new *-shm file is created, an attempt will be made to create it
  3492   3570       ** with the same permissions. The actual permissions the file is created
  3493   3571       ** with are subject to the current umask setting.
  3494   3572       */
  3495         -    if( fstat(pDbFd->h, &sStat) ){
         3573  +    if( osFstat(pDbFd->h, &sStat) ){
  3496   3574         rc = SQLITE_IOERR_FSTAT;
  3497   3575         goto shm_open_err;
  3498   3576       }
  3499   3577   
  3500   3578   #ifdef SQLITE_SHM_DIRECTORY
  3501   3579       nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 30;
  3502   3580   #else
................................................................................
  3521   3599       pShmNode->pInode = pDbFd->pInode;
  3522   3600       pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  3523   3601       if( pShmNode->mutex==0 ){
  3524   3602         rc = SQLITE_NOMEM;
  3525   3603         goto shm_open_err;
  3526   3604       }
  3527   3605   
  3528         -    pShmNode->h = open(zShmFilename, O_RDWR|O_CREAT, (sStat.st_mode & 0777));
         3606  +    pShmNode->h = osOpen(zShmFilename, O_RDWR|O_CREAT, (sStat.st_mode & 0777));
  3529   3607       if( pShmNode->h<0 ){
  3530   3608         rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename);
  3531   3609         goto shm_open_err;
  3532   3610       }
  3533   3611   
  3534   3612       /* Check to see if another process is holding the dead-man switch.
  3535   3613       ** If not, truncate the file to zero length. 
................................................................................
  3625   3703   
  3626   3704       pShmNode->szRegion = szRegion;
  3627   3705   
  3628   3706       /* The requested region is not mapped into this processes address space.
  3629   3707       ** Check to see if it has been allocated (i.e. if the wal-index file is
  3630   3708       ** large enough to contain the requested region).
  3631   3709       */
  3632         -    if( fstat(pShmNode->h, &sStat) ){
         3710  +    if( osFstat(pShmNode->h, &sStat) ){
  3633   3711         rc = SQLITE_IOERR_SHMSIZE;
  3634   3712         goto shmpage_out;
  3635   3713       }
  3636   3714   
  3637   3715       if( sStat.st_size<nByte ){
  3638   3716         /* The requested memory region does not exist. If bExtend is set to
  3639   3717         ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
................................................................................
  4084   4162     ** Test byte-range lock using fcntl(). If the call succeeds, 
  4085   4163     ** assume that the file-system supports POSIX style locks. 
  4086   4164     */
  4087   4165     lockInfo.l_len = 1;
  4088   4166     lockInfo.l_start = 0;
  4089   4167     lockInfo.l_whence = SEEK_SET;
  4090   4168     lockInfo.l_type = F_RDLCK;
  4091         -  if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
         4169  +  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
  4092   4170       if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
  4093   4171         return &nfsIoMethods;
  4094   4172       } else {
  4095   4173         return &posixIoMethods;
  4096   4174       }
  4097   4175     }else{
  4098   4176       return &dotlockIoMethods;
................................................................................
  4126   4204     /* Test if fcntl() is supported and use POSIX style locks.
  4127   4205     ** Otherwise fall back to the named semaphore method.
  4128   4206     */
  4129   4207     lockInfo.l_len = 1;
  4130   4208     lockInfo.l_start = 0;
  4131   4209     lockInfo.l_whence = SEEK_SET;
  4132   4210     lockInfo.l_type = F_RDLCK;
  4133         -  if( fcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
         4211  +  if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
  4134   4212       return &posixIoMethods;
  4135   4213     }else{
  4136   4214       return &semIoMethods;
  4137   4215     }
  4138   4216   }
  4139   4217   static const sqlite3_io_methods 
  4140   4218     *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
................................................................................
  4349   4427     int fd = -1;
  4350   4428     char zDirname[MAX_PATHNAME+1];
  4351   4429   
  4352   4430     sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
  4353   4431     for(ii=(int)strlen(zDirname); ii>1 && zDirname[ii]!='/'; ii--);
  4354   4432     if( ii>0 ){
  4355   4433       zDirname[ii] = '\0';
  4356         -    fd = open(zDirname, O_RDONLY|O_BINARY, 0);
         4434  +    fd = osOpen(zDirname, O_RDONLY|O_BINARY, 0);
  4357   4435       if( fd>=0 ){
  4358   4436   #ifdef FD_CLOEXEC
  4359         -      fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
         4437  +      osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
  4360   4438   #endif
  4361   4439         OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
  4362   4440       }
  4363   4441     }
  4364   4442     *pFd = fd;
  4365   4443     return (fd>=0?SQLITE_OK:unixLogError(SQLITE_CANTOPEN_BKPT, "open", zDirname));
  4366   4444   }
................................................................................
  4382   4460     struct stat buf;
  4383   4461     const char *zDir = 0;
  4384   4462   
  4385   4463     azDirs[0] = sqlite3_temp_directory;
  4386   4464     if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
  4387   4465     for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
  4388   4466       if( zDir==0 ) continue;
  4389         -    if( stat(zDir, &buf) ) continue;
         4467  +    if( osStat(zDir, &buf) ) continue;
  4390   4468       if( !S_ISDIR(buf.st_mode) ) continue;
  4391         -    if( access(zDir, 07) ) continue;
         4469  +    if( osAccess(zDir, 07) ) continue;
  4392   4470       break;
  4393   4471     }
  4394   4472     return zDir;
  4395   4473   }
  4396   4474   
  4397   4475   /*
  4398   4476   ** Create a temporary file name in zBuf.  zBuf must be allocated
................................................................................
  4427   4505       sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
  4428   4506       j = (int)strlen(zBuf);
  4429   4507       sqlite3_randomness(15, &zBuf[j]);
  4430   4508       for(i=0; i<15; i++, j++){
  4431   4509         zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
  4432   4510       }
  4433   4511       zBuf[j] = 0;
  4434         -  }while( access(zBuf,0)==0 );
         4512  +  }while( osAccess(zBuf,0)==0 );
  4435   4513     return SQLITE_OK;
  4436   4514   }
  4437   4515   
  4438   4516   #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
  4439   4517   /*
  4440   4518   ** Routine to transform a unixFile into a proxy-locking unixFile.
  4441   4519   ** Implementation in the proxy-lock division, but used by unixOpen()
................................................................................
  4688   4766       mode_t openMode;              /* Permissions to create file with */
  4689   4767       rc = findCreateFileMode(zName, flags, &openMode);
  4690   4768       if( rc!=SQLITE_OK ){
  4691   4769         assert( !p->pUnused );
  4692   4770         assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
  4693   4771         return rc;
  4694   4772       }
  4695         -    fd = open(zName, openFlags, openMode);
         4773  +    fd = osOpen(zName, openFlags, openMode);
  4696   4774       OSTRACE(("OPENX   %-3d %s 0%o\n", fd, zName, openFlags));
  4697   4775       if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
  4698   4776         /* Failed to open the file for read/write access. Try read-only. */
  4699   4777         flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
  4700   4778         openFlags &= ~(O_RDWR|O_CREAT);
  4701   4779         flags |= SQLITE_OPEN_READONLY;
  4702   4780         openFlags |= O_RDONLY;
  4703         -      fd = open(zName, openFlags, openMode);
         4781  +      fd = osOpen(zName, openFlags, openMode);
  4704   4782       }
  4705   4783       if( fd<0 ){
  4706   4784         rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
  4707   4785         goto open_finished;
  4708   4786       }
  4709   4787     }
  4710   4788     assert( fd>=0 );
................................................................................
  4740   4818         assert( eType!=SQLITE_OPEN_MAIN_DB );
  4741   4819         robust_close(p, fd, __LINE__);
  4742   4820         goto open_finished;
  4743   4821       }
  4744   4822     }
  4745   4823   
  4746   4824   #ifdef FD_CLOEXEC
  4747         -  fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
         4825  +  osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
  4748   4826   #endif
  4749   4827   
  4750   4828     noLock = eType!=SQLITE_OPEN_MAIN_DB;
  4751   4829   
  4752   4830     
  4753   4831   #if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
  4754   4832     struct statfs fsInfo;
................................................................................
  4886   4964       case SQLITE_ACCESS_READ:
  4887   4965         amode = R_OK;
  4888   4966         break;
  4889   4967   
  4890   4968       default:
  4891   4969         assert(!"Invalid flags argument");
  4892   4970     }
  4893         -  *pResOut = (access(zPath, amode)==0);
         4971  +  *pResOut = (osAccess(zPath, amode)==0);
  4894   4972     if( flags==SQLITE_ACCESS_EXISTS && *pResOut ){
  4895   4973       struct stat buf;
  4896   4974       if( 0==stat(zPath, &buf) && buf.st_size==0 ){
  4897   4975         *pResOut = 0;
  4898   4976       }
  4899   4977     }
  4900   4978     return SQLITE_OK;
................................................................................
  4928   5006     UNUSED_PARAMETER(pVfs);
  4929   5007   
  4930   5008     zOut[nOut-1] = '\0';
  4931   5009     if( zPath[0]=='/' ){
  4932   5010       sqlite3_snprintf(nOut, zOut, "%s", zPath);
  4933   5011     }else{
  4934   5012       int nCwd;
  4935         -    if( getcwd(zOut, nOut-1)==0 ){
         5013  +    if( osGetcwd(zOut, nOut-1)==0 ){
  4936   5014         return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
  4937   5015       }
  4938   5016       nCwd = (int)strlen(zOut);
  4939   5017       sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
  4940   5018     }
  4941   5019     return SQLITE_OK;
  4942   5020   }
................................................................................
  5023   5101     ** that we always use the same random number sequence.  This makes the
  5024   5102     ** tests repeatable.
  5025   5103     */
  5026   5104     memset(zBuf, 0, nBuf);
  5027   5105   #if !defined(SQLITE_TEST)
  5028   5106     {
  5029   5107       int pid, fd;
  5030         -    fd = open("/dev/urandom", O_RDONLY);
         5108  +    fd = osOpen("/dev/urandom", O_RDONLY, 0);
  5031   5109       if( fd<0 ){
  5032   5110         time_t t;
  5033   5111         time(&t);
  5034   5112         memcpy(zBuf, &t, sizeof(t));
  5035   5113         pid = getpid();
  5036   5114         memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
  5037   5115         assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
................................................................................
  5432   5510     }else{
  5433   5511       pUnused = sqlite3_malloc(sizeof(*pUnused));
  5434   5512       if( !pUnused ){
  5435   5513         return SQLITE_NOMEM;
  5436   5514       }
  5437   5515     }
  5438   5516     if( fd<0 ){
  5439         -    fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
         5517  +    fd = osOpen(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
  5440   5518       terrno = errno;
  5441   5519       if( fd<0 && errno==ENOENT && islockfile ){
  5442   5520         if( proxyCreateLockPath(path) == SQLITE_OK ){
  5443         -        fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
         5521  +        fd = osOpen(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
  5444   5522         }
  5445   5523       }
  5446   5524     }
  5447   5525     if( fd<0 ){
  5448   5526       openFlags = O_RDONLY;
  5449         -    fd = open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
         5527  +    fd = osOpen(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS);
  5450   5528       terrno = errno;
  5451   5529     }
  5452   5530     if( fd<0 ){
  5453   5531       if( islockfile ){
  5454   5532         return SQLITE_BUSY;
  5455   5533       }
  5456   5534       switch (terrno) {
................................................................................
  5562   5640     /* read the conch content */
  5563   5641     readLen = pread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
  5564   5642     if( readLen<PROXY_PATHINDEX ){
  5565   5643       sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
  5566   5644       goto end_breaklock;
  5567   5645     }
  5568   5646     /* write it out to the temporary break file */
  5569         -  fd = open(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS);
         5647  +  fd = osOpen(tPath, (O_RDWR|O_CREAT|O_EXCL), SQLITE_DEFAULT_FILE_PERMISSIONS);
  5570   5648     if( fd<0 ){
  5571   5649       sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
  5572   5650       goto end_breaklock;
  5573   5651     }
  5574   5652     if( pwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
  5575   5653       sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
  5576   5654       goto end_breaklock;
................................................................................
  5613   5691         /* If the lock failed (busy):
  5614   5692          * 1st try: get the mod time of the conch, wait 0.5s and try again. 
  5615   5693          * 2nd try: fail if the mod time changed or host id is different, wait 
  5616   5694          *           10 sec and try again
  5617   5695          * 3rd try: break the lock unless the mod time has changed.
  5618   5696          */
  5619   5697         struct stat buf;
  5620         -      if( fstat(conchFile->h, &buf) ){
         5698  +      if( osFstat(conchFile->h, &buf) ){
  5621   5699           pFile->lastErrno = errno;
  5622   5700           return SQLITE_IOERR_LOCK;
  5623   5701         }
  5624   5702         
  5625   5703         if( nTries==1 ){
  5626   5704           conchModTime = buf.st_mtimespec;
  5627   5705           usleep(500000); /* wait 0.5 sec and try the lock again*/
................................................................................
  5803   5881           fsync(conchFile->h);
  5804   5882           /* If we created a new conch file (not just updated the contents of a 
  5805   5883            ** valid conch file), try to match the permissions of the database 
  5806   5884            */
  5807   5885           if( rc==SQLITE_OK && createConch ){
  5808   5886             struct stat buf;
  5809   5887             int rc;
  5810         -          int err = fstat(pFile->h, &buf);
         5888  +          int err = osFstat(pFile->h, &buf);
  5811   5889             if( err==0 ){
  5812   5890               mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
  5813   5891                                           S_IROTH|S_IWOTH);
  5814   5892               /* try to match the database file R/W permissions, ignore failure */
  5815   5893   #ifndef SQLITE_PROXY_DEBUG
  5816   5894               fchmod(conchFile->h, cmode);
  5817   5895   #else
................................................................................
  5838   5916       end_takeconch:
  5839   5917         OSTRACE(("TRANSPROXY: CLOSE  %d\n", pFile->h));
  5840   5918         if( rc==SQLITE_OK && pFile->openFlags ){
  5841   5919           if( pFile->h>=0 ){
  5842   5920             robust_close(pFile, pFile->h, __LINE__) ){
  5843   5921           }
  5844   5922           pFile->h = -1;
  5845         -        int fd = open(pCtx->dbPath, pFile->openFlags,
         5923  +        int fd = osOpen(pCtx->dbPath, pFile->openFlags,
  5846   5924                         SQLITE_DEFAULT_FILE_PERMISSIONS);
  5847   5925           OSTRACE(("TRANSPROXY: OPEN  %d\n", fd));
  5848   5926           if( fd>=0 ){
  5849   5927             pFile->h = fd;
  5850   5928           }else{
  5851   5929             rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
  5852   5930              during locking */
................................................................................
  6064   6142         ** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
  6065   6143         ** that openFlags will have only one of O_RDONLY or O_RDWR.
  6066   6144         */
  6067   6145         struct statfs fsInfo;
  6068   6146         struct stat conchInfo;
  6069   6147         int goLockless = 0;
  6070   6148   
  6071         -      if( stat(pCtx->conchFilePath, &conchInfo) == -1 ) {
         6149  +      if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
  6072   6150           int err = errno;
  6073   6151           if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
  6074   6152             goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
  6075   6153           }
  6076   6154         }
  6077   6155         if( goLockless ){
  6078   6156           pCtx->conchHeld = -1; /* read only FS/ lockless */
................................................................................
  6349   6427     ** Most finders simply return a pointer to a fixed sqlite3_io_methods
  6350   6428     ** object.  But the "autolockIoFinder" available on MacOSX does a little
  6351   6429     ** more than that; it looks at the filesystem type that hosts the 
  6352   6430     ** database file and tries to choose an locking method appropriate for
  6353   6431     ** that filesystem time.
  6354   6432     */
  6355   6433     #define UNIXVFS(VFSNAME, FINDER) {                        \
  6356         -    2,                    /* iVersion */                    \
         6434  +    3,                    /* iVersion */                    \
  6357   6435       sizeof(unixFile),     /* szOsFile */                    \
  6358   6436       MAX_PATHNAME,         /* mxPathname */                  \
  6359   6437       0,                    /* pNext */                       \
  6360   6438       VFSNAME,              /* zName */                       \
  6361   6439       (void*)&FINDER,       /* pAppData */                    \
  6362   6440       unixOpen,             /* xOpen */                       \
  6363   6441       unixDelete,           /* xDelete */                     \
................................................................................
  6368   6446       unixDlSym,            /* xDlSym */                      \
  6369   6447       unixDlClose,          /* xDlClose */                    \
  6370   6448       unixRandomness,       /* xRandomness */                 \
  6371   6449       unixSleep,            /* xSleep */                      \
  6372   6450       unixCurrentTime,      /* xCurrentTime */                \
  6373   6451       unixGetLastError,     /* xGetLastError */               \
  6374   6452       unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
         6453  +    unixSetSystemCall,    /* xSetSystemCall */              \
  6375   6454     }
  6376   6455   
  6377   6456     /*
  6378   6457     ** All default VFSes for unix are contained in the following array.
  6379   6458     **
  6380   6459     ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
  6381   6460     ** by the SQLite core when the VFS is registered.  So the following

Changes to src/os_win.c.

  2742   2742   
  2743   2743   
  2744   2744   /*
  2745   2745   ** Initialize and deinitialize the operating system interface.
  2746   2746   */
  2747   2747   int sqlite3_os_init(void){
  2748   2748     static sqlite3_vfs winVfs = {
  2749         -    2,                   /* iVersion */
         2749  +    3,                   /* iVersion */
  2750   2750       sizeof(winFile),     /* szOsFile */
  2751   2751       MAX_PATH,            /* mxPathname */
  2752   2752       0,                   /* pNext */
  2753   2753       "win32",             /* zName */
  2754   2754       0,                   /* pAppData */
  2755   2755       winOpen,             /* xOpen */
  2756   2756       winDelete,           /* xDelete */
................................................................................
  2761   2761       winDlSym,            /* xDlSym */
  2762   2762       winDlClose,          /* xDlClose */
  2763   2763       winRandomness,       /* xRandomness */
  2764   2764       winSleep,            /* xSleep */
  2765   2765       winCurrentTime,      /* xCurrentTime */
  2766   2766       winGetLastError,     /* xGetLastError */
  2767   2767       winCurrentTimeInt64, /* xCurrentTimeInt64 */
         2768  +    0,                   /* xSetSystemCall */
  2768   2769     };
  2769   2770   
  2770   2771   #ifndef SQLITE_OMIT_WAL
  2771   2772     /* get memory map allocation granularity */
  2772   2773     memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
  2773   2774     GetSystemInfo(&winSysInfo);
  2774   2775     assert(winSysInfo.dwAllocationGranularity > 0);

Changes to src/sqlite.h.in.

   892    892   ** ^SQLite will use the xCurrentTimeInt64() method to get the current
   893    893   ** date and time if that method is available (if iVersion is 2 or 
   894    894   ** greater and the function pointer is not NULL) and will fall back
   895    895   ** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
   896    896   */
   897    897   typedef struct sqlite3_vfs sqlite3_vfs;
   898    898   struct sqlite3_vfs {
   899         -  int iVersion;            /* Structure version number (currently 2) */
          899  +  int iVersion;            /* Structure version number (currently 3) */
   900    900     int szOsFile;            /* Size of subclassed sqlite3_file */
   901    901     int mxPathname;          /* Maximum file pathname length */
   902    902     sqlite3_vfs *pNext;      /* Next registered VFS */
   903    903     const char *zName;       /* Name of this virtual file system */
   904    904     void *pAppData;          /* Pointer to application-specific data */
   905    905     int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
   906    906                  int flags, int *pOutFlags);
................................................................................
   918    918     /*
   919    919     ** The methods above are in version 1 of the sqlite_vfs object
   920    920     ** definition.  Those that follow are added in version 2 or later
   921    921     */
   922    922     int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
   923    923     /*
   924    924     ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
          925  +  ** Those below are for version 3 and greater.
          926  +  */
          927  +  int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, void *pFunc);
          928  +  /*
          929  +  ** The methods above are in versions 1 through 3 of the sqlite_vfs object.
   925    930     ** New fields may be appended in figure versions.  The iVersion
   926    931     ** value will increment whenever this happens. 
   927    932     */
   928    933   };
   929    934   
   930    935   /*
   931    936   ** CAPI3REF: Flags for the xAccess VFS method