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 #define WRITECRASH_NAME "writecrash" 32 33 typedef struct devsym_file devsym_file; 34 struct devsym_file { 35 sqlite3_file base; 36 sqlite3_file *pReal; 37 }; 38 39 /* 40 ** Method declarations for devsym_file. 41 */ 42 static int devsymClose(sqlite3_file*); 43 static int devsymRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); 44 static int devsymWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); 45 static int devsymTruncate(sqlite3_file*, sqlite3_int64 size); 46 static int devsymSync(sqlite3_file*, int flags); 47 static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize); 48 static int devsymLock(sqlite3_file*, int); 49 static int devsymUnlock(sqlite3_file*, int); 50 static int devsymCheckReservedLock(sqlite3_file*, int *); 51 static int devsymFileControl(sqlite3_file*, int op, void *pArg); 52 static int devsymSectorSize(sqlite3_file*); 53 static int devsymDeviceCharacteristics(sqlite3_file*); 54 static int devsymShmLock(sqlite3_file*,int,int,int); 55 static int devsymShmMap(sqlite3_file*,int,int,int, void volatile **); 56 static void devsymShmBarrier(sqlite3_file*); 57 static int devsymShmUnmap(sqlite3_file*,int); 58 59 /* 60 ** Method declarations for devsym_vfs. 61 */ 62 static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); 63 static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir); 64 static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *); 65 static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); 66 #ifndef SQLITE_OMIT_LOAD_EXTENSION 67 static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename); 68 static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg); 69 static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void); 70 static void devsymDlClose(sqlite3_vfs*, void*); 71 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 72 static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut); 73 static int devsymSleep(sqlite3_vfs*, int microseconds); 74 static int devsymCurrentTime(sqlite3_vfs*, double*); 75 76 struct DevsymGlobal { 77 sqlite3_vfs *pVfs; 78 int iDeviceChar; 79 int iSectorSize; 80 int nWriteCrash; 81 }; 82 struct DevsymGlobal g = {0, 0, 512, 0}; 83 84 /* 85 ** Close an devsym-file. 86 */ 87 static int devsymClose(sqlite3_file *pFile){ 88 devsym_file *p = (devsym_file *)pFile; 89 sqlite3OsClose(p->pReal); 90 return SQLITE_OK; 91 } 92 93 /* 94 ** Read data from an devsym-file. 95 */ 96 static int devsymRead( 97 sqlite3_file *pFile, 98 void *zBuf, 99 int iAmt, 100 sqlite_int64 iOfst 101 ){ 102 devsym_file *p = (devsym_file *)pFile; 103 return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); 104 } 105 106 /* 107 ** Write data to an devsym-file. 108 */ 109 static int devsymWrite( 110 sqlite3_file *pFile, 111 const void *zBuf, 112 int iAmt, 113 sqlite_int64 iOfst 114 ){ 115 devsym_file *p = (devsym_file *)pFile; 116 return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); 117 } 118 119 /* 120 ** Truncate an devsym-file. 121 */ 122 static int devsymTruncate(sqlite3_file *pFile, sqlite_int64 size){ 123 devsym_file *p = (devsym_file *)pFile; 124 return sqlite3OsTruncate(p->pReal, size); 125 } 126 127 /* 128 ** Sync an devsym-file. 129 */ 130 static int devsymSync(sqlite3_file *pFile, int flags){ 131 devsym_file *p = (devsym_file *)pFile; 132 return sqlite3OsSync(p->pReal, flags); 133 } 134 135 /* 136 ** Return the current file-size of an devsym-file. 137 */ 138 static int devsymFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ 139 devsym_file *p = (devsym_file *)pFile; 140 return sqlite3OsFileSize(p->pReal, pSize); 141 } 142 143 /* 144 ** Lock an devsym-file. 145 */ 146 static int devsymLock(sqlite3_file *pFile, int eLock){ 147 devsym_file *p = (devsym_file *)pFile; 148 return sqlite3OsLock(p->pReal, eLock); 149 } 150 151 /* 152 ** Unlock an devsym-file. 153 */ 154 static int devsymUnlock(sqlite3_file *pFile, int eLock){ 155 devsym_file *p = (devsym_file *)pFile; 156 return sqlite3OsUnlock(p->pReal, eLock); 157 } 158 159 /* 160 ** Check if another file-handle holds a RESERVED lock on an devsym-file. 161 */ 162 static int devsymCheckReservedLock(sqlite3_file *pFile, int *pResOut){ 163 devsym_file *p = (devsym_file *)pFile; 164 return sqlite3OsCheckReservedLock(p->pReal, pResOut); 165 } 166 167 /* 168 ** File control method. For custom operations on an devsym-file. 169 */ 170 static int devsymFileControl(sqlite3_file *pFile, int op, void *pArg){ 171 devsym_file *p = (devsym_file *)pFile; 172 return sqlite3OsFileControl(p->pReal, op, pArg); 173 } 174 175 /* 176 ** Return the sector-size in bytes for an devsym-file. 177 */ 178 static int devsymSectorSize(sqlite3_file *pFile){ 179 return g.iSectorSize; 180 } 181 182 /* 183 ** Return the device characteristic flags supported by an devsym-file. 184 */ 185 static int devsymDeviceCharacteristics(sqlite3_file *pFile){ 186 return g.iDeviceChar; 187 } 188 189 /* 190 ** Shared-memory methods are all pass-thrus. 191 */ 192 static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ 193 devsym_file *p = (devsym_file *)pFile; 194 return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); 195 } 196 static int devsymShmMap( 197 sqlite3_file *pFile, 198 int iRegion, 199 int szRegion, 200 int isWrite, 201 void volatile **pp 202 ){ 203 devsym_file *p = (devsym_file *)pFile; 204 return p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp); 205 } 206 static void devsymShmBarrier(sqlite3_file *pFile){ 207 devsym_file *p = (devsym_file *)pFile; 208 p->pReal->pMethods->xShmBarrier(p->pReal); 209 } 210 static int devsymShmUnmap(sqlite3_file *pFile, int delFlag){ 211 devsym_file *p = (devsym_file *)pFile; 212 return p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); 213 } 214 215 216 217 /* 218 ** Open an devsym file handle. 219 */ 220 static int devsymOpen( 221 sqlite3_vfs *pVfs, 222 const char *zName, 223 sqlite3_file *pFile, 224 int flags, 225 int *pOutFlags 226 ){ 227 static sqlite3_io_methods devsym_io_methods = { 228 2, /* iVersion */ 229 devsymClose, /* xClose */ 230 devsymRead, /* xRead */ 231 devsymWrite, /* xWrite */ 232 devsymTruncate, /* xTruncate */ 233 devsymSync, /* xSync */ 234 devsymFileSize, /* xFileSize */ 235 devsymLock, /* xLock */ 236 devsymUnlock, /* xUnlock */ 237 devsymCheckReservedLock, /* xCheckReservedLock */ 238 devsymFileControl, /* xFileControl */ 239 devsymSectorSize, /* xSectorSize */ 240 devsymDeviceCharacteristics, /* xDeviceCharacteristics */ 241 devsymShmMap, /* xShmMap */ 242 devsymShmLock, /* xShmLock */ 243 devsymShmBarrier, /* xShmBarrier */ 244 devsymShmUnmap /* xShmUnmap */ 245 }; 246 247 int rc; 248 devsym_file *p = (devsym_file *)pFile; 249 p->pReal = (sqlite3_file *)&p[1]; 250 rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); 251 if( p->pReal->pMethods ){ 252 pFile->pMethods = &devsym_io_methods; 253 } 254 return rc; 255 } 256 257 /* 258 ** Delete the file located at zPath. If the dirSync argument is true, 259 ** ensure the file-system modifications are synced to disk before 260 ** returning. 261 */ 262 static int devsymDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ 263 return sqlite3OsDelete(g.pVfs, zPath, dirSync); 264 } 265 266 /* 267 ** Test for access permissions. Return true if the requested permission 268 ** is available, or false otherwise. 269 */ 270 static int devsymAccess( 271 sqlite3_vfs *pVfs, 272 const char *zPath, 273 int flags, 274 int *pResOut 275 ){ 276 return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut); 277 } 278 279 /* 280 ** Populate buffer zOut with the full canonical pathname corresponding 281 ** to the pathname in zPath. zOut is guaranteed to point to a buffer 282 ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. 283 */ 284 static int devsymFullPathname( 285 sqlite3_vfs *pVfs, 286 const char *zPath, 287 int nOut, 288 char *zOut 289 ){ 290 return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut); 291 } 292 293 #ifndef SQLITE_OMIT_LOAD_EXTENSION 294 /* 295 ** Open the dynamic library located at zPath and return a handle. 296 */ 297 static void *devsymDlOpen(sqlite3_vfs *pVfs, const char *zPath){ 298 return sqlite3OsDlOpen(g.pVfs, zPath); 299 } 300 301 /* 302 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable 303 ** utf-8 string describing the most recent error encountered associated 304 ** with dynamic libraries. 305 */ 306 static void devsymDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ 307 sqlite3OsDlError(g.pVfs, nByte, zErrMsg); 308 } 309 310 /* 311 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle. 312 */ 313 static void (*devsymDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ 314 return sqlite3OsDlSym(g.pVfs, p, zSym); 315 } 316 317 /* 318 ** Close the dynamic library handle pHandle. 319 */ 320 static void devsymDlClose(sqlite3_vfs *pVfs, void *pHandle){ 321 sqlite3OsDlClose(g.pVfs, pHandle); 322 } 323 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 324 325 /* 326 ** Populate the buffer pointed to by zBufOut with nByte bytes of 327 ** random data. 328 */ 329 static int devsymRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ 330 return sqlite3OsRandomness(g.pVfs, nByte, zBufOut); 331 } 332 333 /* 334 ** Sleep for nMicro microseconds. Return the number of microseconds 335 ** actually slept. 336 */ 337 static int devsymSleep(sqlite3_vfs *pVfs, int nMicro){ 338 return sqlite3OsSleep(g.pVfs, nMicro); 339 } 340 341 /* 342 ** Return the current time as a Julian Day number in *pTimeOut. 343 */ 344 static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ 345 return g.pVfs->xCurrentTime(g.pVfs, pTimeOut); 346 } 347 348 /* 349 ** Return the sector-size in bytes for an writecrash-file. 350 */ 351 static int writecrashSectorSize(sqlite3_file *pFile){ 352 devsym_file *p = (devsym_file *)pFile; 353 return sqlite3OsSectorSize(p->pReal); 354 } 355 356 /* 357 ** Return the device characteristic flags supported by an writecrash-file. 358 */ 359 static int writecrashDeviceCharacteristics(sqlite3_file *pFile){ 360 devsym_file *p = (devsym_file *)pFile; 361 return sqlite3OsDeviceCharacteristics(p->pReal); 362 } 363 364 /* 365 ** Write data to an writecrash-file. 366 */ 367 static int writecrashWrite( 368 sqlite3_file *pFile, 369 const void *zBuf, 370 int iAmt, 371 sqlite_int64 iOfst 372 ){ 373 devsym_file *p = (devsym_file *)pFile; 374 if( g.nWriteCrash>0 ){ 375 g.nWriteCrash--; 376 if( g.nWriteCrash==0 ) abort(); 377 } 378 return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); 379 } 380 381 /* 382 ** Open an writecrash file handle. 383 */ 384 static int writecrashOpen( 385 sqlite3_vfs *pVfs, 386 const char *zName, 387 sqlite3_file *pFile, 388 int flags, 389 int *pOutFlags 390 ){ 391 static sqlite3_io_methods writecrash_io_methods = { 392 2, /* iVersion */ 393 devsymClose, /* xClose */ 394 devsymRead, /* xRead */ 395 writecrashWrite, /* xWrite */ 396 devsymTruncate, /* xTruncate */ 397 devsymSync, /* xSync */ 398 devsymFileSize, /* xFileSize */ 399 devsymLock, /* xLock */ 400 devsymUnlock, /* xUnlock */ 401 devsymCheckReservedLock, /* xCheckReservedLock */ 402 devsymFileControl, /* xFileControl */ 403 writecrashSectorSize, /* xSectorSize */ 404 writecrashDeviceCharacteristics, /* xDeviceCharacteristics */ 405 devsymShmMap, /* xShmMap */ 406 devsymShmLock, /* xShmLock */ 407 devsymShmBarrier, /* xShmBarrier */ 408 devsymShmUnmap /* xShmUnmap */ 409 }; 410 411 int rc; 412 devsym_file *p = (devsym_file *)pFile; 413 p->pReal = (sqlite3_file *)&p[1]; 414 rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags); 415 if( p->pReal->pMethods ){ 416 pFile->pMethods = &writecrash_io_methods; 417 } 418 return rc; 419 } 420 421 static sqlite3_vfs devsym_vfs = { 422 2, /* iVersion */ 423 sizeof(devsym_file), /* szOsFile */ 424 DEVSYM_MAX_PATHNAME, /* mxPathname */ 425 0, /* pNext */ 426 DEVSYM_VFS_NAME, /* zName */ 427 0, /* pAppData */ 428 devsymOpen, /* xOpen */ 429 devsymDelete, /* xDelete */ 430 devsymAccess, /* xAccess */ 431 devsymFullPathname, /* xFullPathname */ 432 #ifndef SQLITE_OMIT_LOAD_EXTENSION 433 devsymDlOpen, /* xDlOpen */ 434 devsymDlError, /* xDlError */ 435 devsymDlSym, /* xDlSym */ 436 devsymDlClose, /* xDlClose */ 437 #else 438 0, /* xDlOpen */ 439 0, /* xDlError */ 440 0, /* xDlSym */ 441 0, /* xDlClose */ 442 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 443 devsymRandomness, /* xRandomness */ 444 devsymSleep, /* xSleep */ 445 devsymCurrentTime, /* xCurrentTime */ 446 0, /* xGetLastError */ 447 0 /* xCurrentTimeInt64 */ 448 }; 449 450 static sqlite3_vfs writecrash_vfs = { 451 2, /* iVersion */ 452 sizeof(devsym_file), /* szOsFile */ 453 DEVSYM_MAX_PATHNAME, /* mxPathname */ 454 0, /* pNext */ 455 WRITECRASH_NAME, /* zName */ 456 0, /* pAppData */ 457 writecrashOpen, /* xOpen */ 458 devsymDelete, /* xDelete */ 459 devsymAccess, /* xAccess */ 460 devsymFullPathname, /* xFullPathname */ 461 #ifndef SQLITE_OMIT_LOAD_EXTENSION 462 devsymDlOpen, /* xDlOpen */ 463 devsymDlError, /* xDlError */ 464 devsymDlSym, /* xDlSym */ 465 devsymDlClose, /* xDlClose */ 466 #else 467 0, /* xDlOpen */ 468 0, /* xDlError */ 469 0, /* xDlSym */ 470 0, /* xDlClose */ 471 #endif /* SQLITE_OMIT_LOAD_EXTENSION */ 472 devsymRandomness, /* xRandomness */ 473 devsymSleep, /* xSleep */ 474 devsymCurrentTime, /* xCurrentTime */ 475 0, /* xGetLastError */ 476 0 /* xCurrentTimeInt64 */ 477 }; 478 479 480 /* 481 ** This procedure registers the devsym vfs with SQLite. If the argument is 482 ** true, the devsym vfs becomes the new default vfs. It is the only publicly 483 ** available function in this file. 484 */ 485 void devsym_register(int iDeviceChar, int iSectorSize){ 486 487 if( g.pVfs==0 ){ 488 g.pVfs = sqlite3_vfs_find(0); 489 devsym_vfs.szOsFile += g.pVfs->szOsFile; 490 writecrash_vfs.szOsFile += g.pVfs->szOsFile; 491 sqlite3_vfs_register(&devsym_vfs, 0); 492 sqlite3_vfs_register(&writecrash_vfs, 0); 493 } 494 if( iDeviceChar>=0 ){ 495 g.iDeviceChar = iDeviceChar; 496 }else{ 497 g.iDeviceChar = 0; 498 } 499 if( iSectorSize>=0 ){ 500 g.iSectorSize = iSectorSize; 501 }else{ 502 g.iSectorSize = 512; 503 } 504 } 505 506 void devsym_unregister(){ 507 sqlite3_vfs_unregister(&devsym_vfs); 508 sqlite3_vfs_unregister(&writecrash_vfs); 509 g.pVfs = 0; 510 g.iDeviceChar = 0; 511 g.iSectorSize = 0; 512 } 513 514 void devsym_crash_on_write(int nWrite){ 515 if( g.pVfs==0 ){ 516 g.pVfs = sqlite3_vfs_find(0); 517 devsym_vfs.szOsFile += g.pVfs->szOsFile; 518 writecrash_vfs.szOsFile += g.pVfs->szOsFile; 519 sqlite3_vfs_register(&devsym_vfs, 0); 520 sqlite3_vfs_register(&writecrash_vfs, 0); 521 } 522 g.nWriteCrash = nWrite; 523 } 524 525 #endif 526