Modify the sqlite3OsFileControl() interface to detect unopened sqlite3_file
[sqlite.git] / src / test_devsym.c
blob0da6671cf4c48832dc35bcee80f802291f9a7313
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.
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 */
19 #include "sqlite3.h"
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;
34 struct devsym_file {
35 sqlite3_file base;
36 sqlite3_file *pReal;
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*);
76 struct DevsymGlobal {
77 sqlite3_vfs *pVfs;
78 int iDeviceChar;
79 int iSectorSize;
80 int nWriteCrash;
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);
90 return SQLITE_OK;
94 ** Read data from an devsym-file.
96 static int devsymRead(
97 sqlite3_file *pFile,
98 void *zBuf,
99 int iAmt,
100 sqlite_int64 iOfst
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(
110 sqlite3_file *pFile,
111 const void *zBuf,
112 int iAmt,
113 sqlite_int64 iOfst
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 sqlite3OsShmLock(p->pReal, ofst, n, flags);
196 static int devsymShmMap(
197 sqlite3_file *pFile,
198 int iRegion,
199 int szRegion,
200 int isWrite,
201 void volatile **pp
203 devsym_file *p = (devsym_file *)pFile;
204 return sqlite3OsShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
206 static void devsymShmBarrier(sqlite3_file *pFile){
207 devsym_file *p = (devsym_file *)pFile;
208 sqlite3OsShmBarrier(p->pReal);
210 static int devsymShmUnmap(sqlite3_file *pFile, int delFlag){
211 devsym_file *p = (devsym_file *)pFile;
212 return sqlite3OsShmUnmap(p->pReal, delFlag);
218 ** Open an devsym file handle.
220 static int devsymOpen(
221 sqlite3_vfs *pVfs,
222 const char *zName,
223 sqlite3_file *pFile,
224 int flags,
225 int *pOutFlags
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 */
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;
254 return rc;
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.
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(
271 sqlite3_vfs *pVfs,
272 const char *zPath,
273 int flags,
274 int *pResOut
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(
285 sqlite3_vfs *pVfs,
286 const char *zPath,
287 int nOut,
288 char *zOut
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
327 ** random data.
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
335 ** actually slept.
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(
368 sqlite3_file *pFile,
369 const void *zBuf,
370 int iAmt,
371 sqlite_int64 iOfst
373 devsym_file *p = (devsym_file *)pFile;
374 if( g.nWriteCrash>0 ){
375 g.nWriteCrash--;
376 if( g.nWriteCrash==0 ) abort();
378 return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
382 ** Open an writecrash file handle.
384 static int writecrashOpen(
385 sqlite3_vfs *pVfs,
386 const char *zName,
387 sqlite3_file *pFile,
388 int flags,
389 int *pOutFlags
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 */
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;
418 return rc;
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 */
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 */
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){
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);
494 if( iDeviceChar>=0 ){
495 g.iDeviceChar = iDeviceChar;
496 }else{
497 g.iDeviceChar = 0;
499 if( iSectorSize>=0 ){
500 g.iSectorSize = iSectorSize;
501 }else{
502 g.iSectorSize = 512;
506 void devsym_unregister(){
507 sqlite3_vfs_unregister(&devsym_vfs);
508 g.pVfs = 0;
509 g.iDeviceChar = 0;
510 g.iSectorSize = 0;
513 void devsym_crash_on_write(int nWrite){
514 if( g.pVfs==0 ){
515 g.pVfs = sqlite3_vfs_find(0);
516 devsym_vfs.szOsFile += g.pVfs->szOsFile;
517 writecrash_vfs.szOsFile += g.pVfs->szOsFile;
518 sqlite3_vfs_register(&devsym_vfs, 0);
519 sqlite3_vfs_register(&writecrash_vfs, 0);
521 g.nWriteCrash = nWrite;
524 #endif