4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
11 ******************************************************************************
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).
17 #if SQLITE_TEST /* This file is used for testing only */
20 #include "sqliteInt.h"
23 ** Maximum pathname length supported by the devsym backend.
25 #define DEVSYM_MAX_PATHNAME 512
28 ** Name used to identify this VFS.
30 #define DEVSYM_VFS_NAME "devsym"
31 #define WRITECRASH_NAME "writecrash"
33 typedef struct devsym_file devsym_file
;
40 ** Method declarations for devsym_file.
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);
60 ** Method declarations for devsym_vfs.
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*);
82 struct DevsymGlobal g
= {0, 0, 512, 0};
85 ** Close an devsym-file.
87 static int devsymClose(sqlite3_file
*pFile
){
88 devsym_file
*p
= (devsym_file
*)pFile
;
89 sqlite3OsClose(p
->pReal
);
94 ** Read data from an devsym-file.
96 static int devsymRead(
102 devsym_file
*p
= (devsym_file
*)pFile
;
103 return sqlite3OsRead(p
->pReal
, zBuf
, iAmt
, iOfst
);
107 ** Write data to an devsym-file.
109 static int devsymWrite(
115 devsym_file
*p
= (devsym_file
*)pFile
;
116 return sqlite3OsWrite(p
->pReal
, zBuf
, iAmt
, iOfst
);
120 ** Truncate an devsym-file.
122 static int devsymTruncate(sqlite3_file
*pFile
, sqlite_int64 size
){
123 devsym_file
*p
= (devsym_file
*)pFile
;
124 return sqlite3OsTruncate(p
->pReal
, size
);
128 ** Sync an devsym-file.
130 static int devsymSync(sqlite3_file
*pFile
, int flags
){
131 devsym_file
*p
= (devsym_file
*)pFile
;
132 return sqlite3OsSync(p
->pReal
, flags
);
136 ** Return the current file-size of an devsym-file.
138 static int devsymFileSize(sqlite3_file
*pFile
, sqlite_int64
*pSize
){
139 devsym_file
*p
= (devsym_file
*)pFile
;
140 return sqlite3OsFileSize(p
->pReal
, pSize
);
144 ** Lock an devsym-file.
146 static int devsymLock(sqlite3_file
*pFile
, int eLock
){
147 devsym_file
*p
= (devsym_file
*)pFile
;
148 return sqlite3OsLock(p
->pReal
, eLock
);
152 ** Unlock an devsym-file.
154 static int devsymUnlock(sqlite3_file
*pFile
, int eLock
){
155 devsym_file
*p
= (devsym_file
*)pFile
;
156 return sqlite3OsUnlock(p
->pReal
, eLock
);
160 ** Check if another file-handle holds a RESERVED lock on an devsym-file.
162 static int devsymCheckReservedLock(sqlite3_file
*pFile
, int *pResOut
){
163 devsym_file
*p
= (devsym_file
*)pFile
;
164 return sqlite3OsCheckReservedLock(p
->pReal
, pResOut
);
168 ** File control method. For custom operations on an devsym-file.
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
);
176 ** Return the sector-size in bytes for an devsym-file.
178 static int devsymSectorSize(sqlite3_file
*pFile
){
179 return g
.iSectorSize
;
183 ** Return the device characteristic flags supported by an devsym-file.
185 static int devsymDeviceCharacteristics(sqlite3_file
*pFile
){
186 return g
.iDeviceChar
;
190 ** Shared-memory methods are all pass-thrus.
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
);
196 static int devsymShmMap(
203 devsym_file
*p
= (devsym_file
*)pFile
;
204 return p
->pReal
->pMethods
->xShmMap(p
->pReal
, iRegion
, szRegion
, isWrite
, pp
);
206 static void devsymShmBarrier(sqlite3_file
*pFile
){
207 devsym_file
*p
= (devsym_file
*)pFile
;
208 p
->pReal
->pMethods
->xShmBarrier(p
->pReal
);
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
);
218 ** Open an devsym file handle.
220 static int devsymOpen(
227 static sqlite3_io_methods devsym_io_methods
= {
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 */
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
;
258 ** Delete the file located at zPath. If the dirSync argument is true,
259 ** ensure the file-system modifications are synced to disk before
262 static int devsymDelete(sqlite3_vfs
*pVfs
, const char *zPath
, int dirSync
){
263 return sqlite3OsDelete(g
.pVfs
, zPath
, dirSync
);
267 ** Test for access permissions. Return true if the requested permission
268 ** is available, or false otherwise.
270 static int devsymAccess(
276 return sqlite3OsAccess(g
.pVfs
, zPath
, flags
, pResOut
);
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.
284 static int devsymFullPathname(
290 return sqlite3OsFullPathname(g
.pVfs
, zPath
, nOut
, zOut
);
293 #ifndef SQLITE_OMIT_LOAD_EXTENSION
295 ** Open the dynamic library located at zPath and return a handle.
297 static void *devsymDlOpen(sqlite3_vfs
*pVfs
, const char *zPath
){
298 return sqlite3OsDlOpen(g
.pVfs
, zPath
);
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.
306 static void devsymDlError(sqlite3_vfs
*pVfs
, int nByte
, char *zErrMsg
){
307 sqlite3OsDlError(g
.pVfs
, nByte
, zErrMsg
);
311 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
313 static void (*devsymDlSym(sqlite3_vfs
*pVfs
, void *p
, const char *zSym
))(void){
314 return sqlite3OsDlSym(g
.pVfs
, p
, zSym
);
318 ** Close the dynamic library handle pHandle.
320 static void devsymDlClose(sqlite3_vfs
*pVfs
, void *pHandle
){
321 sqlite3OsDlClose(g
.pVfs
, pHandle
);
323 #endif /* SQLITE_OMIT_LOAD_EXTENSION */
326 ** Populate the buffer pointed to by zBufOut with nByte bytes of
329 static int devsymRandomness(sqlite3_vfs
*pVfs
, int nByte
, char *zBufOut
){
330 return sqlite3OsRandomness(g
.pVfs
, nByte
, zBufOut
);
334 ** Sleep for nMicro microseconds. Return the number of microseconds
337 static int devsymSleep(sqlite3_vfs
*pVfs
, int nMicro
){
338 return sqlite3OsSleep(g
.pVfs
, nMicro
);
342 ** Return the current time as a Julian Day number in *pTimeOut.
344 static int devsymCurrentTime(sqlite3_vfs
*pVfs
, double *pTimeOut
){
345 return g
.pVfs
->xCurrentTime(g
.pVfs
, pTimeOut
);
349 ** Return the sector-size in bytes for an writecrash-file.
351 static int writecrashSectorSize(sqlite3_file
*pFile
){
352 devsym_file
*p
= (devsym_file
*)pFile
;
353 return sqlite3OsSectorSize(p
->pReal
);
357 ** Return the device characteristic flags supported by an writecrash-file.
359 static int writecrashDeviceCharacteristics(sqlite3_file
*pFile
){
360 devsym_file
*p
= (devsym_file
*)pFile
;
361 return sqlite3OsDeviceCharacteristics(p
->pReal
);
365 ** Write data to an writecrash-file.
367 static int writecrashWrite(
373 devsym_file
*p
= (devsym_file
*)pFile
;
374 if( g
.nWriteCrash
>0 ){
376 if( g
.nWriteCrash
==0 ) abort();
378 return sqlite3OsWrite(p
->pReal
, zBuf
, iAmt
, iOfst
);
382 ** Open an writecrash file handle.
384 static int writecrashOpen(
391 static sqlite3_io_methods writecrash_io_methods
= {
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 */
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
;
421 static sqlite3_vfs devsym_vfs
= {
423 sizeof(devsym_file
), /* szOsFile */
424 DEVSYM_MAX_PATHNAME
, /* mxPathname */
426 DEVSYM_VFS_NAME
, /* zName */
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 */
442 #endif /* SQLITE_OMIT_LOAD_EXTENSION */
443 devsymRandomness
, /* xRandomness */
444 devsymSleep
, /* xSleep */
445 devsymCurrentTime
, /* xCurrentTime */
446 0, /* xGetLastError */
447 0 /* xCurrentTimeInt64 */
450 static sqlite3_vfs writecrash_vfs
= {
452 sizeof(devsym_file
), /* szOsFile */
453 DEVSYM_MAX_PATHNAME
, /* mxPathname */
455 WRITECRASH_NAME
, /* zName */
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 */
471 #endif /* SQLITE_OMIT_LOAD_EXTENSION */
472 devsymRandomness
, /* xRandomness */
473 devsymSleep
, /* xSleep */
474 devsymCurrentTime
, /* xCurrentTime */
475 0, /* xGetLastError */
476 0 /* xCurrentTimeInt64 */
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.
485 void devsym_register(int iDeviceChar
, int iSectorSize
){
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);
494 if( iDeviceChar
>=0 ){
495 g
.iDeviceChar
= iDeviceChar
;
499 if( iSectorSize
>=0 ){
500 g
.iSectorSize
= iSectorSize
;
506 void devsym_unregister(){
507 sqlite3_vfs_unregister(&devsym_vfs
);
508 sqlite3_vfs_unregister(&writecrash_vfs
);
514 void devsym_crash_on_write(int nWrite
){
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);
522 g
.nWriteCrash
= nWrite
;