diff options
author | danielk1977 <danielk1977@noemail.net> | 2007-08-17 15:53:36 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2007-08-17 15:53:36 +0000 |
commit | b4b47411ab9ffcf594c239ceeb942acebabc0ece (patch) | |
tree | 3ee8070132b7ae4dad20a147205d47c0b9329243 /src/os_unix.c | |
parent | e53831d644a0ce94628a8a1576d819d7bea40999 (diff) | |
download | sqlite-b4b47411ab9ffcf594c239ceeb942acebabc0ece.tar.gz sqlite-b4b47411ab9ffcf594c239ceeb942acebabc0ece.zip |
Begin migration to using sqlite3_vfs interface. (CVS 4240)
FossilOrigin-Name: af3e3c7acdc67013dd733effebe981620d922dd1
Diffstat (limited to 'src/os_unix.c')
-rw-r--r-- | src/os_unix.c | 593 |
1 files changed, 320 insertions, 273 deletions
diff --git a/src/os_unix.c b/src/os_unix.c index 71f4bafdd..a3d3ba4ec 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -74,6 +74,10 @@ # define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 #endif +/* +** Maximum supported path-length. +*/ +#define MAX_PATHNAME 512 /* @@ -386,6 +390,13 @@ typedef enum { } sqlite3LockingStyle; #endif /* SQLITE_ENABLE_LOCKING_STYLE */ +static void enterMutex(){ + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL)); +} +static void leaveMutex(){ + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL)); +} + #ifdef SQLITE_UNIX_THREADS /* ** This variable records whether or not threads can override each others @@ -529,7 +540,6 @@ static void testThreadLockingBehavior(int fd_orig){ ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ - assert( sqlite3OsInMutex(1) ); if (pLock == NULL) return; pLock->nRef--; @@ -543,7 +553,6 @@ static void releaseLockInfo(struct lockInfo *pLock){ ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ - assert( sqlite3OsInMutex(1) ); if (pOpen == NULL) return; pOpen->nRef--; @@ -646,7 +655,6 @@ static int findLockInfo( rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; - assert( sqlite3OsInMutex(1) ); memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; @@ -820,6 +828,7 @@ static int allocateUnixFile( ** On failure, the function returns SQLITE_CANTOPEN and leaves ** *id and *pReadonly unchanged. */ +#if 0 int sqlite3UnixOpenReadWrite( const char *zFilename, sqlite3_file **pId, @@ -903,6 +912,7 @@ int sqlite3UnixOpenReadOnly(const char *zFilename, sqlite3_file **pId){ zFilename, pId, allocateUnixFile(h, pId, zFilename, 0) ); } +#endif /* ** Attempt to open a file descriptor for the directory that contains a @@ -944,46 +954,6 @@ static int unixOpenDirectory( } /* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at least SQLITE_TEMPNAME_SIZE characters. -*/ -int sqlite3UnixTempFileName(char *zBuf){ - static const char *azDirs[] = { - 0, - "/var/tmp", - "/usr/tmp", - "/tmp", - ".", - }; - static const unsigned char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i, j; - struct stat buf; - const char *zDir = "."; - azDirs[0] = sqlite3_temp_directory; - for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ - if( azDirs[i]==0 ) continue; - if( stat(azDirs[i], &buf) ) continue; - if( !S_ISDIR(buf.st_mode) ) continue; - if( access(azDirs[i], 07) ) continue; - zDir = azDirs[i]; - break; - } - do{ - sqlite3_snprintf(SQLITE_TEMPNAME_SIZE, zBuf, "%s/"TEMP_FILE_PREFIX, zDir); - j = strlen(zBuf); - sqlite3Randomness(15, &zBuf[j]); - for(i=0; i<15; i++, j++){ - zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; - } - zBuf[j] = 0; - }while( access(zBuf,0)==0 ); - return SQLITE_OK; -} - -/* ** Check that a given pathname is a directory and is writable ** */ @@ -1325,7 +1295,7 @@ static int unixCheckReservedLock(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; assert( pFile ); - sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ + enterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pLock->locktype>SHARED_LOCK ){ @@ -1346,7 +1316,7 @@ static int unixCheckReservedLock(sqlite3_file *id){ } } - sqlite3OsLeaveMutex(); + leaveMutex(); OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); return r; @@ -1428,7 +1398,7 @@ static int unixLock(sqlite3_file *id, int locktype){ /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as - ** sqlite3OsEnterMutex() hasn't been called yet. + ** enterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, @@ -1444,13 +1414,13 @@ static int unixLock(sqlite3_file *id, int locktype){ /* This mutex is needed because pFile->pLock is shared across threads */ - sqlite3OsEnterMutex(); + enterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ - sqlite3OsLeaveMutex(); + leaveMutex(); return rc; } pLock = pFile->pLock; @@ -1565,7 +1535,7 @@ static int unixLock(sqlite3_file *id, int locktype){ } end_lock: - sqlite3OsLeaveMutex(); + leaveMutex(); OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; @@ -1595,7 +1565,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){ if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } - sqlite3OsEnterMutex(); + enterMutex(); pLock = pFile->pLock; assert( pLock->cnt!=0 ); if( pFile->locktype>SHARED_LOCK ){ @@ -1656,7 +1626,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){ pOpen->aPending = 0; } } - sqlite3OsLeaveMutex(); + leaveMutex(); pFile->locktype = locktype; return rc; } @@ -1670,7 +1640,7 @@ static int unixClose(sqlite3_file *id){ unixUnlock(id, NO_LOCK); if( pFile->dirfd>=0 ) close(pFile->dirfd); pFile->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); if( pFile->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just @@ -1695,11 +1665,11 @@ static int unixClose(sqlite3_file *id){ releaseLockInfo(pFile->pLock); releaseOpenCnt(pFile->pOpen); - sqlite3OsLeaveMutex(); + leaveMutex(); pFile->isOpen = 0; OSTRACE2("CLOSE %-3d\n", pFile->h); OpenCounter(-1); - sqlite3_free(id); + memset(pFile, 0, sizeof(unixFile)); return SQLITE_OK; } @@ -1806,7 +1776,7 @@ static int afpUnixLock(OsFile *id, int locktype) locktypeName(locktype), locktypeName(pFile->locktype), getpid()); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the afp_end_lock: exit path, as - ** sqlite3OsEnterMutex() hasn't been called yet. + ** enterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, @@ -1822,13 +1792,13 @@ static int afpUnixLock(OsFile *id, int locktype) /* This mutex is needed because pFile->pLock is shared across threads */ - sqlite3OsEnterMutex(); + enterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ - sqlite3OsLeaveMutex(); + leaveMutex(); return rc; } @@ -1915,7 +1885,7 @@ static int afpUnixLock(OsFile *id, int locktype) } afp_end_lock: - sqlite3OsLeaveMutex(); + leaveMutex(); OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), rc==SQLITE_OK ? "ok" : "failed"); return rc; @@ -1945,7 +1915,7 @@ static int afpUnixUnlock(OsFile *id, int locktype) { if( CHECK_THREADID(pFile) ){ return SQLITE_MISUSE; } - sqlite3OsEnterMutex(); + enterMutex(); if( pFile->locktype>SHARED_LOCK ){ if( locktype==SHARED_LOCK ){ int failed = 0; @@ -1989,7 +1959,7 @@ static int afpUnixUnlock(OsFile *id, int locktype) { } if (rc == SQLITE_OK) pFile->locktype = locktype; - sqlite3OsLeaveMutex(); + leaveMutex(); return rc; } @@ -2103,10 +2073,10 @@ static int flockUnixClose(OsFile **pId) { if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); close(id->h); - sqlite3OsLeaveMutex(); + leaveMutex(); id->isOpen = 0; OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); @@ -2221,11 +2191,11 @@ static int dotlockUnixClose(OsFile **pId) { if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); close(id->h); - sqlite3OsLeaveMutex(); + leaveMutex(); id->isOpen = 0; OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); @@ -2263,11 +2233,11 @@ static int nolockUnixClose(OsFile **pId) { if( !id ) return SQLITE_OK; if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; - sqlite3OsEnterMutex(); + enterMutex(); close(id->h); - sqlite3OsLeaveMutex(); + leaveMutex(); id->isOpen = 0; OSTRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); @@ -2279,56 +2249,6 @@ static int nolockUnixClose(OsFile **pId) { #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* -** Turn a relative pathname into a full pathname. Return a pointer -** to the full pathname stored in space obtained from sqliteMalloc(). -** The calling function is responsible for freeing this space once it -** is no longer needed. -*/ -char *sqlite3UnixFullPathname(const char *zRelative){ - char *zFull = 0; - if( zRelative[0]=='/' ){ - sqlite3SetString(&zFull, zRelative, (char*)0); - }else{ - char *zBuf = sqlite3_malloc(5000); - if( zBuf==0 ){ - return 0; - } - zBuf[0] = 0; - sqlite3SetString(&zFull, getcwd(zBuf, 5000), "/", zRelative, - (char*)0); - sqlite3_free(zBuf); - } - -#if 0 - /* - ** Remove "/./" path elements and convert "/A/./" path elements - ** to just "/". - */ - if( zFull ){ - int i, j; - for(i=j=0; zFull[i]; i++){ - if( zFull[i]=='/' ){ - if( zFull[i+1]=='/' ) continue; - if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ - i += 1; - continue; - } - if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ - while( j>0 && zFull[j-1]!='/' ){ j--; } - i += 3; - continue; - } - } - zFull[j++] = zFull[i]; - } - zFull[j] = 0; - } -#endif - - return zFull; -} - -/* ** Change the value of the fullsync flag in the given file descriptor. */ static void unixSetFullSync(OsFile *id, int v){ @@ -2510,9 +2430,9 @@ static int allocateUnixFile( memset(&f, 0, sizeof(f)); lockingStyle = sqlite3DetectLockingStyle(zFilename, h); if ( lockingStyle == posixLockingStyle ) { - sqlite3OsEnterMutex(); + enterMutex(); rc = findLockInfo(h, &f.pLock, &f.pOpen); - sqlite3OsLeaveMutex(); + leaveMutex(); if( rc ){ close(h); unlink(zFilename); @@ -2532,10 +2452,10 @@ static int allocateUnixFile( pNew = sqlite3_malloc( sizeof(unixFile) ); if( pNew==0 ){ close(h); - sqlite3OsEnterMutex(); + enterMutex(); releaseLockInfo(f.pLock); releaseOpenCnt(f.pOpen); - sqlite3OsLeaveMutex(); + leaveMutex(); *pId = 0; return SQLITE_NOMEM; }else{ @@ -2590,50 +2510,34 @@ static int allocateUnixFile( } } #else /* SQLITE_ENABLE_LOCKING_STYLE */ -static int allocateUnixFile( +static int fillInUnixFile( int h, /* Open file descriptor on file being opened */ - sqlite3_file **pId, /* Write the resul unixFile structure here */ - const char *zFilename, /* Name of the file being opened */ - int delFlag /* If true, delete the file on or before closing */ + sqlite3_file *pId, /* Write to the unixFile structure here */ + const char *zFilename /* Name of the file being opened */ ){ - unixFile *pNew; - unixFile f; + unixFile *pNew = (unixFile *)pId; int rc; #ifdef FD_CLOEXEC fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); #endif - memset(&f, 0, sizeof(f)); - sqlite3OsEnterMutex(); - rc = findLockInfo(h, &f.pLock, &f.pOpen); - sqlite3OsLeaveMutex(); - if( delFlag ){ - unlink(zFilename); - } + + enterMutex(); + rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); + leaveMutex(); if( rc ){ close(h); return SQLITE_NOMEM; } + OSTRACE3("OPEN %-3d %s\n", h, zFilename); - f.dirfd = -1; - f.h = h; - SET_THREADID(&f); - pNew = sqlite3_malloc( sizeof(unixFile) ); - if( pNew==0 ){ - close(h); - sqlite3OsEnterMutex(); - releaseLockInfo(f.pLock); - releaseOpenCnt(f.pOpen); - sqlite3OsLeaveMutex(); - *pId = 0; - return SQLITE_NOMEM; - }else{ - *pNew = f; - pNew->pMethod = &sqlite3UnixIoMethod; - *pId = (sqlite3_file*)pNew; - OpenCounter(+1); - return SQLITE_OK; - } + pNew->dirfd = -1; + pNew->h = h; + SET_THREADID(pNew); + + pNew->pMethod = &sqlite3UnixIoMethod; + OpenCounter(+1); + return SQLITE_OK; } #endif /* SQLITE_ENABLE_LOCKING_STYLE */ @@ -2643,6 +2547,199 @@ static int allocateUnixFile( ** with other miscellanous aspects of the operating system interface ****************************************************************************/ +/* +** Previously, the SQLite OS layer used three functions in place of this +** one: +** +** sqlite3OsOpenReadWrite(); +** sqlite3OsOpenReadOnly(); +** sqlite3OsOpenExclusive(); +** +** These calls correspond to the following combinations of flags: +** +** ReadWrite() -> (READWRITE | CREATE) +** ReadOnly() -> (READONLY) +** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE) +** +** The old OpenExclusive() accepted a boolean argument - "delFlag". If +** true, the file was configured to be automatically deleted when the +** file handle closed. To achieve the same effect using this new +** interface, add the DELETEONCLOSE flag to those specified above for +** OpenExclusive(). +*/ +static int unixOpen( + void *pNotUsed, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + int fd = 0; + int oflags = 0; + + int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); + int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); + int isCreate = (flags & SQLITE_OPEN_CREATE); + int isReadonly = (flags & SQLITE_OPEN_READONLY); + int isReadWrite = (flags & SQLITE_OPEN_READWRITE); + + /* Exactly one of the READWRITE and READONLY flags must be set */ + assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); + + /* If isCreate is true, then the file must be opened for read/write access. */ + assert(isCreate==0 || isReadWrite); + + /* If isExclusive is true, then isCreate must also be true */ + assert(isExclusive==0 || isCreate); + + if( isReadonly ) oflags |= O_RDONLY; + if( isReadWrite ) oflags |= O_RDWR; + if( isCreate ) oflags |= O_CREAT; + if( isExclusive ) oflags |= (O_EXCL|O_NOFOLLOW); + oflags |= (O_LARGEFILE|O_BINARY); + + memset(pFile, 0, sizeof(unixFile)); + fd = open(zPath, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); + if( fd<0 && isReadWrite && !isExclusive ){ + /* Failed to open the file for read/write access. Try read-only. */ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + flags |= SQLITE_OPEN_READONLY; + return unixOpen(pNotUsed, zPath, pFile, flags, pOutFlags); + } + if( fd<0 ){ + return SQLITE_CANTOPEN; + } + if( isDelete ){ + unlink(zPath); + } + if( pOutFlags ){ + *pOutFlags = flags; + } + + assert(fd!=0); + return fillInUnixFile(fd, pFile, zPath); +} + +/* +** Delete the file at zPath. +*/ +static int unixDelete(void *pNotUsed, const char *zPath){ + SimulateIOError(return SQLITE_IOERR_DELETE); + unlink(zPath); + return SQLITE_OK; +} + +static int unixAccess(void *pNotUsed, const char *zPath, int flags){ + int amode; + switch( flags ){ + case SQLITE_ACCESS_EXISTS: + amode = F_OK; + break; + case SQLITE_ACCESS_READWRITE: + amode = W_OK|R_OK; + break; + case SQLITE_ACCESS_READONLY: + amode = R_OK; + break; + + default: + assert(!"Invalid flags argument"); + } + return (access(zPath, amode)==0); +} + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at least MAX_PATHNAME characters. +*/ +static int unixGetTempName(void *pNotUsed, char *zBuf){ + static const char *azDirs[] = { + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + ".", + }; + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + struct stat buf; + const char *zDir = "."; + azDirs[0] = sqlite3_temp_directory; + for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){ + if( azDirs[i]==0 ) continue; + if( stat(azDirs[i], &buf) ) continue; + if( !S_ISDIR(buf.st_mode) ) continue; + if( access(azDirs[i], 07) ) continue; + zDir = azDirs[i]; + break; + } + do{ + sqlite3_snprintf(MAX_PATHNAME-17, zBuf, "%s/"TEMP_FILE_PREFIX, zDir); + j = strlen(zBuf); + sqlite3Randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + }while( access(zBuf,0)==0 ); + return SQLITE_OK; +} + + +/* +** Turn a relative pathname into a full pathname. The relative path +** is stored as a nul-terminated string in the buffer pointed to by +** zPath. +** +** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes +** (in this case, MAX_PATHNAME bytes). The full-path is written to +** this buffer before returning. +*/ +static int unixFullPathname(void *pNotUsed, const char *zPath, char *zOut){ + zOut[MAX_PATHNAME-1] = '\0'; + if( zPath[0]=='/' ){ + strncpy(zOut, zPath, MAX_PATHNAME-1); + }else{ + int nCwd; + if( getcwd(zOut, MAX_PATHNAME-1)==0 ){ + return SQLITE_ERROR; + } + nCwd = strlen(zOut); + zOut[nCwd] = '/'; + strncpy(&zOut[nCwd+1], zPath, MAX_PATHNAME-1-nCwd-1); + } + return SQLITE_OK; + +#if 0 + /* + ** Remove "/./" path elements and convert "/A/./" path elements + ** to just "/". + */ + if( zFull ){ + int i, j; + for(i=j=0; zFull[i]; i++){ + if( zFull[i]=='/' ){ + if( zFull[i+1]=='/' ) continue; + if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ + i += 1; + continue; + } + if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ + while( j>0 && zFull[j-1]!='/' ){ j--; } + i += 3; + continue; + } + } + zFull[j++] = zFull[i]; + } + zFull[j] = 0; + } +#endif +} + #ifndef SQLITE_OMIT_LOAD_EXTENSION /* @@ -2650,23 +2747,46 @@ static int allocateUnixFile( ** within the shared library, and closing the shared library. */ #include <dlfcn.h> -void *sqlite3UnixDlopen(const char *zFilename){ +static void *unixDlOpen(void *pNotUsed, const char *zFilename){ return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); } -void *sqlite3UnixDlsym(void *pHandle, const char *zSymbol){ +static void unixDlError(void *pNotUsed, int nBuf, char *zBufOut){ + char *zErr; + enterMutex(); + zErr = dlerror(); + if( zErr ){ + strncpy(zBufOut, zErr, nBuf-1); + zBufOut[nBuf-1] = '\0'; + }else if(nBuf>0) { + zBufOut[0] = '\0'; + } + leaveMutex(); +} +void *unixDlSym(void *pHandle, const char *zSymbol){ return dlsym(pHandle, zSymbol); } -int sqlite3UnixDlclose(void *pHandle){ - return dlclose(pHandle); +void unixDlClose(void *pHandle){ + dlclose(pHandle); } -#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define unixDlOpen 0 + #define unixDlError 0 + #define unixDlSym 0 + #define unixDlClose 0 +#endif + +/* +** Both arguments are integers. This macro returns the lowest of the +** two arguments. +*/ +#define MIN(x,y) ((x)>(y)?(y):(x)) /* ** Get information to seed the random number generator. The seed ** is written into the buffer zBuf[256]. The calling function must ** supply a sufficiently large buffer. */ -int sqlite3UnixRandomSeed(char *zBuf){ +static int unixRandomness(void *pNotUsed, int nBuf, char *zBuf){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the @@ -2679,7 +2799,7 @@ int sqlite3UnixRandomSeed(char *zBuf){ ** that we always use the same random number sequence. This makes the ** tests repeatable. */ - memset(zBuf, 0, 256); + memset(zBuf, 0, nBuf); #if !defined(SQLITE_TEST) { int pid, fd; @@ -2687,11 +2807,13 @@ int sqlite3UnixRandomSeed(char *zBuf){ if( fd<0 ){ time_t t; time(&t); - memcpy(zBuf, &t, sizeof(t)); - pid = getpid(); - memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); + memcpy(zBuf, &t, MIN(nBuf, sizeof(t))); + if( (nBuf-sizeof(t))>0 ){ + pid = getpid(); + memcpy(&zBuf[sizeof(t)], &pid, MIN(nBuf-sizeof(t), sizeof(pid))); + } }else{ - read(fd, zBuf, 256); + read(fd, zBuf, nBuf); close(fd); } } @@ -2699,120 +2821,19 @@ int sqlite3UnixRandomSeed(char *zBuf){ return SQLITE_OK; } + /* ** Sleep for a little while. Return the amount of time slept. -** The argument is the number of milliseconds we want to sleep. +** The argument is the number of microseconds we want to sleep. */ -int sqlite3UnixSleep(int ms){ +static int unixSleep(void *pNotUsed, int microseconds){ #if defined(HAVE_USLEEP) && HAVE_USLEEP - usleep(ms*1000); - return ms; -#else - sleep((ms+999)/1000); - return 1000*((ms+999)/1000); -#endif -} - -/* -** Static variables used for thread synchronization. -** -** inMutex the nesting depth of the recursive mutex. The thread -** holding mutexMain can read this variable at any time. -** But is must hold mutexAux to change this variable. Other -** threads must hold mutexAux to read the variable and can -** never write. -** -** mutexOwner The thread id of the thread holding mutexMain. Same -** access rules as for inMutex. -** -** mutexOwnerValid True if the value in mutexOwner is valid. The same -** access rules apply as for inMutex. -** -** mutexMain The main mutex. Hold this mutex in order to get exclusive -** access to SQLite data structures. -** -** mutexAux An auxiliary mutex needed to access variables defined above. -** -** Mutexes are always acquired in this order: mutexMain mutexAux. It -** is not necessary to acquire mutexMain in order to get mutexAux - just -** do not attempt to acquire them in the reverse order: mutexAux mutexMain. -** Either get the mutexes with mutexMain first or get mutexAux only. -** -** When running on a platform where the three variables inMutex, mutexOwner, -** and mutexOwnerValid can be set atomically, the mutexAux is not required. -** On many systems, all three are 32-bit integers and writing to a 32-bit -** integer is atomic. I think. But there are no guarantees. So it seems -** safer to protect them using mutexAux. -*/ -static int inMutex = 0; -#ifdef SQLITE_UNIX_THREADS -static pthread_t mutexOwner; /* Thread holding mutexMain */ -static int mutexOwnerValid = 0; /* True if mutexOwner is valid */ -static pthread_mutex_t mutexMain = PTHREAD_MUTEX_INITIALIZER; /* The mutex */ -static pthread_mutex_t mutexAux = PTHREAD_MUTEX_INITIALIZER; /* Aux mutex */ -#endif - -/* -** The following pair of routine implement mutual exclusion for -** multi-threaded processes. Only a single thread is allowed to -** executed code that is surrounded by EnterMutex() and LeaveMutex(). -** -** SQLite uses only a single Mutex. There is not much critical -** code and what little there is executes quickly and without blocking. -** -** As of version 3.3.2, this mutex must be recursive. -*/ -void sqlite3UnixEnterMutex(){ -#ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutexAux); - if( !mutexOwnerValid || !pthread_equal(mutexOwner, pthread_self()) ){ - pthread_mutex_unlock(&mutexAux); - pthread_mutex_lock(&mutexMain); - assert( inMutex==0 ); - assert( !mutexOwnerValid ); - pthread_mutex_lock(&mutexAux); - mutexOwner = pthread_self(); - mutexOwnerValid = 1; - } - inMutex++; - pthread_mutex_unlock(&mutexAux); + usleep(microseconds); + return microseconds; #else - inMutex++; -#endif -} -void sqlite3UnixLeaveMutex(){ - assert( inMutex>0 ); -#ifdef SQLITE_UNIX_THREADS - pthread_mutex_lock(&mutexAux); - inMutex--; - assert( pthread_equal(mutexOwner, pthread_self()) ); - if( inMutex==0 ){ - assert( mutexOwnerValid ); - mutexOwnerValid = 0; - pthread_mutex_unlock(&mutexMain); - } - pthread_mutex_unlock(&mutexAux); -#else - inMutex--; -#endif -} - -/* -** Return TRUE if the mutex is currently held. -** -** If the thisThrd parameter is true, return true only if the -** calling thread holds the mutex. If the parameter is false, return -** true if any thread holds the mutex. -*/ -int sqlite3UnixInMutex(int thisThrd){ -#ifdef SQLITE_UNIX_THREADS - int rc; - pthread_mutex_lock(&mutexAux); - rc = inMutex>0 && (thisThrd==0 || pthread_equal(mutexOwner,pthread_self())); - pthread_mutex_unlock(&mutexAux); - return rc; -#else - return inMutex>0; + int seconds = (microseconds+999999)/1000000; + sleep(seconds); + return seconds; #endif } @@ -2829,7 +2850,7 @@ int sqlite3_current_time = 0; ** current time and date as a Julian Day number into *prNow and ** return 0. Return 1 if the time and date cannot be found. */ -int sqlite3UnixCurrentTime(double *prNow){ +static int unixCurrentTime(void *pNotUsed, double *prNow){ #ifdef NO_GETTOD time_t t; time(&t); @@ -2846,5 +2867,31 @@ int sqlite3UnixCurrentTime(double *prNow){ #endif return 0; } + + +sqlite3_vfs sqlite3DefaultVfs = { + 1, /* iVersion */ + sizeof(unixFile), /* szOsFile */ + MAX_PATHNAME, /* mxPathname */ + 0, /* nRef */ + 0, /* vfsMutex */ + 0, /* pNext */ + 0, /* pPrev */ + "unix", /* zName */ + 0, /* pAppData */ + + unixOpen, /* xOpen */ + unixDelete, /* xDelete */ + unixAccess, /* xAccess */ + unixGetTempName, /* xGetTempName */ + unixFullPathname, /* xFullPathname */ + unixDlOpen, /* xDlOpen */ + unixDlError, /* xDlError */ + unixDlSym, /* xDlSym */ + unixDlClose, /* xDlClose */ + unixRandomness, /* xRandomness */ + unixSleep, /* xSleep */ + unixCurrentTime /* xCurrentTime */ +}; #endif /* OS_UNIX */ |