aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/btree.c5
-rw-r--r--src/loadext.c31
-rw-r--r--src/main.c12
-rw-r--r--src/mem1.c4
-rw-r--r--src/os.c103
-rw-r--r--src/os.h37
-rw-r--r--src/os_unix.c593
-rw-r--r--src/pager.c203
-rw-r--r--src/pager.h5
-rw-r--r--src/pragma.c6
-rw-r--r--src/random.c8
-rw-r--r--src/sqlite.h.in12
-rw-r--r--src/sqliteInt.h4
-rw-r--r--src/test1.c6
-rw-r--r--src/test2.c15
-rw-r--r--src/test6.c30
-rw-r--r--src/vdbe.c9
-rw-r--r--src/vdbeapi.c4
-rw-r--r--src/vdbeaux.c26
19 files changed, 665 insertions, 448 deletions
diff --git a/src/btree.c b/src/btree.c
index ce78a46e8..f1ad2d3ce 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.399 2007/08/17 01:14:38 drh Exp $
+** $Id: btree.c,v 1.400 2007/08/17 15:53:36 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -1063,6 +1063,7 @@ int sqlite3BtreeOpen(
Btree **ppBtree, /* Pointer to new Btree object written here */
int flags /* Options */
){
+ sqlite3_vfs *pVfs = (pSqlite?pSqlite->pVfs:sqlite3_find_vfs(0));
BtShared *pBt = 0; /* Shared part of btree structure */
Btree *p; /* Handle to return */
int rc = SQLITE_OK;
@@ -1137,7 +1138,7 @@ int sqlite3BtreeOpen(
rc = SQLITE_NOMEM;
goto btree_open_out;
}
- rc = sqlite3PagerOpen(&pBt->pPager, zFilename, EXTRA_SIZE, flags);
+ rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, EXTRA_SIZE, flags);
if( rc==SQLITE_OK ){
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
}
diff --git a/src/loadext.c b/src/loadext.c
index de085c7f1..4f6e3b3db 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -267,6 +267,7 @@ int sqlite3_load_extension(
const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */
char **pzErrMsg /* Put error message here if not 0 */
){
+ sqlite3_vfs *pVfs = db->pVfs;
void *handle;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
char *zErrmsg = 0;
@@ -289,7 +290,7 @@ int sqlite3_load_extension(
zProc = "sqlite3_extension_init";
}
- handle = sqlite3OsDlopen(zFile);
+ handle = sqlite3OsDlOpen(pVfs, zFile);
if( handle==0 ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("unable to open shared library [%s]", zFile);
@@ -297,20 +298,20 @@ int sqlite3_load_extension(
return SQLITE_ERROR;
}
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
- sqlite3OsDlsym(handle, zProc);
+ sqlite3OsDlSym(pVfs, handle, zProc);
if( xInit==0 ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]",
zProc, zFile);
}
- sqlite3OsDlclose(handle);
+ sqlite3OsDlClose(pVfs, handle);
return SQLITE_ERROR;
}else if( xInit(db, &zErrmsg, &sqlite3_apis) ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
}
sqlite3_free(zErrmsg);
- sqlite3OsDlclose(handle);
+ sqlite3OsDlClose(pVfs, handle);
return SQLITE_ERROR;
}
@@ -337,7 +338,7 @@ int sqlite3_load_extension(
void sqlite3CloseExtensions(sqlite3 *db){
int i;
for(i=0; i<db->nExtension; i++){
- sqlite3OsDlclose(db->aExtension[i]);
+ sqlite3OsDlClose(db->pVfs, db->aExtension[i]);
}
sqlite3_free(db->aExtension);
}
@@ -372,14 +373,14 @@ static void **aAutoExtension = 0;
int sqlite3_auto_extension(void *xInit){
int i;
int rc = SQLITE_OK;
- sqlite3OsEnterMutex();
+ sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL);
+ sqlite3_mutex_enter(mutex);
for(i=0; i<nAutoExtension; i++){
if( aAutoExtension[i]==xInit ) break;
}
if( i==nAutoExtension ){
- nAutoExtension++;
- aAutoExtension = sqlite3_realloc( aAutoExtension,
- nAutoExtension*sizeof(aAutoExtension[0]) );
+ int nByte = (++nAutoExtension)*sizeof(aAutoExtension[0]);
+ aAutoExtension = sqlite3_realloc(aAutoExtension, nByte);
if( aAutoExtension==0 ){
nAutoExtension = 0;
rc = SQLITE_NOMEM;
@@ -387,7 +388,7 @@ int sqlite3_auto_extension(void *xInit){
aAutoExtension[nAutoExtension-1] = xInit;
}
}
- sqlite3OsLeaveMutex();
+ sqlite3_mutex_leave(mutex);
assert( (rc&0xff)==rc );
return rc;
}
@@ -396,11 +397,12 @@ int sqlite3_auto_extension(void *xInit){
** Reset the automatic extension loading mechanism.
*/
void sqlite3_reset_auto_extension(void){
- sqlite3OsEnterMutex();
+ sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL);
+ sqlite3_mutex_enter(mutex);
sqlite3_free(aAutoExtension);
aAutoExtension = 0;
nAutoExtension = 0;
- sqlite3OsLeaveMutex();
+ sqlite3_mutex_leave(mutex);
}
/*
@@ -418,7 +420,8 @@ int sqlite3AutoLoadExtensions(sqlite3 *db){
}
for(i=0; go; i++){
char *zErrmsg = 0;
- sqlite3OsEnterMutex();
+ sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL);
+ sqlite3_mutex_enter(mutex);
if( i>=nAutoExtension ){
xInit = 0;
go = 0;
@@ -426,7 +429,7 @@ int sqlite3AutoLoadExtensions(sqlite3 *db){
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
aAutoExtension[i];
}
- sqlite3OsLeaveMutex();
+ sqlite3_mutex_leave(mutex);
if( xInit && xInit(db, &zErrmsg, &sqlite3_apis) ){
sqlite3Error(db, SQLITE_ERROR,
"automatic extension loading failed: %s", zErrmsg);
diff --git a/src/main.c b/src/main.c
index 4e8b7a8a7..b3eab1757 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.383 2007/08/17 01:14:38 drh Exp $
+** $Id: main.c,v 1.384 2007/08/17 15:53:36 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -304,7 +304,8 @@ static int sqliteDefaultBusyCallback(
static const u8 totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
- int timeout = ((sqlite3 *)ptr)->busyTimeout;
+ sqlite3 *db = (sqlite3 *)ptr;
+ int timeout = db->busyTimeout;
int delay, prior;
assert( count>=0 );
@@ -319,7 +320,7 @@ static int sqliteDefaultBusyCallback(
delay = timeout - prior;
if( delay<=0 ) return 0;
}
- sqlite3OsSleep(delay);
+ sqlite3OsSleep(db->pVfs, delay);
return 1;
#else
int timeout = ((sqlite3 *)ptr)->busyTimeout;
@@ -898,6 +899,7 @@ static int openDatabase(
/* Allocate the sqlite data structure */
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
+ db->pVfs = sqlite3_find_vfs(0);
db->errMask = 0xff;
db->priorNewRowid = 0;
db->magic = SQLITE_MAGIC_BUSY;
@@ -1374,7 +1376,9 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
** Sleep for a little while. Return the amount of time slept.
*/
int sqlite3_sleep(int ms){
- return sqlite3OsSleep(ms);
+ sqlite3_vfs *pVfs;
+ pVfs = sqlite3_find_vfs(0);
+ return sqlite3OsSleep(pVfs, 1000*ms);
}
/*
diff --git a/src/mem1.c b/src/mem1.c
index 4fc77b04f..52f61547f 100644
--- a/src/mem1.c
+++ b/src/mem1.c
@@ -12,7 +12,7 @@
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite.
**
-** $Id: mem1.c,v 1.5 2007/08/16 19:40:17 drh Exp $
+** $Id: mem1.c,v 1.6 2007/08/17 15:53:36 danielk1977 Exp $
*/
/*
@@ -204,7 +204,7 @@ void *sqlite3_realloc(void *pPrior, unsigned int nBytes){
}
if( nBytes==0 ){
sqlite3_free(pPrior);
- return;
+ return 0;
}
p = pPrior;
p--;
diff --git a/src/os.c b/src/os.c
index d55cfa703..4307a57c6 100644
--- a/src/os.c
+++ b/src/os.c
@@ -24,16 +24,9 @@
** of this would be completely automatic if SQLite were coded using
** C++ instead of plain old C.
*/
-int sqlite3OsClose(sqlite3_file **pId){
- int rc = SQLITE_OK;
- sqlite3_file *id;
- if( pId!=0 && (id = *pId)!=0 ){
- rc = id->pMethods->xClose(id);
- if( rc==SQLITE_OK ){
- *pId = 0;
- }
- }
- return rc;
+int sqlite3OsClose(sqlite3_file *pId){
+ if( !pId->pMethods ) return SQLITE_OK;
+ return pId->pMethods->xClose(pId);
}
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
return id->pMethods->xRead(id, pBuf, amt, offset);
@@ -82,17 +75,83 @@ int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
}
#endif
-#ifdef SQLITE_ENABLE_REDEF_IO
-/*
-** A function to return a pointer to the virtual function table.
-** This routine really does not accomplish very much since the
-** virtual function table is a global variable and anybody who
-** can call this function can just as easily access the variable
-** for themselves. Nevertheless, we include this routine for
-** backwards compatibility with an earlier redefinable I/O
-** interface design.
+int sqlite3OsOpen(
+ sqlite3_vfs *pVfs,
+ const char *zPath,
+ sqlite3_file *pFile,
+ int flags,
+ int *pFlagsOut
+){
+ return pVfs->xOpen(pVfs->pAppData, zPath, pFile, flags, pFlagsOut);
+}
+int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath){
+ return pVfs->xDelete(pVfs->pAppData, zPath);
+}
+int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){
+ return pVfs->xAccess(pVfs->pAppData, zPath, flags);
+}
+int sqlite3OsGetTempName(sqlite3_vfs *pVfs, char *zBufOut){
+ return pVfs->xGetTempName(pVfs->pAppData, zBufOut);
+}
+int sqlite3OsFullPathname(sqlite3_vfs *pVfs, const char *zPath, char *zPathOut){
+ return pVfs->xFullPathname(pVfs->pAppData, zPath, zPathOut);
+}
+void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+ return pVfs->xDlOpen(pVfs->pAppData, zPath);
+}
+void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+ pVfs->xDlError(pVfs->pAppData, nByte, zBufOut);
+}
+void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
+ return pVfs->xDlSym(pHandle, zSymbol);
+}
+void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
+ pVfs->xDlClose(pHandle);
+}
+int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+ return pVfs->xRandomness(pVfs->pAppData, nByte, zBufOut);
+}
+int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
+ return pVfs->xSleep(pVfs->pAppData, nMicro);
+}
+int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
+ return pVfs->xCurrentTime(pVfs->pAppData, pTimeOut);
+}
+
+int sqlite3OsOpenMalloc(
+ sqlite3_vfs *pVfs,
+ const char *zFile,
+ sqlite3_file **ppFile,
+ int flags
+){
+ int rc = SQLITE_NOMEM;
+ sqlite3_file *pFile;
+ pFile = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile);
+ if( pFile ){
+ rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, 0);
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pFile);
+ }else{
+ *ppFile = pFile;
+ }
+ }
+ return rc;
+}
+int sqlite3OsCloseFree(sqlite3_file *pFile){
+ int rc = SQLITE_OK;
+ if( pFile ){
+ rc = sqlite3OsClose(pFile);
+ sqlite3_free(pFile);
+ }
+ return rc;
+}
+
+/*
+** Default vfs implementation. Defined by the various os_X.c implementations.
*/
-struct sqlite3OsVtbl *sqlite3_os_switch(void){
- return &sqlite3Os;
+extern sqlite3_vfs sqlite3DefaultVfs;
+
+sqlite3_vfs *sqlite3_find_vfs(const char *zVfs){
+ return &sqlite3DefaultVfs;
}
-#endif
+
diff --git a/src/os.h b/src/os.h
index 30bc91443..d6b3f5a33 100644
--- a/src/os.h
+++ b/src/os.h
@@ -121,6 +121,8 @@
# define TEMP_FILE_PREFIX "etilqs_"
#endif
+#if 0
+
/*
** Define the interfaces for Unix, Windows, and OS/2.
*/
@@ -200,6 +202,7 @@
#define sqlite3OsDlclose sqlite3Os2Dlclose
#endif
+#endif
@@ -345,10 +348,10 @@ extern unsigned int sqlite3_pending_byte;
#define SHARED_FIRST (PENDING_BYTE+2)
#define SHARED_SIZE 510
-/*
-** Prototypes for operating system interface routines.
+/*
+** Functions for accessing sqlite3_file methods
*/
-int sqlite3OsClose(sqlite3_file**);
+int sqlite3OsClose(sqlite3_file*);
int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
int sqlite3OsTruncate(sqlite3_file*, i64 size);
@@ -361,10 +364,33 @@ int sqlite3OsCheckReservedLock(sqlite3_file *id);
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
+/*
+** Functions for accessing sqlite3_vfs methods
+*/
+int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
+int sqlite3OsDelete(sqlite3_vfs *, const char *);
+int sqlite3OsAccess(sqlite3_vfs *, const char *, int);
+int sqlite3OsGetTempName(sqlite3_vfs *, char *);
+int sqlite3OsFullPathname(sqlite3_vfs *, const char *, char *);
+void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
+void sqlite3OsDlError(sqlite3_vfs *, int, char *);
+void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *);
+void sqlite3OsDlClose(sqlite3_vfs *, void *);
+int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
+int sqlite3OsSleep(sqlite3_vfs *, int);
+int sqlite3OsCurrentTime(sqlite3_vfs *, double*);
+
+/*
+** Convenience functions for opening and closing files using
+** sqlite3_malloc() to obtain space for the file-handle structure.
+*/
+int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int);
+int sqlite3OsCloseFree(sqlite3_file *);
+
+#if 0
int sqlite3OsOpenReadWrite(const char*, sqlite3_file**, int*);
int sqlite3OsOpenExclusive(const char*, sqlite3_file**, int);
int sqlite3OsOpenReadOnly(const char*, sqlite3_file**);
-
int sqlite3OsDelete(const char*);
int sqlite3OsFileExists(const char*);
char *sqlite3OsFullPathname(const char*);
@@ -385,6 +411,7 @@ int sqlite3OsAllocationSize(void *);
void *sqlite3OsDlopen(const char*);
void *sqlite3OsDlsym(void*, const char*);
int sqlite3OsDlclose(void*);
+#endif
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
int sqlite3OsFileHandle(sqlite3_file *id);
@@ -478,7 +505,7 @@ struct sqlite3OsVtbl {
sqlite3OsEnterMutex,
sqlite3OsLeaveMutex,
sqlite3OsInMutex,
- sqlite3OsThreadSpecificData,
+ 0,
sqlite3OsMalloc,
sqlite3OsRealloc,
sqlite3OsFree,
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 */
diff --git a/src/pager.c b/src/pager.c
index 418b13ef1..5fbedba31 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.358 2007/08/16 10:09:03 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.359 2007/08/17 15:53:37 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
@@ -297,6 +297,7 @@ struct PgHistory {
** APIs, they may still be used successfully.
*/
struct Pager {
+ sqlite3_vfs *pVfs; /* OS functions to use for IO */
u8 journalOpen; /* True if journal file descriptors is valid */
u8 journalStarted; /* True if header of journal is synced */
u8 useJournal; /* Use a rollback journal on this file */
@@ -1011,7 +1012,7 @@ static int pager_end_transaction(Pager *pPager){
}
sqlite3PagerStmtCommit(pPager);
if( pPager->stmtOpen && !pPager->exclusiveMode ){
- sqlite3OsClose(&pPager->stfd);
+ sqlite3OsClose(pPager->stfd);
pPager->stmtOpen = 0;
}
if( pPager->journalOpen ){
@@ -1020,10 +1021,10 @@ static int pager_end_transaction(Pager *pPager){
pPager->journalOff = 0;
pPager->journalStarted = 0;
}else{
- sqlite3OsClose(&pPager->jfd);
+ sqlite3OsClose(pPager->jfd);
pPager->journalOpen = 0;
if( rc==SQLITE_OK ){
- rc = sqlite3OsDelete(pPager->zJournal);
+ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal);
}
}
sqlite3_free( pPager->aInJournal );
@@ -1225,21 +1226,29 @@ static int pager_playback_one_page(
** children. If all children are either missing or do not refer to
** a different master journal, then this master journal can be deleted.
*/
-static int pager_delmaster(const char *zMaster){
+static int pager_delmaster(Pager *pPager, const char *zMaster){
+ sqlite3_vfs *pVfs = pPager->pVfs;
int rc;
int master_open = 0;
- sqlite3_file *master = 0;
+ sqlite3_file *pMaster;
+ sqlite3_file *pJournal;
char *zMasterJournal = 0; /* Contents of master journal file */
i64 nMasterJournal; /* Size of master journal file */
/* Open the master journal file exclusively in case some other process
** is running this routine also. Not that it makes too much difference.
*/
- rc = sqlite3OsOpenReadOnly(zMaster, &master);
- assert( rc!=SQLITE_OK || master );
+ pMaster = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile * 2);
+ if( !pMaster ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
+ rc = sqlite3OsOpen(pVfs, zMaster, pMaster, SQLITE_OPEN_READONLY, 0);
+ }
if( rc!=SQLITE_OK ) goto delmaster_out;
master_open = 1;
- rc = sqlite3OsFileSize(master, &nMasterJournal);
+
+ rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
if( rc!=SQLITE_OK ) goto delmaster_out;
if( nMasterJournal>0 ){
@@ -1254,27 +1263,25 @@ static int pager_delmaster(const char *zMaster){
rc = SQLITE_NOMEM;
goto delmaster_out;
}
- rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal, 0);
+ rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0);
if( rc!=SQLITE_OK ) goto delmaster_out;
zJournal = zMasterJournal;
while( (zJournal-zMasterJournal)<nMasterJournal ){
- if( sqlite3OsFileExists(zJournal) ){
+ if( sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS) ){
/* One of the journals pointed to by the master journal exists.
** Open it and check if it points at the master journal. If
** so, return without deleting the master journal file.
*/
- sqlite3_file *journal = 0;
int c;
- rc = sqlite3OsOpenReadOnly(zJournal, &journal);
- assert( rc!=SQLITE_OK || journal );
+ rc = sqlite3OsOpen(pVfs, zJournal, pJournal, SQLITE_OPEN_READONLY, 0);
if( rc!=SQLITE_OK ){
goto delmaster_out;
}
- rc = readMasterJournal(journal, &zMasterPtr);
- sqlite3OsClose(&journal);
+ rc = readMasterJournal(pJournal, &zMasterPtr);
+ sqlite3OsClose(pJournal);
if( rc!=SQLITE_OK ){
goto delmaster_out;
}
@@ -1290,15 +1297,16 @@ static int pager_delmaster(const char *zMaster){
}
}
- rc = sqlite3OsDelete(zMaster);
+ rc = sqlite3OsDelete(pVfs, zMaster);
delmaster_out:
if( zMasterJournal ){
sqlite3_free(zMasterJournal);
}
if( master_open ){
- sqlite3OsClose(&master);
+ sqlite3OsClose(pMaster);
}
+ sqlite3_free(pMaster);
return rc;
}
@@ -1388,6 +1396,7 @@ static void setSectorSize(Pager *pPager){
** and an error code is returned.
*/
static int pager_playback(Pager *pPager, int isHot){
+ sqlite3_vfs *pVfs = pPager->pVfs;
i64 szJ; /* Size of the journal file in bytes */
u32 nRec; /* Number of Records in the journal */
int i; /* Loop counter */
@@ -1411,7 +1420,9 @@ static int pager_playback(Pager *pPager, int isHot){
*/
rc = readMasterJournal(pPager->jfd, &zMaster);
assert( rc!=SQLITE_DONE );
- if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){
+ if( rc!=SQLITE_OK
+ || (zMaster && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS))
+ ){
sqlite3_free(zMaster);
zMaster = 0;
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
@@ -1496,7 +1507,7 @@ end_playback:
** see if it is possible to delete the master journal.
*/
if( rc==SQLITE_OK ){
- rc = pager_delmaster(zMaster);
+ rc = pager_delmaster(pPager, zMaster);
}
sqlite3_free(zMaster);
}
@@ -1681,20 +1692,36 @@ int sqlite3_opentemp_count = 0;
** The OS will automatically delete the temporary file when it is
** closed.
*/
-static int sqlite3PagerOpentemp(sqlite3_file **pFd){
+static int sqlite3PagerOpentemp(
+ sqlite3_vfs *pVfs,
+ sqlite3_file *pFile,
+ char *zNameOut
+){
int cnt = 8;
int rc;
- char zFile[SQLITE_TEMPNAME_SIZE];
+ int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_EXCLUSIVE);
+
+ char *zFree = 0;
+ if( zNameOut==0 ){
+ zFree = (char *)sqlite3_malloc(pVfs->mxPathname);
+ if( !zFree ){
+ return SQLITE_NOMEM;
+ }
+ zNameOut = zFree;
+ }
#ifdef SQLITE_TEST
sqlite3_opentemp_count++; /* Used for testing and analysis only */
#endif
+
do{
cnt--;
- sqlite3OsTempFileName(zFile);
- rc = sqlite3OsOpenExclusive(zFile, pFd, 1);
- assert( rc!=SQLITE_OK || *pFd );
+ sqlite3OsGetTempName(pVfs, zNameOut);
+ rc = sqlite3OsOpen(pVfs, zNameOut, pFile, flags, 0);
+ assert( rc!=SQLITE_OK || pFile->pMethods );
}while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM );
+
+ sqlite3_free(zFree);
return rc;
}
@@ -1713,15 +1740,15 @@ static int sqlite3PagerOpentemp(sqlite3_file **pFd){
** in-memory database.
*/
int sqlite3PagerOpen(
+ sqlite3_vfs *pVfs,
Pager **ppPager, /* Return the Pager structure here */
const char *zFilename, /* Name of the database file to open */
int nExtra, /* Extra bytes append to each in-memory page */
int flags /* flags controlling this file */
){
+ u8 *pPtr;
Pager *pPager = 0;
char *zFullPathname = 0;
- int nameLen; /* Compiler is wrong. This is always initialized before use */
- sqlite3_file *fd = 0;
int rc = SQLITE_OK;
int i;
int tempFile = 0;
@@ -1729,7 +1756,7 @@ int sqlite3PagerOpen(
int readOnly = 0;
int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
- char zTemp[SQLITE_TEMPNAME_SIZE];
+
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to
** malloc() must have already been made by this thread before it gets
@@ -1750,6 +1777,24 @@ int sqlite3PagerOpen(
*/
*ppPager = 0;
+ /* Allocate memory for the pager structure */
+ pPager = sqlite3MallocZero(
+ sizeof(*pPager) + /* Pager structure */
+ pVfs->szOsFile * 3 + /* The db, journal and stmt journal files */
+ pVfs->mxPathname * 3 + 30 /* zFilename, zDirectory, zJournal */
+ );
+ if( !pPager ){
+ return SQLITE_NOMEM;
+ }
+ pPtr = (u8 *)&pPager[1];
+ pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
+ pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
+ pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
+ pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*3];
+ pPager->zDirectory = &pPager->zFilename[pVfs->mxPathname];
+ pPager->zJournal = &pPager->zDirectory[pVfs->mxPathname];
+ pPager->pVfs = pVfs;
+
/* Open the pager file and set zFullPathname to point at malloc()ed
** memory containing the complete filename (i.e. including the directory).
*/
@@ -1757,65 +1802,56 @@ int sqlite3PagerOpen(
#ifndef SQLITE_OMIT_MEMORYDB
if( strcmp(zFilename,":memory:")==0 ){
memDb = 1;
- zFullPathname = sqlite3StrDup("");
+ pPager->zFilename[0] = '\0';
}else
#endif
{
- zFullPathname = sqlite3OsFullPathname(zFilename);
- if( zFullPathname ){
- rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly);
- assert( rc!=SQLITE_OK || fd );
+ rc = sqlite3OsFullPathname(pVfs, zFilename, pPager->zFilename);
+ if( rc==SQLITE_OK ){
+ if( strlen(pPager->zFilename)>(pVfs->mxPathname - strlen("-journal")) ){
+ rc = SQLITE_CANTOPEN;
+ }else{
+ int flag = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
+ int fout = 0;
+ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, flag, &fout);
+ readOnly = (fout&SQLITE_OPEN_READONLY);
+ }
}
}
}else{
- rc = sqlite3PagerOpentemp(&fd);
- sqlite3OsTempFileName(zTemp);
- zFilename = zTemp;
- zFullPathname = sqlite3OsFullPathname(zFilename);
+ rc = sqlite3PagerOpentemp(pVfs, pPager->fd, pPager->zFilename);
if( rc==SQLITE_OK ){
tempFile = 1;
}
}
- /* Allocate the Pager structure. As part of the same allocation, allocate
- ** space for the full paths of the file, directory and journal
- ** (Pager.zFilename, Pager.zDirectory and Pager.zJournal).
- */
- if( zFullPathname ){
- nameLen = strlen(zFullPathname);
- pPager = sqlite3MallocZero( sizeof(*pPager) + nameLen*3 + 30 );
- if( pPager && rc==SQLITE_OK ){
- pPager->pTmpSpace = (char *)sqlite3_malloc(SQLITE_DEFAULT_PAGE_SIZE);
- }
+ if( pPager && rc==SQLITE_OK ){
+ pPager->pTmpSpace = (char *)sqlite3_malloc(SQLITE_DEFAULT_PAGE_SIZE);
}
-
/* If an error occured in either of the blocks above, free the memory
** pointed to by zFullPathname, free the Pager structure and close the
** file. Since the pager is not allocated there is no need to set
** any Pager.errMask variables.
*/
- if( !pPager || !zFullPathname || !pPager->pTmpSpace || rc!=SQLITE_OK ){
- sqlite3OsClose(&fd);
- sqlite3_free(zFullPathname);
+ if( !pPager || !pPager->pTmpSpace ){
+ sqlite3OsClose(pPager->fd);
sqlite3_free(pPager);
return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
}
PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname);
IOTRACE(("OPEN %p %s\n", pPager, zFullPathname))
- pPager->zFilename = (char*)&pPager[1];
- pPager->zDirectory = &pPager->zFilename[nameLen+1];
- pPager->zJournal = &pPager->zDirectory[nameLen+1];
- memcpy(pPager->zFilename, zFullPathname, nameLen+1);
- memcpy(pPager->zDirectory, zFullPathname, nameLen+1);
- for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){}
+ /* Fill in Pager.zDirectory[] */
+ memcpy(pPager->zDirectory, pPager->zFilename, pVfs->mxPathname);
+ for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
if( i>0 ) pPager->zDirectory[i-1] = 0;
- memcpy(pPager->zJournal, zFullPathname,nameLen);
- sqlite3_free(zFullPathname);
- memcpy(&pPager->zJournal[nameLen], "-journal",sizeof("-journal"));
- pPager->fd = fd;
+
+ /* Fill in Pager.zJournal[] */
+ memcpy(pPager->zJournal, pPager->zFilename, pVfs->mxPathname);
+ memcpy(&pPager->zJournal[strlen(pPager->zJournal)], "-journal", 9);
+
/* pPager->journalOpen = 0; */
pPager->useJournal = useJournal && !memDb;
pPager->noReadlock = noReadlock && readOnly;
@@ -1846,7 +1882,7 @@ int sqlite3PagerOpen(
/* pPager->pFirstSynced = 0; */
/* pPager->pLast = 0; */
pPager->nExtra = FORCE_ALIGNMENT(nExtra);
- assert(fd||memDb);
+ assert(pPager->fd->pMethods||memDb);
if( !memDb ){
setSectorSize(pPager);
}
@@ -2229,13 +2265,13 @@ int sqlite3PagerClose(Pager *pPager){
IOTRACE(("CLOSE %p\n", pPager))
assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
if( pPager->journalOpen ){
- sqlite3OsClose(&pPager->jfd);
+ sqlite3OsClose(pPager->jfd);
}
sqlite3_free(pPager->aInJournal);
if( pPager->stmtOpen ){
- sqlite3OsClose(&pPager->stfd);
+ sqlite3OsClose(pPager->stfd);
}
- sqlite3OsClose(&pPager->fd);
+ sqlite3OsClose(pPager->fd);
/* Temp files are automatically deleted by the OS
** if( pPager->tempFile ){
** sqlite3OsDelete(pPager->zFilename);
@@ -2579,15 +2615,16 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
** database with the same name. Just delete the journal.
*/
static int hasHotJournal(Pager *pPager){
+ sqlite3_vfs *pVfs = pPager->pVfs;
if( !pPager->useJournal ) return 0;
- if( !sqlite3OsFileExists(pPager->zJournal) ){
+ if( !sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){
return 0;
}
if( sqlite3OsCheckReservedLock(pPager->fd) ){
return 0;
}
if( sqlite3PagerPagecount(pPager)==0 ){
- sqlite3OsDelete(pPager->zJournal);
+ sqlite3OsDelete(pVfs, pPager->zJournal);
return 0;
}else{
return 1;
@@ -2702,9 +2739,11 @@ int sqlite3PagerReleaseMemory(int nReq){
** some of the code invoked by this function may also
** try to obtain the mutex, resulting in a deadlock.
*/
+#if 0
if( sqlite3OsInMutex(0) ){
return 0;
}
+#endif
/* Outermost loop runs for at most two iterations. First iteration we
** try to find memory that can be released without calling fsync(). Second
@@ -2817,6 +2856,7 @@ static int pagerSharedLock(Pager *pPager){
int rc = SQLITE_OK;
if( pPager->state==PAGER_UNLOCK ){
+ sqlite3_vfs *pVfs = pPager->pVfs;
if( !MEMDB ){
assert( pPager->nRef==0 );
if( !pPager->noReadlock ){
@@ -2864,14 +2904,15 @@ static int pagerSharedLock(Pager *pPager){
** a read/write file handle.
*/
rc = SQLITE_BUSY;
- if( sqlite3OsFileExists(pPager->zJournal) ){
- int ro;
+ if( sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){
+ int fout = 0;
+ int flags = SQLITE_OPEN_READWRITE;
assert( !pPager->tempFile );
- rc = sqlite3OsOpenReadWrite(pPager->zJournal, &pPager->jfd, &ro);
- assert( rc!=SQLITE_OK || pPager->jfd );
- if( ro ){
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, &fout);
+ assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
+ if( fout&SQLITE_OPEN_READONLY ){
rc = SQLITE_BUSY;
- sqlite3OsClose(&pPager->jfd);
+ sqlite3OsClose(pPager->jfd);
}
}
if( rc!=SQLITE_OK ){
@@ -3294,6 +3335,9 @@ int sqlite3PagerUnref(DbPage *pPg){
** write lock if anything goes wrong.
*/
static int pager_open_journal(Pager *pPager){
+ sqlite3_vfs *pVfs = pPager->pVfs;
+ int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE);
+
int rc;
assert( !MEMDB );
assert( pPager->state>=PAGER_RESERVED );
@@ -3306,15 +3350,18 @@ static int pager_open_journal(Pager *pPager){
rc = SQLITE_NOMEM;
goto failed_to_open_journal;
}
- rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,
- pPager->tempFile);
- assert( rc!=SQLITE_OK || pPager->jfd );
+
+ if( pPager->tempFile ){
+ flags |= SQLITE_OPEN_DELETEONCLOSE;
+ }
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+ assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
pPager->journalOff = 0;
pPager->setMaster = 0;
pPager->journalHdr = 0;
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM ){
- sqlite3OsDelete(pPager->zJournal);
+ sqlite3OsDelete(pVfs, pPager->zJournal);
}
goto failed_to_open_journal;
}
@@ -4180,7 +4227,7 @@ int sqlite3PagerStmtBegin(Pager *pPager){
pPager->stmtHdrOff = 0;
pPager->stmtCksum = pPager->cksumInit;
if( !pPager->stmtOpen ){
- rc = sqlite3PagerOpentemp(&pPager->stfd);
+ rc = sqlite3PagerOpentemp(pPager->pVfs, pPager->stfd, 0);
if( rc ) goto stmt_begin_failed;
pPager->stmtOpen = 1;
pPager->stmtNRec = 0;
diff --git a/src/pager.h b/src/pager.h
index ca193dae1..554c4999a 100644
--- a/src/pager.h
+++ b/src/pager.h
@@ -13,7 +13,7 @@
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
-** @(#) $Id: pager.h,v 1.61 2007/05/08 21:45:28 drh Exp $
+** @(#) $Id: pager.h,v 1.62 2007/08/17 15:53:37 danielk1977 Exp $
*/
#ifndef _PAGER_H_
@@ -54,8 +54,7 @@ typedef struct PgHdr DbPage;
** See source code comments for a detailed description of the following
** routines:
*/
-int sqlite3PagerOpen(Pager **ppPager, const char *zFilename,
- int nExtra, int flags);
+int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char *, int, int);
void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int));
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
diff --git a/src/pragma.c b/src/pragma.c
index 66edcee87..f5ed28a4e 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.144 2007/08/16 10:09:03 danielk1977 Exp $
+** $Id: pragma.c,v 1.145 2007/08/17 15:53:37 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -557,7 +557,9 @@ void sqlite3Pragma(
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
}
}else{
- if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){
+ if( zRight[0]
+ && !sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE)
+ ){
sqlite3ErrorMsg(pParse, "not a writable directory");
goto pragma_out;
}
diff --git a/src/random.c b/src/random.c
index 03ed7a424..27ee0e508 100644
--- a/src/random.c
+++ b/src/random.c
@@ -15,7 +15,7 @@
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
-** $Id: random.c,v 1.16 2007/01/05 14:38:56 drh Exp $
+** $Id: random.c,v 1.17 2007/08/17 15:53:37 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -63,7 +63,7 @@ static int randomByte(void){
char k[256];
prng.j = 0;
prng.i = 0;
- sqlite3OsRandomSeed(k);
+ sqlite3OsRandomness(sqlite3_find_vfs(0), 256, k);
for(i=0; i<256; i++){
prng.s[i] = i;
}
@@ -92,9 +92,9 @@ static int randomByte(void){
*/
void sqlite3Randomness(int N, void *pBuf){
unsigned char *zBuf = pBuf;
- sqlite3OsEnterMutex();
+ sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_PRNG));
while( N-- ){
*(zBuf++) = randomByte();
}
- sqlite3OsLeaveMutex();
+ sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_PRNG));
}
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 8492399d2..2378b7861 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -30,7 +30,7 @@
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
-** @(#) $Id: sqlite.h.in,v 1.227 2007/08/17 01:14:38 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.228 2007/08/17 15:53:37 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@@ -644,10 +644,10 @@ struct sqlite3_vfs {
int (*xAccess)(void *pAppData, const char *zName, int flags);
int (*xGetTempName)(void *pAppData, char *zOut);
int (*xFullPathname)(void *pAppData, const char *zName, char *zOut);
- void *(*xDlOpen)(void *pAppData, char *zFilename);
- void (*xDlError)(void*, int nByte, char *zErrMsg);
+ void *(*xDlOpen)(void *pAppData, const char *zFilename);
+ void (*xDlError)(void *pAppData, int nByte, char *zErrMsg);
void *(*xDlSym)(void*, const char *zSymbol);
- void (*xDlclose)(void*);
+ void (*xDlClose)(void*);
int (*xRandomness)(void *pAppData, int nByte, char *zOut);
int (*xSleep)(void *pAppData, int microseconds);
int (*xCurrentTime)(void *pAppData, double*);
@@ -655,6 +655,10 @@ struct sqlite3_vfs {
** value will increment whenever this happens. */
};
+#define SQLITE_ACCESS_EXISTS 0
+#define SQLITE_ACCESS_READWRITE 1
+#define SQLITE_ACCESS_READONLY 2
+
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
**
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 7a7238320..7ae793c60 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.590 2007/08/17 01:14:38 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.591 2007/08/17 15:53:37 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -187,7 +187,7 @@ typedef UINT8_TYPE i8; /* 1-byte signed integer */
*/
#define SQLITE_MUTEX_MEM 1 /* Used by the memory allocator */
#define SQLITE_MUTEX_PRNG 2 /* Used by pseudorandom generator */
-#define SQLITE_MUTEX_CACHE 3 /* Used by shared cache */
+#define SQLITE_MUTEX_GLOBAL 3 /* Used by global variables */
#define SQLITE_MUTEX_STATIC_MAX 3
/*
diff --git a/src/test1.c b/src/test1.c
index 599ef2fac..012f22a71 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test1.c,v 1.263 2007/08/17 01:14:38 drh Exp $
+** $Id: test1.c,v 1.264 2007/08/17 15:53:37 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -3587,6 +3587,7 @@ static int test_stmt_int(
}
#ifndef SQLITE_OMIT_DISKIO
+#if 0
/*
** Usage: sqlite3OsOpenReadWrite <filename>
*/
@@ -3744,6 +3745,7 @@ static int test_sqlite3OsTempFileName(
return TCL_OK;
}
#endif
+#endif
/*
** Usage: sqlite_set_magic DB MAGIC-NUMBER
@@ -4285,6 +4287,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
/* Functions from os.h */
#ifndef SQLITE_OMIT_DISKIO
+#if 0
{ "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
{ "sqlite3OsClose", test_sqlite3OsClose, 0 },
{ "sqlite3OsLock", test_sqlite3OsLock, 0 },
@@ -4293,6 +4296,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
/* Custom test interfaces */
{ "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
#endif
+#endif
#ifndef SQLITE_OMIT_UTF16
{ "add_test_collate", test_collate, 0 },
{ "add_test_collate_needed", test_collate_needed, 0 },
diff --git a/src/test2.c b/src/test2.c
index c8464c6c9..a45d60c96 100644
--- a/src/test2.c
+++ b/src/test2.c
@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test2.c,v 1.45 2007/08/16 10:09:03 danielk1977 Exp $
+** $Id: test2.c,v 1.46 2007/08/17 15:53:37 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -78,7 +78,7 @@ static int pager_open(
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
- rc = sqlite3PagerOpen(&pPager, argv[1], 0, 0);
+ rc = sqlite3PagerOpen(sqlite3_find_vfs(0), &pPager, argv[1], 0, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;
@@ -528,18 +528,21 @@ static int fake_big_file(
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
+ sqlite3_vfs *pVfs;
+ sqlite3_file *fd = 0;
+ int flags = SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
int rc;
int n;
i64 offset;
- sqlite3_file *fd = 0;
- int readOnly = 0;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" N-MEGABYTES FILE\"", 0);
return TCL_ERROR;
}
if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
- rc = sqlite3OsOpenReadWrite(argv[2], &fd, &readOnly);
+
+ pVfs = sqlite3_find_vfs(0);
+ rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd, flags);
if( rc ){
Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0);
return TCL_ERROR;
@@ -547,7 +550,7 @@ static int fake_big_file(
offset = n;
offset *= 1024*1024;
rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
- sqlite3OsClose(&fd);
+ sqlite3OsCloseFree(fd);
if( rc ){
Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0);
return TCL_ERROR;
diff --git a/src/test6.c b/src/test6.c
index 6c9dc6787..cc02b5f31 100644
--- a/src/test6.c
+++ b/src/test6.c
@@ -263,7 +263,7 @@ static int writeListAppend(
assert((zBuf && nBuf) || (!nBuf && !zBuf));
- pNew = (WriteBuffer *)sqlite3_malloc(sizeof(WriteBuffer) + nBuf);
+ pNew = (WriteBuffer *)sqlite3MallocZero(sizeof(WriteBuffer) + nBuf);
pNew->iOffset = iOffset;
pNew->nBuf = nBuf;
pNew->pFile = (CrashFile *)pFile;
@@ -544,8 +544,8 @@ static int crashParamsObjCmd(
int objc,
Tcl_Obj *CONST objv[]
){
+ sqlite3_vfs *pVfs;
int i;
-
int iDelay;
const char *zCrashFile;
int nCrashFile;
@@ -575,17 +575,19 @@ static int crashParamsObjCmd(
if( objc<3 ){
Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE");
- return TCL_ERROR;
+ goto error;
}
- zCrashFile = sqlite3OsFullPathname(Tcl_GetString(objv[objc-1]));
+ pVfs = sqlite3_find_vfs(0);
+ zCrashFile = sqlite3_malloc(pVfs->mxPathname);
+ sqlite3OsFullPathname(pVfs, Tcl_GetString(objv[objc-1]), zCrashFile);
nCrashFile = strlen(zCrashFile);
if( nCrashFile>=sizeof(g.zCrashFile) ){
Tcl_AppendResult(interp, "Filename is too long: \"", zCrashFile, "\"", 0);
- return TCL_ERROR;
+ goto error;
}
if( Tcl_GetIntFromObj(interp, objv[objc-2], &iDelay) ){
- return TCL_ERROR;
+ goto error;
}
for(i=1; i<(objc-2); i+=2){
@@ -599,16 +601,16 @@ static int crashParamsObjCmd(
"Bad option: \"", zOpt,
"\" - must be \"-characteristics\" or \"-sectorsize\"", 0
);
- return TCL_ERROR;
+ goto error;
}
if( i==objc-3 ){
Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0);
- return TCL_ERROR;
+ goto error;
}
if( zOpt[1]=='s' ){
if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){
- return TCL_ERROR;
+ goto error;
}
setSectorsize = 1;
}else{
@@ -616,7 +618,7 @@ static int crashParamsObjCmd(
Tcl_Obj **apObj;
int nObj;
if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){
- return TCL_ERROR;
+ goto error;
}
for(j=0; j<nObj; j++){
int rc;
@@ -630,7 +632,7 @@ static int crashParamsObjCmd(
);
Tcl_DecrRefCount(pFlag);
if( rc ){
- return TCL_ERROR;
+ goto error;
}
iDc |= aFlag[iChoice].iValue;
@@ -647,9 +649,13 @@ static int crashParamsObjCmd(
}
g.iCrash = iDelay;
memcpy(g.zCrashFile, zCrashFile, nCrashFile+1);
-
+ sqlite3_free(zCrashFile);
sqlite3CrashTestEnable = 1;
return TCL_OK;
+
+error:
+ sqlite3_free(zCrashFile);
+ return TCL_ERROR;
}
#endif /* SQLITE_OMIT_DISKIO */
diff --git a/src/vdbe.c b/src/vdbe.c
index 02069a3f4..6b12c5f93 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.641 2007/08/16 10:09:03 danielk1977 Exp $
+** $Id: vdbe.c,v 1.642 2007/08/17 15:53:37 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -486,7 +486,7 @@ int sqlite3VdbeExec(
sqlite3VdbeIOTraceSql(p);
#ifdef SQLITE_DEBUG
if( (p->db->flags & SQLITE_VdbeListing)!=0
- || sqlite3OsFileExists("vdbe_explain")
+ || sqlite3OsAccess(db->pVfs, "vdbe_explain", SQLITE_ACCESS_EXISTS)
){
int i;
printf("VDBE Program Listing:\n");
@@ -495,7 +495,7 @@ int sqlite3VdbeExec(
sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
}
}
- if( sqlite3OsFileExists("vdbe_trace") ){
+ if( sqlite3OsAccess(db->pVfs, "vdbe_trace", SQLITE_ACCESS_EXISTS) ){
p->trace = stdout;
}
#endif
@@ -519,7 +519,8 @@ int sqlite3VdbeExec(
}
sqlite3VdbePrintOp(p->trace, pc, pOp);
}
- if( p->trace==0 && pc==0 && sqlite3OsFileExists("vdbe_sqltrace") ){
+ if( p->trace==0 && pc==0
+ && sqlite3OsAccess(db->pVfs, "vdbe_sqltrace", SQLITE_ACCESS_EXISTS) ){
sqlite3VdbePrintSql(p);
}
#endif
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index 948d4b042..e8d9ddad5 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -221,7 +221,7 @@ static int sqlite3Step(Vdbe *p){
}
if( db->xProfile && !db->init.busy ){
double rNow;
- sqlite3OsCurrentTime(&rNow);
+ sqlite3OsCurrentTime(db->pVfs, &rNow);
p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
}
#endif
@@ -258,7 +258,7 @@ static int sqlite3Step(Vdbe *p){
double rNow;
u64 elapseTime;
- sqlite3OsCurrentTime(&rNow);
+ sqlite3OsCurrentTime(db->pVfs, &rNow);
elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index ec8bd8487..3771296d4 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -1132,10 +1132,12 @@ static int vdbeCommit(sqlite3 *db){
*/
#ifndef SQLITE_OMIT_DISKIO
else{
+ sqlite3_vfs *pVfs = db->pVfs;
+ int flag = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_EXCLUSIVE);
int needSync = 0;
char *zMaster = 0; /* File-name for the master journal */
char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
- sqlite3_file *master = 0;
+ sqlite3_file *pMaster = 0;
i64 offset = 0;
/* Select a master journal file name */
@@ -1147,12 +1149,14 @@ static int vdbeCommit(sqlite3 *db){
if( !zMaster ){
return SQLITE_NOMEM;
}
- }while( sqlite3OsFileExists(zMaster) );
+ }while( sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS) );
/* Open the master journal. */
- rc = sqlite3OsOpenExclusive(zMaster, &master, 0);
+ pMaster = sqlite3_malloc(pVfs->szOsFile);
+ rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flag, 0);
if( rc!=SQLITE_OK ){
sqlite3_free(zMaster);
+ sqlite3_free(pMaster);
return rc;
}
@@ -1171,12 +1175,13 @@ static int vdbeCommit(sqlite3 *db){
if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
needSync = 1;
}
- rc = sqlite3OsWrite(master, zFile, strlen(zFile)+1, offset);
+ rc = sqlite3OsWrite(pMaster, zFile, strlen(zFile)+1, offset);
offset += strlen(zFile)+1;
if( rc!=SQLITE_OK ){
- sqlite3OsClose(&master);
- sqlite3OsDelete(zMaster);
+ sqlite3OsClose(pMaster);
+ sqlite3OsDelete(pVfs, zMaster);
sqlite3_free(zMaster);
+ sqlite3_free(pMaster);
return rc;
}
}
@@ -1214,9 +1219,10 @@ static int vdbeCommit(sqlite3 *db){
rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);
}
}
- sqlite3OsClose(&master);
+ sqlite3OsClose(pMaster);
if( rc!=SQLITE_OK ){
sqlite3_free(zMaster);
+ sqlite3_free(pMaster);
return rc;
}
@@ -1224,13 +1230,17 @@ static int vdbeCommit(sqlite3 *db){
** doing this the directory is synced again before any individual
** transaction files are deleted.
*/
- rc = sqlite3OsDelete(zMaster);
+ rc = sqlite3OsDelete(pVfs, zMaster);
sqlite3_free(zMaster);
+ sqlite3_free(pMaster);
zMaster = 0;
+ pMaster = 0;
if( rc ){
return rc;
}
+#if 0
rc = sqlite3OsSyncDirectory(zMainFile);
+#endif
if( rc!=SQLITE_OK ){
/* This is not good. The master journal file has been deleted, but
** the directory sync failed. There is no completely safe course of