1 /* 2 ** 2008 Jan 22 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 code that modified the OS layer in order to simulate 14 ** different device types (by overriding the return values of the 15 ** xDeviceCharacteristics() and xSectorSize() methods). 16 */ 17 #if SQLITE_TEST /* This file is used for testing only */ 18 19 #include "sqlite3.h" 20 #include "sqliteInt.h" 21 22 /* 23 ** Maximum pathname length supported by the devsym backend. 24 */ 25 #define DEVSYM_MAX_PATHNAME 512 26 27 /* 28 ** Name used to identify this VFS. 29 */ 30 #define DEVSYM_VFS_NAME "devsym" 31 32 typedef struct devsym_file devsym_file; 33 struct devsym_file { 34 sqlite3_file base; 35 sqlite3_file *pReal; 36 }; 37 38 /* 39 ** Method declarations for devsym_file. 40 */ 41 static int devsymClose(sqlite3_file*); 42 static int devsymRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); 43 static int devsymWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); 44 static int devsymTruncate(sqlite3_file*, sqlite3_int64 size); 45 static int devsymSync(sqlite3_file*, int flags); 46 static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize); 47 static int devsymLock(sqlite3_file*, int); 48 static int devsymUnlock(sqlite3_file*, int); 49 static int devsymCheckReservedLock(sqlite3_file*, int *); 50 static int devsymFileControl(sqlite3_file*, int op, void *pArg); 51 static int devsymSectorSize(sqlite3_file*); 52 static int devsymDeviceCharacteristics(sqlite3_file*); 53 54 /* 55 ** Method declarations for devsym_vfs. 56 */ 57 static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); 58 static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir); 59 static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *); 60 static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); 61 #ifndef SQLITE_OMIT_LOAD_EXTENSION 62 static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename); 63 static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg); 64 static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); 65 static void devsymDlClose(sqlite3_vfs*, void*); 66 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 67 static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut); 68 static int devsymSleep(sqlite3_vfs*, int microseconds); 69 static int devsymCurrentTime(sqlite3_vfs*, double*); 70 71 static int devsymShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **); 72 static int devsymShmSize(sqlite3_shm *, int , int *); 73 static int devsymShmGet(sqlite3_shm *, int , int *, void **); 74 static int devsymShmRelease(sqlite3_shm *); 75 static int devsymShmLock(sqlite3_shm *, int , int *); 76 static int devsymShmClose(sqlite3_shm *, int); 77 78 static sqlite3_vfs devsym_vfs = { 79 2, /* iVersion */ 80 sizeof(devsym_file), /* szOsFile */ 81 DEVSYM_MAX_PATHNAME, /* mxPathname */ 82 0, /* pNext */ 83 DEVSYM_VFS_NAME, /* zName */ 84 0, /* pAppData */ 85 devsymOpen, /* xOpen */ 86 devsymDelete, /* xDelete */ 87 devsymAccess, /* xAccess */ 88 devsymFullPathname, /* xFullPathname */ 89 #ifndef SQLITE_OMIT_LOAD_EXTENSION 90 devsymDlOpen, /* xDlOpen */ 91 devsymDlError, /* xDlError */ 92 devsymDlSym, /* xDlSym */ 93 devsymDlClose, /* xDlClose */ 94 #else 95 0, /* xDlOpen */ 96 0, /* xDlError */ 97 0, /* xDlSym */ 98 0, /* xDlClose */ 99 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 100 devsymRandomness, /* xRandomness */ 101 devsymSleep, /* xSleep */ 102 devsymCurrentTime, /* xCurrentTime */ 103 0, /* xGetLastError */ 104 devsymShmOpen, 105 devsymShmSize, 106 devsymShmGet, 107 devsymShmRelease, 108 0, 109 0, 110 devsymShmLock, 111 devsymShmClose, 112 0, 113 0, 114 }; 115 116 static sqlite3_io_methods devsym_io_methods = { 117 1, /* iVersion */ 118 devsymClose, /* xClose */ 119 devsymRead, /* xRead */ 120 devsymWrite, /* xWrite */ 121 devsymTruncate, /* xTruncate */ 122 devsymSync, /* xSync */ 123 devsymFileSize, /* xFileSize */ 124 devsymLock, /* xLock */ 125 devsymUnlock, /* xUnlock */ 126 devsymCheckReservedLock, /* xCheckReservedLock */ 127 devsymFileControl, /* xFileControl */ 128 devsymSectorSize, /* xSectorSize */ 129 devsymDeviceCharacteristics /* xDeviceCharacteristics */ 130 }; 131 132 struct DevsymGlobal { 133 sqlite3_vfs *pVfs; 134 int iDeviceChar; 135 int iSectorSize; 136 }; 137 struct DevsymGlobal g = {0, 0, 512}; 138 139 /* 140 ** Close an devsym-file. 141 */ 142 static int devsymClose(sqlite3_file *pFile){ 143 devsym_file *p = (devsym_file *)pFile; 144 return sqlite3OsClose(p->pReal); 145 } 146 147 /* 148 ** Read data from an devsym-file. 149 */ 150 static int devsymRead( 151 sqlite3_file *pFile, 152 void *zBuf, 153 int iAmt, 154 sqlite_int64 iOfst 155 ){ 156 devsym_file *p = (devsym_file *)pFile; 157 return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); 158 } 159 160 /* 161 ** Write data to an devsym-file. 162 */ 163 static int devsymWrite( 164 sqlite3_file *pFile, 165 const void *zBuf, 166 int iAmt, 167 sqlite_int64 iOfst 168 ){ 169 devsym_file *p = (devsym_file *)pFile; 170 return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); 171 } 172 173 /* 174 ** Truncate an devsym-file. 175 */ 176 static int devsymTruncate(sqlite3_file *pFile, sqlite_int64 size){ 177 devsym_file *p = (devsym_file *)pFile; 178 return sqlite3OsTruncate(p->pReal, size); 179 } 180 181 /* 182 ** Sync an devsym-file. 183 */ 184 static int devsymSync(sqlite3_file *pFile, int flags){ 185 devsym_file *p = (devsym_file *)pFile; 186 return sqlite3OsSync(p->pReal, flags); 187 } 188 189 /* 190 ** Return the current file-size of an devsym-file. 191 */ 192 static int devsymFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ 193 devsym_file *p = (devsym_file *)pFile; 194 return sqlite3OsFileSize(p->pReal, pSize); 195 } 196 197 /* 198 ** Lock an devsym-file. 199 */ 200 static int devsymLock(sqlite3_file *pFile, int eLock){ 201 devsym_file *p = (devsym_file *)pFile; 202 return sqlite3OsLock(p->pReal, eLock); 203 } 204 205 /* 206 ** Unlock an devsym-file. 207 */ 208 static int devsymUnlock(sqlite3_file *pFile, int eLock){ 209 devsym_file *p = (devsym_file *)pFile; 210 return sqlite3OsUnlock(p->pReal, eLock); 211 } 212 213 /* 214 ** Check if another file-handle holds a RESERVED lock on an devsym-file. 215 */ 216 static int devsymCheckReservedLock(sqlite3_file *pFile, int *pResOut){ 217 devsym_file *p = (devsym_file *)pFile; 218 return sqlite3OsCheckReservedLock(p->pReal, pResOut); 219 } 220 221 /* 222 ** File control method. For custom operations on an devsym-file. 223 */ 224 static int devsymFileControl(sqlite3_file *pFile, int op, void *pArg){ 225 devsym_file *p = (devsym_file *)pFile; 226 return sqlite3OsFileControl(p->pReal, op, pArg); 227 } 228 229 /* 230 ** Return the sector-size in bytes for an devsym-file. 231 */ 232 static int devsymSectorSize(sqlite3_file *pFile){ 233 return g.iSectorSize; 234 } 235 236 /* 237 ** Return the device characteristic flags supported by an devsym-file. 238 */ 239 static int devsymDeviceCharacteristics(sqlite3_file *pFile){ 240 return g.iDeviceChar; 241 } 242 243 /* 244 ** Open an devsym file handle. 245 */ 246 static int devsymOpen( 247 sqlite3_vfs *pVfs, 248 const char *zName, 249 sqlite3_file *pFile, 250 int flags, 251 int *pOutFlags 252 ){ 253 int rc; 254 devsym_file *p = (devsym_file *)pFile; 255 p->pReal = (sqlite3_file *)&p[1]; 256 rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); 257 if( p->pReal->pMethods ){ 258 pFile->pMethods = &devsym_io_methods; 259 } 260 return rc; 261 } 262 263 /* 264 ** Delete the file located at zPath. If the dirSync argument is true, 265 ** ensure the file-system modifications are synced to disk before 266 ** returning. 267 */ 268 static int devsymDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ 269 return sqlite3OsDelete(g.pVfs, zPath, dirSync); 270 } 271 272 /* 273 ** Test for access permissions. Return true if the requested permission 274 ** is available, or false otherwise. 275 */ 276 static int devsymAccess( 277 sqlite3_vfs *pVfs, 278 const char *zPath, 279 int flags, 280 int *pResOut 281 ){ 282 return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut); 283 } 284 285 /* 286 ** Populate buffer zOut with the full canonical pathname corresponding 287 ** to the pathname in zPath. zOut is guaranteed to point to a buffer 288 ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. 289 */ 290 static int devsymFullPathname( 291 sqlite3_vfs *pVfs, 292 const char *zPath, 293 int nOut, 294 char *zOut 295 ){ 296 return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut); 297 } 298 299 #ifndef SQLITE_OMIT_LOAD_EXTENSION 300 /* 301 ** Open the dynamic library located at zPath and return a handle. 302 */ 303 static void *devsymDlOpen(sqlite3_vfs *pVfs, const char *zPath){ 304 return sqlite3OsDlOpen(g.pVfs, zPath); 305 } 306 307 /* 308 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable 309 ** utf-8 string describing the most recent error encountered associated 310 ** with dynamic libraries. 311 */ 312 static void devsymDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ 313 sqlite3OsDlError(g.pVfs, nByte, zErrMsg); 314 } 315 316 /* 317 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle. 318 */ 319 static void (*devsymDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ 320 return sqlite3OsDlSym(g.pVfs, p, zSym); 321 } 322 323 /* 324 ** Close the dynamic library handle pHandle. 325 */ 326 static void devsymDlClose(sqlite3_vfs *pVfs, void *pHandle){ 327 sqlite3OsDlClose(g.pVfs, pHandle); 328 } 329 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 330 331 /* 332 ** Populate the buffer pointed to by zBufOut with nByte bytes of 333 ** random data. 334 */ 335 static int devsymRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ 336 return sqlite3OsRandomness(g.pVfs, nByte, zBufOut); 337 } 338 339 /* 340 ** Sleep for nMicro microseconds. Return the number of microseconds 341 ** actually slept. 342 */ 343 static int devsymSleep(sqlite3_vfs *pVfs, int nMicro){ 344 return sqlite3OsSleep(g.pVfs, nMicro); 345 } 346 347 /* 348 ** Return the current time as a Julian Day number in *pTimeOut. 349 */ 350 static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ 351 return sqlite3OsCurrentTime(g.pVfs, pTimeOut); 352 } 353 354 355 static int devsymShmOpen( 356 sqlite3_vfs *pVfs, 357 const char *zName, 358 sqlite3_shm **pp 359 ){ 360 return g.pVfs->xShmOpen(g.pVfs, zName, pp); 361 } 362 static int devsymShmSize(sqlite3_shm *p, int reqSize, int *pNewSize){ 363 return g.pVfs->xShmSize(p, reqSize, pNewSize); 364 } 365 static int devsymShmGet( 366 sqlite3_shm *p, 367 int reqMapSize, 368 int *pMapSize, 369 void **pp 370 ){ 371 return g.pVfs->xShmGet(p, reqMapSize, pMapSize, pp); 372 } 373 static int devsymShmRelease(sqlite3_shm *p){ 374 return g.pVfs->xShmRelease(p); 375 } 376 static int devsymShmLock(sqlite3_shm *p, int desiredLock, int *gotLock){ 377 return g.pVfs->xShmLock(p, desiredLock, gotLock); 378 } 379 static int devsymShmClose(sqlite3_shm *p, int deleteFlag){ 380 return g.pVfs->xShmClose(p, deleteFlag); 381 } 382 383 /* 384 ** This procedure registers the devsym vfs with SQLite. If the argument is 385 ** true, the devsym vfs becomes the new default vfs. It is the only publicly 386 ** available function in this file. 387 */ 388 void devsym_register(int iDeviceChar, int iSectorSize){ 389 if( g.pVfs==0 ){ 390 g.pVfs = sqlite3_vfs_find(0); 391 devsym_vfs.szOsFile += g.pVfs->szOsFile; 392 devsym_vfs.xShmOpen = (g.pVfs->xShmOpen ? devsymShmOpen : 0); 393 devsym_vfs.xShmSize = (g.pVfs->xShmSize ? devsymShmSize : 0); 394 devsym_vfs.xShmGet = (g.pVfs->xShmGet ? devsymShmGet : 0); 395 devsym_vfs.xShmRelease = (g.pVfs->xShmRelease ? devsymShmRelease : 0); 396 devsym_vfs.xShmLock = (g.pVfs->xShmLock ? devsymShmLock : 0); 397 devsym_vfs.xShmClose = (g.pVfs->xShmClose ? devsymShmClose : 0); 398 sqlite3_vfs_register(&devsym_vfs, 0); 399 } 400 if( iDeviceChar>=0 ){ 401 g.iDeviceChar = iDeviceChar; 402 }else{ 403 g.iDeviceChar = 0; 404 } 405 if( iSectorSize>=0 ){ 406 g.iSectorSize = iSectorSize; 407 }else{ 408 g.iSectorSize = 512; 409 } 410 } 411 412 #endif 413