/*** 2005 November 29**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.************************************************************************************ This file contains OS interface code that is common to all** architectures.*/#include "sqliteInt.h"/*** If we compile with the SQLITE_TEST macro set, then the following block** of code will give us the ability to simulate a disk I/O error. This** is used for testing the I/O recovery logic.*/#if defined(SQLITE_TEST)int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */int sqlite3_io_error_pending = 0; /* Count down to first I/O error */int sqlite3_io_error_persist = 0; /* True if I/O errors persist */int sqlite3_io_error_benign = 0; /* True if errors are benign */int sqlite3_diskfull_pending = 0;int sqlite3_diskfull = 0;#endif /* defined(SQLITE_TEST) *//*** When testing, also keep a count of the number of open files.*/#if defined(SQLITE_TEST)int sqlite3_open_file_count = 0;#endif /* defined(SQLITE_TEST) *//*** The default SQLite sqlite3_vfs implementations do not allocate** memory (actually, os_unix.c allocates a small amount of memory** from within OsOpen()), but some third-party implementations may.** So we test the effects of a malloc() failing and the sqlite3OsXXX()** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.**** The following functions are instrumented for malloc() failure** testing:**** sqlite3OsRead()** sqlite3OsWrite()** sqlite3OsSync()** sqlite3OsFileSize()** sqlite3OsLock()** sqlite3OsCheckReservedLock()** sqlite3OsFileControl()** sqlite3OsShmMap()** sqlite3OsOpen()** sqlite3OsDelete()** sqlite3OsAccess()** sqlite3OsFullPathname()***/#if defined(SQLITE_TEST)int sqlite3_memdebug_vfs_oom_test = 1;#define DO_OS_MALLOC_TEST(x) \if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \void *pTstAlloc = sqlite3Malloc(10); \if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \sqlite3_free(pTstAlloc); \}#else#define DO_OS_MALLOC_TEST(x)#endif/*** The following routines are convenience wrappers around methods** of the sqlite3_file object. This is mostly just syntactic sugar. All** of this would be completely automatic if SQLite were coded using** C++ instead of plain old C.*/void sqlite3OsClose(sqlite3_file *pId){if( pId->pMethods ){pId->pMethods->xClose(pId);pId->pMethods = 0;}}int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){DO_OS_MALLOC_TEST(id);return id->pMethods->xRead(id, pBuf, amt, offset);}int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){DO_OS_MALLOC_TEST(id);return id->pMethods->xWrite(id, pBuf, amt, offset);}int sqlite3OsTruncate(sqlite3_file *id, i64 size){return id->pMethods->xTruncate(id, size);}int sqlite3OsSync(sqlite3_file *id, int flags){DO_OS_MALLOC_TEST(id);return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;}int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){DO_OS_MALLOC_TEST(id);return id->pMethods->xFileSize(id, pSize);}int sqlite3OsLock(sqlite3_file *id, int lockType){DO_OS_MALLOC_TEST(id);assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE );return id->pMethods->xLock(id, lockType);}int sqlite3OsUnlock(sqlite3_file *id, int lockType){assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED );return id->pMethods->xUnlock(id, lockType);}int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){DO_OS_MALLOC_TEST(id);return id->pMethods->xCheckReservedLock(id, pResOut);}/*** Use sqlite3OsFileControl() when we are doing something that might fail** and we need to know about the failures. Use sqlite3OsFileControlHint()** when simply tossing information over the wall to the VFS and we do not** really care if the VFS receives and understands the information since it** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()** routine has no return value since the return value would be meaningless.*/int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){if( id->pMethods==0 ) return SQLITE_NOTFOUND;#ifdef SQLITE_TESTif( op!=SQLITE_FCNTL_COMMIT_PHASETWO&& op!=SQLITE_FCNTL_LOCK_TIMEOUT&& op!=SQLITE_FCNTL_CKPT_DONE&& op!=SQLITE_FCNTL_CKPT_START){/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite** is using a regular VFS, it is called after the corresponding** transaction has been committed. Injecting a fault at this point** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM** but the transaction is committed anyway.**** The core must call OsFileControl() though, not OsFileControlHint(),** as if a custom VFS (e.g. zipvfs) returns an error here, it probably** means the commit really has failed and an error should be returned** to the user.**** The CKPT_DONE and CKPT_START file-controls are write-only signals** to the cksumvfs. Their return code is meaningless and is ignored** by the SQLite core, so there is no point in simulating OOMs for them.*/DO_OS_MALLOC_TEST(id);}#endifreturn id->pMethods->xFileControl(id, op, pArg);}void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);}int sqlite3OsSectorSize(sqlite3_file *id){int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);}int sqlite3OsDeviceCharacteristics(sqlite3_file *id){if( NEVER(id->pMethods==0) ) return 0;return id->pMethods->xDeviceCharacteristics(id);}#ifndef SQLITE_OMIT_WALint sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){return id->pMethods->xShmLock(id, offset, n, flags);}void sqlite3OsShmBarrier(sqlite3_file *id){id->pMethods->xShmBarrier(id);}int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){return id->pMethods->xShmUnmap(id, deleteFlag);}int sqlite3OsShmMap(sqlite3_file *id, /* Database file handle */int iPage,int pgsz,int bExtend, /* True to extend file if necessary */void volatile **pp /* OUT: Pointer to mapping */){DO_OS_MALLOC_TEST(id);return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);}#endif /* SQLITE_OMIT_WAL */#if SQLITE_MAX_MMAP_SIZE>0/* The real implementation of xFetch and xUnfetch */int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){DO_OS_MALLOC_TEST(id);return id->pMethods->xFetch(id, iOff, iAmt, pp);}int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){return id->pMethods->xUnfetch(id, iOff, p);}#else/* No-op stubs to use when memory-mapped I/O is disabled */int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){*pp = 0;return SQLITE_OK;}int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){return SQLITE_OK;}#endif/*** The next group of routines are convenience wrappers around the** VFS methods.*/int sqlite3OsOpen(sqlite3_vfs *pVfs,const char *zPath,sqlite3_file *pFile,int flags,int *pFlagsOut){int rc;DO_OS_MALLOC_TEST(0);/* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before** reaching the VFS. */assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) );rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);assert( rc==SQLITE_OK || pFile->pMethods==0 );return rc;}int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){DO_OS_MALLOC_TEST(0);assert( dirSync==0 || dirSync==1 );return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;}int sqlite3OsAccess(sqlite3_vfs *pVfs,const char *zPath,int flags,int *pResOut){DO_OS_MALLOC_TEST(0);return pVfs->xAccess(pVfs, zPath, flags, pResOut);}int sqlite3OsFullPathname(sqlite3_vfs *pVfs,const char *zPath,int nPathOut,char *zPathOut){DO_OS_MALLOC_TEST(0);zPathOut[0] = 0;return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);}#ifndef SQLITE_OMIT_LOAD_EXTENSIONvoid *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){assert( zPath!=0 );assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */return pVfs->xDlOpen(pVfs, zPath);}void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){pVfs->xDlError(pVfs, nByte, zBufOut);}void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){return pVfs->xDlSym(pVfs, pHdle, zSym);}void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){pVfs->xDlClose(pVfs, pHandle);}#endif /* SQLITE_OMIT_LOAD_EXTENSION */int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){if( sqlite3Config.iPrngSeed ){memset(zBufOut, 0, nByte);if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int);memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);return SQLITE_OK;}else{return pVfs->xRandomness(pVfs, nByte, zBufOut);}}int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){return pVfs->xSleep(pVfs, nMicro);}int sqlite3OsGetLastError(sqlite3_vfs *pVfs){return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0;}int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){int rc;/* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()** method to get the current date and time if that method is available** (if iVersion is 2 or greater and the function pointer is not NULL) and** will fall back to xCurrentTime() if xCurrentTimeInt64() is** unavailable.*/if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);}else{double r;rc = pVfs->xCurrentTime(pVfs, &r);*pTimeOut = (sqlite3_int64)(r*86400000.0);}return rc;}int sqlite3OsOpenMalloc(sqlite3_vfs *pVfs,const char *zFile,sqlite3_file **ppFile,int flags,int *pOutFlags){int rc;sqlite3_file *pFile;pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);if( pFile ){rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);if( rc!=SQLITE_OK ){sqlite3_free(pFile);*ppFile = 0;}else{*ppFile = pFile;}}else{*ppFile = 0;rc = SQLITE_NOMEM_BKPT;}assert( *ppFile!=0 || rc!=SQLITE_OK );return rc;}void sqlite3OsCloseFree(sqlite3_file *pFile){assert( pFile );sqlite3OsClose(pFile);sqlite3_free(pFile);}/*** This function is a wrapper around the OS specific implementation of** sqlite3_os_init(). The purpose of the wrapper is to provide the** ability to simulate a malloc failure, so that the handling of an** error in sqlite3_os_init() by the upper layers can be tested.*/int sqlite3OsInit(void){void *p = sqlite3_malloc(10);if( p==0 ) return SQLITE_NOMEM_BKPT;sqlite3_free(p);return sqlite3_os_init();}/*** The list of all registered VFS implementations.*/static sqlite3_vfs * SQLITE_WSD vfsList = 0;#define vfsList GLOBAL(sqlite3_vfs *, vfsList)/*** Locate a VFS by name. If no name is given, simply return the** first VFS on the list.*/sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){sqlite3_vfs *pVfs = 0;#if SQLITE_THREADSAFEsqlite3_mutex *mutex;#endif#ifndef SQLITE_OMIT_AUTOINITint rc = sqlite3_initialize();if( rc ) return 0;#endif#if SQLITE_THREADSAFEmutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);#endifsqlite3_mutex_enter(mutex);for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){if( zVfs==0 ) break;if( strcmp(zVfs, pVfs->zName)==0 ) break;}sqlite3_mutex_leave(mutex);return pVfs;}/*** Unlink a VFS from the linked list*/static void vfsUnlink(sqlite3_vfs *pVfs){assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) );if( pVfs==0 ){/* No-op */}else if( vfsList==pVfs ){vfsList = pVfs->pNext;}else if( vfsList ){sqlite3_vfs *p = vfsList;while( p->pNext && p->pNext!=pVfs ){p = p->pNext;}if( p->pNext==pVfs ){p->pNext = pVfs->pNext;}}}/*** Register a VFS with the system. It is harmless to register the same** VFS multiple times. The new VFS becomes the default if makeDflt is** true.*/int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){MUTEX_LOGIC(sqlite3_mutex *mutex;)#ifndef SQLITE_OMIT_AUTOINITint rc = sqlite3_initialize();if( rc ) return rc;#endif#ifdef SQLITE_ENABLE_API_ARMORif( pVfs==0 ) return SQLITE_MISUSE_BKPT;#endifMUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )sqlite3_mutex_enter(mutex);vfsUnlink(pVfs);if( makeDflt || vfsList==0 ){pVfs->pNext = vfsList;vfsList = pVfs;}else{pVfs->pNext = vfsList->pNext;vfsList->pNext = pVfs;}assert(vfsList);sqlite3_mutex_leave(mutex);return SQLITE_OK;}/*** Unregister a VFS so that it is no longer accessible.*/int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){MUTEX_LOGIC(sqlite3_mutex *mutex;)#ifndef SQLITE_OMIT_AUTOINITint rc = sqlite3_initialize();if( rc ) return rc;#endifMUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )sqlite3_mutex_enter(mutex);vfsUnlink(pVfs);sqlite3_mutex_leave(mutex);return SQLITE_OK;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。