aboutsummaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c764
1 files changed, 380 insertions, 384 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index 22cadf0bf..e478502f4 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -40,7 +40,7 @@
** * sqlite3_file methods not associated with locking
** * Implementations of sqlite3_os_init() and sqlite3_os_end()
**
-** $Id: os_unix.c,v 1.222 2008/11/28 15:37:20 drh Exp $
+** $Id: os_unix.c,v 1.223 2008/11/29 00:56:53 drh Exp $
*/
#include "sqliteInt.h"
#if SQLITE_OS_UNIX /* This file is used on unix only */
@@ -157,49 +157,6 @@
#define MAX_PATHNAME 512
/*
-** The locking styles are associated with the different file locking
-** capabilities supported by different file systems.
-**
-** POSIX support for shared and exclusive byte-range locks
-**
-** NONE no locking will be attempted, this is only used for
-** read-only file systems currently
-**
-** DOTLOCK isn't a true locking style, it refers to the use of a special
-** file named the same as the database file with a '.lock'
-** extension, this can be used on file systems that do not
-** offer any reliable file locking
-**
-** FLOCK only a single file-global exclusive lock (Not on VxWorks)
-**
-** NAMEDSEM similar to DOTLOCK but uses a named semaphore instead of an
-** indicator file. (VxWorks only)
-**
-** AFP support exclusive byte-range locks (MacOSX only)
-**
-** PROXY uses a second file to represent the lock state of the database
-** file which is never actually locked, a third file controls
-** access to the proxy (MacOSX only)
-**
-** Note that because FLOCK and NAMEDSEM are never used together, they
-** share the same code number (3). The locking mode numbering is
-** chosen so that a set of locking modes that are contiguous integers
-** from 1 to N. On generic unix systems without flock() support,
-** the modes are 1..3. On generic unix with flock() support, the modes
-** are 1..4. On VxWorks, the modes are 1..4. On MacOSX the modes
-** are 1..6.
-*/
-#define LOCKING_STYLE_POSIX 1
-#define LOCKING_STYLE_NONE 2
-#define LOCKING_STYLE_DOTFILE 3
-#define LOCKING_STYLE_FLOCK 4
-#define LOCKING_STYLE_NAMEDSEM 4
-#define LOCKING_STYLE_AFP 5
-#define LOCKING_STYLE_PROXY 6
-
-#define LOCKING_STYLE_AUTOMATIC 0 /* Choose lock style automatically */
-
-/*
** Only set the lastErrno if the error code is a real error and not
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
*/
@@ -864,57 +821,6 @@ static void testThreadLockingBehavior(int fd_orig){
#endif /* SQLITE_THERADSAFE && defined(__linux__) */
/*
-** If we are currently in a different thread than the thread that the
-** unixFile argument belongs to, then transfer ownership of the unixFile
-** over to the current thread.
-**
-** A unixFile is only owned by a thread on systems where one thread is
-** unable to override locks created by a different thread. RedHat9 is
-** an example of such a system.
-**
-** Ownership transfer is only allowed if the unixFile is currently unlocked.
-** If the unixFile is locked and an ownership is wrong, then return
-** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
-*/
-#if SQLITE_THREADSAFE && defined(__linux__)
-static int transferOwnership(unixFile *pFile){
- int rc;
- pthread_t hSelf;
- if( threadsOverrideEachOthersLocks ){
- /* Ownership transfers not needed on this system */
- return SQLITE_OK;
- }
- hSelf = pthread_self();
- if( pthread_equal(pFile->tid, hSelf) ){
- /* We are still in the same thread */
- OSTRACE1("No-transfer, same thread\n");
- return SQLITE_OK;
- }
- if( pFile->locktype!=NO_LOCK ){
- /* We cannot change ownership while we are holding a lock! */
- return SQLITE_MISUSE;
- }
- OSTRACE4("Transfer ownership of %d from %d to %d\n",
- pFile->h, pFile->tid, hSelf);
- pFile->tid = hSelf;
- if (pFile->pLock != NULL) {
- releaseLockInfo(pFile->pLock);
- rc = findLockInfo(pFile, &pFile->pLock, 0);
- OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
- locktypeName(pFile->locktype),
- locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
- return rc;
- } else {
- return SQLITE_OK;
- }
-}
-#else /* if not SQLITE_THREADSAFE */
- /* On single-threaded builds, ownership transfer is a no-op */
-# define transferOwnership(X) SQLITE_OK
-#endif /* SQLITE_THREADSAFE */
-
-
-/*
** Release a unixLockInfo structure previously allocated by findLockInfo().
*/
static void releaseLockInfo(struct unixLockInfo *pLock){
@@ -1087,6 +993,54 @@ exit_findlockinfo:
return rc;
}
+/*
+** If we are currently in a different thread than the thread that the
+** unixFile argument belongs to, then transfer ownership of the unixFile
+** over to the current thread.
+**
+** A unixFile is only owned by a thread on systems that use LinuxThreads.
+**
+** Ownership transfer is only allowed if the unixFile is currently unlocked.
+** If the unixFile is locked and an ownership is wrong, then return
+** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
+*/
+#if SQLITE_THREADSAFE && defined(__linux__)
+static int transferOwnership(unixFile *pFile){
+ int rc;
+ pthread_t hSelf;
+ if( threadsOverrideEachOthersLocks ){
+ /* Ownership transfers not needed on this system */
+ return SQLITE_OK;
+ }
+ hSelf = pthread_self();
+ if( pthread_equal(pFile->tid, hSelf) ){
+ /* We are still in the same thread */
+ OSTRACE1("No-transfer, same thread\n");
+ return SQLITE_OK;
+ }
+ if( pFile->locktype!=NO_LOCK ){
+ /* We cannot change ownership while we are holding a lock! */
+ return SQLITE_MISUSE;
+ }
+ OSTRACE4("Transfer ownership of %d from %d to %d\n",
+ pFile->h, pFile->tid, hSelf);
+ pFile->tid = hSelf;
+ if (pFile->pLock != NULL) {
+ releaseLockInfo(pFile->pLock);
+ rc = findLockInfo(pFile, &pFile->pLock, 0);
+ OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
+ locktypeName(pFile->locktype),
+ locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
+ return rc;
+ } else {
+ return SQLITE_OK;
+ }
+}
+#else /* if not SQLITE_THREADSAFE */
+ /* On single-threaded builds, ownership transfer is a no-op */
+# define transferOwnership(X) SQLITE_OK
+#endif /* SQLITE_THREADSAFE */
+
/*
** This routine checks if there is a RESERVED lock held on the specified
@@ -1646,6 +1600,11 @@ static int nolockClose(sqlite3_file *id) {
**
** Nevertheless, a dotlock is an appropriate locking mode for use if no
** other locking strategy is available.
+**
+** Dotfile locking works by creating a file in the same directory as the
+** database and with the same name but with a ".lock" extension added.
+** The existance of a lock file implies an EXCLUSIVE lock. All other lock
+** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
*/
/*
@@ -1654,8 +1613,16 @@ static int nolockClose(sqlite3_file *id) {
*/
#define DOTLOCK_SUFFIX ".lock"
-/* Dotlock-style reserved lock checking following the behavior of
-** unixCheckReservedLock, see the unixCheckReservedLock function comments */
+/*
+** 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
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+**
+** In dotfile locking, either a lock exists or it does not. So in this
+** variation of CheckReservedLock(), *pResOut is set to true if any lock
+** is held on the file and false if the file is unlocked.
+*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
int rc = SQLITE_OK;
int reserved = 0;
@@ -1667,55 +1634,63 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
/* Check if a thread in this process holds such a lock */
if( pFile->locktype>SHARED_LOCK ){
+ /* Either this connection or some other connection in the same process
+ ** holds a lock on the file. No need to check further. */
reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- char *zLockFile = (char *)pFile->lockingContext;
- struct stat statBuf;
-
- if( lstat(zLockFile, &statBuf)==0 ){
- /* file exists, someone else has the lock */
- reserved = 1;
- }else{
- /* file does not exist, we could have it if we want it */
- int tErrno = errno;
- if( ENOENT != tErrno ){
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- pFile->lastErrno = tErrno;
- }
- }
+ }else{
+ /* The lock is held if and only if the lockfile exists */
+ const char *zLockFile = (const char*)pFile->lockingContext;
+ reserved = access(zLockFile, 0)==0;
}
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
-
*pResOut = reserved;
return rc;
}
+/*
+** Lock the file with the lock specified by parameter locktype - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+**
+** With dotfile locking, we really only support state (4): EXCLUSIVE.
+** But we track the other locking levels internally.
+*/
static int dotlockLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
char *zLockFile = (char *)pFile->lockingContext;
- int rc=SQLITE_OK;
+ int rc = SQLITE_OK;
- /* if we already have a lock, it is exclusive.
- ** Just adjust level and punt on outta here. */
- if (pFile->locktype > NO_LOCK) {
+
+ /* If we have any lock, then the lock file already exists. All we have
+ ** to do is adjust our internal record of the lock level.
+ */
+ if( pFile->locktype > NO_LOCK ){
pFile->locktype = locktype;
#if !OS_VXWORKS
/* Always update the timestamp on the old file */
utimes(zLockFile, NULL);
#endif
- rc = SQLITE_OK;
- goto dotlock_end_lock;
- }
-
- /* check to see if lock file already exists */
- struct stat statBuf;
- if (lstat(zLockFile,&statBuf) == 0){
- rc = SQLITE_BUSY; /* it does, busy */
- goto dotlock_end_lock;
+ return SQLITE_OK;
}
/* grab an exclusive lock */
@@ -1731,7 +1706,7 @@ static int dotlockLock(sqlite3_file *id, int locktype) {
pFile->lastErrno = tErrno;
}
}
- goto dotlock_end_lock;
+ return rc;
}
if( close(fd) ){
pFile->lastErrno = errno;
@@ -1740,11 +1715,18 @@ static int dotlockLock(sqlite3_file *id, int locktype) {
/* got it, set the type and return ok */
pFile->locktype = locktype;
-
- dotlock_end_lock:
return rc;
}
+/*
+** Lower the locking level on file descriptor pFile to locktype. locktype
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+**
+** When the locking level reaches NO_LOCK, delete the lock file.
+*/
static int dotlockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
char *zLockFile = (char *)pFile->lockingContext;
@@ -1758,15 +1740,18 @@ static int dotlockUnlock(sqlite3_file *id, int locktype) {
if( pFile->locktype==locktype ){
return SQLITE_OK;
}
-
- /* shared can just be set because we always have an exclusive */
- if (locktype==SHARED_LOCK) {
- pFile->locktype = locktype;
+
+ /* To downgrade to shared, simply update our internal notion of the
+ ** lock state. No need to mess with the file on disk.
+ */
+ if( locktype==SHARED_LOCK ){
+ pFile->locktype = SHARED_LOCK;
return SQLITE_OK;
}
- /* no, really, unlock. */
- if (unlink(zLockFile) ) {
+ /* To fully unlock the database, delete the lock file */
+ assert( locktype==NO_LOCK );
+ if( unlink(zLockFile) ){
int rc, tErrno = errno;
if( ENOENT != tErrno ){
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
@@ -1807,6 +1792,7 @@ static int dotlockClose(sqlite3_file *id) {
** compiling for VXWORKS.
*/
#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+#include <sys/file.h>
/*
** The flockLockingContext is not used
@@ -1870,7 +1856,6 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
static int flockLock(sqlite3_file *id, int locktype) {
int rc = SQLITE_OK;
- int lrc;
unixFile *pFile = (unixFile*)id;
assert( pFile );
@@ -2629,39 +2614,12 @@ static int afpClose(sqlite3_file *id) {
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath);
static int getLockPath(const char *dbPath, char *lPath, size_t maxLen);
-static sqlite3_io_methods *ioMethodForLockingStyle(int style);
static int createProxyUnixFile(const char *path, unixFile **ppFile);
static int fillInUnixFile(sqlite3_vfs *pVfs, int h, int dirfd, sqlite3_file *pId, const char *zFilename, int noLock, int isDelete);
static int takeConch(unixFile *pFile);
static int releaseConch(unixFile *pFile);
static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf);
-/*
-** Tests a byte-range locking query to see if byte range locks are
-** supported, if not we fall back to dotlockLockingStyle.
-** On vxWorks we fall back to semLockingStyle.
-*/
-static int testLockingStyle(int fd){
- struct flock lockInfo;
-
- /* Test byte-range lock using fcntl(). If the call succeeds,
- ** assume that the file-system supports POSIX style locks.
- */
- lockInfo.l_len = 1;
- lockInfo.l_start = 0;
- lockInfo.l_whence = SEEK_SET;
- lockInfo.l_type = F_RDLCK;
- if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
- return LOCKING_STYLE_POSIX;
- }
-
- /* Testing for flock() can give false positives. So if if the above
- ** test fails, then we fall back to using dot-file style locking (or
- ** named-semaphore locking on vxworks).
- */
- return (OS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE);
-}
-
#ifdef SQLITE_TEST
/* simulate multiple hosts by creating unique hostid file paths */
@@ -3022,8 +2980,7 @@ end_takeconch:
if( tLockPath ){
pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath);
- if( pCtx->lockProxy->pMethod ==
- ioMethodForLockingStyle(LOCKING_STYLE_AFP) ){
+ if( pCtx->lockProxy->pMethod == &afpIoMethods ){
((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath =
pCtx->lockProxyPath;
}
@@ -3212,7 +3169,7 @@ end_transform_file:
pCtx->oldLockingContext = pFile->lockingContext;
pFile->lockingContext = pCtx;
pCtx->pOldMethod = pFile->pMethod;
- pFile->pMethod = ioMethodForLockingStyle(LOCKING_STYLE_PROXY);
+ pFile->pMethod = &proxyIoMethods;
}else{
if( pCtx->conchFile ){
rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
@@ -3646,10 +3603,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = ((unixFile*)id)->locktype;
return SQLITE_OK;
}
+ case SQLITE_LAST_ERRNO: {
+ *(int*)pArg = ((unixFile*)id)->lastErrno;
+ return SQLITE_OK;
+ }
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
case SQLITE_GET_LOCKPROXYFILE: {
-#if SQLITE_ENABLE_LOCKING_STYLE
unixFile *pFile = (unixFile*)id;
- if( pFile->pMethod == ioMethodForLockingStyle(LOCKING_STYLE_PROXY) ){
+ if( pFile->pMethod == &proxyIoMethods ){
proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
takeConch(pFile);
if( pCtx->lockProxyPath ){
@@ -3660,22 +3621,18 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
} else {
*(const char **)pArg = NULL;
}
-#else
- *(void**)pArg = NULL;
-#endif
return SQLITE_OK;
}
case SQLITE_SET_LOCKPROXYFILE: {
-#if SQLITE_ENABLE_LOCKING_STYLE
unixFile *pFile = (unixFile*)id;
int rc = SQLITE_OK;
- int isProxyStyle = (pFile->pMethod == ioMethodForLockingStyle(LOCKING_STYLE_PROXY));
+ int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
if( pArg==NULL || (const char *)pArg==0 ){
if( isProxyStyle ){
- // turn off proxy locking - not supported
+ /* turn off proxy locking - not supported */
rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
}else{
- // turn off proxy locking - already off - NOOP
+ /* turn off proxy locking - already off - NOOP */
rc = SQLITE_OK;
}
}else{
@@ -3683,26 +3640,22 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
if( isProxyStyle ){
proxyLockingContext *pCtx =
(proxyLockingContext*)pFile->lockingContext;
- if( !strcmp(pArg, ":auto:") || (pCtx->lockProxyPath && !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN)) ){
+ if( !strcmp(pArg, ":auto:")
+ || (pCtx->lockProxyPath &&
+ !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
+ ){
rc = SQLITE_OK;
}else{
rc = switchLockProxyPath(pFile, proxyPath);
}
}else{
- // turn on proxy file locking
+ /* turn on proxy file locking */
rc = transformUnixFileForLockProxy(pFile, proxyPath);
}
}
return rc;
-#else
- return SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
-#endif
- }
- case SQLITE_LAST_ERRNO: {
- *(int*)pArg = ((unixFile*)id)->lastErrno;
- return SQLITE_OK;
}
-
+#endif
}
return SQLITE_ERROR;
}
@@ -3737,135 +3690,183 @@ static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
******************************************************************************/
/*
-** The following constant array describes all of the methods for the
-** sqlite3_file object for each of the various locking modes.
+** Each instance of this macro generates two objects:
+**
+** * A constant sqlite3_io_methods object call METHOD that has locking
+** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
**
-** The order in which the methods are defined is important and must
-** agree with the numeric values of the method identifier constants.
-** For example, LOCKING_STYLE_UNIX has a numeric value of zero, so
-** it must be the 0-th entry in the array.
+** * An I/O method finder function called FINDER that returns a pointer
+** to the METHOD object in the previous bullet.
*/
-#define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) { \
- 1, /* iVersion */ \
- xClose, /* xClose */ \
- unixRead, /* xRead */ \
- unixWrite, /* xWrite */ \
- unixTruncate, /* xTruncate */ \
- unixSync, /* xSync */ \
- unixFileSize, /* xFileSize */ \
- xLock, /* xLock */ \
- xUnlock, /* xUnlock */ \
- xCheckReservedLock, /* xCheckReservedLock */ \
- unixFileControl, /* xFileControl */ \
- unixSectorSize, /* xSectorSize */ \
- unixDeviceCharacteristics /* xDeviceCapabilities */ \
+#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK) \
+static const sqlite3_io_methods METHOD = { \
+ 1, /* iVersion */ \
+ CLOSE, /* xClose */ \
+ unixRead, /* xRead */ \
+ unixWrite, /* xWrite */ \
+ unixTruncate, /* xTruncate */ \
+ unixSync, /* xSync */ \
+ unixFileSize, /* xFileSize */ \
+ LOCK, /* xLock */ \
+ UNLOCK, /* xUnlock */ \
+ CKLOCK, /* xCheckReservedLock */ \
+ unixFileControl, /* xFileControl */ \
+ unixSectorSize, /* xSectorSize */ \
+ unixDeviceCharacteristics /* xDeviceCapabilities */ \
+}; \
+static const sqlite3_io_methods *FINDER(const char *z, int h){ \
+ UNUSED_PARAMETER(z); UNUSED_PARAMETER(h); \
+ return &METHOD; \
}
-static sqlite3_io_methods aIoMethod[] = {
- IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock),
- IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock),
- IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock),
+
+/*
+** Here are all of the sqlite3_io_methods objects for each of the
+** locking strategies. Functions that return pointers to these methods
+** are also created.
+*/
+IOMETHODS(
+ posixIoFinder, /* Finder function name */
+ posixIoMethods, /* sqlite3_io_methods object name */
+ unixClose, /* xClose method */
+ unixLock, /* xLock method */
+ unixUnlock, /* xUnlock method */
+ unixCheckReservedLock /* xCheckReservedLock method */
+);
+IOMETHODS(
+ nolockIoFinder, /* Finder function name */
+ nolockIoMethods, /* sqlite3_io_methods object name */
+ nolockClose, /* xClose method */
+ nolockLock, /* xLock method */
+ nolockUnlock, /* xUnlock method */
+ nolockCheckReservedLock /* xCheckReservedLock method */
+);
+IOMETHODS(
+ dotlockIoFinder, /* Finder function name */
+ dotlockIoMethods, /* sqlite3_io_methods object name */
+ dotlockClose, /* xClose method */
+ dotlockLock, /* xLock method */
+ dotlockUnlock, /* xUnlock method */
+ dotlockCheckReservedLock /* xCheckReservedLock method */
+);
+
+#if SQLITE_ENABLE_LOCKING_STYLE
+IOMETHODS(
+ flockIoFinder, /* Finder function name */
+ flockIoMethods, /* sqlite3_io_methods object name */
+ flockClose, /* xClose method */
+ flockLock, /* xLock method */
+ flockUnlock, /* xUnlock method */
+ flockCheckReservedLock /* xCheckReservedLock method */
+);
+#endif
+
#if OS_VXWORKS
- IOMETHODS(semClose, semLock, semUnlock, semCheckReservedLock),
-#elif SQLITE_ENABLE_LOCKING_STYLE
- IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock),
+IOMETHODS(
+ semIoFinder, /* Finder function name */
+ semIoMethods, /* sqlite3_io_methods object name */
+ semClose, /* xClose method */
+ semLock, /* xLock method */
+ semUnlock, /* xUnlock method */
+ semCheckReservedLock /* xCheckReservedLock method */
+);
#endif
+
#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
- IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock),
- IOMETHODS(proxyClose, proxyLock, proxyUnlock, proxyCheckReservedLock),
+IOMETHODS(
+ afpIoFinder, /* Finder function name */
+ afpIoMethods, /* sqlite3_io_methods object name */
+ afpClose, /* xClose method */
+ afpLock, /* xLock method */
+ afpUnlock, /* xUnlock method */
+ afpCheckReservedLock /* xCheckReservedLock method */
+);
+IOMETHODS(
+ proxyIoFinder, /* Finder function name */
+ proxyIoMethods, /* sqlite3_io_methods object name */
+ proxyClose, /* xClose method */
+ proxyLock, /* xLock method */
+ proxyUnlock, /* xUnlock method */
+ proxyCheckReservedLock /* xCheckReservedLock method */
+);
#endif
- /* The order of the IOMETHODS macros above is important. It must be the
- ** same order as the LOCKING_STYLE numbers
- */
-};
-/****************************************************************************
-**************************** sqlite3_vfs methods ****************************
-**
-** This division contains the implementation of methods on the
-** sqlite3_vfs object.
-*/
+#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
/*
-** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the
-** f_fstypename entry in the statfs structure as returned by stat() for
-** the file system hosting the database file and selects the appropriate
-** locking style based on its value. These values and assignments are
-** based on Darwin/OSX behavior and have not been thoroughly tested on
-** other systems.
-**
-** If SQLITE_ENABLE_LOCKING_STYLE is not defined, this function always
-** returns LOCKING_STYLE_POSIX.
+** This procedure attempts to determine the best locking strategy for
+** the given database file. It then returns the sqlite3_io_methods
+** object that implements that strategy.
+**
+** This is for MacOSX only.
*/
-#if SQLITE_ENABLE_LOCKING_STYLE
-static int detectLockingStyle(
- sqlite3_vfs *pVfs,
- const char *filePath,
- int fd
+static const sqlite3_io_methods *autolockIoFinder(
+ const char *filePath, /* name of the database file */
+ int fd /* file descriptor open on the database file */
){
-#if OS_VXWORKS
- if( !filePath ){
- return LOCKING_STYLE_NONE;
- }
- if( pVfs->pAppData ){
- return SQLITE_PTR_TO_INT(pVfs->pAppData);
- }
- if (access(filePath, 0) != -1){
- return testLockingStyle(fd);
- }
-#else
- struct Mapping {
+ static const struct Mapping {
const char *zFilesystem;
- int eLockingStyle;
+ const sqlite3_io_methods *pMethods;
} aMap[] = {
- { "hfs", LOCKING_STYLE_POSIX },
- { "ufs", LOCKING_STYLE_POSIX },
- { "afpfs", LOCKING_STYLE_AFP },
+ { "hfs", &posixIoMethods },
+ { "ufs", &posixIoMethods },
+ { "afpfs", &afpIoMethods },
#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
- { "smbfs", LOCKING_STYLE_AFP },
+ { "smbfs", &afpIoMethods },
#else
- { "smbfs", LOCKING_STYLE_FLOCK },
+ { "smbfs", &flockIoMethods },
#endif
- { "webdav", LOCKING_STYLE_NONE },
+ { "webdav", &nolockIoMethods },
{ 0, 0 }
};
int i;
struct statfs fsInfo;
+ struct flock lockInfo;
if( !filePath ){
- return LOCKING_STYLE_NONE;
- }
- if( pVfs && pVfs->pAppData ){
- return SQLITE_PTR_TO_INT(pVfs->pAppData);
+ return &nolockIoMethods;
}
-
if( statfs(filePath, &fsInfo) != -1 ){
if( fsInfo.f_flags & MNT_RDONLY ){
- return LOCKING_STYLE_NONE;
+ return &nolockIoMethods;
}
for(i=0; aMap[i].zFilesystem; i++){
if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
- return aMap[i].eLockingStyle;
+ return aMap[i].pMethods;
}
}
}
- /* Default case. Handles, amongst others, "nfs". */
- return testLockingStyle(fd);
-#endif /* if OS_VXWORKS */
- return LOCKING_STYLE_POSIX;
+ /* Default case. Handles, amongst others, "nfs".
+ ** Test byte-range lock using fcntl(). If the call succeeds,
+ ** assume that the file-system supports POSIX style locks.
+ */
+ lockInfo.l_len = 1;
+ lockInfo.l_start = 0;
+ lockInfo.l_whence = SEEK_SET;
+ lockInfo.l_type = F_RDLCK;
+ if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
+ return &posixIoMethods;
+ }else{
+ return &dotlockIoMethods;
+ }
}
-#else
- #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
-#endif /* if SQLITE_ENABLE_LOCKING_STYLE */
+#endif /* defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE */
+
+/*
+** An abstract type for a pointer to a IO method finder function:
+*/
+typedef const sqlite3_io_methods *(*finder_type)(const char*,int);
+/****************************************************************************
+**************************** sqlite3_vfs methods ****************************
+**
+** This division contains the implementation of methods on the
+** sqlite3_vfs object.
+*/
+
/*
** Initialize the contents of the unixFile structure pointed to by pId.
-**
-** When locking extensions are enabled, the filepath and locking style
-** are needed to determine the unixFile pMethod to use for locking operations.
-** The locking-style specific lockingContext data structure is created
-** and assigned here also.
*/
static int fillInUnixFile(
sqlite3_vfs *pVfs, /* Pointer to vfs object */
@@ -3876,7 +3877,7 @@ static int fillInUnixFile(
int noLock, /* Omit locking if true */
int isDelete /* Delete on close if true */
){
- int eLockingStyle;
+ const sqlite3_io_methods *pLockingStyle;
unixFile *pNew = (unixFile *)pId;
int rc = SQLITE_OK;
@@ -3887,9 +3888,15 @@ static int fillInUnixFile(
** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly
** here to prevent compiler warnings about unused parameters.
*/
- if( !OS_VXWORKS ) UNUSED_PARAMETER(isDelete);
- if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs);
- if( !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename);
+#if !OS_VXWORKS
+ UNUSED_PARAMETER(isDelete);
+#endif
+#if !SQLITE_ENABLE_LOCKING_STYLE
+ UNUSED_PARAMETER(pVfs);
+#endif
+#if !OS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE
+ UNUSED_PARAMETER(zFilename);
+#endif
OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->h = h;
@@ -3905,9 +3912,9 @@ static int fillInUnixFile(
#endif
if( noLock ){
- eLockingStyle = LOCKING_STYLE_NONE;
+ pLockingStyle = &nolockIoMethods;
}else{
- eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
+ pLockingStyle = (*(finder_type)pVfs->pAppData)(zFilename, h);
#if SQLITE_ENABLE_LOCKING_STYLE
/* Cache zFilename in the locking context (AFP and dotlock override) for
** proxyLock activation is possible (remote proxy is based on db name)
@@ -3916,88 +3923,75 @@ static int fillInUnixFile(
#endif
}
-
- switch( eLockingStyle ){
+ if( pLockingStyle == &posixIoMethods ){
+ unixEnterMutex();
+ rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
+ unixLeaveMutex();
+ }
- case LOCKING_STYLE_POSIX: {
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+ else if( pLockingStyle == &apfIoMethods ){
+ /* AFP locking uses the file path so it needs to be included in
+ ** the afpLockingContext.
+ */
+ afpLockingContext *pCtx;
+ pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
+ if( pCtx==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ /* NB: zFilename exists and remains valid until the file is closed
+ ** according to requirement F11141. So we do not need to make a
+ ** copy of the filename. */
+ pCtx->dbPath = zFilename;
+ srandomdev();
unixEnterMutex();
- rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
- unixLeaveMutex();
- break;
+ rc = findLockInfo(pNew, NULL, &pNew->pOpen);
+ unixLeaveMutex();
}
+ }
+#endif
#if SQLITE_ENABLE_LOCKING_STYLE
-
-#if !OS_VXWORKS
- case LOCKING_STYLE_AFP: {
- /* AFP locking uses the file path so it needs to be included in
- ** the afpLockingContext.
- */
- afpLockingContext *pCtx;
- pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
- if( pCtx==0 ){
- rc = SQLITE_NOMEM;
- }else{
- /* NB: zFilename exists and remains valid until the file is closed
- ** according to requirement F11141. So we do not need to make a
- ** copy of the filename. */
- pCtx->dbPath = zFilename;
- srandomdev();
- unixEnterMutex();
- rc = findLockInfo(pNew, NULL, &pNew->pOpen);
- unixLeaveMutex();
- }
- break;
+ else if( pLockingStyle == &dotlockIoMethods ){
+ /* Dotfile locking uses the file path so it needs to be included in
+ ** the dotlockLockingContext
+ */
+ char *zLockFile;
+ int nFilename;
+ nFilename = strlen(zFilename) + 6;
+ zLockFile = (char *)sqlite3_malloc(nFilename);
+ if( zLockFile==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
}
+ pNew->lockingContext = zLockFile;
+ }
#endif
- case LOCKING_STYLE_DOTFILE: {
- /* Dotfile locking uses the file path so it needs to be included in
- ** the dotlockLockingContext
- */
- char *zLockFile;
- int nFilename;
- nFilename = strlen(zFilename) + 6;
- zLockFile = (char *)sqlite3_malloc(nFilename);
- if( zLockFile==0 ){
- rc = SQLITE_NOMEM;
- }else{
- sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
- }
- pNew->lockingContext = zLockFile;
- break;
- }
-
#if OS_VXWORKS
- case LOCKING_STYLE_NAMEDSEM: {
- /* Named semaphore locking uses the file path so it needs to be
- ** included in the semLockingContext
- */
- unixEnterMutex();
- rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
- if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
- char *zSemName = pNew->pOpen->aSemName;
- int n;
- sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem",
- pNew->pId->zCanonicalName);
- for( n=0; zSemName[n]; n++ )
- if( zSemName[n]=='/' ) zSemName[n] = '_';
- pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
- if( pNew->pOpen->pSem == SEM_FAILED ){
- rc = SQLITE_NOMEM;
- pNew->pOpen->aSemName[0] = '\0';
- }
+ else if( pLockingStyle == &semIoMethods ){
+ /* Named semaphore locking uses the file path so it needs to be
+ ** included in the semLockingContext
+ */
+ unixEnterMutex();
+ rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
+ if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
+ char *zSemName = pNew->pOpen->aSemName;
+ int n;
+ sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem",
+ pNew->pId->zCanonicalName);
+ for( n=0; zSemName[n]; n++ )
+ if( zSemName[n]=='/' ) zSemName[n] = '_';
+ pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
+ if( pNew->pOpen->pSem == SEM_FAILED ){
+ rc = SQLITE_NOMEM;
+ pNew->pOpen->aSemName[0] = '\0';
}
- unixLeaveMutex();
- break;
}
-#endif
-
- case LOCKING_STYLE_FLOCK:
- case LOCKING_STYLE_NONE:
- break;
-#endif
+ unixLeaveMutex();
}
+#endif
pNew->lastErrno = 0;
#if OS_VXWORKS
@@ -4011,34 +4005,32 @@ static int fillInUnixFile(
if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */
close(h);
}else{
- pNew->pMethod = &aIoMethod[eLockingStyle-1];
+ pNew->pMethod = pLockingStyle;
OpenCounter(+1);
}
return rc;
}
#if SQLITE_ENABLE_LOCKING_STYLE
-static sqlite3_io_methods *ioMethodForLockingStyle(int style){
- return &aIoMethod[style];
-}
-
static int getDbPathForUnixFile(unixFile *pFile, char *dbPath){
- if( pFile->pMethod==ioMethodForLockingStyle(LOCKING_STYLE_AFP) ){
+#if defined(__DARWIN__)
+ if( pFile->pMethod == &afpIoMethods ){
/* afp style keeps a reference to the db path in the filePath field
** of the struct */
- strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath,
- MAXPATHLEN);
- return SQLITE_OK;
- }
- if( pFile->pMethod==ioMethodForLockingStyle(LOCKING_STYLE_DOTFILE) ){
+ assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+ strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath)
+ }else
+#endif
+ if( pFile->pMethod == &dotlockIoMethods ){
/* dot lock style uses the locking context to store the dot lock
** file path */
int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
- strlcpy(dbPath, (char *)pFile->lockingContext, len + 1);
- return SQLITE_OK;
+ memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
+ }else{
+ /* all other styles use the locking context to store the db file path */
+ assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+ strcpy(dbPath, (char *)pFile->lockingContext);
}
- /* all other styles use the locking context to store the db file path */
- strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
return SQLITE_OK;
}
#endif
@@ -4283,8 +4275,8 @@ static int unixOpen(
int useProxy = 0;
/* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy,
- ** 0 means never use proxy, NULL means use proxy for non-local files only
- */
+ ** 0 means never use proxy, NULL means use proxy for non-local files only
+ */
if( envforce!=NULL ){
useProxy = atoi(envforce)>0;
}else{
@@ -4595,13 +4587,13 @@ int sqlite3_os_init(void){
** the sqlite3_vfs.zName and sqlite3_vfs.pAppData fields, respectively.
**
*/
- #define UNIXVFS(zVfsName, pVfsAppData) { \
+ #define UNIXVFS(VFSNAME, FINDER) { \
1, /* iVersion */ \
sizeof(unixFile), /* szOsFile */ \
MAX_PATHNAME, /* mxPathname */ \
0, /* pNext */ \
- zVfsName, /* zName */ \
- (void *)pVfsAppData, /* pAppData */ \
+ VFSNAME, /* zName */ \
+ (void*)FINDER, /* pAppData */ \
unixOpen, /* xOpen */ \
unixDelete, /* xDelete */ \
unixAccess, /* xAccess */ \
@@ -4616,21 +4608,25 @@ int sqlite3_os_init(void){
unixGetLastError /* xGetLastError */ \
}
- int i;
+ unsigned int i;
static sqlite3_vfs aVfs[] = {
- UNIXVFS("unix", LOCKING_STYLE_AUTOMATIC),
- UNIXVFS("unix-posix", LOCKING_STYLE_POSIX),
- UNIXVFS("unix-none", LOCKING_STYLE_NONE),
- UNIXVFS("unix-dotfile", LOCKING_STYLE_DOTFILE),
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+ UNIXVFS("unix", autolockIoFinder ),
+#else
+ UNIXVFS("unix", posixIoFinder ),
+#endif
+ UNIXVFS("unix-none", nolockIoFinder ),
+ UNIXVFS("unix-dotfile", dotlockIoFinder ),
#if OS_VXWORKS
- UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
+ UNIXVFS("unix-namedsem", semIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
- UNIXVFS("unix-flock", LOCKING_STYLE_FLOCK),
+ UNIXVFS("unix-posix", posixIoFinder ),
+ UNIXVFS("unix-flock", flockIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
- UNIXVFS("unix-afp", LOCKING_STYLE_AFP),
- UNIXVFS("unix-proxy", LOCKING_STYLE_PROXY)
+ UNIXVFS("unix-afp", afpIoFinder ),
+ UNIXVFS("unix-proxy", proxyIoFinder ),
#endif
};
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){