1 /* 2 ** 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 ** 16 ** $Id: os.c,v 1.127 2009/07/27 11:41:21 danielk1977 Exp $ 17 */ 18 #define _SQLITE_OS_C_ 1 19 #include "sqliteInt.h" 20 #undef _SQLITE_OS_C_ 21 22 /* 23 ** The default SQLite sqlite3_vfs implementations do not allocate 24 ** memory (actually, os_unix.c allocates a small amount of memory 25 ** from within OsOpen()), but some third-party implementations may. 26 ** So we test the effects of a malloc() failing and the sqlite3OsXXX() 27 ** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. 28 ** 29 ** The following functions are instrumented for malloc() failure 30 ** testing: 31 ** 32 ** sqlite3OsOpen() 33 ** sqlite3OsRead() 34 ** sqlite3OsWrite() 35 ** sqlite3OsSync() 36 ** sqlite3OsLock() 37 ** 38 */ 39 #if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) 40 #define DO_OS_MALLOC_TEST(x) if (!x || !sqlite3IsMemJournal(x)) { \ 41 void *pTstAlloc = sqlite3Malloc(10); \ 42 if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ 43 sqlite3_free(pTstAlloc); \ 44 } 45 #else 46 #define DO_OS_MALLOC_TEST(x) 47 #endif 48 49 /* 50 ** The following routines are convenience wrappers around methods 51 ** of the sqlite3_file object. This is mostly just syntactic sugar. All 52 ** of this would be completely automatic if SQLite were coded using 53 ** C++ instead of plain old C. 54 */ 55 int sqlite3OsClose(sqlite3_file *pId){ 56 int rc = SQLITE_OK; 57 if( pId->pMethods ){ 58 rc = pId->pMethods->xClose(pId); 59 pId->pMethods = 0; 60 } 61 return rc; 62 } 63 int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ 64 DO_OS_MALLOC_TEST(id); 65 return id->pMethods->xRead(id, pBuf, amt, offset); 66 } 67 int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ 68 DO_OS_MALLOC_TEST(id); 69 return id->pMethods->xWrite(id, pBuf, amt, offset); 70 } 71 int sqlite3OsTruncate(sqlite3_file *id, i64 size){ 72 return id->pMethods->xTruncate(id, size); 73 } 74 int sqlite3OsSync(sqlite3_file *id, int flags){ 75 DO_OS_MALLOC_TEST(id); 76 return id->pMethods->xSync(id, flags); 77 } 78 int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ 79 DO_OS_MALLOC_TEST(id); 80 return id->pMethods->xFileSize(id, pSize); 81 } 82 int sqlite3OsLock(sqlite3_file *id, int lockType){ 83 DO_OS_MALLOC_TEST(id); 84 return id->pMethods->xLock(id, lockType); 85 } 86 int sqlite3OsUnlock(sqlite3_file *id, int lockType){ 87 return id->pMethods->xUnlock(id, lockType); 88 } 89 int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ 90 DO_OS_MALLOC_TEST(id); 91 return id->pMethods->xCheckReservedLock(id, pResOut); 92 } 93 int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ 94 return id->pMethods->xFileControl(id, op, pArg); 95 } 96 int sqlite3OsSectorSize(sqlite3_file *id){ 97 int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; 98 return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); 99 } 100 int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ 101 return id->pMethods->xDeviceCharacteristics(id); 102 } 103 104 /* 105 ** The next group of routines are convenience wrappers around the 106 ** VFS methods. 107 */ 108 int sqlite3OsOpen( 109 sqlite3_vfs *pVfs, 110 const char *zPath, 111 sqlite3_file *pFile, 112 int flags, 113 int *pFlagsOut 114 ){ 115 int rc; 116 DO_OS_MALLOC_TEST(0); 117 rc = pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut); 118 assert( rc==SQLITE_OK || pFile->pMethods==0 ); 119 return rc; 120 } 121 int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ 122 return pVfs->xDelete(pVfs, zPath, dirSync); 123 } 124 int sqlite3OsAccess( 125 sqlite3_vfs *pVfs, 126 const char *zPath, 127 int flags, 128 int *pResOut 129 ){ 130 DO_OS_MALLOC_TEST(0); 131 return pVfs->xAccess(pVfs, zPath, flags, pResOut); 132 } 133 int sqlite3OsFullPathname( 134 sqlite3_vfs *pVfs, 135 const char *zPath, 136 int nPathOut, 137 char *zPathOut 138 ){ 139 return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); 140 } 141 #ifndef SQLITE_OMIT_LOAD_EXTENSION 142 void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ 143 return pVfs->xDlOpen(pVfs, zPath); 144 } 145 void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ 146 pVfs->xDlError(pVfs, nByte, zBufOut); 147 } 148 void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){ 149 return pVfs->xDlSym(pVfs, pHdle, zSym); 150 } 151 void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ 152 pVfs->xDlClose(pVfs, pHandle); 153 } 154 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 155 int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ 156 return pVfs->xRandomness(pVfs, nByte, zBufOut); 157 } 158 int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ 159 return pVfs->xSleep(pVfs, nMicro); 160 } 161 int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ 162 return pVfs->xCurrentTime(pVfs, pTimeOut); 163 } 164 165 int sqlite3OsOpenMalloc( 166 sqlite3_vfs *pVfs, 167 const char *zFile, 168 sqlite3_file **ppFile, 169 int flags, 170 int *pOutFlags 171 ){ 172 int rc = SQLITE_NOMEM; 173 sqlite3_file *pFile; 174 pFile = (sqlite3_file *)sqlite3Malloc(pVfs->szOsFile); 175 if( pFile ){ 176 rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); 177 if( rc!=SQLITE_OK ){ 178 sqlite3_free(pFile); 179 }else{ 180 *ppFile = pFile; 181 } 182 } 183 return rc; 184 } 185 int sqlite3OsCloseFree(sqlite3_file *pFile){ 186 int rc = SQLITE_OK; 187 assert( pFile ); 188 rc = sqlite3OsClose(pFile); 189 sqlite3_free(pFile); 190 return rc; 191 } 192 193 /* 194 ** This function is a wrapper around the OS specific implementation of 195 ** sqlite3_os_init(). The purpose of the wrapper is to provide the 196 ** ability to simulate a malloc failure, so that the handling of an 197 ** error in sqlite3_os_init() by the upper layers can be tested. 198 */ 199 int sqlite3OsInit(void){ 200 void *p = sqlite3_malloc(10); 201 if( p==0 ) return SQLITE_NOMEM; 202 sqlite3_free(p); 203 return sqlite3_os_init(); 204 } 205 206 /* 207 ** The list of all registered VFS implementations. 208 */ 209 static sqlite3_vfs * SQLITE_WSD vfsList = 0; 210 #define vfsList GLOBAL(sqlite3_vfs *, vfsList) 211 212 /* 213 ** Locate a VFS by name. If no name is given, simply return the 214 ** first VFS on the list. 215 */ 216 sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ 217 sqlite3_vfs *pVfs = 0; 218 #if SQLITE_THREADSAFE 219 sqlite3_mutex *mutex; 220 #endif 221 #ifndef SQLITE_OMIT_AUTOINIT 222 int rc = sqlite3_initialize(); 223 if( rc ) return 0; 224 #endif 225 #if SQLITE_THREADSAFE 226 mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); 227 #endif 228 sqlite3_mutex_enter(mutex); 229 for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ 230 if( zVfs==0 ) break; 231 if( strcmp(zVfs, pVfs->zName)==0 ) break; 232 } 233 sqlite3_mutex_leave(mutex); 234 return pVfs; 235 } 236 237 /* 238 ** Unlink a VFS from the linked list 239 */ 240 static void vfsUnlink(sqlite3_vfs *pVfs){ 241 assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) ); 242 if( pVfs==0 ){ 243 /* No-op */ 244 }else if( vfsList==pVfs ){ 245 vfsList = pVfs->pNext; 246 }else if( vfsList ){ 247 sqlite3_vfs *p = vfsList; 248 while( p->pNext && p->pNext!=pVfs ){ 249 p = p->pNext; 250 } 251 if( p->pNext==pVfs ){ 252 p->pNext = pVfs->pNext; 253 } 254 } 255 } 256 257 /* 258 ** Register a VFS with the system. It is harmless to register the same 259 ** VFS multiple times. The new VFS becomes the default if makeDflt is 260 ** true. 261 */ 262 int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ 263 sqlite3_mutex *mutex = 0; 264 #ifndef SQLITE_OMIT_AUTOINIT 265 int rc = sqlite3_initialize(); 266 if( rc ) return rc; 267 #endif 268 mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); 269 sqlite3_mutex_enter(mutex); 270 vfsUnlink(pVfs); 271 if( makeDflt || vfsList==0 ){ 272 pVfs->pNext = vfsList; 273 vfsList = pVfs; 274 }else{ 275 pVfs->pNext = vfsList->pNext; 276 vfsList->pNext = pVfs; 277 } 278 assert(vfsList); 279 sqlite3_mutex_leave(mutex); 280 return SQLITE_OK; 281 } 282 283 /* 284 ** Unregister a VFS so that it is no longer accessible. 285 */ 286 int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ 287 #if SQLITE_THREADSAFE 288 sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); 289 #endif 290 sqlite3_mutex_enter(mutex); 291 vfsUnlink(pVfs); 292 sqlite3_mutex_leave(mutex); 293 return SQLITE_OK; 294 } 295