ds@1952: /* ds@1952: ** 2005 November 29 ds@1952: ** ds@1952: ** The author disclaims copyright to this source code. In place of ds@1952: ** a legal notice, here is a blessing: ds@1952: ** ds@1952: ** May you do good and not evil. ds@1952: ** May you find forgiveness for yourself and forgive others. ds@1952: ** May you share freely, never taking more than you give. ds@1952: ** ds@1952: ****************************************************************************** ds@1952: ** ds@1952: ** This file contains OS interface code that is common to all ds@1952: ** architectures. ds@1952: */ ds@1952: #define _SQLITE_OS_C_ 1 ds@1952: #include "sqliteInt.h" ds@1952: #undef _SQLITE_OS_C_ ds@1952: ds@1952: /* ds@1952: ** The default SQLite sqlite3_vfs implementations do not allocate ds@1952: ** memory (actually, os_unix.c allocates a small amount of memory ds@1952: ** from within OsOpen()), but some third-party implementations may. ds@1952: ** So we test the effects of a malloc() failing and the sqlite3OsXXX() ds@1952: ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. ds@1952: ** ds@1952: ** The following functions are instrumented for malloc() failure ds@1952: ** testing: ds@1952: ** ds@1952: ** sqlite3OsOpen() ds@1952: ** sqlite3OsRead() ds@1952: ** sqlite3OsWrite() ds@1952: ** sqlite3OsSync() ds@1952: ** sqlite3OsLock() ds@1952: ** ds@1952: */ ds@1952: #ifdef SQLITE_TEST ds@1952: #define DO_OS_MALLOC_TEST if (1) { \ ds@1952: void *pTstAlloc = sqlite3_malloc(10); \ ds@1952: if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ ds@1952: sqlite3_free(pTstAlloc); \ ds@1952: } ds@1952: #else ds@1952: #define DO_OS_MALLOC_TEST ds@1952: #endif ds@1952: ds@1952: /* ds@1952: ** The following routines are convenience wrappers around methods ds@1952: ** of the sqlite3_file object. This is mostly just syntactic sugar. All ds@1952: ** of this would be completely automatic if SQLite were coded using ds@1952: ** C++ instead of plain old C. ds@1952: */ ds@1952: int sqlite3OsClose(sqlite3_file *pId){ ds@1952: int rc = SQLITE_OK; ds@1952: if( pId->pMethods ){ ds@1952: rc = pId->pMethods->xClose(pId); ds@1952: pId->pMethods = 0; ds@1952: } ds@1952: return rc; ds@1952: } ds@1952: int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ ds@1952: DO_OS_MALLOC_TEST; ds@1952: return id->pMethods->xRead(id, pBuf, amt, offset); ds@1952: } ds@1952: int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ ds@1952: DO_OS_MALLOC_TEST; ds@1952: return id->pMethods->xWrite(id, pBuf, amt, offset); ds@1952: } ds@1952: int sqlite3OsTruncate(sqlite3_file *id, i64 size){ ds@1952: return id->pMethods->xTruncate(id, size); ds@1952: } ds@1952: int sqlite3OsSync(sqlite3_file *id, int flags){ ds@1952: DO_OS_MALLOC_TEST; ds@1952: return id->pMethods->xSync(id, flags); ds@1952: } ds@1952: int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ ds@1952: return id->pMethods->xFileSize(id, pSize); ds@1952: } ds@1952: int sqlite3OsLock(sqlite3_file *id, int lockType){ ds@1952: DO_OS_MALLOC_TEST; ds@1952: return id->pMethods->xLock(id, lockType); ds@1952: } ds@1952: int sqlite3OsUnlock(sqlite3_file *id, int lockType){ ds@1952: return id->pMethods->xUnlock(id, lockType); ds@1952: } ds@1952: int sqlite3OsCheckReservedLock(sqlite3_file *id){ ds@1952: return id->pMethods->xCheckReservedLock(id); ds@1952: } ds@1952: int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ ds@1952: return id->pMethods->xFileControl(id,op,pArg); ds@1952: } ds@1952: ds@1952: #ifdef SQLITE_TEST ds@1952: /* The following two variables are used to override the values returned ds@1952: ** by the xSectorSize() and xDeviceCharacteristics() vfs methods for ds@1952: ** testing purposes. They are usually set by a test command implemented ds@1952: ** in test6.c. ds@1952: */ ds@1952: int sqlite3_test_sector_size = 0; ds@1952: int sqlite3_test_device_characteristics = 0; ds@1952: int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ ds@1952: int dc = id->pMethods->xDeviceCharacteristics(id); ds@1952: return dc | sqlite3_test_device_characteristics; ds@1952: } ds@1952: int sqlite3OsSectorSize(sqlite3_file *id){ ds@1952: if( sqlite3_test_sector_size==0 ){ ds@1952: int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; ds@1952: return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); ds@1952: } ds@1952: return sqlite3_test_sector_size; ds@1952: } ds@1952: #else ds@1952: int sqlite3OsSectorSize(sqlite3_file *id){ ds@1952: int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; ds@1952: return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); ds@1952: } ds@1952: int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ ds@1952: return id->pMethods->xDeviceCharacteristics(id); ds@1952: } ds@1952: #endif ds@1952: ds@1952: /* ds@1952: ** The next group of routines are convenience wrappers around the ds@1952: ** VFS methods. ds@1952: */ ds@1952: int sqlite3OsOpen( ds@1952: sqlite3_vfs *pVfs, ds@1952: const char *zPath, ds@1952: sqlite3_file *pFile, ds@1952: int flags, ds@1952: int *pFlagsOut ds@1952: ){ ds@1952: DO_OS_MALLOC_TEST; ds@1952: return pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut); ds@1952: } ds@1952: int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ ds@1952: return pVfs->xDelete(pVfs, zPath, dirSync); ds@1952: } ds@1952: int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ ds@1952: return pVfs->xAccess(pVfs, zPath, flags); ds@1952: } ds@1952: int sqlite3OsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){ ds@1952: return pVfs->xGetTempname(pVfs, nBufOut, zBufOut); ds@1952: } ds@1952: int sqlite3OsFullPathname( ds@1952: sqlite3_vfs *pVfs, ds@1952: const char *zPath, ds@1952: int nPathOut, ds@1952: char *zPathOut ds@1952: ){ ds@1952: return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); ds@1952: } ds@1952: void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ ds@1952: return pVfs->xDlOpen(pVfs, zPath); ds@1952: } ds@1952: void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ ds@1952: pVfs->xDlError(pVfs, nByte, zBufOut); ds@1952: } ds@1952: void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ ds@1952: return pVfs->xDlSym(pVfs, pHandle, zSymbol); ds@1952: } ds@1952: void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ ds@1952: pVfs->xDlClose(pVfs, pHandle); ds@1952: } ds@1952: int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ ds@1952: return pVfs->xRandomness(pVfs, nByte, zBufOut); ds@1952: } ds@1952: int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ ds@1952: return pVfs->xSleep(pVfs, nMicro); ds@1952: } ds@1952: int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ ds@1952: return pVfs->xCurrentTime(pVfs, pTimeOut); ds@1952: } ds@1952: ds@1952: int sqlite3OsOpenMalloc( ds@1952: sqlite3_vfs *pVfs, ds@1952: const char *zFile, ds@1952: sqlite3_file **ppFile, ds@1952: int flags, ds@1952: int *pOutFlags ds@1952: ){ ds@1952: int rc = SQLITE_NOMEM; ds@1952: sqlite3_file *pFile; ds@1952: pFile = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile); ds@1952: if( pFile ){ ds@1952: rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); ds@1952: if( rc!=SQLITE_OK ){ ds@1952: sqlite3_free(pFile); ds@1952: }else{ ds@1952: *ppFile = pFile; ds@1952: } ds@1952: } ds@1952: return rc; ds@1952: } ds@1952: int sqlite3OsCloseFree(sqlite3_file *pFile){ ds@1952: int rc = SQLITE_OK; ds@1952: if( pFile ){ ds@1952: rc = sqlite3OsClose(pFile); ds@1952: sqlite3_free(pFile); ds@1952: } ds@1952: return rc; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** The list of all registered VFS implementations. This list is ds@1952: ** initialized to the single VFS returned by sqlite3OsDefaultVfs() ds@1952: ** upon the first call to sqlite3_vfs_find(). ds@1952: */ ds@1952: static sqlite3_vfs *vfsList = 0; ds@1952: ds@1952: /* ds@1952: ** Locate a VFS by name. If no name is given, simply return the ds@1952: ** first VFS on the list. ds@1952: */ ds@1952: sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ ds@1952: sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ds@1952: sqlite3_vfs *pVfs; ds@1952: static int isInit = 0; ds@1952: sqlite3_mutex_enter(mutex); ds@1952: if( !isInit ){ ds@1952: vfsList = sqlite3OsDefaultVfs(); ds@1952: isInit = 1; ds@1952: } ds@1952: for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ ds@1952: if( zVfs==0 ) break; ds@1952: if( strcmp(zVfs, pVfs->zName)==0 ) break; ds@1952: } ds@1952: sqlite3_mutex_leave(mutex); ds@1952: return pVfs; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Unlink a VFS from the linked list ds@1952: */ ds@1952: static void vfsUnlink(sqlite3_vfs *pVfs){ ds@1952: assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) ); ds@1952: if( vfsList==pVfs ){ ds@1952: vfsList = pVfs->pNext; ds@1952: }else{ ds@1952: sqlite3_vfs *p = vfsList; ds@1952: while( p->pNext && p->pNext!=pVfs ){ ds@1952: p = p->pNext; ds@1952: } ds@1952: if( p->pNext==pVfs ){ ds@1952: p->pNext = pVfs->pNext; ds@1952: } ds@1952: } ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Register a VFS with the system. It is harmless to register the same ds@1952: ** VFS multiple times. The new VFS becomes the default if makeDflt is ds@1952: ** true. ds@1952: */ ds@1952: int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ ds@1952: sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ds@1952: sqlite3_vfs_find(0); /* Make sure we are initialized */ ds@1952: sqlite3_mutex_enter(mutex); ds@1952: vfsUnlink(pVfs); ds@1952: if( makeDflt || vfsList==0 ){ ds@1952: pVfs->pNext = vfsList; ds@1952: vfsList = pVfs; ds@1952: }else{ ds@1952: pVfs->pNext = vfsList->pNext; ds@1952: vfsList->pNext = pVfs; ds@1952: } ds@1952: assert(vfsList); ds@1952: sqlite3_mutex_leave(mutex); ds@1952: return SQLITE_OK; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Unregister a VFS so that it is no longer accessible. ds@1952: */ ds@1952: int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ ds@1952: sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ds@1952: sqlite3_mutex_enter(mutex); ds@1952: vfsUnlink(pVfs); ds@1952: assert(vfsList); ds@1952: sqlite3_mutex_leave(mutex); ds@1952: return SQLITE_OK; ds@1952: }