diff --git a/manifest b/manifest index 032d5098ea..ad4bafe7c9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\scomments\sand\svariable\snaming\smore\sconsistent\sWRT\srowid\sversus\ndocid/blockid.\s\sThis\sshould\shave\sno\scode\simpact.\s(CVS\s4281) -D 2007-08-23T20:28:49 +C The\swin32\sdriver\scompiles\sbut\sdoes\snot\syet\swork\swell.\s\sMany\sbugs\nfixed.\s(CVS\s4282) +D 2007-08-24T03:51:33 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -80,13 +80,13 @@ F src/alter.c f0aac0060ae8102e58f210b44d35b53438d53173 F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6 F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8 F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3 -F src/btree.c 8fa6341b74ab70a28001e4ed4bc5ba14ce1401a6 +F src/btree.c fe9d292cee1a7fee1e5834ecaa3eb2103f7398bc F src/btree.h 76c89673981cb77575300c0b78a76eaa00a28743 F src/btreeInt.h 7fc6e51dc3d4bbed15639a8ea1aae737631d6670 F src/build.c bc7406e2ea5bfa8276ee1abeae1db27a98fd0b33 F src/callback.c a542236a68060caad378efa30006ca46cf77b1b2 F src/complete.c b6dea59fb6d7b3201fa1e0e552cda8c2258a4f50 -F src/date.c a80b33f6e70d619978622547d2c78ab8b036b31a +F src/date.c af235f38f50809abd0a96da3bb3e0cc32be6226e F src/delete.c 849846d06d29851dde0d9f424a5de5817eb140d1 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/expr.c 978afdceb2693ef58ec0040a43fe57afc6e4236c @@ -98,34 +98,34 @@ F src/journal.c 03d6b5cc1afe7c5e3cd0af55415f5168eb094398 F src/legacy.c 7e1b1c57694e49cbadf561e2a7d9cd984dc743b5 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 F src/loadext.c 8b31e2e0e961918fa045515459aee1c122d8c266 -F src/main.c 527f27c74d22d83713abbd1550fd5a4ecce89aca -F src/malloc.c 8078d4c3f9217c0bb018e432d8655c14996bb107 +F src/main.c 795ec066ce38908b5c35ca4353bb601d022e2275 +F src/malloc.c d4282f50964ab1ca31f504c97b7cf2fdb4d4195d F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 -F src/mem1.c 7b023d45dd71944414db469c742457239e24d74d -F src/mem2.c 48919353f72b8f6e957a0021eb9deaf863998189 +F src/mem1.c afe2fbf6d7e8247c6c9f69c1481358b1cad60c08 +F src/mem2.c dfe802143189d491ae00f2c5aa50ce619d02f5bf F src/mutex.c 9cf641f556a4119ef90ed41b82f2d5647f81686e -F src/os.c 86593b6e8cc22304d7c2d24b06c0aae49254b181 -F src/os.h 399c89cafa93b9ef35c3dc70f77644d10936b535 +F src/os.c 3b0d37208ea3ec9e1f913fbdeaf88841ed443b9d +F src/os.h 2bfbbad126a775e4d8c7d59eb4d9585a5fd7dfb5 F src/os_common.h a5c446d3b93f09f369d13bf217de4bed3437dd1c F src/os_os2.c 8769301bff502de642ad2634cedcb77d967ce199 F src/os_os2.h c3f7d0af7e3453d1d7aa81b06c0a56f5a226530b F src/os_test.c 49833426101f99aee4bb5f6a44b7c4b2029fda1c F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3 -F src/os_unix.c 3ff776e03535b64df12dcc272a913a52d69f3e4a +F src/os_unix.c c45b20f868fab1178710ea2f1c8043ce706d3a99 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e -F src/os_win.c 29c0e19c1072679a4c7818c49fab2f35d2ad7747 +F src/os_win.c 1cb94dd33d38e01de82d77bef107c7f3323463ec F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 0879439873a9da769ee400b3b8c0967afd786fe8 +F src/pager.c 89dfc6a0bd72898d147264517a43bdf35348dd2c F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8 F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590 F src/pragma.c 9b989506a1b7c8aecd6befb8235e2f57a4aba7e5 F src/prepare.c 29ea14cf6b0558f2f80aa53e112bff55f1119e36 -F src/printf.c 0f46bc3a805d5620f5aedfec1c3768d293a5ee5e +F src/printf.c 33d23a68e498006136ca9770579cf2d14a7ec68e F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb -F src/sqlite.h.in a1a5bc9e7e63bf73c2bb68be3749dec2bbd8cc44 +F src/sqlite.h.in 09a5256ee80dfc7cb4353739f78e4267be323574 F src/sqlite3ext.h 9a26028378c288af500d8b94ed079666fed5806b F src/sqliteInt.h 951229c727f14f12f1c5555d2ed079bd2201415c F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa @@ -136,7 +136,7 @@ F src/test2.c 4f742e99ed1bea5c14692f627bdb59a146f30504 F src/test3.c a7d011c51d6b2e2a73c43983d5c2b731d69c74d7 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071 F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4 -F src/test6.c 5d6286568b12ec6c813cb30d2a14de8229f8e388 +F src/test6.c de2dbcd67401f00bfa0affc044ba671aa62384a5 F src/test7.c a9d509d0e9ad214b4772696f49f6e61be26213d1 F src/test8.c e6a543c8b248efe120ae33a6859fcd55dcf46a96 F src/test9.c b46c8fe02ac7cca1a7316436d8d38d50c66f4b2f @@ -146,7 +146,7 @@ F src/test_btree.c c1308ba0b88ab577fa56c9e493a09829dfcded9c F src/test_config.c f0b911bb615d93a192647e76910dce65cbbcf3ad F src/test_hexio.c 82916f918687502658f02533b519c38cb180db6d F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8 -F src/test_malloc.c 9d5fb38bc0647ba9376d8d954be5b5aa01e12c80 +F src/test_malloc.c 5f5566bb799e72cb328df8933ef9fdb9d90d270e F src/test_md5.c 34599caee5b1c73dcf86ca31f55846fab8c19ef7 F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f F src/test_server.c 319f6b1a99bab5f7149387442243d6e65a8ab4eb @@ -160,12 +160,12 @@ F src/vacuum.c 318ccae7c4e3ddf241aeaee4d2611bfe1949a373 F src/vdbe.c 9d4d00589c174aad9a616f1615464ddddebba0ec F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3 F src/vdbeInt.h 39fb069ce04137545ca0bc790f80ddc64a8c99d9 -F src/vdbeapi.c 81cb7f018e56c20b40365f005ff69e1af9ea9494 -F src/vdbeaux.c 8b41802973560274c15acdc1ac1d4147c110e8d7 +F src/vdbeapi.c bdd0aea216744482dd1b7fab56de18ba5b6fbdf4 +F src/vdbeaux.c b040c3787ea1c32ba025b1c5822553469abe4efa F src/vdbeblob.c d12ed95dac0992e1e372d079d76af047cc42f7c7 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 896fa3f8df9d2661eb15c7ce361857741b447268 -F src/vtab.c 6a7ce44edf7ad824d7e9307394121fe943bb419c +F src/vtab.c 72e5347cca4d55e55e180015f4dc78736f852e14 F src/where.c 2776a0caf8cbbfd6ec79cfb1cd9bc25074055e5e F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -238,7 +238,7 @@ F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab F test/descidx1.test 2177c4ad55edcf56ad5f4c6490f307d7774e8a10 F test/descidx2.test eb3a2882ec58aa6e1e8131d9bb54436e5b4a3ce2 F test/descidx3.test 3a55b8d73bc3e9ad084e0da7fec781cf0d2a0356 -F test/diskfull.test a91fa95a8729b71fdac4738a49755f70b48c61f3 +F test/diskfull.test 34ef53e88372c5b5e488ad1581514559a224c2b1 F test/distinctagg.test 2b89d1c5220d966a30ba4b40430338669301188b F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea F test/enc2.test 45710bacfa9df29720bc84c067dfdf8c8ddfb797 @@ -561,7 +561,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 6eb2d74a8cfce322930f05c97d4ec255f3711efb -R 6c3888d041c9e4f3c4ea7193ec7eeec0 -U shess -Z 0c8d40ad377805b9a794c415d7962113 +P 76f1e18ebc25d692f122784e87d202992c4cfed2 +R 72f6a976f09cdaf5e13abeade770ec1c +U drh +Z 8bcbe7ef9d6a537a157463bef713e3c1 diff --git a/manifest.uuid b/manifest.uuid index 8d4de48a20..b2535dadeb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -76f1e18ebc25d692f122784e87d202992c4cfed2 \ No newline at end of file +3a68fcddfa9184e4b310ce0a21312c54b9462ec8 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index bb740a74f7..a3d48809dd 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.410 2007/08/23 02:47:53 drh Exp $ +** $Id: btree.c,v 1.411 2007/08/24 03:51:33 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -1102,13 +1102,6 @@ int sqlite3BtreeOpen( int nReserve; unsigned char zDbHeader[100]; - if( pSqlite ){ - pVfs = pSqlite->pVfs; - }else{ - pVfs = sqlite3_vfs_find(0); - } - assert( sqlite3BtreeMutexHeld(pSqlite->mutex) ); - /* Set the variable isMemdb to true for an in-memory database, or ** false for a file-based database. This symbol is only required if ** either of the shared-data or autovacuum features are compiled @@ -1122,6 +1115,13 @@ int sqlite3BtreeOpen( #endif #endif + if( pSqlite ){ + pVfs = pSqlite->pVfs; + }else{ + pVfs = sqlite3_vfs_find(0); + } + assert( sqlite3BtreeMutexHeld(pSqlite->mutex) ); + p = sqlite3MallocZero(sizeof(Btree)); if( !p ){ return SQLITE_NOMEM; diff --git a/src/date.c b/src/date.c index a807f35253..50f5f4a837 100644 --- a/src/date.c +++ b/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.71 2007/08/21 19:33:56 drh Exp $ +** $Id: date.c,v 1.72 2007/08/24 03:51:33 drh Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon @@ -426,7 +426,7 @@ static double localtimeOffset(DateTime *p){ #else { struct tm *pTm; - sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL)); + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); pTm = localtime(&t); y.Y = pTm->tm_year + 1900; y.M = pTm->tm_mon + 1; @@ -434,7 +434,7 @@ static double localtimeOffset(DateTime *p){ y.h = pTm->tm_hour; y.m = pTm->tm_min; y.s = pTm->tm_sec; - sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_GLOBAL)); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); } #endif y.validYMD = 1; diff --git a/src/main.c b/src/main.c index b08aca1705..7200532308 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.396 2007/08/22 20:18:22 drh Exp $ +** $Id: main.c,v 1.397 2007/08/24 03:51:34 drh Exp $ */ #include "sqliteInt.h" #include @@ -945,15 +945,16 @@ static int openDatabase( if( db==0 ) goto opendb_out; db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ - db->mallocFailed = 1; + sqlite3_free(db); + db = 0; goto opendb_out; } sqlite3_mutex_enter(db->mutex); db->pVfs = sqlite3_vfs_find(zVfs); db->errMask = 0xff; db->priorNewRowid = 0; - db->magic = SQLITE_MAGIC_BUSY; db->nDb = 2; + db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; db->autoCommit = 1; db->flags |= SQLITE_ShortColNames @@ -1076,7 +1077,7 @@ static int openDatabase( #endif opendb_out: - if( db ){ + if( db && db->mutex ){ sqlite3_mutex_leave(db->mutex); } if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ diff --git a/src/malloc.c b/src/malloc.c index 62fa2d2fab..bd86636e9c 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -12,7 +12,7 @@ ** Memory allocation functions used throughout sqlite. ** ** -** $Id: malloc.c,v 1.10 2007/08/22 20:18:22 drh Exp $ +** $Id: malloc.c,v 1.11 2007/08/24 03:51:34 drh Exp $ */ #include "sqliteInt.h" #include @@ -25,8 +25,8 @@ */ static void softHeapLimitEnforcer( void *NotUsed, - sqlite3_uint64 inUse, - unsigned int allocSize + sqlite3_int64 inUse, + int allocSize ){ sqlite3_release_memory(allocSize); } diff --git a/src/mem1.c b/src/mem1.c index 5a533005df..abaafe1ec9 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.7 2007/08/22 20:18:22 drh Exp $ +** $Id: mem1.c,v 1.8 2007/08/24 03:51:34 drh Exp $ */ /* @@ -51,8 +51,8 @@ static struct { ** issued. The alarmBusy variable is set to prevent recursive ** callbacks. */ - sqlite3_uint64 alarmThreshold; - void (*alarmCallback)(void*, sqlite3_uint64, unsigned); + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); void *alarmArg; int alarmBusy; @@ -64,22 +64,18 @@ static struct { /* ** Current allocation and high-water mark. */ - sqlite3_uint64 nowUsed; - sqlite3_uint64 mxUsed; + sqlite3_int64 nowUsed; + sqlite3_int64 mxUsed; -} mem = { /* This variable holds all of the local data */ - ((sqlite3_uint64)1)<<63, /* alarmThreshold */ - /* Everything else is initialized to zero */ -}; - +} mem; /* ** Return the amount of memory currently checked out. */ -sqlite3_uint64 sqlite3_memory_used(void){ - sqlite3_uint64 n; +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); } @@ -94,8 +90,8 @@ sqlite3_uint64 sqlite3_memory_used(void){ ** checked out since either the beginning of this process ** or since the most recent reset. */ -sqlite3_uint64 sqlite3_memory_highwater(int resetFlag){ - sqlite3_uint64 n; +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 n; if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); } @@ -112,9 +108,9 @@ sqlite3_uint64 sqlite3_memory_highwater(int resetFlag){ ** Change the alarm callback */ int sqlite3_memory_alarm( - void(*xCallback)(void *pArg, sqlite3_uint64 used, unsigned int N), + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), void *pArg, - sqlite3_uint64 iThreshold + sqlite3_int64 iThreshold ){ if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); @@ -130,9 +126,9 @@ int sqlite3_memory_alarm( /* ** Trigger the alarm */ -static void sqlite3MemsysAlarm(unsigned nByte){ - void (*xCallback)(void*,sqlite3_uint64,unsigned); - sqlite3_uint64 nowUsed; +static void sqlite3MemsysAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; void *pArg; if( mem.alarmCallback==0 || mem.alarmBusy ) return; mem.alarmBusy = 1; @@ -149,7 +145,7 @@ static void sqlite3MemsysAlarm(unsigned nByte){ ** Allocate nBytes of memory */ void *sqlite3_malloc(int nBytes){ - sqlite3_uint64 *p; + sqlite3_int64 *p; if( nBytes<=0 ){ return 0; } @@ -157,7 +153,7 @@ void *sqlite3_malloc(int nBytes){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); } sqlite3_mutex_enter(mem.mutex); - if( mem.nowUsed+nBytes>=mem.alarmThreshold ){ + if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ sqlite3MemsysAlarm(nBytes); } p = malloc(nBytes+8); @@ -181,15 +177,15 @@ void *sqlite3_malloc(int nBytes){ ** Free memory. */ void sqlite3_free(void *pPrior){ - sqlite3_uint64 *p; - unsigned nByte; + sqlite3_int64 *p; + int nByte; if( pPrior==0 ){ return; } assert( mem.mutex!=0 ); p = pPrior; p--; - nByte = (unsigned int)*p; + nByte = (int)*p; sqlite3_mutex_enter(mem.mutex); mem.nowUsed -= nByte; free(p); @@ -200,8 +196,8 @@ void sqlite3_free(void *pPrior){ ** Change the size of an existing memory allocation */ void *sqlite3_realloc(void *pPrior, int nBytes){ - unsigned nOld; - sqlite3_uint64 *p; + int nOld; + sqlite3_int64 *p; if( pPrior==0 ){ return sqlite3_malloc(nBytes); } @@ -211,7 +207,7 @@ void *sqlite3_realloc(void *pPrior, int nBytes){ } p = pPrior; p--; - nOld = (unsigned int)p[0]; + nOld = (int)p[0]; assert( mem.mutex!=0 ); sqlite3_mutex_enter(mem.mutex); if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){ diff --git a/src/mem2.c b/src/mem2.c index 4b3c4f58f8..c489279159 100644 --- a/src/mem2.c +++ b/src/mem2.c @@ -12,7 +12,7 @@ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: mem2.c,v 1.8 2007/08/23 02:47:53 drh Exp $ +** $Id: mem2.c,v 1.9 2007/08/24 03:51:34 drh Exp $ */ /* @@ -71,11 +71,11 @@ */ struct MemBlockHdr { struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */ - unsigned int iSize; /* Size of this allocation */ - unsigned char nBacktrace; /* Number of backtraces on this alloc */ - unsigned char nBacktraceSlots; /* Available backtrace slots */ - unsigned short nTitle; /* Bytes of title; includes '\0' */ - unsigned int iForeGuard; /* Guard word for sanity */ + int iSize; /* Size of this allocation */ + char nBacktrace; /* Number of backtraces on this alloc */ + char nBacktraceSlots; /* Available backtrace slots */ + short nTitle; /* Bytes of title; includes '\0' */ + int iForeGuard; /* Guard word for sanity */ }; /* @@ -98,8 +98,8 @@ static struct { ** issued. The alarmBusy variable is set to prevent recursive ** callbacks. */ - sqlite3_uint64 alarmThreshold; - void (*alarmCallback)(void*, sqlite3_uint64, unsigned); + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64, int); void *alarmArg; int alarmBusy; @@ -111,8 +111,8 @@ static struct { /* ** Current allocation and high-water mark. */ - sqlite3_uint64 nowUsed; - sqlite3_uint64 mxUsed; + sqlite3_int64 nowUsed; + sqlite3_int64 mxUsed; /* ** Head and tail of a linked list of all outstanding allocations @@ -147,18 +147,14 @@ static struct { int disallow; /* Do not allow memory allocation */ -} mem = { /* This variable holds all of the local data */ - ((sqlite3_uint64)1)<<63, /* alarmThreshold */ - /* Everything else is initialized to zero */ -}; - +} mem; /* ** Return the amount of memory currently checked out. */ -sqlite3_uint64 sqlite3_memory_used(void){ - sqlite3_uint64 n; +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); } @@ -173,8 +169,8 @@ sqlite3_uint64 sqlite3_memory_used(void){ ** checked out since either the beginning of this process ** or since the most recent reset. */ -sqlite3_uint64 sqlite3_memory_highwater(int resetFlag){ - sqlite3_uint64 n; +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 n; if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); } @@ -191,9 +187,9 @@ sqlite3_uint64 sqlite3_memory_highwater(int resetFlag){ ** Change the alarm callback */ int sqlite3_memory_alarm( - void(*xCallback)(void *pArg, sqlite3_uint64 used, unsigned int N), + void(*xCallback)(void *pArg, sqlite3_int64 used, int N), void *pArg, - sqlite3_uint64 iThreshold + sqlite3_int64 iThreshold ){ if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); @@ -209,9 +205,9 @@ int sqlite3_memory_alarm( /* ** Trigger the alarm */ -static void sqlite3MemsysAlarm(unsigned nByte){ - void (*xCallback)(void*,sqlite3_uint64,unsigned); - sqlite3_uint64 nowUsed; +static void sqlite3MemsysAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; void *pArg; if( mem.alarmCallback==0 || mem.alarmBusy ) return; mem.alarmBusy = 1; @@ -232,14 +228,14 @@ static void sqlite3MemsysAlarm(unsigned nByte){ */ static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){ struct MemBlockHdr *p; - unsigned int *pInt; + int *pInt; p = (struct MemBlockHdr*)pAllocation; p--; assert( p->iForeGuard==FOREGUARD ); assert( (p->iSize & 3)==0 ); - pInt = (unsigned int*)pAllocation; - assert( pInt[p->iSize/sizeof(unsigned int)]==REARGUARD ); + pInt = (int*)pAllocation; + assert( pInt[p->iSize/sizeof(int)]==REARGUARD ); return p; } @@ -260,9 +256,9 @@ void *sqlite3_malloc(int nByte){ struct MemBlockHdr *pHdr; void **pBt; char *z; - unsigned int *pInt; + int *pInt; void *p; - unsigned int totalSize; + int totalSize; if( nByte<=0 ){ return 0; @@ -272,11 +268,11 @@ void *sqlite3_malloc(int nByte){ } sqlite3_mutex_enter(mem.mutex); assert( mem.disallow==0 ); - if( mem.nowUsed+nByte>=mem.alarmThreshold ){ + if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){ sqlite3MemsysAlarm(nByte); } nByte = (nByte+3)&~3; - totalSize = nByte + sizeof(*pHdr) + sizeof(unsigned int) + + totalSize = nByte + sizeof(*pHdr) + sizeof(int) + mem.nBacktrace*sizeof(void*) + mem.nTitle; if( mem.iFail>0 ){ if( mem.iFail==1 ){ @@ -323,8 +319,8 @@ void *sqlite3_malloc(int nByte){ memcpy(z, mem.zTitle, mem.nTitle); } pHdr->iSize = nByte; - pInt = (unsigned int *)&pHdr[1]; - pInt[nByte/sizeof(unsigned int)] = REARGUARD; + pInt = (int*)&pHdr[1]; + pInt[nByte/sizeof(int)] = REARGUARD; memset(pInt, 0x65, nByte); mem.nowUsed += nByte; if( mem.nowUsed>mem.mxUsed ){ @@ -369,7 +365,7 @@ void sqlite3_free(void *pPrior){ z = (char*)pBt; z -= pHdr->nTitle; memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + - pHdr->iSize + sizeof(unsigned int) + pHdr->nTitle); + pHdr->iSize + sizeof(int) + pHdr->nTitle); free(z); sqlite3_mutex_leave(mem.mutex); } @@ -488,15 +484,6 @@ int sqlite3_memdebug_fail(int iFail, int iRepeat){ return n; } -/* -** This routine returns the number of successful mallocs remaining until -** the next simulated malloc failure. -1 is returned if no simulated -** failure is currently scheduled. -*/ -int sqlite3_memdebug_pending(void){ - return mem.iFail-1; -} - /* ** The following two routines are used to assert that no memory ** allocations occur between one call and the next. The use of diff --git a/src/os.c b/src/os.c index 3ba530e77a..c0649c349a 100644 --- a/src/os.c +++ b/src/os.c @@ -110,40 +110,40 @@ int sqlite3OsOpen( int flags, int *pFlagsOut ){ - return pVfs->xOpen(pVfs->pAppData, zPath, pFile, flags, pFlagsOut); + return pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut); } int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - return pVfs->xDelete(pVfs->pAppData, zPath, dirSync); + return pVfs->xDelete(pVfs, zPath, dirSync); } int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ - return pVfs->xAccess(pVfs->pAppData, zPath, flags); + return pVfs->xAccess(pVfs, zPath, flags); } int sqlite3OsGetTempName(sqlite3_vfs *pVfs, char *zBufOut){ - return pVfs->xGetTempName(pVfs->pAppData, zBufOut); + return pVfs->xGetTempName(pVfs, zBufOut); } int sqlite3OsFullPathname(sqlite3_vfs *pVfs, const char *zPath, char *zPathOut){ - return pVfs->xFullPathname(pVfs->pAppData, zPath, zPathOut); + return pVfs->xFullPathname(pVfs, zPath, zPathOut); } void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ - return pVfs->xDlOpen(pVfs->pAppData, zPath); + return pVfs->xDlOpen(pVfs, zPath); } void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - pVfs->xDlError(pVfs->pAppData, nByte, zBufOut); + pVfs->xDlError(pVfs, nByte, zBufOut); } void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ - return pVfs->xDlSym(pHandle, zSymbol); + return pVfs->xDlSym(pVfs, pHandle, zSymbol); } void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ - pVfs->xDlClose(pHandle); + pVfs->xDlClose(pVfs, pHandle); } int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ - return pVfs->xRandomness(pVfs->pAppData, nByte, zBufOut); + return pVfs->xRandomness(pVfs, nByte, zBufOut); } int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ - return pVfs->xSleep(pVfs->pAppData, nMicro); + return pVfs->xSleep(pVfs, nMicro); } int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ - return pVfs->xCurrentTime(pVfs->pAppData, pTimeOut); + return pVfs->xCurrentTime(pVfs, pTimeOut); } int sqlite3OsOpenMalloc( @@ -175,15 +175,12 @@ int sqlite3OsCloseFree(sqlite3_file *pFile){ return rc; } -/* -** Default vfs implementation. Defined by the various os_X.c implementations. -*/ -extern sqlite3_vfs sqlite3DefaultVfs; - /* -** The list of all registered VFS implementations. +** The list of all registered VFS implementations. This list is +** initialized to the single VFS returned by sqlite3OsDefaultVfs() +** upon the first call to sqlite3_vfs_find(). */ -static sqlite3_vfs *vfsList = &sqlite3DefaultVfs; +static sqlite3_vfs *vfsList = 0; /* ** Locate a VFS by name. If no name is given, simply return the @@ -192,7 +189,12 @@ static sqlite3_vfs *vfsList = &sqlite3DefaultVfs; sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_vfs *pVfs; + static int isInit = 0; sqlite3_mutex_enter(mutex); + if( !isInit ){ + vfsList = sqlite3OsDefaultVfs(); + isInit = 1; + } for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ if( zVfs==0 ) break; if( strcmp(zVfs, pVfs->zName)==0 ) break; @@ -217,7 +219,7 @@ int sqlite3_vfs_release(sqlite3_vfs *pVfs){ sqlite3_mutex_enter(mutex); assert( pVfs->nRef>0 ); pVfs->nRef--; - if( pVfs->nRef==0 ){ + if( pVfs->nRef==0 && pVfs->vfsMutex ){ sqlite3_mutex_free(pVfs->vfsMutex); pVfs->vfsMutex = 0; } diff --git a/src/os.h b/src/os.h index 0f6c782c2e..e5c8e7bc6a 100644 --- a/src/os.h +++ b/src/os.h @@ -109,7 +109,7 @@ ** If sqlite is being embedded in another program, you may wish to change the ** prefix to reflect your program's name, so that if your program exits ** prematurely, old temporary files can be easily identified. This can be done -** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. ** ** 2006-10-31: The default prefix used to be "sqlite_". But then ** Mcafee started using SQLite in their anti-virus product and it @@ -123,8 +123,8 @@ ** enough to know that calling the developer will not help get rid ** of the file. */ -#ifndef TEMP_FILE_PREFIX -# define TEMP_FILE_PREFIX "etilqs_" +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" #endif /* @@ -273,4 +273,18 @@ int sqlite3OsCloseFree(sqlite3_file *); int sqlite3OsLockState(sqlite3_file *id); #endif +/* +** Each OS-specific backend defines an instance of the following +** structure for returning a pointer to its sqlite3_vfs. If OS_OTHER +** is defined (meaning that the application-defined OS interface layer +** is used) then there is no default VFS. The application must +** register one or more VFS structures using sqlite3_vfs_register() +** before attempting to use SQLite. +*/ +#if OS_UNIX || OS_WIN || OS_OS2 +sqlite3_vfs *sqlite3OsDefaultVfs(void); +#else +# define sqlite3OsDefaultVfs(X) 0 +#endif + #endif /* _SQLITE_OS_H_ */ diff --git a/src/os_unix.c b/src/os_unix.c index eb7a66b64f..4287e23513 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -108,13 +108,6 @@ struct unixFile { */ #include "os_common.h" -/* -** Do not include any of the File I/O interface procedures if the -** SQLITE_OMIT_DISKIO macro is defined (indicating that the database -** will be in-memory only) -*/ -#ifndef SQLITE_OMIT_DISKIO - /* ** Define various macros that are missing from some systems. */ @@ -2300,12 +2293,6 @@ static int fillInUnixFile( } #endif /* SQLITE_ENABLE_LOCKING_STYLE */ -#endif /* SQLITE_OMIT_DISKIO */ -/*************************************************************************** -** Everything above deals with file I/O. Everything that follows deals -** with other miscellanous aspects of the operating system interface -****************************************************************************/ - /* ** Open a file descriptor to the directory containing file zFilename. ** If successful, *pFd is set to the opened file descriptor and @@ -2321,8 +2308,7 @@ static int openDirectory(const char *zFilename, int *pFd){ int fd; char zDirname[MAX_PATHNAME+1]; - strncpy(zDirname, zFilename, MAX_PATHNAME); - zDirname[MAX_PATHNAME-1] = '\0'; + sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); for(ii=strlen(zDirname); ii>=0 && zDirname[ii]!='/'; ii--); if( ii>0 ){ zDirname[ii] = '\0'; @@ -2361,7 +2347,7 @@ static int openDirectory(const char *zFilename, int *pFd){ ** OpenExclusive(). */ static int unixOpen( - void *pNotUsed, + sqlite3_vfs *pVfs, const char *zPath, sqlite3_file *pFile, int flags, @@ -2414,7 +2400,7 @@ static int unixOpen( /* 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); + return unixOpen(pVfs, zPath, pFile, flags, pOutFlags); } if( fd<0 ){ return SQLITE_CANTOPEN; @@ -2441,7 +2427,7 @@ static int unixOpen( ** Delete the file at zPath. If the dirSync argument is true, fsync() ** the directory after deleting the file. */ -static int unixDelete(void *pNotUsed, const char *zPath, int dirSync){ +static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ int rc = SQLITE_OK; SimulateIOError(return SQLITE_IOERR_DELETE); unlink(zPath); @@ -2468,7 +2454,7 @@ static int unixDelete(void *pNotUsed, const char *zPath, int dirSync){ ** ** Otherwise return 0. */ -static int unixAccess(void *pNotUsed, const char *zPath, int flags){ +static int unixAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ int amode; switch( flags ){ case SQLITE_ACCESS_EXISTS: @@ -2488,10 +2474,11 @@ static int unixAccess(void *pNotUsed, const char *zPath, int flags){ } /* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at least MAX_PATHNAME characters. +** Create a temporary file name in zBuf. zBuf must be allocated +** by the calling process and must be big enough to hold at least +** pVfs->mxPathname bytes. */ -static int unixGetTempName(void *pNotUsed, char *zBuf){ +static int unixGetTempName(sqlite3_vfs *pVfs, char *zBuf){ static const char *azDirs[] = { 0, "/var/tmp", @@ -2516,7 +2503,8 @@ static int unixGetTempName(void *pNotUsed, char *zBuf){ break; } do{ - sqlite3_snprintf(MAX_PATHNAME-17, zBuf, "%s/"TEMP_FILE_PREFIX, zDir); + assert( pVfs->mxPathname==MAX_PATHNAME ); + sqlite3_snprintf(MAX_PATHNAME-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); j = strlen(zBuf); sqlite3Randomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ @@ -2537,18 +2525,18 @@ static int unixGetTempName(void *pNotUsed, char *zBuf){ ** (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){ +static int unixFullPathname(sqlite3_vfs *pVfs, const char *zPath, char *zOut){ + assert( pVfs->mxPathname==MAX_PATHNAME ); zOut[MAX_PATHNAME-1] = '\0'; if( zPath[0]=='/' ){ - strncpy(zOut, zPath, MAX_PATHNAME-1); + sqlite3_snprintf(MAX_PATHNAME, zOut, "%s", zPath); }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); + sqlite3_snprintf(MAX_PATHNAME-nCwd, &zOut[nCwd], "/%s", zPath); } return SQLITE_OK; @@ -2586,25 +2574,24 @@ static int unixFullPathname(void *pNotUsed, const char *zPath, char *zOut){ ** within the shared library, and closing the shared library. */ #include -static void *unixDlOpen(void *pNotUsed, const char *zFilename){ +static void *unixDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); } -static void unixDlError(void *pNotUsed, int nBuf, char *zBufOut){ +static void unixDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ char *zErr; enterMutex(); zErr = dlerror(); if( zErr ){ - strncpy(zBufOut, zErr, nBuf-1); - zBufOut[nBuf-1] = '\0'; + sqlite3_snprintf(nBuf, zBufOut, "%s", zErr); }else if(nBuf>0) { zBufOut[0] = '\0'; } leaveMutex(); } -void *unixDlSym(void *pHandle, const char *zSymbol){ +void *unixDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ return dlsym(pHandle, zSymbol); } -void unixDlClose(void *pHandle){ +void unixDlClose(sqlite3_vfs *pVfs, void *pHandle){ dlclose(pHandle); } #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ @@ -2617,7 +2604,7 @@ void unixDlClose(void *pHandle){ /* ** Write nBuf bytes of random data to the supplied buffer zBuf. */ -static int unixRandomness(void *pNotUsed, int nBuf, char *zBuf){ +static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ assert(nBuf>=(sizeof(time_t)+sizeof(int))); @@ -2662,7 +2649,7 @@ static int unixRandomness(void *pNotUsed, int nBuf, char *zBuf){ ** might be greater than or equal to the argument, but not less ** than the argument. */ -static int unixSleep(void *pNotUsed, int microseconds){ +static int unixSleep(sqlite3_vfs *pVfs, int microseconds){ #if defined(HAVE_USLEEP) && HAVE_USLEEP usleep(microseconds); return microseconds; @@ -2686,7 +2673,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. */ -static int unixCurrentTime(void *pNotUsed, double *prNow){ +static int unixCurrentTime(sqlite3_vfs *pVfs, double *prNow){ #ifdef NO_GETTOD time_t t; time(&t); @@ -2704,29 +2691,38 @@ static int unixCurrentTime(void *pNotUsed, double *prNow){ return 0; } - -sqlite3_vfs sqlite3DefaultVfs = { - 1, /* iVersion */ - sizeof(unixFile), /* szOsFile */ - MAX_PATHNAME, /* mxPathname */ - 0, /* nRef */ - 0, /* vfsMutex */ - 0, /* pNext */ - "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 */ -}; +/* +** Return a pointer to the sqlite3DefaultVfs structure. We use +** a function rather than give the structure global scope because +** some compilers (MSVC) do not allow forward declarations of +** initialized structures. +*/ +sqlite3_vfs *sqlite3OsDefaultVfs(void){ + static sqlite3_vfs unixVfs = { + 1, /* iVersion */ + sizeof(unixFile), /* szOsFile */ + MAX_PATHNAME, /* mxPathname */ + 0, /* nRef */ + 0, /* vfsMutex */ + 0, /* pNext */ + "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 */ + }; + + return &unixVfs; +} #endif /* OS_UNIX */ diff --git a/src/os_win.c b/src/os_win.c index 66bf4f6b60..6b6496d85a 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -58,12 +58,12 @@ typedef struct winceLock { #endif /* -** The winFile structure is a subclass of OsFile specific to the win32 +** The winFile structure is a subclass of sqlite3_file* specific to the win32 ** portability layer. */ typedef struct winFile winFile; struct winFile { - IoMethod const *pMethod;/* Must be first */ + const sqlite3_io_methods *pMethod;/* Must be first */ HANDLE h; /* Handle for accessing the file */ unsigned char locktype; /* Type of lock currently held on this file */ short sharedLockByte; /* Randomly chosen byte used as a shared lock */ @@ -77,13 +77,6 @@ struct winFile { }; -/* -** Do not include any of the File I/O interface procedures if the -** SQLITE_OMIT_DISKIO macro is defined (indicating that there database -** will be in-memory only) -*/ -#ifndef SQLITE_OMIT_DISKIO - /* ** The following variable is (normally) set once and never changes ** thereafter. It records whether the operating system is Win95 @@ -96,7 +89,11 @@ struct winFile { ** In order to facilitate testing on a WinNT system, the test fixture ** can manually set this value to 1 to emulate Win98 behavior. */ +#ifdef SQLITE_TEST int sqlite3_os_type = 0; +#else +static int sqlite3_os_type = 0; +#endif /* ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, @@ -126,20 +123,20 @@ int sqlite3_os_type = 0; /* ** Convert a UTF-8 string to microsoft unicode (UTF-16?). ** -** Space to hold the returned string is obtained from sqliteMalloc. +** Space to hold the returned string is obtained from sqlite3_malloc. */ static WCHAR *utf8ToUnicode(const char *zFilename){ int nChar; WCHAR *zWideFilename; nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); - zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) ); + zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) ); if( zWideFilename==0 ){ return 0; } nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); if( nChar==0 ){ - sqliteFree(zWideFilename); + sqlite3_free(zWideFilename); zWideFilename = 0; } return zWideFilename; @@ -147,21 +144,21 @@ static WCHAR *utf8ToUnicode(const char *zFilename){ /* ** Convert microsoft unicode to UTF-8. Space to hold the returned string is -** obtained from sqliteMalloc(). +** obtained from sqlite3_malloc(). */ static char *unicodeToUtf8(const WCHAR *zWideFilename){ int nByte; char *zFilename; nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); - zFilename = sqliteMalloc( nByte ); + zFilename = sqlite3_malloc( nByte ); if( zFilename==0 ){ return 0; } nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, 0, 0); if( nByte == 0 ){ - sqliteFree(zFilename); + sqlite3_free(zFilename); zFilename = 0; } return zFilename; @@ -172,7 +169,7 @@ static char *unicodeToUtf8(const WCHAR *zWideFilename){ ** current codepage settings for file apis. ** ** Space to hold the returned string is obtained -** from sqliteMalloc. +** from sqlite3_malloc. */ static WCHAR *mbcsToUnicode(const char *zFilename){ int nByte; @@ -180,13 +177,13 @@ static WCHAR *mbcsToUnicode(const char *zFilename){ int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); - zMbcsFilename = sqliteMalloc( nByte*sizeof(zMbcsFilename[0]) ); + zMbcsFilename = sqlite3_malloc( nByte*sizeof(zMbcsFilename[0]) ); if( zMbcsFilename==0 ){ return 0; } nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); if( nByte==0 ){ - sqliteFree(zMbcsFilename); + sqlite3_free(zMbcsFilename); zMbcsFilename = 0; } return zMbcsFilename; @@ -197,7 +194,7 @@ static WCHAR *mbcsToUnicode(const char *zFilename){ ** user's Ansi codepage. ** ** Space to hold the returned string is obtained from -** sqliteMalloc(). +** sqlite3_malloc(). */ static char *unicodeToMbcs(const WCHAR *zWideFilename){ int nByte; @@ -205,14 +202,14 @@ static char *unicodeToMbcs(const WCHAR *zWideFilename){ int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); - zFilename = sqliteMalloc( nByte ); + zFilename = sqlite3_malloc( nByte ); if( zFilename==0 ){ return 0; } nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, 0, 0); if( nByte == 0 ){ - sqliteFree(zFilename); + sqlite3_free(zFilename); zFilename = 0; } return zFilename; @@ -220,7 +217,7 @@ static char *unicodeToMbcs(const WCHAR *zWideFilename){ /* ** Convert multibyte character string to UTF-8. Space to hold the -** returned string is obtained from sqliteMalloc(). +** returned string is obtained from sqlite3_malloc(). */ static char *mbcsToUtf8(const char *zFilename){ char *zFilenameUtf8; @@ -231,13 +228,13 @@ static char *mbcsToUtf8(const char *zFilename){ return 0; } zFilenameUtf8 = unicodeToUtf8(zTmpWide); - sqliteFree(zTmpWide); + sqlite3_free(zTmpWide); return zFilenameUtf8; } /* ** Convert UTF-8 to multibyte character string. Space to hold the -** returned string is obtained from sqliteMalloc(). +** returned string is obtained from sqlite3_malloc(). */ static char *utf8ToMbcs(const char *zFilename){ char *zFilenameMbcs; @@ -248,7 +245,7 @@ static char *utf8ToMbcs(const char *zFilename){ return 0; } zFilenameMbcs = unicodeToMbcs(zTmpWide); - sqliteFree(zTmpWide); + sqlite3_free(zTmpWide); return zFilenameMbcs; } @@ -328,7 +325,7 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ /* Create/open the named mutex */ pFile->hMutex = CreateMutexW(NULL, FALSE, zName); if (!pFile->hMutex){ - sqliteFree(zName); + sqlite3_free(zName); return FALSE; } @@ -350,7 +347,7 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ bInit = FALSE; } - sqliteFree(zName); + sqlite3_free(zName); /* If we succeeded in making the shared memory handle, map it. */ if (pFile->hShared){ @@ -409,7 +406,7 @@ static void winceDestroyLock(winFile *pFile){ if( pFile->zDeleteOnClose ){ DeleteFileW(pFile->zDeleteOnClose); - sqliteFree(pFile->zDeleteOnClose); + sqlite3_free(pFile->zDeleteOnClose); pFile->zDeleteOnClose = 0; } @@ -564,400 +561,10 @@ static BOOL winceLockFileEx( *****************************************************************************/ #endif /* OS_WINCE */ -/* -** Convert a UTF-8 filename into whatever form the underlying -** operating system wants filenames in. Space to hold the result -** is obtained from sqliteMalloc and must be freed by the calling -** function. -*/ -static void *convertUtf8Filename(const char *zFilename){ - void *zConverted = 0; - if( isNT() ){ - zConverted = utf8ToUnicode(zFilename); - }else{ - zConverted = utf8ToMbcs(zFilename); - } - /* caller will handle out of memory */ - return zConverted; -} - -/* -** Delete the named file. -** -** Note that windows does not allow a file to be deleted if some other -** process has it open. Sometimes a virus scanner or indexing program -** will open a journal file shortly after it is created in order to do -** whatever it is it does. While this other process is holding the -** file open, we will be unable to delete it. To work around this -** problem, we delay 100 milliseconds and try to delete again. Up -** to MX_DELETION_ATTEMPTs deletion attempts are run before giving -** up and returning an error. -*/ -#define MX_DELETION_ATTEMPTS 3 -int sqlite3WinDelete(const char *zFilename){ - int cnt = 0; - int rc; - void *zConverted = convertUtf8Filename(zFilename); - if( zConverted==0 ){ - return SQLITE_NOMEM; - } - SimulateIOError(return SQLITE_IOERR_DELETE); - if( isNT() ){ - do{ - rc = DeleteFileW(zConverted); - }while( rc==0 && GetFileAttributesW(zConverted)!=0xffffffff - && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); - }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - do{ - rc = DeleteFileA(zConverted); - }while( rc==0 && GetFileAttributesA(zConverted)!=0xffffffff - && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); -#endif - } - sqliteFree(zConverted); - OSTRACE2("DELETE \"%s\"\n", zFilename); - return rc!=0 ? SQLITE_OK : SQLITE_IOERR; -} - -/* -** Return TRUE if the named file exists. -*/ -int sqlite3WinFileExists(const char *zFilename){ - int exists = 0; - void *zConverted = convertUtf8Filename(zFilename); - if( zConverted==0 ){ - return SQLITE_NOMEM; - } - if( isNT() ){ - exists = GetFileAttributesW((WCHAR*)zConverted) != 0xffffffff; - }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - exists = GetFileAttributesA((char*)zConverted) != 0xffffffff; -#endif - } - sqliteFree(zConverted); - return exists; -} - -/* Forward declaration */ -static int allocateWinFile(winFile *pInit, OsFile **pId); - -/* -** Attempt to open a file for both reading and writing. If that -** fails, try opening it read-only. If the file does not exist, -** try to create it. -** -** On success, a handle for the open file is written to *id -** and *pReadonly is set to 0 if the file was opened for reading and -** writing or 1 if the file was opened read-only. The function returns -** SQLITE_OK. -** -** On failure, the function returns SQLITE_CANTOPEN and leaves -** *id and *pReadonly unchanged. -*/ -int sqlite3WinOpenReadWrite( - const char *zFilename, - OsFile **pId, - int *pReadonly -){ - winFile f; - HANDLE h; - void *zConverted = convertUtf8Filename(zFilename); - if( zConverted==0 ){ - return SQLITE_NOMEM; - } - assert( *pId==0 ); - - if( isNT() ){ - h = CreateFileW((WCHAR*)zConverted, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - h = CreateFileW((WCHAR*)zConverted, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - sqliteFree(zConverted); - return SQLITE_CANTOPEN; - } - *pReadonly = 1; - }else{ - *pReadonly = 0; - } -#if OS_WINCE - if (!winceCreateLock(zFilename, &f)){ - CloseHandle(h); - sqliteFree(zConverted); - return SQLITE_CANTOPEN; - } -#endif - }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - h = CreateFileA((char*)zConverted, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - h = CreateFileA((char*)zConverted, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - if( h==INVALID_HANDLE_VALUE ){ - sqliteFree(zConverted); - return SQLITE_CANTOPEN; - } - *pReadonly = 1; - }else{ - *pReadonly = 0; - } -#endif /* OS_WINCE */ - } - - sqliteFree(zConverted); - - f.h = h; -#if OS_WINCE - f.zDeleteOnClose = 0; -#endif - OSTRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); - return allocateWinFile(&f, pId); -} - - -/* -** Attempt to open a new file for exclusive access by this process. -** The file will be opened for both reading and writing. To avoid -** a potential security problem, we do not allow the file to have -** previously existed. Nor do we allow the file to be a symbolic -** link. -** -** If delFlag is true, then make arrangements to automatically delete -** the file when it is closed. -** -** On success, write the file handle into *id and return SQLITE_OK. -** -** On failure, return SQLITE_CANTOPEN. -** -** Sometimes if we have just deleted a prior journal file, windows -** will fail to open a new one because there is a "pending delete". -** To work around this bug, we pause for 100 milliseconds and attempt -** a second open after the first one fails. The whole operation only -** fails if both open attempts are unsuccessful. -*/ -int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ - winFile f; - HANDLE h; - DWORD fileflags; - void *zConverted = convertUtf8Filename(zFilename); - if( zConverted==0 ){ - return SQLITE_NOMEM; - } - assert( *pId == 0 ); - fileflags = FILE_FLAG_RANDOM_ACCESS; -#if !OS_WINCE - if( delFlag ){ - fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; - } -#endif - if( isNT() ){ - int cnt = 0; - do{ - h = CreateFileW((WCHAR*)zConverted, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - fileflags, - NULL - ); - }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); - }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - int cnt = 0; - do{ - h = CreateFileA((char*)zConverted, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - fileflags, - NULL - ); - }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); -#endif /* OS_WINCE */ - } -#if OS_WINCE - if( delFlag && h!=INVALID_HANDLE_VALUE ){ - f.zDeleteOnClose = zConverted; - zConverted = 0; - } - f.hMutex = NULL; -#endif - sqliteFree(zConverted); - if( h==INVALID_HANDLE_VALUE ){ - return SQLITE_CANTOPEN; - } - f.h = h; - OSTRACE3("OPEN EX %d \"%s\"\n", h, zFilename); - return allocateWinFile(&f, pId); -} - -/* -** Attempt to open a new file for read-only access. -** -** On success, write the file handle into *id and return SQLITE_OK. -** -** On failure, return SQLITE_CANTOPEN. -*/ -int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ - winFile f; - HANDLE h; - void *zConverted = convertUtf8Filename(zFilename); - if( zConverted==0 ){ - return SQLITE_NOMEM; - } - assert( *pId==0 ); - if( isNT() ){ - h = CreateFileW((WCHAR*)zConverted, - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); - }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - h = CreateFileA((char*)zConverted, - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); -#endif - } - sqliteFree(zConverted); - if( h==INVALID_HANDLE_VALUE ){ - return SQLITE_CANTOPEN; - } - f.h = h; -#if OS_WINCE - f.zDeleteOnClose = 0; - f.hMutex = NULL; -#endif - OSTRACE3("OPEN RO %d \"%s\"\n", h, zFilename); - return allocateWinFile(&f, pId); -} - -/* -** Attempt to open a file descriptor for the directory that contains a -** file. This file descriptor can be used to fsync() the directory -** in order to make sure the creation of a new file is actually written -** to disk. -** -** This routine is only meaningful for Unix. It is a no-op under -** windows since windows does not support hard links. -** -** On success, a handle for a previously open file is at *id is -** updated with the new directory file descriptor and SQLITE_OK is -** returned. -** -** On failure, the function returns SQLITE_CANTOPEN and leaves -** *id unchanged. -*/ -static int winOpenDirectory( - OsFile *id, - const char *zDirname -){ - return SQLITE_OK; -} - -/* -** Create a temporary file name in zBuf. zBuf must be big enough to -** hold at least SQLITE_TEMPNAME_SIZE characters. -*/ -int sqlite3WinTempFileName(char *zBuf){ - static char zChars[] = - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"; - int i, j; - char zTempPath[SQLITE_TEMPNAME_SIZE]; - if( sqlite3_temp_directory ){ - strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30); - zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; - }else if( isNT() ){ - char *zMulti; - WCHAR zWidePath[SQLITE_TEMPNAME_SIZE]; - GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath); - zMulti = unicodeToUtf8(zWidePath); - if( zMulti ){ - strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30); - zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; - sqliteFree(zMulti); - }else{ - return SQLITE_NOMEM; - } - }else{ - char *zUtf8; - char zMbcsPath[SQLITE_TEMPNAME_SIZE]; - GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zMbcsPath); - zUtf8 = mbcsToUtf8(zMbcsPath); - if( zUtf8 ){ - strncpy(zTempPath, zUtf8, SQLITE_TEMPNAME_SIZE-30); - zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; - sqliteFree(zUtf8); - }else{ - return SQLITE_NOMEM; - } - } - for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} - zTempPath[i] = 0; - for(;;){ - sqlite3_snprintf(SQLITE_TEMPNAME_SIZE, zBuf, - "%s\\"TEMP_FILE_PREFIX, zTempPath); - 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; - if( !sqlite3OsFileExists(zBuf) ) break; - } - OSTRACE2("TEMP FILENAME: %s\n", zBuf); - return SQLITE_OK; -} +/***************************************************************************** +** The next group of routines implement the I/O methods specified +** by the sqlite3_io_methods object. +******************************************************************************/ /* ** Close a file. @@ -970,36 +577,51 @@ int sqlite3WinTempFileName(char *zBuf){ ** giving up and returning an error. */ #define MX_CLOSE_ATTEMPT 3 -static int winClose(OsFile **pId){ - winFile *pFile; - int rc = 1; - if( pId && (pFile = (winFile*)*pId)!=0 ){ - int rc, cnt = 0; - OSTRACE2("CLOSE %d\n", pFile->h); - do{ - rc = CloseHandle(pFile->h); - }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); +static int winClose(sqlite3_file *id){ + int rc, cnt = 0; + winFile *pFile = (winFile*)id; + OSTRACE2("CLOSE %d\n", pFile->h); + do{ + rc = CloseHandle(pFile->h); + }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); #if OS_WINCE - winceDestroyLock(pFile); + winceDestroyLock(pFile); #endif - OpenCounter(-1); - sqliteFree(pFile); - *pId = 0; - } + OpenCounter(-1); return rc ? SQLITE_OK : SQLITE_IOERR; } +/* +** Some microsoft compilers lack this definition. +*/ +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + /* ** Read data from a file into a buffer. Return SQLITE_OK if all ** bytes were read successfully and SQLITE_IOERR if anything goes ** wrong. */ -static int winRead(OsFile *id, void *pBuf, int amt){ +static int winRead( + sqlite3_file *id, /* File to read from */ + void *pBuf, /* Write content into this buffer */ + int amt, /* Number of bytes to read */ + sqlite3_int64 offset /* Begin reading at this offset */ +){ + LONG upperBits = (offset>>32) & 0x7fffffff; + LONG lowerBits = offset & 0xffffffff; + DWORD rc; DWORD got; + winFile *pFile = (winFile*)id; assert( id!=0 ); SimulateIOError(return SQLITE_IOERR_READ); - OSTRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); - if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){ + OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype); + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ + return SQLITE_FULL; + } + if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){ return SQLITE_IOERR_READ; } if( got==(DWORD)amt ){ @@ -1014,16 +636,31 @@ static int winRead(OsFile *id, void *pBuf, int amt){ ** Write data from a buffer into a file. Return SQLITE_OK on success ** or some other error code on failure. */ -static int winWrite(OsFile *id, const void *pBuf, int amt){ - int rc = 0; +static int winWrite( + sqlite3_file *id, /* File to write into */ + const void *pBuf, /* The bytes to be written */ + int amt, /* Number of bytes to write */ + sqlite3_int64 offset /* Offset into the file to begin writing at */ +){ + LONG upperBits = (offset>>32) & 0x7fffffff; + LONG lowerBits = offset & 0xffffffff; + DWORD rc; DWORD wrote; + winFile *pFile = (winFile*)id; assert( id!=0 ); - SimulateIOError(return SQLITE_IOERR_READ); + SimulateIOError(return SQLITE_IOERR_WRITE); SimulateDiskfullError(return SQLITE_FULL); - OSTRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype); + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ + return SQLITE_FULL; + } assert( amt>0 ); - while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0 - && wrote>0 ){ + while( + amt>0 + && (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0 + && wrote>0 + ){ amt -= wrote; pBuf = &((char*)pBuf)[wrote]; } @@ -1034,75 +671,41 @@ static int winWrite(OsFile *id, const void *pBuf, int amt){ } /* -** Some microsoft compilers lack this definition. +** Truncate an open file to a specified size */ -#ifndef INVALID_SET_FILE_POINTER -# define INVALID_SET_FILE_POINTER ((DWORD)-1) -#endif - -/* -** Move the read/write pointer in a file. -*/ -static int winSeek(OsFile *id, i64 offset){ - LONG upperBits = offset>>32; - LONG lowerBits = offset & 0xffffffff; - DWORD rc; - assert( id!=0 ); -#ifdef SQLITE_TEST - if( offset ) SimulateDiskfullError(return SQLITE_FULL); -#endif - rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN); - OSTRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset); - if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ - return SQLITE_FULL; - } +static int winTruncate(sqlite3_file *id, i64 nByte){ + LONG upperBits = (nByte>>32) & 0x7fffffff; + LONG lowerBits = nByte & 0xffffffff; + winFile *pFile = (winFile*)id; + OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte); + SimulateIOError(return SQLITE_IOERR_TRUNCATE); + SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + SetEndOfFile(pFile->h); return SQLITE_OK; } /* ** Make sure all writes to a particular file are committed to disk. */ -static int winSync(OsFile *id, int dataOnly){ - assert( id!=0 ); - OSTRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); - if( FlushFileBuffers(((winFile*)id)->h) ){ +static int winSync(sqlite3_file *id, int flags){ + winFile *pFile = (winFile*)id; + OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype); + if( FlushFileBuffers(pFile->h) ){ return SQLITE_OK; }else{ return SQLITE_IOERR; } } -/* -** Sync the directory zDirname. This is a no-op on operating systems other -** than UNIX. -*/ -int sqlite3WinSyncDirectory(const char *zDirname){ - SimulateIOError(return SQLITE_IOERR_READ); - return SQLITE_OK; -} - -/* -** Truncate an open file to a specified size -*/ -static int winTruncate(OsFile *id, i64 nByte){ - LONG upperBits = nByte>>32; - assert( id!=0 ); - OSTRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte); - SimulateIOError(return SQLITE_IOERR_TRUNCATE); - SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN); - SetEndOfFile(((winFile*)id)->h); - return SQLITE_OK; -} - /* ** Determine the current size of a file in bytes */ -static int winFileSize(OsFile *id, i64 *pSize){ +static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ + winFile *pFile = (winFile*)id; DWORD upperBits, lowerBits; - assert( id!=0 ); SimulateIOError(return SQLITE_IOERR_FSTAT); - lowerBits = GetFileSize(((winFile*)id)->h, &upperBits); - *pSize = (((i64)upperBits)<<32) + lowerBits; + lowerBits = GetFileSize(pFile->h, &upperBits); + *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; return SQLITE_OK; } @@ -1118,19 +721,20 @@ static int winFileSize(OsFile *id, i64 *pSize){ ** Different API routines are called depending on whether or not this ** is Win95 or WinNT. */ -static int getReadLock(winFile *id){ +static int getReadLock(winFile *pFile){ int res; if( isNT() ){ OVERLAPPED ovlp; ovlp.Offset = SHARED_FIRST; ovlp.OffsetHigh = 0; ovlp.hEvent = 0; - res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp); + res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, + 0, SHARED_SIZE, 0, &ovlp); }else{ int lk; sqlite3Randomness(sizeof(lk), &lk); - id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); - res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0); + pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); } return res; } @@ -1148,39 +752,6 @@ static int unlockReadLock(winFile *pFile){ return res; } -#ifndef SQLITE_OMIT_PAGER_PRAGMAS -/* -** Check that a given pathname is a directory and is writable -** -*/ -int sqlite3WinIsDirWritable(char *zDirname){ - int fileAttr; - void *zConverted; - if( zDirname==0 ) return 0; - if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0; - - zConverted = convertUtf8Filename(zDirname); - if( zConverted==0 ){ - return SQLITE_NOMEM; - } - if( isNT() ){ - fileAttr = GetFileAttributesW((WCHAR*)zConverted); - }else{ -#if OS_WINCE - return 0; -#else - fileAttr = GetFileAttributesA((char*)zConverted); -#endif - } - sqliteFree(zConverted); - if( fileAttr == 0xffffffff ) return 0; - if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ - return 0; - } - return 1; -} -#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ - /* ** Lock the file with the lock specified by parameter locktype - one ** of the following: @@ -1207,10 +778,10 @@ int sqlite3WinIsDirWritable(char *zDirname){ ** It is not possible to lower the locking level one step at a time. You ** must go straight to locking level 0. */ -static int winLock(OsFile *id, int locktype){ +static int winLock(sqlite3_file *id, int locktype){ int rc = SQLITE_OK; /* Return code from subroutines */ int res = 1; /* Result of a windows lock call */ - int newLocktype; /* Set id->locktype to this value before exiting */ + int newLocktype; /* Set pFile->locktype to this value before exiting */ int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ winFile *pFile = (winFile*)id; @@ -1319,7 +890,7 @@ static int winLock(OsFile *id, int locktype){ ** file by this or any other process. If such a lock is held, return ** non-zero, otherwise zero. */ -static int winCheckReservedLock(OsFile *id){ +static int winCheckReservedLock(sqlite3_file *id){ int rc; winFile *pFile = (winFile*)id; assert( pFile!=0 ); @@ -1348,10 +919,10 @@ static int winCheckReservedLock(OsFile *id){ ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine ** might return SQLITE_IOERR; */ -static int winUnlock(OsFile *id, int locktype){ +static int winUnlock(sqlite3_file *id, int locktype){ int type; - int rc = SQLITE_OK; winFile *pFile = (winFile*)id; + int rc = SQLITE_OK; assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, @@ -1379,75 +950,19 @@ static int winUnlock(OsFile *id, int locktype){ } /* -** 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. +** Currently unimplemented */ -char *sqlite3WinFullPathname(const char *zRelative){ - char *zFull; -#if defined(__CYGWIN__) - int nByte; - nByte = strlen(zRelative) + MAX_PATH + 1001; - zFull = sqliteMalloc( nByte ); - if( zFull==0 ) return 0; - if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; -#elif OS_WINCE - /* WinCE has no concept of a relative pathname, or so I am told. */ - zFull = sqliteStrDup(zRelative); -#else - int nByte; - void *zConverted; - zConverted = convertUtf8Filename(zRelative); - if( isNT() ){ - WCHAR *zTemp; - nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; - zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); - if( zTemp==0 ){ - sqliteFree(zConverted); - return 0; - } - GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); - sqliteFree(zConverted); - zFull = unicodeToUtf8(zTemp); - sqliteFree(zTemp); - }else{ - char *zTemp; - nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; - zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); - if( zTemp==0 ){ - sqliteFree(zConverted); - return 0; - } - GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); - sqliteFree(zConverted); - zFull = mbcsToUtf8(zTemp); - sqliteFree(zTemp); - } -#endif - return zFull; -} - -/* -** The fullSync option is meaningless on windows. This is a no-op. -*/ -static void winSetFullSync(OsFile *id, int v){ - return; -} - -/* -** Return the underlying file handle for an OsFile -*/ -static int winFileHandle(OsFile *id){ - return (int)((winFile*)id)->h; +static int winBreakLock(sqlite3_file *id){ + return SQLITE_ERROR; } /* ** Return an integer that indices the type of lock currently held ** by this handle. (Used for testing and analysis only.) */ -static int winLockState(OsFile *id){ - return ((winFile*)id)->locktype; +static int winLockState(sqlite3_file *id){ + winFile *pFile = (winFile*)id; + return pFile->locktype; } /* @@ -1460,71 +975,378 @@ static int winLockState(OsFile *id){ ** a database and it's journal file) that the sector size will be the ** same for both. */ -static int winSectorSize(OsFile *id){ +static int winSectorSize(sqlite3_file *id){ return SQLITE_DEFAULT_SECTOR_SIZE; } /* -** This vector defines all the methods that can operate on an OsFile -** for win32. +** Return a vector of device characteristics. */ -static const IoMethod sqlite3WinIoMethod = { +static int winDeviceCharacteristics(sqlite3_file *id){ + return 0; +} + +/* +** This vector defines all the methods that can operate on an +** sqlite3_file for win32. +*/ +static const sqlite3_io_methods winIoMethod = { + 1, /* iVersion */ winClose, - winOpenDirectory, winRead, winWrite, - winSeek, winTruncate, winSync, - winSetFullSync, - winFileHandle, winFileSize, winLock, winUnlock, - winLockState, winCheckReservedLock, + winBreakLock, + winLockState, winSectorSize, + winDeviceCharacteristics }; +/*************************************************************************** +** Here ends the I/O methods that form the sqlite3_io_methods object. +** +** The next block of code implements the VFS methods. +****************************************************************************/ + /* -** Allocate memory for an OsFile. Initialize the new OsFile -** to the value given in pInit and return a pointer to the new -** OsFile. If we run out of memory, close the file and return NULL. +** Convert a UTF-8 filename into whatever form the underlying +** operating system wants filenames in. Space to hold the result +** is obtained from sqlite3_malloc and must be freed by the calling +** function. */ -static int allocateWinFile(winFile *pInit, OsFile **pId){ - winFile *pNew; - pNew = sqliteMalloc( sizeof(*pNew) ); - if( pNew==0 ){ - CloseHandle(pInit->h); -#if OS_WINCE - sqliteFree(pInit->zDeleteOnClose); -#endif - *pId = 0; - return SQLITE_NOMEM; +static void *convertUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( isNT() ){ + zConverted = utf8ToUnicode(zFilename); }else{ - *pNew = *pInit; - pNew->pMethod = &sqlite3WinIoMethod; - pNew->locktype = NO_LOCK; - pNew->sharedLockByte = 0; - *pId = (OsFile*)pNew; - OpenCounter(+1); - return SQLITE_OK; + zConverted = utf8ToMbcs(zFilename); } + /* caller will handle out of memory */ + return zConverted; +} + +/* +** Open a file. +*/ +static int winOpen( + sqlite3_vfs *pVfs, /* Not used */ + const char *zName, /* Name of the file (UTF-8) */ + sqlite3_file *id, /* Write the SQLite file handle here */ + int flags, /* Open mode flags */ + int *pOutFlags /* Status return flags */ +){ + HANDLE h; + DWORD dwDesiredAccess; + DWORD dwShareMode; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes = 0; + winFile *pFile = (winFile*)id; + void *zConverted = convertUtf8Filename(zName); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + + if( flags & SQLITE_OPEN_READWRITE ){ + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + }else{ + dwDesiredAccess = GENERIC_READ; + } + if( flags & SQLITE_OPEN_CREATE ){ + dwCreationDisposition = OPEN_ALWAYS; + }else{ + dwCreationDisposition = OPEN_EXISTING; + } + if( flags & SQLITE_OPEN_MAIN_DB ){ + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + }else{ + dwShareMode = 0; + } + if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL + | SQLITE_OPEN_SUBJOURNAL) ){ + dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY + | FILE_ATTRIBUTE_HIDDEN + | FILE_FLAG_DELETE_ON_CLOSE; + }else{ + dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + } + if( flags & (SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB) ){ + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + }else{ + dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN; + } + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL + ); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + h = CreateFileA((char*)zConverted, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL + ); +#endif + } + if( h==INVALID_HANDLE_VALUE ){ + if( flags & SQLITE_OPEN_READWRITE ){ + sqlite3_free(zConverted); + return winOpen(0, zName, id, + ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); + }else{ + return SQLITE_CANTOPEN; + } + } + if( pOutFlags ){ + if( flags & SQLITE_OPEN_READWRITE ){ + *pOutFlags = SQLITE_OPEN_READWRITE; + }else{ + *pOutFlags = SQLITE_OPEN_READONLY; + } + } + memset(pFile, 0, sizeof(*pFile)); + pFile->pMethod = &winIoMethod; + pFile->h = h; +#if OS_WINCE + if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) == + (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) + && !winceCreateLock(zFilename, &f) + ){ + CloseHandle(h); + sqlite3_free(zConverted); + return SQLITE_CANTOPEN; + } + if( dwFlagsAndAttributes & FILE_FLAG_DELETEONCLOSE ){ + pFile->zDeleteOnClose = zConverted; + }else +#endif + { + sqlite3_free(zConverted); + } + return SQLITE_OK; +} + +/* +** Delete the named file. +** +** Note that windows does not allow a file to be deleted if some other +** process has it open. Sometimes a virus scanner or indexing program +** will open a journal file shortly after it is created in order to do +** whatever it is it does. While this other process is holding the +** file open, we will be unable to delete it. To work around this +** problem, we delay 100 milliseconds and try to delete again. Up +** to MX_DELETION_ATTEMPTs deletion attempts are run before giving +** up and returning an error. +*/ +#define MX_DELETION_ATTEMPTS 3 +static int winDelete( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to delete */ + int syncDir /* Not used on win32 */ +){ + int cnt = 0; + int rc; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + SimulateIOError(return SQLITE_IOERR_DELETE); + if( isNT() ){ + do{ + rc = DeleteFileW(zConverted); + }while( rc==0 && GetFileAttributesW(zConverted)!=0xffffffff + && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + do{ + rc = DeleteFileA(zConverted); + }while( rc==0 && GetFileAttributesA(zConverted)!=0xffffffff + && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); +#endif + } + sqlite3_free(zConverted); + OSTRACE2("DELETE \"%s\"\n", zFilename); + return rc!=0 ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Check the existance and status of a file. +*/ +static int winAccess( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to check */ + int flags /* Type of test to make on this file */ +){ + DWORD attr; + int rc; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + if( isNT() ){ + attr = GetFileAttributesW((WCHAR*)zConverted); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + attr = GetFileAttributesA((char*)zConverted); +#endif + } + sqlite3_free(zConverted); + switch( flags ){ + case SQLITE_ACCESS_EXISTS: + rc = attr!=0xffffffff; + break; + case SQLITE_ACCESS_READWRITE: + rc = (attr & FILE_ATTRIBUTE_READONLY)==0; + break; + case SQLITE_ACCESS_READONLY: + rc = (attr!=0xffffffff) && ((attr & FILE_ATTRIBUTE_READONLY)==1); + break; + default: + assert(!"Invalid flags argument"); + } + return rc; } -#endif /* SQLITE_OMIT_DISKIO */ -/*************************************************************************** -** Everything above deals with file I/O. Everything that follows deals -** with other miscellanous aspects of the operating system interface -****************************************************************************/ +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at pVfs->mxPathname characters. +*/ +static int winGetTempName(sqlite3_vfs *pVfs, char *zBuf){ + static char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + char zTempPath[MAX_PATH+1]; + if( sqlite3_temp_directory ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); + }else if( isNT() ){ + char *zMulti; + WCHAR zWidePath[MAX_PATH]; + GetTempPathW(MAX_PATH-30, zWidePath); + zMulti = unicodeToUtf8(zWidePath); + if( zMulti ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%z", zMulti); + }else{ + return SQLITE_NOMEM; + } + }else{ + char *zUtf8; + char zMbcsPath[MAX_PATH]; + GetTempPathA(MAX_PATH-30, zMbcsPath); + zUtf8 = mbcsToUtf8(zMbcsPath); + if( zUtf8 ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%z", zUtf8); + }else{ + return SQLITE_NOMEM; + } + } + for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} + zTempPath[i] = 0; + for(;;){ + sqlite3_snprintf(pVfs->mxPathname-30, zBuf, + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); + 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; + if( !sqlite3OsAccess(pVfs, zBuf, SQLITE_ACCESS_EXISTS) ) break; + } + OSTRACE2("TEMP FILENAME: %s\n", zBuf); + return SQLITE_OK; +} -#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +/* +** Turn a relative pathname into a full pathname. Write the full +** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname +** bytes in size. +*/ +static int winFullPathname( + sqlite3_vfs *pVfs, + const char *zRelative, + char *zFull +){ + +#if defined(__CYGWIN__) + cygwin_conv_to_full_win32_path(zRelative, zFull); + return SQLITE_OK +#endif + +#if OS_WINCE + /* WinCE has no concept of a relative pathname, or so I am told. */ + sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); +#endif + +#if !OS_WINCE && !defined(__CYGWIN__) + int nByte; + void *zConverted; + char *zOut; + zConverted = convertUtf8Filename(zRelative); + if( isNT() ){ + WCHAR *zTemp; + nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; + zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + sqlite3_free(zConverted); + return SQLITE_NOMEM; + } + GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); + sqlite3_free(zConverted); + zOut = unicodeToUtf8(zTemp); + sqlite3_free(zTemp); + }else{ + char *zTemp; + nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; + zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + sqlite3_free(zConverted); + return SQLITE_NOMEM; + } + GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); + sqlite3_free(zConverted); + zOut = mbcsToUtf8(zTemp); + sqlite3_free(zTemp); + } + if( zOut ){ + sqlite3_snprintf(pVfs->mxPathname, zFull, "%z", zOut); + return SQLITE_OK; + }else{ + return SQLITE_NOMEM; + } +#endif +} + +#ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Interfaces for opening a shared library, finding entry points ** within the shared library, and closing the shared library. */ -void *sqlite3WinDlopen(const char *zFilename){ +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ @@ -1539,11 +1361,21 @@ void *sqlite3WinDlopen(const char *zFilename){ h = LoadLibraryA((char*)zConverted); #endif } - sqliteFree(zConverted); + sqlite3_free(zConverted); return (void*)h; - } -void *sqlite3WinDlsym(void *pHandle, const char *zSymbol){ +static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + 0, + zBufOut, + nBuf-1, + 0 + ); +} +void *winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ #if OS_WINCE /* The GetProcAddressA() routine is only available on wince. */ return GetProcAddressA((HANDLE)pHandle, zSymbol); @@ -1553,104 +1385,38 @@ void *sqlite3WinDlsym(void *pHandle, const char *zSymbol){ return GetProcAddress((HANDLE)pHandle, zSymbol); #endif } -int sqlite3WinDlclose(void *pHandle){ - return FreeLibrary((HANDLE)pHandle); +void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ + FreeLibrary((HANDLE)pHandle); } -#endif /* !SQLITE_OMIT_LOAD_EXTENSION */ +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define winDlOpen 0 + #define winDlError 0 + #define winDlSym 0 + #define winDlClose 0 +#endif + /* -** 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. +** Write up to nBuf bytes of randomness into zBuf. */ -int sqlite3WinRandomSeed(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 - ** uninitialized space in zBuf - but valgrind errors tend to worry - ** some users. Rather than argue, it seems easier just to initialize - ** the whole array and silence valgrind, even if that means less randomness - ** in the random seed. - ** - ** When testing, initializing zBuf[] to zero is all we do. That means - ** that we always use the same random number sequence.* This makes the - ** tests repeatable. - */ - memset(zBuf, 0, 256); - GetSystemTime((LPSYSTEMTIME)zBuf); - return SQLITE_OK; +static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + if( sizeof(LPSYSTEMTIME)>=nBuf ){ + GetSystemTime((LPSYSTEMTIME)zBuf); + return sizeof(LPSYSTEMTIME); + }else{ + return 0; + } } + /* ** Sleep for a little while. Return the amount of time slept. */ -int sqlite3WinSleep(int ms){ - Sleep(ms); - return ms; +static int winSleep(sqlite3_vfs *pVfs, int microsec){ + Sleep((microsec+999)/1000); + return ((microsec+999)/1000)*1000; } -/* -** Static variables used for thread synchronization -*/ -static int inMutex = 0; -#ifdef SQLITE_W32_THREADS - static DWORD mutexOwner; - static CRITICAL_SECTION cs; -#endif - -/* -** The following pair of routines 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. -** -** Version 3.3.1 and earlier used a simple mutex. Beginning with -** version 3.3.2, a recursive mutex is required. -*/ -void sqlite3WinEnterMutex(){ -#ifdef SQLITE_W32_THREADS - static int isInit = 0; - while( !isInit ){ - static long lock = 0; - if( InterlockedIncrement(&lock)==1 ){ - InitializeCriticalSection(&cs); - isInit = 1; - }else{ - Sleep(1); - } - } - EnterCriticalSection(&cs); - mutexOwner = GetCurrentThreadId(); -#endif - inMutex++; -} -void sqlite3WinLeaveMutex(){ - assert( inMutex ); - inMutex--; -#ifdef SQLITE_W32_THREADS - assert( mutexOwner==GetCurrentThreadId() ); - LeaveCriticalSection(&cs); -#endif -} - -/* -** Return TRUE if the mutex is currently held. -** -** If the thisThreadOnly parameter is true, return true if and only if the -** calling thread holds the mutex. If the parameter is false, return -** true if any thread holds the mutex. -*/ -int sqlite3WinInMutex(int thisThreadOnly){ -#ifdef SQLITE_W32_THREADS - return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId()); -#else - return inMutex>0; -#endif -} - - /* ** The following variable, if set to a non-zero value, becomes the result ** returned from sqlite3OsCurrentTime(). This is used for testing. @@ -1664,7 +1430,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 sqlite3WinCurrentTime(double *prNow){ +int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ FILETIME ft; /* FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). @@ -1687,71 +1453,39 @@ int sqlite3WinCurrentTime(double *prNow){ return 0; } -/* -** Remember the number of thread-specific-data blocks allocated. -** Use this to verify that we are not leaking thread-specific-data. -** Ticket #1601 -*/ -#ifdef SQLITE_TEST -int sqlite3_tsd_count = 0; -# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count) -# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count) -#else -# define TSD_COUNTER_INCR /* no-op */ -# define TSD_COUNTER_DECR /* no-op */ -#endif - - /* -** If called with allocateFlag>1, then return a pointer to thread -** specific data for the current thread. Allocate and zero the -** thread-specific data if it does not already exist necessary. -** -** If called with allocateFlag==0, then check the current thread -** specific data. Return it if it exists. If it does not exist, -** then return NULL. -** -** If called with allocateFlag<0, check to see if the thread specific -** data is allocated and is all zero. If it is then deallocate it. -** Return a pointer to the thread specific data or NULL if it is -** unallocated or gets deallocated. +** Return a pointer to the sqlite3DefaultVfs structure. We use +** a function rather than give the structure global scope because +** some compilers (MSVC) do not allow forward declarations of +** initialized structures. */ -ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){ - static int key; - static int keyInit = 0; - static const ThreadData zeroData = {0}; - ThreadData *pTsd; - - if( !keyInit ){ - sqlite3OsEnterMutex(); - if( !keyInit ){ - key = TlsAlloc(); - if( key==0xffffffff ){ - sqlite3OsLeaveMutex(); - return 0; - } - keyInit = 1; - } - sqlite3OsLeaveMutex(); - } - pTsd = TlsGetValue(key); - if( allocateFlag>0 ){ - if( !pTsd ){ - pTsd = sqlite3OsMalloc( sizeof(zeroData) ); - if( pTsd ){ - *pTsd = zeroData; - TlsSetValue(key, pTsd); - TSD_COUNTER_INCR; - } - } - }else if( pTsd!=0 && allocateFlag<0 - && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ - sqlite3OsFree(pTsd); - TlsSetValue(key, 0); - TSD_COUNTER_DECR; - pTsd = 0; - } - return pTsd; +sqlite3_vfs *sqlite3OsDefaultVfs(void){ + static sqlite3_vfs winVfs = { + 1, /* iVersion */ + sizeof(winFile), /* szOsFile */ + MAX_PATH, /* mxPathname */ + 0, /* nRef */ + 0, /* vfsMutex */ + 0, /* pNext */ + "win32", /* zName */ + 0, /* pAppData */ + + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winGetTempName, /* xGetTempName */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime /* xCurrentTime */ + }; + + return &winVfs; } + #endif /* OS_WIN */ diff --git a/src/pager.c b/src/pager.c index 504bfcbf1b..2c5c9cab6c 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.371 2007/08/23 14:48:24 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.372 2007/08/24 03:51:34 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -1873,7 +1873,6 @@ int sqlite3PagerOpen( ){ u8 *pPtr; Pager *pPager = 0; - char *zFullPathname = 0; int rc = SQLITE_OK; int i; int tempFile = 0; @@ -1905,8 +1904,7 @@ int sqlite3PagerOpen( 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). + /* Open the pager file. */ if( zFilename && zFilename[0] ){ #ifndef SQLITE_OMIT_MEMORYDB @@ -1942,9 +1940,9 @@ int sqlite3PagerOpen( 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 + /* If an error occured in either of the blocks above. + ** 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 || !pPager->pTmpSpace ){ @@ -1953,8 +1951,8 @@ int sqlite3PagerOpen( return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); } - PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), zFullPathname); - IOTRACE(("OPEN %p %s\n", pPager, zFullPathname)) + PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename); + IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) /* Fill in Pager.zDirectory[] */ memcpy(pPager->zDirectory, pPager->zFilename, pVfs->mxPathname); @@ -2682,6 +2680,7 @@ static PgHdr *sort_pagelist(PgHdr *pIn){ */ static int pager_write_pagelist(PgHdr *pList){ Pager *pPager; + PgHdr *p; int rc; if( pList==0 ) return SQLITE_OK; @@ -2709,6 +2708,10 @@ static int pager_write_pagelist(PgHdr *pList){ } pList = sort_pagelist(pList); + for(p=pList; p; p=p->pDirty){ + assert( p->dirty ); + p->dirty = 0; + } while( pList ){ /* If the file has not yet been opened, open it now. */ @@ -2718,7 +2721,6 @@ static int pager_write_pagelist(PgHdr *pList){ if( rc ) return rc; } - assert( pList->dirty ); /* If there are dirty pages in the page cache with page numbers greater ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to ** make the file smaller (presumably by auto-vacuum code). Do not write @@ -2743,7 +2745,6 @@ static int pager_write_pagelist(PgHdr *pList){ } #endif if( rc ) return rc; - pList->dirty = 0; #ifdef SQLITE_CHECK_PAGES pList->pageHash = pager_pagehash(pList); #endif @@ -2846,6 +2847,7 @@ static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ pPg->dirty = 1; pPg->pDirty = 0; rc = pager_write_pagelist( pPg ); + pPg->dirty = 0; if( rc!=SQLITE_OK ){ return rc; } @@ -3698,11 +3700,14 @@ static void makeClean(PgHdr *pPg){ if( pPg->dirty ){ pPg->dirty = 0; if( pPg->pDirty ){ + assert( pPg->pDirty->pPrevDirty==pPg ); pPg->pDirty->pPrevDirty = pPg->pPrevDirty; } if( pPg->pPrevDirty ){ + assert( pPg->pPrevDirty->pDirty==pPg ); pPg->pPrevDirty->pDirty = pPg->pDirty; }else{ + assert( pPg->pPager->pDirty==pPg ); pPg->pPager->pDirty = pPg->pDirty; } } @@ -4263,7 +4268,11 @@ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ /* Write all dirty pages to the database file */ pPg = pager_get_all_dirty_pages(pPager); rc = pager_write_pagelist(pPg); - if( rc!=SQLITE_OK ) goto sync_exit; + if( rc!=SQLITE_OK ){ + while( pPg && !pPg->dirty ){ pPg = pPg->pDirty; } + pPager->pDirty = pPg; + goto sync_exit; + } pPager->pDirty = 0; /* Sync the database file. */ diff --git a/src/printf.c b/src/printf.c index ece53b7fd4..37390a5f00 100644 --- a/src/printf.c +++ b/src/printf.c @@ -113,7 +113,7 @@ static const et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 }, { 'g', 0, 1, etGENERIC, 30, 0 }, - { 'z', 0, 6, etDYNSTRING, 0, 0 }, + { 'z', 0, 4, etDYNSTRING, 0, 0 }, { 'q', 0, 4, etSQLESCAPE, 0, 0 }, { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, diff --git a/src/sqlite.h.in b/src/sqlite.h.in index b6b56686e8..bd813a222b 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.238 2007/08/23 02:47:53 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.239 2007/08/24 03:51:34 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -339,10 +339,10 @@ int sqlite3_exec( #define SQLITE_OPEN_EXCLUSIVE 0x00000010 #define SQLITE_OPEN_MAIN_DB 0x00000100 #define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000300 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00000400 -#define SQLITE_OPEN_SUBJOURNAL 0x00000500 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00000600 +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000400 +#define SQLITE_OPEN_TEMP_JOURNAL 0x00000800 +#define SQLITE_OPEN_SUBJOURNAL 0x00001000 +#define SQLITE_OPEN_MASTER_JOURNAL 0x00002000 /* ** CAPI3REF: Device Characteristics @@ -424,7 +424,7 @@ int sqlite3_exec( */ typedef struct sqlite3_file sqlite3_file; struct sqlite3_file { - struct sqlite3_io_methods *pMethods; /* Methods against the open file */ + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ }; /* @@ -552,10 +552,10 @@ typedef struct sqlite3_mutex sqlite3_mutex; ** nRef transitions from 1 to 0. ** ** Registered vfs modules are kept on a linked list formed by -** the pNext and pPrev pointers. The [sqlite3_register_vfs()] +** the pNext pointer. The [sqlite3_register_vfs()] ** and [sqlite3_unregister_vfs()] interfaces manage this list -** in a thread-safe way. The [sqlite3_acquire_vfs()] searches the -** list. +** in a thread-safe way. The [sqlite3_find_vfs()] interface +** searches the list. ** ** The zName field holds the name of the VFS module. The name must ** be unique across all VFS modules. @@ -644,19 +644,19 @@ struct sqlite3_vfs { sqlite3_vfs *pNext; /* Next registered VFS */ const char *zName; /* Name of this virtual file system */ void *pAppData; /* Application context */ - int (*xOpen)(void *pAppData, const char *zName, sqlite3_file*, + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, int flags, int *pOutFlags); - int (*xDelete)(void *pAppData, const char *zName, int syncDir); - 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, const char *zFilename); - void (*xDlError)(void *pAppData, int nByte, char *zErrMsg); - void *(*xDlSym)(void*, const char *zSymbol); - void (*xDlClose)(void*); - int (*xRandomness)(void *pAppData, int nByte, char *zOut); - int (*xSleep)(void *pAppData, int microseconds); - int (*xCurrentTime)(void *pAppData, double*); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); + int (*xGetTempName)(sqlite3_vfs*, char *zOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); /* New fields may be appended in figure versions. The iVersion ** value will increment whenever this happens. */ }; @@ -997,7 +997,7 @@ void sqlite3_free_table(char **result); ** These routines all implement some additional formatting ** options that are useful for constructing SQL statements. ** All of the usual printf formatting options apply. In addition, there -** is are "%q" and "%Q" options. +** is are "%q", "%Q", and "%z" options. ** ** The %q option works like %s in that it substitutes a null-terminated ** string from the argument list. But %q also doubles every '\'' character. @@ -1050,6 +1050,10 @@ void sqlite3_free_table(char **result); ** ** The code above will render a correct SQL statement in the zSQL ** variable even if the zText variable is a NULL pointer. +** +** The "%z" formatting option works exactly like "%s" with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string. */ char *sqlite3_mprintf(const char*,...); char *sqlite3_vmprintf(const char*, va_list); @@ -1092,8 +1096,8 @@ void sqlite3_free(void*); ** are provided by the default memory subsystem for diagnostic ** purposes. */ -sqlite3_uint64 sqlite3_memory_used(void); -sqlite3_uint64 sqlite3_memory_highwater(int resetFlag); +sqlite3_int64 sqlite3_memory_used(void); +sqlite3_int64 sqlite3_memory_highwater(int resetFlag); /* ** CAPI3REF: Memory Allocation Alarms @@ -1124,9 +1128,9 @@ sqlite3_uint64 sqlite3_memory_highwater(int resetFlag); ** [sqlite3_soft_heap_limit()] module. */ int sqlite3_memory_alarm( - void(*xCallback)(void *pArg, sqlite3_uint64 used, unsigned int N), + void(*xCallback)(void *pArg, sqlite3_int64 used, int N), void *pArg, - sqlite3_uint64 iThreshold + sqlite3_int64 iThreshold ); diff --git a/src/test6.c b/src/test6.c index 902a1efa3f..90bdba1f9b 100644 --- a/src/test6.c +++ b/src/test6.c @@ -678,7 +678,7 @@ static int crashParamsObjCmd( ){ int iDelay; const char *zCrashFile; - int nCrashFile; + int nCrashFile, iDc, iSectorSize; static sqlite3_vfs crashVfs = { 1, /* iVersion */ @@ -704,6 +704,7 @@ static int crashParamsObjCmd( cfCurrentTime /* xCurrentTime */ }; + if( crashVfs.pAppData==0 ){ sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0); crashVfs.xDlError = pOriginalVfs->xDlError; @@ -717,8 +718,8 @@ static int crashParamsObjCmd( sqlite3_vfs_register(&crashVfs, 1); } - int iDc = -1; - int iSectorSize = -1; + iDc = -1; + iSectorSize = -1; if( objc<3 ){ Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE"); diff --git a/src/test_malloc.c b/src/test_malloc.c index 3952882295..d09f3e8993 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -13,7 +13,7 @@ ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** -** $Id: test_malloc.c,v 1.4 2007/08/23 02:47:53 drh Exp $ +** $Id: test_malloc.c,v 1.5 2007/08/24 03:51:34 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -287,25 +287,6 @@ static int test_memdebug_fail( } -/* -** Usage: sqlite3_memdebug_pending -** -** Return the number of successful mallocs remaining before the -** next simulated failure. Return -1 if no simulated failure is -** currently scheduled. -*/ -static int test_memdebug_pending( - void * clientData, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - extern int sqlite3_memdebug_pending(void); - Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_pending())); - return TCL_OK; -} - - /* ** Usage: sqlite3_memdebug_settitle TITLE ** @@ -354,7 +335,6 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){ { "sqlite3_memdebug_backtrace", test_memdebug_backtrace }, { "sqlite3_memdebug_dump", test_memdebug_dump }, { "sqlite3_memdebug_fail", test_memdebug_fail }, - { "sqlite3_memdebug_pending", test_memdebug_pending }, { "sqlite3_memdebug_settitle", test_memdebug_settitle }, }; int i; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index fc7fc73f56..1ad103e821 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -702,9 +702,9 @@ static const void *columnName( n = sqlite3_column_count(pStmt); if( N=0 ){ N += useType*n; + sqlite3_mutex_enter(p->db->mutex); ret = xFunc(&p->aColName[N]); -#if 0 /* A malloc may have failed inside of the xFunc() call. If this ** is the case, clear the mallocFailed flag and return NULL. */ @@ -712,7 +712,7 @@ static const void *columnName( p->db->mallocFailed = 0; ret = 0; } -#endif + sqlite3_mutex_leave(p->db->mutex); } } return ret; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index ff93ac5298..b133f44e21 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1007,7 +1007,6 @@ static void Cleanup(Vdbe *p){ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ Mem *pColName; int n; - sqlite3 *db = p->db; releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); sqlite3_free(p->aColName); @@ -1017,7 +1016,7 @@ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ if( p->aColName==0 ) return; while( n-- > 0 ){ pColName->flags = MEM_Null; - pColName->db = db; + pColName->db = p->db; pColName++; } } diff --git a/src/vtab.c b/src/vtab.c index 09793aef75..70d7efc17e 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to help implement virtual tables. ** -** $Id: vtab.c,v 1.53 2007/08/23 02:47:53 drh Exp $ +** $Id: vtab.c,v 1.54 2007/08/24 03:51:34 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" @@ -24,10 +24,11 @@ static int createModule( void (*xDestroy)(void *) /* Module destructor function */ ) { int rc, nName; + Module *pMod; sqlite3_mutex_enter(db->mutex); nName = strlen(zName); - Module *pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); + pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); if( pMod ){ char *zCopy = (char *)(&pMod[1]); memcpy(zCopy, zName, nName+1); diff --git a/test/diskfull.test b/test/diskfull.test index d81a5e72f3..0983fecde3 100644 --- a/test/diskfull.test +++ b/test/diskfull.test @@ -12,7 +12,7 @@ # focus of this file is testing for correct handling of disk full # errors. # -# $Id: diskfull.test,v 1.6 2007/04/05 17:15:53 danielk1977 Exp $ +# $Id: diskfull.test,v 1.7 2007/08/24 03:51:34 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -113,4 +113,3 @@ do_diskfull_test diskfull-2 VACUUM # } finish_test -