xref: /sqlite-3.40.0/src/test_devsym.c (revision 6a5e2114)
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