blob: 23354312c5d13ac3a4c3472eb51227371a738201 [file] [log] [blame]
danielk1977bf260972008-01-22 11:50:13 +00001/*
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
mlcreechfb80d202008-03-09 02:00:19 +000019#include "sqlite3.h"
danielk1977bf260972008-01-22 11:50:13 +000020#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"
dan33447e72017-07-22 20:12:31 +000031#define WRITECRASH_NAME "writecrash"
danielk1977bf260972008-01-22 11:50:13 +000032
33typedef struct devsym_file devsym_file;
34struct devsym_file {
35 sqlite3_file base;
36 sqlite3_file *pReal;
37};
38
39/*
40** Method declarations for devsym_file.
41*/
42static int devsymClose(sqlite3_file*);
43static int devsymRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
44static int devsymWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
45static int devsymTruncate(sqlite3_file*, sqlite3_int64 size);
46static int devsymSync(sqlite3_file*, int flags);
47static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize);
48static int devsymLock(sqlite3_file*, int);
49static int devsymUnlock(sqlite3_file*, int);
danielk1977861f7452008-06-05 11:39:11 +000050static int devsymCheckReservedLock(sqlite3_file*, int *);
danielk1977bf260972008-01-22 11:50:13 +000051static int devsymFileControl(sqlite3_file*, int op, void *pArg);
52static int devsymSectorSize(sqlite3_file*);
53static int devsymDeviceCharacteristics(sqlite3_file*);
drh73b64e42010-05-30 19:55:15 +000054static int devsymShmLock(sqlite3_file*,int,int,int);
drh6b017cc2010-06-14 18:01:46 +000055static int devsymShmMap(sqlite3_file*,int,int,int, void volatile **);
drh286a2882010-05-20 23:51:06 +000056static void devsymShmBarrier(sqlite3_file*);
drhe11fedc2010-07-14 00:14:30 +000057static int devsymShmUnmap(sqlite3_file*,int);
danielk1977bf260972008-01-22 11:50:13 +000058
59/*
60** Method declarations for devsym_vfs.
61*/
62static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
63static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir);
danielk1977861f7452008-06-05 11:39:11 +000064static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *);
danielk1977bf260972008-01-22 11:50:13 +000065static int devsymFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
shane75998ab2008-05-29 02:52:59 +000066#ifndef SQLITE_OMIT_LOAD_EXTENSION
danielk1977bf260972008-01-22 11:50:13 +000067static void *devsymDlOpen(sqlite3_vfs*, const char *zFilename);
68static void devsymDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
drhec1724e2008-12-09 01:32:03 +000069static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
danielk1977bf260972008-01-22 11:50:13 +000070static void devsymDlClose(sqlite3_vfs*, void*);
shane75998ab2008-05-29 02:52:59 +000071#endif /* SQLITE_OMIT_LOAD_EXTENSION */
danielk1977bf260972008-01-22 11:50:13 +000072static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
73static int devsymSleep(sqlite3_vfs*, int microseconds);
74static int devsymCurrentTime(sqlite3_vfs*, double*);
75
danielk1977bf260972008-01-22 11:50:13 +000076struct DevsymGlobal {
77 sqlite3_vfs *pVfs;
78 int iDeviceChar;
79 int iSectorSize;
dan33447e72017-07-22 20:12:31 +000080 int nWriteCrash;
danielk1977bf260972008-01-22 11:50:13 +000081};
dan33447e72017-07-22 20:12:31 +000082struct DevsymGlobal g = {0, 0, 512, 0};
danielk1977bf260972008-01-22 11:50:13 +000083
84/*
85** Close an devsym-file.
86*/
87static int devsymClose(sqlite3_file *pFile){
88 devsym_file *p = (devsym_file *)pFile;
drh8f2ce912016-04-14 13:16:58 +000089 sqlite3OsClose(p->pReal);
90 return SQLITE_OK;
danielk1977bf260972008-01-22 11:50:13 +000091}
92
93/*
94** Read data from an devsym-file.
95*/
96static 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*/
109static 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*/
122static 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*/
130static 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*/
138static 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*/
146static 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*/
154static 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*/
danielk1977861f7452008-06-05 11:39:11 +0000162static int devsymCheckReservedLock(sqlite3_file *pFile, int *pResOut){
danielk1977bf260972008-01-22 11:50:13 +0000163 devsym_file *p = (devsym_file *)pFile;
danielk1977861f7452008-06-05 11:39:11 +0000164 return sqlite3OsCheckReservedLock(p->pReal, pResOut);
danielk1977bf260972008-01-22 11:50:13 +0000165}
166
167/*
168** File control method. For custom operations on an devsym-file.
169*/
170static 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*/
178static int devsymSectorSize(sqlite3_file *pFile){
179 return g.iSectorSize;
180}
181
182/*
183** Return the device characteristic flags supported by an devsym-file.
184*/
185static int devsymDeviceCharacteristics(sqlite3_file *pFile){
186 return g.iDeviceChar;
187}
188
189/*
drh365e2d22010-05-12 18:30:36 +0000190** Shared-memory methods are all pass-thrus.
191*/
drh73b64e42010-05-30 19:55:15 +0000192static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
drh365e2d22010-05-12 18:30:36 +0000193 devsym_file *p = (devsym_file *)pFile;
drh73b64e42010-05-30 19:55:15 +0000194 return sqlite3OsShmLock(p->pReal, ofst, n, flags);
drh365e2d22010-05-12 18:30:36 +0000195}
dan18801912010-06-14 14:07:50 +0000196static int devsymShmMap(
dan13a3cb82010-06-11 19:04:21 +0000197 sqlite3_file *pFile,
dan18801912010-06-14 14:07:50 +0000198 int iRegion,
199 int szRegion,
dan13a3cb82010-06-11 19:04:21 +0000200 int isWrite,
201 void volatile **pp
202){
203 devsym_file *p = (devsym_file *)pFile;
dan18801912010-06-14 14:07:50 +0000204 return sqlite3OsShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
dan13a3cb82010-06-11 19:04:21 +0000205}
drh6b017cc2010-06-14 18:01:46 +0000206static void devsymShmBarrier(sqlite3_file *pFile){
207 devsym_file *p = (devsym_file *)pFile;
208 sqlite3OsShmBarrier(p->pReal);
209}
drhe11fedc2010-07-14 00:14:30 +0000210static int devsymShmUnmap(sqlite3_file *pFile, int delFlag){
drh6b017cc2010-06-14 18:01:46 +0000211 devsym_file *p = (devsym_file *)pFile;
drhe11fedc2010-07-14 00:14:30 +0000212 return sqlite3OsShmUnmap(p->pReal, delFlag);
drh6b017cc2010-06-14 18:01:46 +0000213}
drh365e2d22010-05-12 18:30:36 +0000214
215
216
217/*
danielk1977bf260972008-01-22 11:50:13 +0000218** Open an devsym file handle.
219*/
220static int devsymOpen(
221 sqlite3_vfs *pVfs,
222 const char *zName,
223 sqlite3_file *pFile,
224 int flags,
225 int *pOutFlags
226){
dan33447e72017-07-22 20:12:31 +0000227static 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
danielk1977755339e2008-09-12 10:22:40 +0000247 int rc;
danielk1977bf260972008-01-22 11:50:13 +0000248 devsym_file *p = (devsym_file *)pFile;
danielk1977bf260972008-01-22 11:50:13 +0000249 p->pReal = (sqlite3_file *)&p[1];
danielk1977755339e2008-09-12 10:22:40 +0000250 rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
251 if( p->pReal->pMethods ){
252 pFile->pMethods = &devsym_io_methods;
253 }
254 return rc;
danielk1977bf260972008-01-22 11:50:13 +0000255}
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*/
262static 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*/
danielk1977861f7452008-06-05 11:39:11 +0000270static 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);
danielk1977bf260972008-01-22 11:50:13 +0000277}
278
279/*
danielk1977bf260972008-01-22 11:50:13 +0000280** 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*/
284static 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
shane75998ab2008-05-29 02:52:59 +0000293#ifndef SQLITE_OMIT_LOAD_EXTENSION
danielk1977bf260972008-01-22 11:50:13 +0000294/*
295** Open the dynamic library located at zPath and return a handle.
296*/
297static 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*/
306static 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*/
drhec1724e2008-12-09 01:32:03 +0000313static void (*devsymDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
314 return sqlite3OsDlSym(g.pVfs, p, zSym);
danielk1977bf260972008-01-22 11:50:13 +0000315}
316
317/*
318** Close the dynamic library handle pHandle.
319*/
320static void devsymDlClose(sqlite3_vfs *pVfs, void *pHandle){
321 sqlite3OsDlClose(g.pVfs, pHandle);
322}
shane75998ab2008-05-29 02:52:59 +0000323#endif /* SQLITE_OMIT_LOAD_EXTENSION */
danielk1977bf260972008-01-22 11:50:13 +0000324
325/*
326** Populate the buffer pointed to by zBufOut with nByte bytes of
327** random data.
328*/
329static 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*/
337static 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*/
344static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
drhb7e8ea22010-05-03 14:32:30 +0000345 return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
danielk1977bf260972008-01-22 11:50:13 +0000346}
347
dan33447e72017-07-22 20:12:31 +0000348/*
349** Return the sector-size in bytes for an writecrash-file.
350*/
351static 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*/
359static 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*/
367static 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*/
384static int writecrashOpen(
385 sqlite3_vfs *pVfs,
386 const char *zName,
387 sqlite3_file *pFile,
388 int flags,
389 int *pOutFlags
390){
391static 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
421static 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
450static 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
dan6ddb4bf2010-04-30 16:19:39 +0000479
danielk1977bf260972008-01-22 11:50:13 +0000480/*
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*/
485void devsym_register(int iDeviceChar, int iSectorSize){
dan33447e72017-07-22 20:12:31 +0000486
danielk1977bf260972008-01-22 11:50:13 +0000487 if( g.pVfs==0 ){
488 g.pVfs = sqlite3_vfs_find(0);
489 devsym_vfs.szOsFile += g.pVfs->szOsFile;
dan33447e72017-07-22 20:12:31 +0000490 writecrash_vfs.szOsFile += g.pVfs->szOsFile;
danielk1977bf260972008-01-22 11:50:13 +0000491 sqlite3_vfs_register(&devsym_vfs, 0);
dan33447e72017-07-22 20:12:31 +0000492 sqlite3_vfs_register(&writecrash_vfs, 0);
danielk1977bf260972008-01-22 11:50:13 +0000493 }
494 if( iDeviceChar>=0 ){
495 g.iDeviceChar = iDeviceChar;
drh47f18f72010-04-12 14:51:10 +0000496 }else{
497 g.iDeviceChar = 0;
danielk1977bf260972008-01-22 11:50:13 +0000498 }
499 if( iSectorSize>=0 ){
500 g.iSectorSize = iSectorSize;
drh47f18f72010-04-12 14:51:10 +0000501 }else{
502 g.iSectorSize = 512;
danielk1977bf260972008-01-22 11:50:13 +0000503 }
504}
505
dan05accd22016-04-27 18:54:49 +0000506void devsym_unregister(){
507 sqlite3_vfs_unregister(&devsym_vfs);
dane88c0cd2019-07-04 19:19:08 +0000508 sqlite3_vfs_unregister(&writecrash_vfs);
dan05accd22016-04-27 18:54:49 +0000509 g.pVfs = 0;
510 g.iDeviceChar = 0;
511 g.iSectorSize = 0;
512}
513
dan33447e72017-07-22 20:12:31 +0000514void 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
danielk1977bf260972008-01-22 11:50:13 +0000525#endif