| OLD | NEW |
| 1 /* | 1 /* |
| 2 ** 2005 November 29 | 2 ** 2005 November 29 |
| 3 ** | 3 ** |
| 4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
| 5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
| 6 ** | 6 ** |
| 7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
| 8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
| 9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
| 10 ** | 10 ** |
| 11 ****************************************************************************** | 11 ****************************************************************************** |
| 12 ** | 12 ** |
| 13 ** This file contains OS interface code that is common to all | 13 ** This file contains OS interface code that is common to all |
| 14 ** architectures. | 14 ** architectures. |
| 15 */ | 15 */ |
| 16 #define _SQLITE_OS_C_ 1 | |
| 17 #include "sqliteInt.h" | 16 #include "sqliteInt.h" |
| 18 #undef _SQLITE_OS_C_ | 17 |
| 18 /* |
| 19 ** If we compile with the SQLITE_TEST macro set, then the following block |
| 20 ** of code will give us the ability to simulate a disk I/O error. This |
| 21 ** is used for testing the I/O recovery logic. |
| 22 */ |
| 23 #if defined(SQLITE_TEST) |
| 24 int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */ |
| 25 int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */ |
| 26 int sqlite3_io_error_pending = 0; /* Count down to first I/O error */ |
| 27 int sqlite3_io_error_persist = 0; /* True if I/O errors persist */ |
| 28 int sqlite3_io_error_benign = 0; /* True if errors are benign */ |
| 29 int sqlite3_diskfull_pending = 0; |
| 30 int sqlite3_diskfull = 0; |
| 31 #endif /* defined(SQLITE_TEST) */ |
| 32 |
| 33 /* |
| 34 ** When testing, also keep a count of the number of open files. |
| 35 */ |
| 36 #if defined(SQLITE_TEST) |
| 37 int sqlite3_open_file_count = 0; |
| 38 #endif /* defined(SQLITE_TEST) */ |
| 19 | 39 |
| 20 /* | 40 /* |
| 21 ** The default SQLite sqlite3_vfs implementations do not allocate | 41 ** The default SQLite sqlite3_vfs implementations do not allocate |
| 22 ** memory (actually, os_unix.c allocates a small amount of memory | 42 ** memory (actually, os_unix.c allocates a small amount of memory |
| 23 ** from within OsOpen()), but some third-party implementations may. | 43 ** from within OsOpen()), but some third-party implementations may. |
| 24 ** So we test the effects of a malloc() failing and the sqlite3OsXXX() | 44 ** So we test the effects of a malloc() failing and the sqlite3OsXXX() |
| 25 ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. | 45 ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. |
| 26 ** | 46 ** |
| 27 ** The following functions are instrumented for malloc() failure | 47 ** The following functions are instrumented for malloc() failure |
| 28 ** testing: | 48 ** testing: |
| 29 ** | 49 ** |
| 30 ** sqlite3OsRead() | 50 ** sqlite3OsRead() |
| 31 ** sqlite3OsWrite() | 51 ** sqlite3OsWrite() |
| 32 ** sqlite3OsSync() | 52 ** sqlite3OsSync() |
| 33 ** sqlite3OsFileSize() | 53 ** sqlite3OsFileSize() |
| 34 ** sqlite3OsLock() | 54 ** sqlite3OsLock() |
| 35 ** sqlite3OsCheckReservedLock() | 55 ** sqlite3OsCheckReservedLock() |
| 36 ** sqlite3OsFileControl() | 56 ** sqlite3OsFileControl() |
| 37 ** sqlite3OsShmMap() | 57 ** sqlite3OsShmMap() |
| 38 ** sqlite3OsOpen() | 58 ** sqlite3OsOpen() |
| 39 ** sqlite3OsDelete() | 59 ** sqlite3OsDelete() |
| 40 ** sqlite3OsAccess() | 60 ** sqlite3OsAccess() |
| 41 ** sqlite3OsFullPathname() | 61 ** sqlite3OsFullPathname() |
| 42 ** | 62 ** |
| 43 */ | 63 */ |
| 44 #if defined(SQLITE_TEST) | 64 #if defined(SQLITE_TEST) |
| 45 int sqlite3_memdebug_vfs_oom_test = 1; | 65 int sqlite3_memdebug_vfs_oom_test = 1; |
| 46 #define DO_OS_MALLOC_TEST(x) \ | 66 #define DO_OS_MALLOC_TEST(x) \ |
| 47 if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \ | 67 if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \ |
| 48 void *pTstAlloc = sqlite3Malloc(10); \ | 68 void *pTstAlloc = sqlite3Malloc(10); \ |
| 49 if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ | 69 if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \ |
| 50 sqlite3_free(pTstAlloc); \ | 70 sqlite3_free(pTstAlloc); \ |
| 51 } | 71 } |
| 52 #else | 72 #else |
| 53 #define DO_OS_MALLOC_TEST(x) | 73 #define DO_OS_MALLOC_TEST(x) |
| 54 #endif | 74 #endif |
| 55 | 75 |
| 56 /* | 76 /* |
| 57 ** The following routines are convenience wrappers around methods | 77 ** The following routines are convenience wrappers around methods |
| 58 ** of the sqlite3_file object. This is mostly just syntactic sugar. All | 78 ** of the sqlite3_file object. This is mostly just syntactic sugar. All |
| 59 ** of this would be completely automatic if SQLite were coded using | 79 ** of this would be completely automatic if SQLite were coded using |
| 60 ** C++ instead of plain old C. | 80 ** C++ instead of plain old C. |
| 61 */ | 81 */ |
| 62 int sqlite3OsClose(sqlite3_file *pId){ | 82 void sqlite3OsClose(sqlite3_file *pId){ |
| 63 int rc = SQLITE_OK; | |
| 64 if( pId->pMethods ){ | 83 if( pId->pMethods ){ |
| 65 rc = pId->pMethods->xClose(pId); | 84 pId->pMethods->xClose(pId); |
| 66 pId->pMethods = 0; | 85 pId->pMethods = 0; |
| 67 } | 86 } |
| 68 return rc; | |
| 69 } | 87 } |
| 70 int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ | 88 int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ |
| 71 DO_OS_MALLOC_TEST(id); | 89 DO_OS_MALLOC_TEST(id); |
| 72 return id->pMethods->xRead(id, pBuf, amt, offset); | 90 return id->pMethods->xRead(id, pBuf, amt, offset); |
| 73 } | 91 } |
| 74 int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ | 92 int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ |
| 75 DO_OS_MALLOC_TEST(id); | 93 DO_OS_MALLOC_TEST(id); |
| 76 return id->pMethods->xWrite(id, pBuf, amt, offset); | 94 return id->pMethods->xWrite(id, pBuf, amt, offset); |
| 77 } | 95 } |
| 78 int sqlite3OsTruncate(sqlite3_file *id, i64 size){ | 96 int sqlite3OsTruncate(sqlite3_file *id, i64 size){ |
| (...skipping 24 matching lines...) Expand all Loading... |
| 103 ** and we need to know about the failures. Use sqlite3OsFileControlHint() | 121 ** and we need to know about the failures. Use sqlite3OsFileControlHint() |
| 104 ** when simply tossing information over the wall to the VFS and we do not | 122 ** when simply tossing information over the wall to the VFS and we do not |
| 105 ** really care if the VFS receives and understands the information since it | 123 ** really care if the VFS receives and understands the information since it |
| 106 ** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() | 124 ** is only a hint and can be safely ignored. The sqlite3OsFileControlHint() |
| 107 ** routine has no return value since the return value would be meaningless. | 125 ** routine has no return value since the return value would be meaningless. |
| 108 */ | 126 */ |
| 109 int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ | 127 int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ |
| 110 #ifdef SQLITE_TEST | 128 #ifdef SQLITE_TEST |
| 111 if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ | 129 if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ |
| 112 /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite | 130 /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite |
| 113 ** is using a regular VFS, it is called after the corresponding | 131 ** is using a regular VFS, it is called after the corresponding |
| 114 ** transaction has been committed. Injecting a fault at this point | 132 ** transaction has been committed. Injecting a fault at this point |
| 115 ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM | 133 ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM |
| 116 ** but the transaction is committed anyway. | 134 ** but the transaction is committed anyway. |
| 117 ** | 135 ** |
| 118 ** The core must call OsFileControl() though, not OsFileControlHint(), | 136 ** The core must call OsFileControl() though, not OsFileControlHint(), |
| 119 ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably | 137 ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably |
| 120 ** means the commit really has failed and an error should be returned | 138 ** means the commit really has failed and an error should be returned |
| 121 ** to the user. */ | 139 ** to the user. */ |
| 122 DO_OS_MALLOC_TEST(id); | 140 DO_OS_MALLOC_TEST(id); |
| 123 } | 141 } |
| 124 #endif | 142 #endif |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ | 191 int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){ |
| 174 return SQLITE_OK; | 192 return SQLITE_OK; |
| 175 } | 193 } |
| 176 #endif | 194 #endif |
| 177 | 195 |
| 178 /* | 196 /* |
| 179 ** The next group of routines are convenience wrappers around the | 197 ** The next group of routines are convenience wrappers around the |
| 180 ** VFS methods. | 198 ** VFS methods. |
| 181 */ | 199 */ |
| 182 int sqlite3OsOpen( | 200 int sqlite3OsOpen( |
| 183 sqlite3_vfs *pVfs, | 201 sqlite3_vfs *pVfs, |
| 184 const char *zPath, | 202 const char *zPath, |
| 185 sqlite3_file *pFile, | 203 sqlite3_file *pFile, |
| 186 int flags, | 204 int flags, |
| 187 int *pFlagsOut | 205 int *pFlagsOut |
| 188 ){ | 206 ){ |
| 189 int rc; | 207 int rc; |
| 190 DO_OS_MALLOC_TEST(0); | 208 DO_OS_MALLOC_TEST(0); |
| 191 /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed | 209 /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed |
| 192 ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, | 210 ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example, |
| 193 ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before | 211 ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before |
| 194 ** reaching the VFS. */ | 212 ** reaching the VFS. */ |
| 195 rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut); | 213 rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut); |
| 196 assert( rc==SQLITE_OK || pFile->pMethods==0 ); | 214 assert( rc==SQLITE_OK || pFile->pMethods==0 ); |
| 197 return rc; | 215 return rc; |
| 198 } | 216 } |
| 199 int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ | 217 int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ |
| 200 DO_OS_MALLOC_TEST(0); | 218 DO_OS_MALLOC_TEST(0); |
| 201 assert( dirSync==0 || dirSync==1 ); | 219 assert( dirSync==0 || dirSync==1 ); |
| 202 return pVfs->xDelete(pVfs, zPath, dirSync); | 220 return pVfs->xDelete(pVfs, zPath, dirSync); |
| 203 } | 221 } |
| 204 int sqlite3OsAccess( | 222 int sqlite3OsAccess( |
| 205 sqlite3_vfs *pVfs, | 223 sqlite3_vfs *pVfs, |
| 206 const char *zPath, | 224 const char *zPath, |
| 207 int flags, | 225 int flags, |
| 208 int *pResOut | 226 int *pResOut |
| 209 ){ | 227 ){ |
| 210 DO_OS_MALLOC_TEST(0); | 228 DO_OS_MALLOC_TEST(0); |
| 211 return pVfs->xAccess(pVfs, zPath, flags, pResOut); | 229 return pVfs->xAccess(pVfs, zPath, flags, pResOut); |
| 212 } | 230 } |
| 213 int sqlite3OsFullPathname( | 231 int sqlite3OsFullPathname( |
| 214 sqlite3_vfs *pVfs, | 232 sqlite3_vfs *pVfs, |
| 215 const char *zPath, | 233 const char *zPath, |
| 216 int nPathOut, | 234 int nPathOut, |
| 217 char *zPathOut | 235 char *zPathOut |
| 218 ){ | 236 ){ |
| 219 DO_OS_MALLOC_TEST(0); | 237 DO_OS_MALLOC_TEST(0); |
| 220 zPathOut[0] = 0; | 238 zPathOut[0] = 0; |
| 221 return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); | 239 return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); |
| 222 } | 240 } |
| 223 #ifndef SQLITE_OMIT_LOAD_EXTENSION | 241 #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| 224 void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ | 242 void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ |
| 225 return pVfs->xDlOpen(pVfs, zPath); | 243 return pVfs->xDlOpen(pVfs, zPath); |
| 226 } | 244 } |
| 227 void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ | 245 void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ |
| 228 pVfs->xDlError(pVfs, nByte, zBufOut); | 246 pVfs->xDlError(pVfs, nByte, zBufOut); |
| 229 } | 247 } |
| 230 void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ | 248 void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ |
| 231 return pVfs->xDlSym(pVfs, pHdle, zSym); | 249 return pVfs->xDlSym(pVfs, pHdle, zSym); |
| 232 } | 250 } |
| 233 void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ | 251 void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ |
| 234 pVfs->xDlClose(pVfs, pHandle); | 252 pVfs->xDlClose(pVfs, pHandle); |
| 235 } | 253 } |
| 236 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ | 254 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ |
| 237 int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ | 255 int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ |
| 238 return pVfs->xRandomness(pVfs, nByte, zBufOut); | 256 return pVfs->xRandomness(pVfs, nByte, zBufOut); |
| 239 } | 257 } |
| 240 int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ | 258 int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ |
| 241 return pVfs->xSleep(pVfs, nMicro); | 259 return pVfs->xSleep(pVfs, nMicro); |
| 242 } | 260 } |
| 261 int sqlite3OsGetLastError(sqlite3_vfs *pVfs){ |
| 262 return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0; |
| 263 } |
| 243 int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ | 264 int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){ |
| 244 int rc; | 265 int rc; |
| 245 /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64() | 266 /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64() |
| 246 ** method to get the current date and time if that method is available | 267 ** method to get the current date and time if that method is available |
| 247 ** (if iVersion is 2 or greater and the function pointer is not NULL) and | 268 ** (if iVersion is 2 or greater and the function pointer is not NULL) and |
| 248 ** will fall back to xCurrentTime() if xCurrentTimeInt64() is | 269 ** will fall back to xCurrentTime() if xCurrentTimeInt64() is |
| 249 ** unavailable. | 270 ** unavailable. |
| 250 */ | 271 */ |
| 251 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ | 272 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){ |
| 252 rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut); | 273 rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut); |
| 253 }else{ | 274 }else{ |
| 254 double r; | 275 double r; |
| 255 rc = pVfs->xCurrentTime(pVfs, &r); | 276 rc = pVfs->xCurrentTime(pVfs, &r); |
| 256 *pTimeOut = (sqlite3_int64)(r*86400000.0); | 277 *pTimeOut = (sqlite3_int64)(r*86400000.0); |
| 257 } | 278 } |
| 258 return rc; | 279 return rc; |
| 259 } | 280 } |
| 260 | 281 |
| 261 int sqlite3OsOpenMalloc( | 282 int sqlite3OsOpenMalloc( |
| 262 sqlite3_vfs *pVfs, | 283 sqlite3_vfs *pVfs, |
| 263 const char *zFile, | 284 const char *zFile, |
| 264 sqlite3_file **ppFile, | 285 sqlite3_file **ppFile, |
| 265 int flags, | 286 int flags, |
| 266 int *pOutFlags | 287 int *pOutFlags |
| 267 ){ | 288 ){ |
| 268 int rc = SQLITE_NOMEM; | 289 int rc; |
| 269 sqlite3_file *pFile; | 290 sqlite3_file *pFile; |
| 270 pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile); | 291 pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile); |
| 271 if( pFile ){ | 292 if( pFile ){ |
| 272 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); | 293 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); |
| 273 if( rc!=SQLITE_OK ){ | 294 if( rc!=SQLITE_OK ){ |
| 274 sqlite3_free(pFile); | 295 sqlite3_free(pFile); |
| 275 }else{ | 296 }else{ |
| 276 *ppFile = pFile; | 297 *ppFile = pFile; |
| 277 } | 298 } |
| 299 }else{ |
| 300 rc = SQLITE_NOMEM_BKPT; |
| 278 } | 301 } |
| 279 return rc; | 302 return rc; |
| 280 } | 303 } |
| 281 int sqlite3OsCloseFree(sqlite3_file *pFile){ | 304 void sqlite3OsCloseFree(sqlite3_file *pFile){ |
| 282 int rc = SQLITE_OK; | |
| 283 assert( pFile ); | 305 assert( pFile ); |
| 284 rc = sqlite3OsClose(pFile); | 306 sqlite3OsClose(pFile); |
| 285 sqlite3_free(pFile); | 307 sqlite3_free(pFile); |
| 286 return rc; | |
| 287 } | 308 } |
| 288 | 309 |
| 289 /* | 310 /* |
| 290 ** This function is a wrapper around the OS specific implementation of | 311 ** This function is a wrapper around the OS specific implementation of |
| 291 ** sqlite3_os_init(). The purpose of the wrapper is to provide the | 312 ** sqlite3_os_init(). The purpose of the wrapper is to provide the |
| 292 ** ability to simulate a malloc failure, so that the handling of an | 313 ** ability to simulate a malloc failure, so that the handling of an |
| 293 ** error in sqlite3_os_init() by the upper layers can be tested. | 314 ** error in sqlite3_os_init() by the upper layers can be tested. |
| 294 */ | 315 */ |
| 295 int sqlite3OsInit(void){ | 316 int sqlite3OsInit(void){ |
| 296 void *p = sqlite3_malloc(10); | 317 void *p = sqlite3_malloc(10); |
| 297 if( p==0 ) return SQLITE_NOMEM; | 318 if( p==0 ) return SQLITE_NOMEM_BKPT; |
| 298 sqlite3_free(p); | 319 sqlite3_free(p); |
| 299 return sqlite3_os_init(); | 320 return sqlite3_os_init(); |
| 300 } | 321 } |
| 301 | 322 |
| 302 /* | 323 /* |
| 303 ** The list of all registered VFS implementations. | 324 ** The list of all registered VFS implementations. |
| 304 */ | 325 */ |
| 305 static sqlite3_vfs * SQLITE_WSD vfsList = 0; | 326 static sqlite3_vfs * SQLITE_WSD vfsList = 0; |
| 306 #define vfsList GLOBAL(sqlite3_vfs *, vfsList) | 327 #define vfsList GLOBAL(sqlite3_vfs *, vfsList) |
| 307 | 328 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 */ | 406 */ |
| 386 int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ | 407 int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ |
| 387 #if SQLITE_THREADSAFE | 408 #if SQLITE_THREADSAFE |
| 388 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); | 409 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); |
| 389 #endif | 410 #endif |
| 390 sqlite3_mutex_enter(mutex); | 411 sqlite3_mutex_enter(mutex); |
| 391 vfsUnlink(pVfs); | 412 vfsUnlink(pVfs); |
| 392 sqlite3_mutex_leave(mutex); | 413 sqlite3_mutex_leave(mutex); |
| 393 return SQLITE_OK; | 414 return SQLITE_OK; |
| 394 } | 415 } |
| OLD | NEW |