blob: 2fd44abf855ad1ea826f52357072f4b3808c4140 [file] [log] [blame]
danielk1977a7a8e142008-02-13 18:25:27 +00001/*
drh054889e2005-11-30 03:20:31 +00002** 2005 November 29
3**
4** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
6**
7** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
10**
11******************************************************************************
12**
13** This file contains OS interface code that is common to all
14** architectures.
15*/
drh3f459022006-01-07 16:06:07 +000016#define _SQLITE_OS_C_ 1
drh054889e2005-11-30 03:20:31 +000017#include "sqliteInt.h"
drhbd08af42007-04-05 21:58:33 +000018#undef _SQLITE_OS_C_
drh054889e2005-11-30 03:20:31 +000019
20/*
mistachkinc04c54b2016-02-11 21:28:16 +000021** If we compile with the SQLITE_TEST macro set, then the following block
22** of code will give us the ability to simulate a disk I/O error. This
23** is used for testing the I/O recovery logic.
24*/
25#if defined(SQLITE_TEST)
26int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
27int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
28int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
29int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
30int sqlite3_io_error_benign = 0; /* True if errors are benign */
31int sqlite3_diskfull_pending = 0;
32int sqlite3_diskfull = 0;
33#endif /* defined(SQLITE_TEST) */
34
35/*
36** When testing, also keep a count of the number of open files.
37*/
38#if defined(SQLITE_TEST)
39int sqlite3_open_file_count = 0;
40#endif /* defined(SQLITE_TEST) */
41
42/*
danielk1977ae72d982007-10-03 08:46:44 +000043** The default SQLite sqlite3_vfs implementations do not allocate
44** memory (actually, os_unix.c allocates a small amount of memory
45** from within OsOpen()), but some third-party implementations may.
46** So we test the effects of a malloc() failing and the sqlite3OsXXX()
47** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
48**
mistachkinc04c54b2016-02-11 21:28:16 +000049** The following functions are instrumented for malloc() failure
danielk1977ae72d982007-10-03 08:46:44 +000050** testing:
51**
danielk1977ae72d982007-10-03 08:46:44 +000052** sqlite3OsRead()
53** sqlite3OsWrite()
54** sqlite3OsSync()
mistachkin6c3c1a02011-11-12 03:17:40 +000055** sqlite3OsFileSize()
danielk1977ae72d982007-10-03 08:46:44 +000056** sqlite3OsLock()
mistachkin6c3c1a02011-11-12 03:17:40 +000057** sqlite3OsCheckReservedLock()
58** sqlite3OsFileControl()
59** sqlite3OsShmMap()
60** sqlite3OsOpen()
61** sqlite3OsDelete()
62** sqlite3OsAccess()
63** sqlite3OsFullPathname()
danielk1977ae72d982007-10-03 08:46:44 +000064**
65*/
shanehfd286392010-07-02 19:49:38 +000066#if defined(SQLITE_TEST)
danc396d4a2010-07-02 11:27:43 +000067int sqlite3_memdebug_vfs_oom_test = 1;
68 #define DO_OS_MALLOC_TEST(x) \
69 if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3IsMemJournal(x))) { \
danielk1977b5a19202009-07-27 11:41:20 +000070 void *pTstAlloc = sqlite3Malloc(10); \
mistachkinfad30392016-02-13 23:43:46 +000071 if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \
danielk1977b5a19202009-07-27 11:41:20 +000072 sqlite3_free(pTstAlloc); \
danielk1977ae72d982007-10-03 08:46:44 +000073 }
74#else
danielk1977b5a19202009-07-27 11:41:20 +000075 #define DO_OS_MALLOC_TEST(x)
danielk1977ae72d982007-10-03 08:46:44 +000076#endif
77
78/*
drh054889e2005-11-30 03:20:31 +000079** The following routines are convenience wrappers around methods
danielk197762079062007-08-15 17:08:46 +000080** of the sqlite3_file object. This is mostly just syntactic sugar. All
drh054889e2005-11-30 03:20:31 +000081** of this would be completely automatic if SQLite were coded using
82** C++ instead of plain old C.
83*/
danielk1977b4b47412007-08-17 15:53:36 +000084int sqlite3OsClose(sqlite3_file *pId){
danielk1977c7b60172007-08-22 11:22:03 +000085 int rc = SQLITE_OK;
86 if( pId->pMethods ){
87 rc = pId->pMethods->xClose(pId);
88 pId->pMethods = 0;
89 }
90 return rc;
drh054889e2005-11-30 03:20:31 +000091}
danielk197762079062007-08-15 17:08:46 +000092int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
danielk1977b5a19202009-07-27 11:41:20 +000093 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +000094 return id->pMethods->xRead(id, pBuf, amt, offset);
drh054889e2005-11-30 03:20:31 +000095}
danielk197762079062007-08-15 17:08:46 +000096int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
danielk1977b5a19202009-07-27 11:41:20 +000097 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +000098 return id->pMethods->xWrite(id, pBuf, amt, offset);
drh054889e2005-11-30 03:20:31 +000099}
danielk197762079062007-08-15 17:08:46 +0000100int sqlite3OsTruncate(sqlite3_file *id, i64 size){
101 return id->pMethods->xTruncate(id, size);
drh054889e2005-11-30 03:20:31 +0000102}
danielk197790949c22007-08-17 16:50:38 +0000103int sqlite3OsSync(sqlite3_file *id, int flags){
danielk1977b5a19202009-07-27 11:41:20 +0000104 DO_OS_MALLOC_TEST(id);
danielk197790949c22007-08-17 16:50:38 +0000105 return id->pMethods->xSync(id, flags);
drh054889e2005-11-30 03:20:31 +0000106}
danielk197762079062007-08-15 17:08:46 +0000107int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
danielk1977b5a19202009-07-27 11:41:20 +0000108 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +0000109 return id->pMethods->xFileSize(id, pSize);
drh054889e2005-11-30 03:20:31 +0000110}
danielk197762079062007-08-15 17:08:46 +0000111int sqlite3OsLock(sqlite3_file *id, int lockType){
danielk1977b5a19202009-07-27 11:41:20 +0000112 DO_OS_MALLOC_TEST(id);
danielk197762079062007-08-15 17:08:46 +0000113 return id->pMethods->xLock(id, lockType);
drh054889e2005-11-30 03:20:31 +0000114}
danielk197762079062007-08-15 17:08:46 +0000115int sqlite3OsUnlock(sqlite3_file *id, int lockType){
116 return id->pMethods->xUnlock(id, lockType);
drh054889e2005-11-30 03:20:31 +0000117}
danielk1977861f7452008-06-05 11:39:11 +0000118int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
danielk1977b5a19202009-07-27 11:41:20 +0000119 DO_OS_MALLOC_TEST(id);
danielk1977861f7452008-06-05 11:39:11 +0000120 return id->pMethods->xCheckReservedLock(id, pResOut);
drh054889e2005-11-30 03:20:31 +0000121}
drhc02372c2012-01-10 17:59:59 +0000122
123/*
124** Use sqlite3OsFileControl() when we are doing something that might fail
125** and we need to know about the failures. Use sqlite3OsFileControlHint()
126** when simply tossing information over the wall to the VFS and we do not
127** really care if the VFS receives and understands the information since it
128** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
129** routine has no return value since the return value would be meaningless.
130*/
drhcc6bb3e2007-08-31 16:11:35 +0000131int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
dan1001ee82013-12-19 17:04:58 +0000132#ifdef SQLITE_TEST
133 if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){
134 /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
mistachkinc04c54b2016-02-11 21:28:16 +0000135 ** is using a regular VFS, it is called after the corresponding
136 ** transaction has been committed. Injecting a fault at this point
dan1001ee82013-12-19 17:04:58 +0000137 ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
138 ** but the transaction is committed anyway.
139 **
140 ** The core must call OsFileControl() though, not OsFileControlHint(),
141 ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
142 ** means the commit really has failed and an error should be returned
143 ** to the user. */
144 DO_OS_MALLOC_TEST(id);
145 }
146#endif
danielk1977861f7452008-06-05 11:39:11 +0000147 return id->pMethods->xFileControl(id, op, pArg);
drhcc6bb3e2007-08-31 16:11:35 +0000148}
drhc02372c2012-01-10 17:59:59 +0000149void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
150 (void)id->pMethods->xFileControl(id, op, pArg);
dan6f2f19a2012-01-10 16:56:39 +0000151}
drhc02372c2012-01-10 17:59:59 +0000152
danielk1977bf260972008-01-22 11:50:13 +0000153int sqlite3OsSectorSize(sqlite3_file *id){
154 int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
155 return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
156}
157int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
158 return id->pMethods->xDeviceCharacteristics(id);
159}
drh73b64e42010-05-30 19:55:15 +0000160int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
161 return id->pMethods->xShmLock(id, offset, n, flags);
drhd9e5c4f2010-05-12 18:01:39 +0000162}
drh286a2882010-05-20 23:51:06 +0000163void sqlite3OsShmBarrier(sqlite3_file *id){
164 id->pMethods->xShmBarrier(id);
165}
drhe11fedc2010-07-14 00:14:30 +0000166int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
danda9fe0c2010-07-13 18:44:03 +0000167 return id->pMethods->xShmUnmap(id, deleteFlag);
drhd9e5c4f2010-05-12 18:01:39 +0000168}
dan18801912010-06-14 14:07:50 +0000169int sqlite3OsShmMap(
danda9fe0c2010-07-13 18:44:03 +0000170 sqlite3_file *id, /* Database file handle */
171 int iPage,
172 int pgsz,
173 int bExtend, /* True to extend file if necessary */
174 void volatile **pp /* OUT: Pointer to mapping */
dan13a3cb82010-06-11 19:04:21 +0000175){
mistachkin6c3c1a02011-11-12 03:17:40 +0000176 DO_OS_MALLOC_TEST(id);
danda9fe0c2010-07-13 18:44:03 +0000177 return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
dan13a3cb82010-06-11 19:04:21 +0000178}
danf23da962013-03-23 21:00:41 +0000179
drh9b4c59f2013-04-15 17:03:42 +0000180#if SQLITE_MAX_MMAP_SIZE>0
drh188d4882013-04-08 20:47:49 +0000181/* The real implementation of xFetch and xUnfetch */
danf23da962013-03-23 21:00:41 +0000182int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
dana64d5a12013-03-25 18:25:49 +0000183 DO_OS_MALLOC_TEST(id);
danf23da962013-03-23 21:00:41 +0000184 return id->pMethods->xFetch(id, iOff, iAmt, pp);
185}
dandf737fe2013-03-25 17:00:24 +0000186int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
187 return id->pMethods->xUnfetch(id, iOff, p);
dan5d8a1372013-03-19 19:28:06 +0000188}
drh188d4882013-04-08 20:47:49 +0000189#else
190/* No-op stubs to use when memory-mapped I/O is disabled */
191int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
192 *pp = 0;
193 return SQLITE_OK;
194}
195int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
196 return SQLITE_OK;
197}
198#endif
drh3f459022006-01-07 16:06:07 +0000199
drhd677b3d2007-08-20 22:48:41 +0000200/*
201** The next group of routines are convenience wrappers around the
202** VFS methods.
203*/
danielk1977b4b47412007-08-17 15:53:36 +0000204int sqlite3OsOpen(
mistachkinc04c54b2016-02-11 21:28:16 +0000205 sqlite3_vfs *pVfs,
206 const char *zPath,
207 sqlite3_file *pFile,
208 int flags,
danielk1977b4b47412007-08-17 15:53:36 +0000209 int *pFlagsOut
210){
drh072db2f2009-03-25 14:24:41 +0000211 int rc;
danielk1977b5a19202009-07-27 11:41:20 +0000212 DO_OS_MALLOC_TEST(0);
dan44659c92011-12-30 05:08:41 +0000213 /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
drhf1f12682009-09-09 14:17:52 +0000214 ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
215 ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
216 ** reaching the VFS. */
drh877eeb32011-07-20 17:13:30 +0000217 rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
drh072db2f2009-03-25 14:24:41 +0000218 assert( rc==SQLITE_OK || pFile->pMethods==0 );
219 return rc;
drh3f459022006-01-07 16:06:07 +0000220}
danielk1977fee2d252007-08-18 10:59:19 +0000221int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
mistachkin6c3c1a02011-11-12 03:17:40 +0000222 DO_OS_MALLOC_TEST(0);
drhe3495192012-01-05 16:07:30 +0000223 assert( dirSync==0 || dirSync==1 );
drh153c62c2007-08-24 03:51:33 +0000224 return pVfs->xDelete(pVfs, zPath, dirSync);
danielk1977b4b47412007-08-17 15:53:36 +0000225}
danielk1977861f7452008-06-05 11:39:11 +0000226int sqlite3OsAccess(
mistachkinc04c54b2016-02-11 21:28:16 +0000227 sqlite3_vfs *pVfs,
228 const char *zPath,
229 int flags,
danielk1977861f7452008-06-05 11:39:11 +0000230 int *pResOut
231){
danielk1977b5a19202009-07-27 11:41:20 +0000232 DO_OS_MALLOC_TEST(0);
danielk1977861f7452008-06-05 11:39:11 +0000233 return pVfs->xAccess(pVfs, zPath, flags, pResOut);
danielk1977b4b47412007-08-17 15:53:36 +0000234}
danielk1977adfb9b02007-09-17 07:02:56 +0000235int sqlite3OsFullPathname(
mistachkinc04c54b2016-02-11 21:28:16 +0000236 sqlite3_vfs *pVfs,
237 const char *zPath,
238 int nPathOut,
danielk1977adfb9b02007-09-17 07:02:56 +0000239 char *zPathOut
240){
mistachkin6c3c1a02011-11-12 03:17:40 +0000241 DO_OS_MALLOC_TEST(0);
drh68ff78b2009-11-16 23:36:33 +0000242 zPathOut[0] = 0;
danielk1977adfb9b02007-09-17 07:02:56 +0000243 return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
danielk1977b4b47412007-08-17 15:53:36 +0000244}
shane75998ab2008-05-29 02:52:59 +0000245#ifndef SQLITE_OMIT_LOAD_EXTENSION
danielk1977b4b47412007-08-17 15:53:36 +0000246void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
drh153c62c2007-08-24 03:51:33 +0000247 return pVfs->xDlOpen(pVfs, zPath);
danielk1977b4b47412007-08-17 15:53:36 +0000248}
249void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
drh153c62c2007-08-24 03:51:33 +0000250 pVfs->xDlError(pVfs, nByte, zBufOut);
danielk1977b4b47412007-08-17 15:53:36 +0000251}
drh1875f7a2008-12-08 18:19:17 +0000252void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
253 return pVfs->xDlSym(pVfs, pHdle, zSym);
danielk1977b4b47412007-08-17 15:53:36 +0000254}
255void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
drh153c62c2007-08-24 03:51:33 +0000256 pVfs->xDlClose(pVfs, pHandle);
danielk1977b4b47412007-08-17 15:53:36 +0000257}
shane75998ab2008-05-29 02:52:59 +0000258#endif /* SQLITE_OMIT_LOAD_EXTENSION */
danielk1977b4b47412007-08-17 15:53:36 +0000259int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
drh153c62c2007-08-24 03:51:33 +0000260 return pVfs->xRandomness(pVfs, nByte, zBufOut);
danielk1977b4b47412007-08-17 15:53:36 +0000261}
262int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
drh153c62c2007-08-24 03:51:33 +0000263 return pVfs->xSleep(pVfs, nMicro);
danielk1977b4b47412007-08-17 15:53:36 +0000264}
drhb7e8ea22010-05-03 14:32:30 +0000265int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
266 int rc;
drhbfccdaf2010-09-01 19:29:57 +0000267 /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
268 ** method to get the current date and time if that method is available
269 ** (if iVersion is 2 or greater and the function pointer is not NULL) and
270 ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
271 ** unavailable.
272 */
drhb7e8ea22010-05-03 14:32:30 +0000273 if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
274 rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
275 }else{
276 double r;
277 rc = pVfs->xCurrentTime(pVfs, &r);
278 *pTimeOut = (sqlite3_int64)(r*86400000.0);
279 }
280 return rc;
danielk1977b4b47412007-08-17 15:53:36 +0000281}
282
283int sqlite3OsOpenMalloc(
mistachkinc04c54b2016-02-11 21:28:16 +0000284 sqlite3_vfs *pVfs,
285 const char *zFile,
286 sqlite3_file **ppFile,
danielk1977967a4a12007-08-20 14:23:44 +0000287 int flags,
288 int *pOutFlags
danielk1977b4b47412007-08-17 15:53:36 +0000289){
mistachkinfad30392016-02-13 23:43:46 +0000290 int rc;
danielk1977b4b47412007-08-17 15:53:36 +0000291 sqlite3_file *pFile;
mistachkinf1c40f42011-09-17 15:34:50 +0000292 pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
danielk1977b4b47412007-08-17 15:53:36 +0000293 if( pFile ){
danielk1977967a4a12007-08-20 14:23:44 +0000294 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
danielk1977b4b47412007-08-17 15:53:36 +0000295 if( rc!=SQLITE_OK ){
296 sqlite3_free(pFile);
297 }else{
298 *ppFile = pFile;
299 }
mistachkinfad30392016-02-13 23:43:46 +0000300 }else{
301 rc = SQLITE_NOMEM_BKPT;
danielk1977b4b47412007-08-17 15:53:36 +0000302 }
303 return rc;
304}
305int sqlite3OsCloseFree(sqlite3_file *pFile){
306 int rc = SQLITE_OK;
mlcreech40032982008-04-08 03:09:22 +0000307 assert( pFile );
308 rc = sqlite3OsClose(pFile);
309 sqlite3_free(pFile);
danielk1977b4b47412007-08-17 15:53:36 +0000310 return rc;
311}
312
drhd677b3d2007-08-20 22:48:41 +0000313/*
dan3d6e0602009-08-17 15:52:25 +0000314** This function is a wrapper around the OS specific implementation of
315** sqlite3_os_init(). The purpose of the wrapper is to provide the
316** ability to simulate a malloc failure, so that the handling of an
317** error in sqlite3_os_init() by the upper layers can be tested.
318*/
319int sqlite3OsInit(void){
drhadad77a2009-08-17 16:01:11 +0000320 void *p = sqlite3_malloc(10);
mistachkinfad30392016-02-13 23:43:46 +0000321 if( p==0 ) return SQLITE_NOMEM_BKPT;
drhadad77a2009-08-17 16:01:11 +0000322 sqlite3_free(p);
dan3d6e0602009-08-17 15:52:25 +0000323 return sqlite3_os_init();
324}
325
326/*
danielk1977c0fa4c52008-06-25 17:19:00 +0000327** The list of all registered VFS implementations.
drhd677b3d2007-08-20 22:48:41 +0000328*/
danielk197795e80d62008-09-02 17:18:51 +0000329static sqlite3_vfs * SQLITE_WSD vfsList = 0;
danielk19775c8f8582008-09-02 10:22:00 +0000330#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
drhd677b3d2007-08-20 22:48:41 +0000331
332/*
333** Locate a VFS by name. If no name is given, simply return the
334** first VFS on the list.
335*/
336sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
drha4189802008-06-19 16:07:07 +0000337 sqlite3_vfs *pVfs = 0;
drh18472fa2008-10-07 15:25:48 +0000338#if SQLITE_THREADSAFE
drh40257ff2008-06-13 18:24:27 +0000339 sqlite3_mutex *mutex;
340#endif
341#ifndef SQLITE_OMIT_AUTOINIT
342 int rc = sqlite3_initialize();
343 if( rc ) return 0;
344#endif
drh18472fa2008-10-07 15:25:48 +0000345#if SQLITE_THREADSAFE
danielk197759f8c082008-06-18 17:09:10 +0000346 mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
drh7e8b8482008-01-23 03:03:05 +0000347#endif
drhd677b3d2007-08-20 22:48:41 +0000348 sqlite3_mutex_enter(mutex);
349 for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
350 if( zVfs==0 ) break;
351 if( strcmp(zVfs, pVfs->zName)==0 ) break;
352 }
drhd677b3d2007-08-20 22:48:41 +0000353 sqlite3_mutex_leave(mutex);
354 return pVfs;
danielk1977b4b47412007-08-17 15:53:36 +0000355}
356
drhd677b3d2007-08-20 22:48:41 +0000357/*
drhd677b3d2007-08-20 22:48:41 +0000358** Unlink a VFS from the linked list
359*/
360static void vfsUnlink(sqlite3_vfs *pVfs){
danielk197759f8c082008-06-18 17:09:10 +0000361 assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
drh9bc54492007-10-23 14:49:59 +0000362 if( pVfs==0 ){
363 /* No-op */
364 }else if( vfsList==pVfs ){
drhd677b3d2007-08-20 22:48:41 +0000365 vfsList = pVfs->pNext;
drh9bc54492007-10-23 14:49:59 +0000366 }else if( vfsList ){
drhd677b3d2007-08-20 22:48:41 +0000367 sqlite3_vfs *p = vfsList;
368 while( p->pNext && p->pNext!=pVfs ){
369 p = p->pNext;
370 }
371 if( p->pNext==pVfs ){
372 p->pNext = pVfs->pNext;
373 }
374 }
375}
376
377/*
378** Register a VFS with the system. It is harmless to register the same
379** VFS multiple times. The new VFS becomes the default if makeDflt is
380** true.
381*/
382int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
drh30ddce62011-10-15 00:16:30 +0000383 MUTEX_LOGIC(sqlite3_mutex *mutex;)
drh40257ff2008-06-13 18:24:27 +0000384#ifndef SQLITE_OMIT_AUTOINIT
385 int rc = sqlite3_initialize();
386 if( rc ) return rc;
387#endif
drh9ca95732014-10-24 00:35:58 +0000388#ifdef SQLITE_ENABLE_API_ARMOR
389 if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
390#endif
391
drh30ddce62011-10-15 00:16:30 +0000392 MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
drhd677b3d2007-08-20 22:48:41 +0000393 sqlite3_mutex_enter(mutex);
394 vfsUnlink(pVfs);
395 if( makeDflt || vfsList==0 ){
396 pVfs->pNext = vfsList;
397 vfsList = pVfs;
398 }else{
399 pVfs->pNext = vfsList->pNext;
danielk197795c8a542007-09-01 06:51:27 +0000400 vfsList->pNext = pVfs;
drhd677b3d2007-08-20 22:48:41 +0000401 }
danielk1977f1da17a2007-08-21 13:07:46 +0000402 assert(vfsList);
drhd677b3d2007-08-20 22:48:41 +0000403 sqlite3_mutex_leave(mutex);
404 return SQLITE_OK;
405}
406
407/*
408** Unregister a VFS so that it is no longer accessible.
409*/
410int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
drh18472fa2008-10-07 15:25:48 +0000411#if SQLITE_THREADSAFE
danielk197759f8c082008-06-18 17:09:10 +0000412 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
drh7e8b8482008-01-23 03:03:05 +0000413#endif
drhd677b3d2007-08-20 22:48:41 +0000414 sqlite3_mutex_enter(mutex);
415 vfsUnlink(pVfs);
416 sqlite3_mutex_leave(mutex);
417 return SQLITE_OK;
418}