1054889ecSdrh /*
2054889ecSdrh ** 2005 November 29
3054889ecSdrh **
4054889ecSdrh ** The author disclaims copyright to this source code. In place of
5054889ecSdrh ** a legal notice, here is a blessing:
6054889ecSdrh **
7054889ecSdrh ** May you do good and not evil.
8054889ecSdrh ** May you find forgiveness for yourself and forgive others.
9054889ecSdrh ** May you share freely, never taking more than you give.
10054889ecSdrh **
11054889ecSdrh ******************************************************************************
12054889ecSdrh **
13054889ecSdrh ** This file contains OS interface code that is common to all
14054889ecSdrh ** architectures.
15054889ecSdrh */
16054889ecSdrh #include "sqliteInt.h"
17054889ecSdrh
18054889ecSdrh /*
19c04c54b8Smistachkin ** If we compile with the SQLITE_TEST macro set, then the following block
20c04c54b8Smistachkin ** of code will give us the ability to simulate a disk I/O error. This
21c04c54b8Smistachkin ** is used for testing the I/O recovery logic.
22c04c54b8Smistachkin */
23c04c54b8Smistachkin #if defined(SQLITE_TEST)
24c04c54b8Smistachkin int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
25c04c54b8Smistachkin int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
26c04c54b8Smistachkin int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
27c04c54b8Smistachkin int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
28c04c54b8Smistachkin int sqlite3_io_error_benign = 0; /* True if errors are benign */
29c04c54b8Smistachkin int sqlite3_diskfull_pending = 0;
30c04c54b8Smistachkin int sqlite3_diskfull = 0;
31c04c54b8Smistachkin #endif /* defined(SQLITE_TEST) */
32c04c54b8Smistachkin
33c04c54b8Smistachkin /*
34c04c54b8Smistachkin ** When testing, also keep a count of the number of open files.
35c04c54b8Smistachkin */
36c04c54b8Smistachkin #if defined(SQLITE_TEST)
37c04c54b8Smistachkin int sqlite3_open_file_count = 0;
38c04c54b8Smistachkin #endif /* defined(SQLITE_TEST) */
39c04c54b8Smistachkin
40c04c54b8Smistachkin /*
41ae72d982Sdanielk1977 ** The default SQLite sqlite3_vfs implementations do not allocate
42ae72d982Sdanielk1977 ** memory (actually, os_unix.c allocates a small amount of memory
43ae72d982Sdanielk1977 ** from within OsOpen()), but some third-party implementations may.
44ae72d982Sdanielk1977 ** So we test the effects of a malloc() failing and the sqlite3OsXXX()
45ae72d982Sdanielk1977 ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
46ae72d982Sdanielk1977 **
47ae72d982Sdanielk1977 ** The following functions are instrumented for malloc() failure
48ae72d982Sdanielk1977 ** testing:
49ae72d982Sdanielk1977 **
50ae72d982Sdanielk1977 ** sqlite3OsRead()
51ae72d982Sdanielk1977 ** sqlite3OsWrite()
52ae72d982Sdanielk1977 ** sqlite3OsSync()
536c3c1a09Smistachkin ** sqlite3OsFileSize()
54ae72d982Sdanielk1977 ** sqlite3OsLock()
556c3c1a09Smistachkin ** sqlite3OsCheckReservedLock()
566c3c1a09Smistachkin ** sqlite3OsFileControl()
576c3c1a09Smistachkin ** sqlite3OsShmMap()
586c3c1a09Smistachkin ** sqlite3OsOpen()
596c3c1a09Smistachkin ** sqlite3OsDelete()
606c3c1a09Smistachkin ** sqlite3OsAccess()
616c3c1a09Smistachkin ** sqlite3OsFullPathname()
62ae72d982Sdanielk1977 **
63ae72d982Sdanielk1977 */
64fd28639fSshaneh #if defined(SQLITE_TEST)
65c396d4afSdan int sqlite3_memdebug_vfs_oom_test = 1;
66c396d4afSdan #define DO_OS_MALLOC_TEST(x) \
672491de28Sdan if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \
68e5ae5735Sdrh void *pTstAlloc = sqlite3Malloc(10); \
69fad3039cSmistachkin if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \
70ae72d982Sdanielk1977 sqlite3_free(pTstAlloc); \
71ae72d982Sdanielk1977 }
72ae72d982Sdanielk1977 #else
73b5a19208Sdanielk1977 #define DO_OS_MALLOC_TEST(x)
74ae72d982Sdanielk1977 #endif
75ae72d982Sdanielk1977
76ae72d982Sdanielk1977 /*
77054889ecSdrh ** The following routines are convenience wrappers around methods
7862079060Sdanielk1977 ** of the sqlite3_file object. This is mostly just syntactic sugar. All
79054889ecSdrh ** of this would be completely automatic if SQLite were coded using
80054889ecSdrh ** C++ instead of plain old C.
81054889ecSdrh */
sqlite3OsClose(sqlite3_file * pId)828f2ce914Sdrh void sqlite3OsClose(sqlite3_file *pId){
83c7b6017cSdanielk1977 if( pId->pMethods ){
848f2ce914Sdrh pId->pMethods->xClose(pId);
85c7b6017cSdanielk1977 pId->pMethods = 0;
86c7b6017cSdanielk1977 }
87054889ecSdrh }
sqlite3OsRead(sqlite3_file * id,void * pBuf,int amt,i64 offset)8862079060Sdanielk1977 int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
89b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(id);
9062079060Sdanielk1977 return id->pMethods->xRead(id, pBuf, amt, offset);
91054889ecSdrh }
sqlite3OsWrite(sqlite3_file * id,const void * pBuf,int amt,i64 offset)9262079060Sdanielk1977 int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
93b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(id);
9462079060Sdanielk1977 return id->pMethods->xWrite(id, pBuf, amt, offset);
95054889ecSdrh }
sqlite3OsTruncate(sqlite3_file * id,i64 size)9662079060Sdanielk1977 int sqlite3OsTruncate(sqlite3_file *id, i64 size){
9762079060Sdanielk1977 return id->pMethods->xTruncate(id, size);
98054889ecSdrh }
sqlite3OsSync(sqlite3_file * id,int flags)9990949c20Sdanielk1977 int sqlite3OsSync(sqlite3_file *id, int flags){
100b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(id);
101daaae7b9Sdrh return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
102054889ecSdrh }
sqlite3OsFileSize(sqlite3_file * id,i64 * pSize)10362079060Sdanielk1977 int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
104b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(id);
10562079060Sdanielk1977 return id->pMethods->xFileSize(id, pSize);
106054889ecSdrh }
sqlite3OsLock(sqlite3_file * id,int lockType)10762079060Sdanielk1977 int sqlite3OsLock(sqlite3_file *id, int lockType){
108b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(id);
109*2eca0614Sdrh assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE );
11062079060Sdanielk1977 return id->pMethods->xLock(id, lockType);
111054889ecSdrh }
sqlite3OsUnlock(sqlite3_file * id,int lockType)11262079060Sdanielk1977 int sqlite3OsUnlock(sqlite3_file *id, int lockType){
113*2eca0614Sdrh assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED );
11462079060Sdanielk1977 return id->pMethods->xUnlock(id, lockType);
115054889ecSdrh }
sqlite3OsCheckReservedLock(sqlite3_file * id,int * pResOut)116861f7456Sdanielk1977 int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
117b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(id);
118861f7456Sdanielk1977 return id->pMethods->xCheckReservedLock(id, pResOut);
119054889ecSdrh }
120c02372ceSdrh
121c02372ceSdrh /*
122c02372ceSdrh ** Use sqlite3OsFileControl() when we are doing something that might fail
123c02372ceSdrh ** and we need to know about the failures. Use sqlite3OsFileControlHint()
124c02372ceSdrh ** when simply tossing information over the wall to the VFS and we do not
125c02372ceSdrh ** really care if the VFS receives and understands the information since it
126c02372ceSdrh ** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
127c02372ceSdrh ** routine has no return value since the return value would be meaningless.
128c02372ceSdrh */
sqlite3OsFileControl(sqlite3_file * id,int op,void * pArg)129cc6bb3eaSdrh int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
1306831dbedSdan if( id->pMethods==0 ) return SQLITE_NOTFOUND;
1311001ee88Sdan #ifdef SQLITE_TEST
132000705bcSdrh if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
133000705bcSdrh && op!=SQLITE_FCNTL_LOCK_TIMEOUT
1341de03abbSdrh && op!=SQLITE_FCNTL_CKPT_DONE
1351de03abbSdrh && op!=SQLITE_FCNTL_CKPT_START
136000705bcSdrh ){
1371001ee88Sdan /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
1381001ee88Sdan ** is using a regular VFS, it is called after the corresponding
1391001ee88Sdan ** transaction has been committed. Injecting a fault at this point
1401001ee88Sdan ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
1411001ee88Sdan ** but the transaction is committed anyway.
1421001ee88Sdan **
1431001ee88Sdan ** The core must call OsFileControl() though, not OsFileControlHint(),
1441001ee88Sdan ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
1451001ee88Sdan ** means the commit really has failed and an error should be returned
1461de03abbSdrh ** to the user.
1471de03abbSdrh **
1481de03abbSdrh ** The CKPT_DONE and CKPT_START file-controls are write-only signals
1491de03abbSdrh ** to the cksumvfs. Their return code is meaningless and is ignored
1501de03abbSdrh ** by the SQLite core, so there is no point in simulating OOMs for them.
1511de03abbSdrh */
1526c3c1a09Smistachkin DO_OS_MALLOC_TEST(id);
1531001ee88Sdan }
1541001ee88Sdan #endif
155cc6bb3eaSdrh return id->pMethods->xFileControl(id, op, pArg);
156cc6bb3eaSdrh }
sqlite3OsFileControlHint(sqlite3_file * id,int op,void * pArg)157c02372ceSdrh void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
158afb39a4cSdrh if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);
1596f2f19a1Sdan }
160c02372ceSdrh
sqlite3OsSectorSize(sqlite3_file * id)16162079060Sdanielk1977 int sqlite3OsSectorSize(sqlite3_file *id){
16262079060Sdanielk1977 int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
163967a4a1cSdanielk1977 return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
164b472117cSdanielk1977 }
sqlite3OsDeviceCharacteristics(sqlite3_file * id)16562079060Sdanielk1977 int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
16676fc88feSdrh if( NEVER(id->pMethods==0) ) return 0;
16762079060Sdanielk1977 return id->pMethods->xDeviceCharacteristics(id);
16862079060Sdanielk1977 }
1692ed5737aSdrh #ifndef SQLITE_OMIT_WAL
sqlite3OsShmLock(sqlite3_file * id,int offset,int n,int flags)17073b64e4dSdrh int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
17173b64e4dSdrh return id->pMethods->xShmLock(id, offset, n, flags);
172d9e5c4f6Sdrh }
sqlite3OsShmBarrier(sqlite3_file * id)173286a2884Sdrh void sqlite3OsShmBarrier(sqlite3_file *id){
174286a2884Sdrh id->pMethods->xShmBarrier(id);
175286a2884Sdrh }
sqlite3OsShmUnmap(sqlite3_file * id,int deleteFlag)176e11fedc5Sdrh int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
177da9fe0c3Sdan return id->pMethods->xShmUnmap(id, deleteFlag);
178d9e5c4f6Sdrh }
sqlite3OsShmMap(sqlite3_file * id,int iPage,int pgsz,int bExtend,void volatile ** pp)17918801915Sdan int sqlite3OsShmMap(
180da9fe0c3Sdan sqlite3_file *id, /* Database file handle */
18113a3cb82Sdan int iPage,
18213a3cb82Sdan int pgsz,
183da9fe0c3Sdan int bExtend, /* True to extend file if necessary */
184da9fe0c3Sdan void volatile **pp /* OUT: Pointer to mapping */
18513a3cb82Sdan ){
1866c3c1a09Smistachkin DO_OS_MALLOC_TEST(id);
187da9fe0c3Sdan return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
18813a3cb82Sdan }
1892ed5737aSdrh #endif /* SQLITE_OMIT_WAL */
190f23da966Sdan
1919b4c59faSdrh #if SQLITE_MAX_MMAP_SIZE>0
192188d4884Sdrh /* The real implementation of xFetch and xUnfetch */
sqlite3OsFetch(sqlite3_file * id,i64 iOff,int iAmt,void ** pp)193f23da966Sdan int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
194a64d5a15Sdan DO_OS_MALLOC_TEST(id);
195f23da966Sdan return id->pMethods->xFetch(id, iOff, iAmt, pp);
196f23da966Sdan }
sqlite3OsUnfetch(sqlite3_file * id,i64 iOff,void * p)197df737fe6Sdan int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
198df737fe6Sdan return id->pMethods->xUnfetch(id, iOff, p);
1995d8a1372Sdan }
200188d4884Sdrh #else
201188d4884Sdrh /* No-op stubs to use when memory-mapped I/O is disabled */
sqlite3OsFetch(sqlite3_file * id,i64 iOff,int iAmt,void ** pp)202188d4884Sdrh int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
203188d4884Sdrh *pp = 0;
204188d4884Sdrh return SQLITE_OK;
205188d4884Sdrh }
sqlite3OsUnfetch(sqlite3_file * id,i64 iOff,void * p)206188d4884Sdrh int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
207188d4884Sdrh return SQLITE_OK;
208188d4884Sdrh }
209188d4884Sdrh #endif
2103f459022Sdrh
211d677b3d6Sdrh /*
212d677b3d6Sdrh ** The next group of routines are convenience wrappers around the
213d677b3d6Sdrh ** VFS methods.
214d677b3d6Sdrh */
sqlite3OsOpen(sqlite3_vfs * pVfs,const char * zPath,sqlite3_file * pFile,int flags,int * pFlagsOut)215b4b47411Sdanielk1977 int sqlite3OsOpen(
216b4b47411Sdanielk1977 sqlite3_vfs *pVfs,
217b4b47411Sdanielk1977 const char *zPath,
218b4b47411Sdanielk1977 sqlite3_file *pFile,
219b4b47411Sdanielk1977 int flags,
220b4b47411Sdanielk1977 int *pFlagsOut
221b4b47411Sdanielk1977 ){
222072db2fbSdrh int rc;
223b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(0);
22444659c94Sdan /* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
225f1f12688Sdrh ** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
226f1f12688Sdrh ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
227f1f12688Sdrh ** reaching the VFS. */
2282756f806Sdan assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) );
229c398c65bSdrh rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
230072db2fbSdrh assert( rc==SQLITE_OK || pFile->pMethods==0 );
231072db2fbSdrh return rc;
2323f459022Sdrh }
sqlite3OsDelete(sqlite3_vfs * pVfs,const char * zPath,int dirSync)233fee2d25aSdanielk1977 int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
2346c3c1a09Smistachkin DO_OS_MALLOC_TEST(0);
235e349519fSdrh assert( dirSync==0 || dirSync==1 );
2368119aab3Sdrh return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
237b4b47411Sdanielk1977 }
sqlite3OsAccess(sqlite3_vfs * pVfs,const char * zPath,int flags,int * pResOut)238861f7456Sdanielk1977 int sqlite3OsAccess(
239861f7456Sdanielk1977 sqlite3_vfs *pVfs,
240861f7456Sdanielk1977 const char *zPath,
241861f7456Sdanielk1977 int flags,
242861f7456Sdanielk1977 int *pResOut
243861f7456Sdanielk1977 ){
244b5a19208Sdanielk1977 DO_OS_MALLOC_TEST(0);
245861f7456Sdanielk1977 return pVfs->xAccess(pVfs, zPath, flags, pResOut);
246b4b47411Sdanielk1977 }
sqlite3OsFullPathname(sqlite3_vfs * pVfs,const char * zPath,int nPathOut,char * zPathOut)247adfb9b05Sdanielk1977 int sqlite3OsFullPathname(
248adfb9b05Sdanielk1977 sqlite3_vfs *pVfs,
249adfb9b05Sdanielk1977 const char *zPath,
250adfb9b05Sdanielk1977 int nPathOut,
251adfb9b05Sdanielk1977 char *zPathOut
252adfb9b05Sdanielk1977 ){
2536c3c1a09Smistachkin DO_OS_MALLOC_TEST(0);
25468ff78b1Sdrh zPathOut[0] = 0;
255adfb9b05Sdanielk1977 return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
256b4b47411Sdanielk1977 }
25775998ab3Sshane #ifndef SQLITE_OMIT_LOAD_EXTENSION
sqlite3OsDlOpen(sqlite3_vfs * pVfs,const char * zPath)258b4b47411Sdanielk1977 void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
259cf145047Sdrh assert( zPath!=0 );
260cf145047Sdrh assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */
261153c62c4Sdrh return pVfs->xDlOpen(pVfs, zPath);
262b4b47411Sdanielk1977 }
sqlite3OsDlError(sqlite3_vfs * pVfs,int nByte,char * zBufOut)263b4b47411Sdanielk1977 void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
264153c62c4Sdrh pVfs->xDlError(pVfs, nByte, zBufOut);
265b4b47411Sdanielk1977 }
sqlite3OsDlSym(sqlite3_vfs * pVfs,void * pHdle,const char * zSym)2661875f7a3Sdrh void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
2671875f7a3Sdrh return pVfs->xDlSym(pVfs, pHdle, zSym);
268b4b47411Sdanielk1977 }
sqlite3OsDlClose(sqlite3_vfs * pVfs,void * pHandle)269b4b47411Sdanielk1977 void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
270153c62c4Sdrh pVfs->xDlClose(pVfs, pHandle);
271b4b47411Sdanielk1977 }
27275998ab3Sshane #endif /* SQLITE_OMIT_LOAD_EXTENSION */
sqlite3OsRandomness(sqlite3_vfs * pVfs,int nByte,char * zBufOut)273b4b47411Sdanielk1977 int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
274ade54d68Sdrh if( sqlite3Config.iPrngSeed ){
275ade54d68Sdrh memset(zBufOut, 0, nByte);
27651755a78Sdrh if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int);
277ade54d68Sdrh memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
278ade54d68Sdrh return SQLITE_OK;
279ade54d68Sdrh }else{
280153c62c4Sdrh return pVfs->xRandomness(pVfs, nByte, zBufOut);
281b4b47411Sdanielk1977 }
282ade54d68Sdrh
283ade54d68Sdrh }
sqlite3OsSleep(sqlite3_vfs * pVfs,int nMicro)284b4b47411Sdanielk1977 int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
285153c62c4Sdrh return pVfs->xSleep(pVfs, nMicro);
286b4b47411Sdanielk1977 }
sqlite3OsGetLastError(sqlite3_vfs * pVfs)2871b9f2141Sdrh int sqlite3OsGetLastError(sqlite3_vfs *pVfs){
2881b9f2141Sdrh return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0;
2891b9f2141Sdrh }
sqlite3OsCurrentTimeInt64(sqlite3_vfs * pVfs,sqlite3_int64 * pTimeOut)290b7e8ea20Sdrh int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
291b7e8ea20Sdrh int rc;
292bfccdaf1Sdrh /* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
293bfccdaf1Sdrh ** method to get the current date and time if that method is available
294bfccdaf1Sdrh ** (if iVersion is 2 or greater and the function pointer is not NULL) and
295bfccdaf1Sdrh ** will fall back to xCurrentTime() if xCurrentTimeInt64() is
296bfccdaf1Sdrh ** unavailable.
297bfccdaf1Sdrh */
298b7e8ea20Sdrh if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
299b7e8ea20Sdrh rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
300b7e8ea20Sdrh }else{
301b7e8ea20Sdrh double r;
302b7e8ea20Sdrh rc = pVfs->xCurrentTime(pVfs, &r);
303b7e8ea20Sdrh *pTimeOut = (sqlite3_int64)(r*86400000.0);
304b7e8ea20Sdrh }
305b7e8ea20Sdrh return rc;
306b4b47411Sdanielk1977 }
307b4b47411Sdanielk1977
sqlite3OsOpenMalloc(sqlite3_vfs * pVfs,const char * zFile,sqlite3_file ** ppFile,int flags,int * pOutFlags)308b4b47411Sdanielk1977 int sqlite3OsOpenMalloc(
309b4b47411Sdanielk1977 sqlite3_vfs *pVfs,
310b4b47411Sdanielk1977 const char *zFile,
311b4b47411Sdanielk1977 sqlite3_file **ppFile,
312967a4a1cSdanielk1977 int flags,
313967a4a1cSdanielk1977 int *pOutFlags
314b4b47411Sdanielk1977 ){
315fad3039cSmistachkin int rc;
316b4b47411Sdanielk1977 sqlite3_file *pFile;
317f1c40f4fSmistachkin pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
318b4b47411Sdanielk1977 if( pFile ){
319967a4a1cSdanielk1977 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
320b4b47411Sdanielk1977 if( rc!=SQLITE_OK ){
321b4b47411Sdanielk1977 sqlite3_free(pFile);
32233d28ab4Sdrh *ppFile = 0;
323b4b47411Sdanielk1977 }else{
324b4b47411Sdanielk1977 *ppFile = pFile;
325b4b47411Sdanielk1977 }
326fad3039cSmistachkin }else{
32733d28ab4Sdrh *ppFile = 0;
328fad3039cSmistachkin rc = SQLITE_NOMEM_BKPT;
329b4b47411Sdanielk1977 }
33033d28ab4Sdrh assert( *ppFile!=0 || rc!=SQLITE_OK );
331b4b47411Sdanielk1977 return rc;
332b4b47411Sdanielk1977 }
sqlite3OsCloseFree(sqlite3_file * pFile)3338f2ce914Sdrh void sqlite3OsCloseFree(sqlite3_file *pFile){
3344003298bSmlcreech assert( pFile );
3358f2ce914Sdrh sqlite3OsClose(pFile);
336b4b47411Sdanielk1977 sqlite3_free(pFile);
337b4b47411Sdanielk1977 }
338b4b47411Sdanielk1977
339b4b47411Sdanielk1977 /*
3403d6e060bSdan ** This function is a wrapper around the OS specific implementation of
3413d6e060bSdan ** sqlite3_os_init(). The purpose of the wrapper is to provide the
3423d6e060bSdan ** ability to simulate a malloc failure, so that the handling of an
3433d6e060bSdan ** error in sqlite3_os_init() by the upper layers can be tested.
3443d6e060bSdan */
sqlite3OsInit(void)3453d6e060bSdan int sqlite3OsInit(void){
346adad77a6Sdrh void *p = sqlite3_malloc(10);
347fad3039cSmistachkin if( p==0 ) return SQLITE_NOMEM_BKPT;
348adad77a6Sdrh sqlite3_free(p);
3493d6e060bSdan return sqlite3_os_init();
3503d6e060bSdan }
3513d6e060bSdan
3523d6e060bSdan /*
353c0fa4c5fSdanielk1977 ** The list of all registered VFS implementations.
354b4b47411Sdanielk1977 */
35595e80d61Sdanielk1977 static sqlite3_vfs * SQLITE_WSD vfsList = 0;
3565c8f8587Sdanielk1977 #define vfsList GLOBAL(sqlite3_vfs *, vfsList)
357d677b3d6Sdrh
358d677b3d6Sdrh /*
359d677b3d6Sdrh ** Locate a VFS by name. If no name is given, simply return the
360d677b3d6Sdrh ** first VFS on the list.
361d677b3d6Sdrh */
sqlite3_vfs_find(const char * zVfs)362d677b3d6Sdrh sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
363a418980bSdrh sqlite3_vfs *pVfs = 0;
36418472fa7Sdrh #if SQLITE_THREADSAFE
36540257ffdSdrh sqlite3_mutex *mutex;
36640257ffdSdrh #endif
36740257ffdSdrh #ifndef SQLITE_OMIT_AUTOINIT
36840257ffdSdrh int rc = sqlite3_initialize();
36940257ffdSdrh if( rc ) return 0;
37040257ffdSdrh #endif
37118472fa7Sdrh #if SQLITE_THREADSAFE
372ccb2113aSdrh mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
3737e8b848aSdrh #endif
374d677b3d6Sdrh sqlite3_mutex_enter(mutex);
375d677b3d6Sdrh for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
376d677b3d6Sdrh if( zVfs==0 ) break;
377d677b3d6Sdrh if( strcmp(zVfs, pVfs->zName)==0 ) break;
378d677b3d6Sdrh }
379d677b3d6Sdrh sqlite3_mutex_leave(mutex);
380d677b3d6Sdrh return pVfs;
381b4b47411Sdanielk1977 }
382b4b47411Sdanielk1977
383d677b3d6Sdrh /*
384d677b3d6Sdrh ** Unlink a VFS from the linked list
385d677b3d6Sdrh */
vfsUnlink(sqlite3_vfs * pVfs)386d677b3d6Sdrh static void vfsUnlink(sqlite3_vfs *pVfs){
387ccb2113aSdrh assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) );
3889bc5449fSdrh if( pVfs==0 ){
3899bc5449fSdrh /* No-op */
3909bc5449fSdrh }else if( vfsList==pVfs ){
391d677b3d6Sdrh vfsList = pVfs->pNext;
3929bc5449fSdrh }else if( vfsList ){
393d677b3d6Sdrh sqlite3_vfs *p = vfsList;
394d677b3d6Sdrh while( p->pNext && p->pNext!=pVfs ){
395d677b3d6Sdrh p = p->pNext;
396d677b3d6Sdrh }
397d677b3d6Sdrh if( p->pNext==pVfs ){
398d677b3d6Sdrh p->pNext = pVfs->pNext;
399d677b3d6Sdrh }
400d677b3d6Sdrh }
401d677b3d6Sdrh }
402d677b3d6Sdrh
403d677b3d6Sdrh /*
404d677b3d6Sdrh ** Register a VFS with the system. It is harmless to register the same
405d677b3d6Sdrh ** VFS multiple times. The new VFS becomes the default if makeDflt is
406d677b3d6Sdrh ** true.
407d677b3d6Sdrh */
sqlite3_vfs_register(sqlite3_vfs * pVfs,int makeDflt)408d677b3d6Sdrh int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
40930ddce6fSdrh MUTEX_LOGIC(sqlite3_mutex *mutex;)
41040257ffdSdrh #ifndef SQLITE_OMIT_AUTOINIT
41140257ffdSdrh int rc = sqlite3_initialize();
41240257ffdSdrh if( rc ) return rc;
41340257ffdSdrh #endif
4149ca95730Sdrh #ifdef SQLITE_ENABLE_API_ARMOR
4159ca95730Sdrh if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
4169ca95730Sdrh #endif
4179ca95730Sdrh
418ccb2113aSdrh MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
419d677b3d6Sdrh sqlite3_mutex_enter(mutex);
420d677b3d6Sdrh vfsUnlink(pVfs);
421d677b3d6Sdrh if( makeDflt || vfsList==0 ){
422d677b3d6Sdrh pVfs->pNext = vfsList;
423d677b3d6Sdrh vfsList = pVfs;
424d677b3d6Sdrh }else{
425d677b3d6Sdrh pVfs->pNext = vfsList->pNext;
42695c8a54cSdanielk1977 vfsList->pNext = pVfs;
427d677b3d6Sdrh }
428f1da17a3Sdanielk1977 assert(vfsList);
429d677b3d6Sdrh sqlite3_mutex_leave(mutex);
430d677b3d6Sdrh return SQLITE_OK;
431d677b3d6Sdrh }
432d677b3d6Sdrh
433d677b3d6Sdrh /*
434d677b3d6Sdrh ** Unregister a VFS so that it is no longer accessible.
435d677b3d6Sdrh */
sqlite3_vfs_unregister(sqlite3_vfs * pVfs)436d677b3d6Sdrh int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
43745f31827Sdan MUTEX_LOGIC(sqlite3_mutex *mutex;)
43845f31827Sdan #ifndef SQLITE_OMIT_AUTOINIT
43945f31827Sdan int rc = sqlite3_initialize();
44045f31827Sdan if( rc ) return rc;
4417e8b848aSdrh #endif
442ccb2113aSdrh MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
443d677b3d6Sdrh sqlite3_mutex_enter(mutex);
444d677b3d6Sdrh vfsUnlink(pVfs);
445d677b3d6Sdrh sqlite3_mutex_leave(mutex);
446d677b3d6Sdrh return SQLITE_OK;
447d677b3d6Sdrh }
448