15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2010 May 05
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_TEST          /* This file is used for testing only */
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains the implementation of the Tcl [testvfs] command,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** used to create SQLite VFS implementations with various properties and
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** instrumentation to support testing SQLite.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   testvfs VFSNAME ?OPTIONS?
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Available options are:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   -noshm      BOOLEAN        (True to omit shm methods. Default false)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   -default    BOOLEAN        (True to make the vfs default. Default false)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   -szosfile   INTEGER        (Value for sqlite3_vfs.szOsFile)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   -mxpathname INTEGER        (Value for sqlite3_vfs.mxPathname)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   -iversion   INTEGER        (Value for sqlite3_vfs.iVersion)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqlite3.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqliteInt.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct Testvfs Testvfs;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct TestvfsShm TestvfsShm;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct TestvfsBuffer TestvfsBuffer;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct TestvfsFile TestvfsFile;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct TestvfsFd TestvfsFd;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An open file handle.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestvfsFile {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file base;              /* Base class.  Must be first */
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd;                 /* File data */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define tvfsGetFd(pFile) (((TestvfsFile *)pFile)->pFd)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestvfsFd {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;              /* The VFS */
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zFilename;          /* Filename as passed to xOpen() */
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pReal;            /* The real, underlying file descriptor */
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *pShmId;                /* Shared memory id for Tcl callbacks */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsBuffer *pShm;            /* Shared memory buffer */
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 excllock;                   /* Mask of exclusive locks */
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u32 sharedlock;                 /* Mask of shared locks */
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pNext;               /* Next handle opened on the same file */
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FAULT_INJECT_NONE       0
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FAULT_INJECT_TRANSIENT  1
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FAULT_INJECT_PERSISTENT 2
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct TestFaultInject TestFaultInject;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestFaultInject {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iCnt;                       /* Remaining calls before fault injection */
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eFault;                     /* A FAULT_INJECT_* value */
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nFail;                      /* Number of faults injected */
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An instance of this structure is allocated for each VFS created. The
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is set to point to it.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Testvfs {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zName;                    /* Name of this VFS */
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent;           /* The VFS to use for file IO */
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp;             /* Interpreter to run script in */
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *pScript;               /* Script to execute */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nScript;                    /* Number of elements in array apScript */
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj **apScript;             /* Array version of pScript */
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsBuffer *pBuffer;         /* List of shared buffers */
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isNoshm;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int mask;                       /* Mask controlling [script] and [ioerr] */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFaultInject ioerr_err;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFaultInject full_err;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestFaultInject cantopen_err;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iIoerrCnt;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ioerr;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nIoerrFail;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iFullCnt;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fullerr;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nFullFail;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iDevchar;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iSectorsize;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The Testvfs.mask variable is set to a combination of the following.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If a bit is clear in Testvfs.mask, then calls made by SQLite to the
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** corresponding VFS method is ignored for purposes of:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   + Simulating IO errors, and
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   + Invoking the Tcl callback script.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_SHMOPEN_MASK    0x00000001
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_SHMLOCK_MASK    0x00000010
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_SHMMAP_MASK     0x00000020
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_SHMBARRIER_MASK 0x00000040
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_SHMCLOSE_MASK   0x00000080
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_OPEN_MASK       0x00000100
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_SYNC_MASK       0x00000200
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_DELETE_MASK     0x00000400
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_CLOSE_MASK      0x00000800
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_WRITE_MASK      0x00001000
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_TRUNCATE_MASK   0x00002000
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_ACCESS_MASK     0x00004000
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_ALL_MASK        0x00007FFF
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_MAX_PAGES 1024
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A shared-memory buffer. There is one of these objects for each shared
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** memory region opened by clients. If two clients open the same file,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** there are two TestvfsFile structures but only one TestvfsBuffer structure.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestvfsBuffer {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFile;                    /* Associated file name */
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pgsz;                       /* Page size */
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 *aPage[TESTVFS_MAX_PAGES];   /* Array of ckalloc'd pages */
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFile;               /* List of open handles */
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsBuffer *pNext;           /* Next in linked list of all buffers */
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TESTVFS_MAX_ARGS 12
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Method declarations for TestvfsFile.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsClose(sqlite3_file*);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsSync(sqlite3_file*, int flags);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsLock(sqlite3_file*, int);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsUnlock(sqlite3_file*, int);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsCheckReservedLock(sqlite3_file*, int *);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsFileControl(sqlite3_file*, int op, void *pArg);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsSectorSize(sqlite3_file*);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsDeviceCharacteristics(sqlite3_file*);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Method declarations for tvfs_vfs.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsDelete(sqlite3_vfs*, const char *zName, int syncDir);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_LOAD_EXTENSION
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *tvfsDlOpen(sqlite3_vfs*, const char *zFilename);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*tvfsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsDlClose(sqlite3_vfs*, void*);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OMIT_LOAD_EXTENSION */
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsSleep(sqlite3_vfs*, int microseconds);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsCurrentTime(sqlite3_vfs*, double*);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmOpen(sqlite3_file*);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmLock(sqlite3_file*, int , int, int);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsShmBarrier(sqlite3_file*);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmUnmap(sqlite3_file*, int);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_io_methods tvfs_io_methods = {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  2,                              /* iVersion */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsClose,                      /* xClose */
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsRead,                       /* xRead */
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsWrite,                      /* xWrite */
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsTruncate,                   /* xTruncate */
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsSync,                       /* xSync */
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsFileSize,                   /* xFileSize */
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsLock,                       /* xLock */
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsUnlock,                     /* xUnlock */
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsCheckReservedLock,          /* xCheckReservedLock */
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsFileControl,                /* xFileControl */
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsSectorSize,                 /* xSectorSize */
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsDeviceCharacteristics,      /* xDeviceCharacteristics */
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsShmMap,                     /* xShmMap */
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsShmLock,                    /* xShmLock */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsShmBarrier,                 /* xShmBarrier */
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tvfsShmUnmap                    /* xShmUnmap */
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsResultCode(Testvfs *p, int *pRc){
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct errcode {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int eCode;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *zCode;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } aCode[] = {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { SQLITE_OK,     "SQLITE_OK"     },
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { SQLITE_ERROR,  "SQLITE_ERROR"  },
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { SQLITE_IOERR,  "SQLITE_IOERR"  },
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { SQLITE_LOCKED, "SQLITE_LOCKED" },
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { SQLITE_BUSY,   "SQLITE_BUSY"   },
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *z;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z = Tcl_GetStringResult(p->interp);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<ArraySize(aCode); i++){
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( 0==strcmp(z, aCode[i].zCode) ){
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pRc = aCode[i].eCode;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsInjectFault(TestFaultInject *p){
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret = 0;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->eFault ){
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->iCnt--;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->iCnt==0 || (p->iCnt<0 && p->eFault==FAULT_INJECT_PERSISTENT ) ){
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ret = 1;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->nFail++;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsInjectIoerr(Testvfs *p){
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tvfsInjectFault(&p->ioerr_err);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsInjectFullerr(Testvfs *p){
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tvfsInjectFault(&p->full_err);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsInjectCantopenerr(Testvfs *p){
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tvfsInjectFault(&p->cantopen_err);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsExecTcl(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zMethod,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *arg1,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *arg2,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *arg3
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                         /* Return code from Tcl_EvalObj() */
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nArg;                       /* Elements in eval'd list */
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nScript;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj ** ap;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( p->pScript );
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !p->apScript ){
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nByte;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( TCL_OK!=Tcl_ListObjGetElements(p->interp, p->pScript, &nScript, &ap) ){
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_BackgroundError(p->interp);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_ResetResult(p->interp);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->nScript = nScript;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nByte = (nScript+TESTVFS_MAX_ARGS)*sizeof(Tcl_Obj *);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->apScript = (Tcl_Obj **)ckalloc(nByte);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(p->apScript, 0, nByte);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; i<nScript; i++){
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->apScript[i] = ap[i];
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->apScript[p->nScript] = Tcl_NewStringObj(zMethod, -1);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->apScript[p->nScript+1] = arg1;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->apScript[p->nScript+2] = arg2;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->apScript[p->nScript+3] = arg3;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(nArg=p->nScript; p->apScript[nArg]; nArg++){
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_IncrRefCount(p->apScript[nArg]);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = Tcl_EvalObjv(p->interp, nArg, p->apScript, TCL_EVAL_GLOBAL);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=TCL_OK ){
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_BackgroundError(p->interp);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_ResetResult(p->interp);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(nArg=p->nScript; p->apScript[nArg]; nArg++){
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_DecrRefCount(p->apScript[nArg]);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->apScript[nArg] = 0;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close an tvfs-file.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsClose(sqlite3_file *pFile){
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFile *pTestfile = (TestvfsFile *)pFile;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = pTestfile->pFd;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xClose",
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFd->pShmId ){
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_DecrRefCount(pFd->pShmId);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFd->pShmId = 0;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->pMethods ){
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ckfree((char *)pFile->pMethods);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3OsClose(pFd->pReal);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ckfree((char *)pFd);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pTestfile->pFd = 0;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from an tvfs-file.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsRead(
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zBuf,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *p = tvfsGetFd(pFile);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data to an tvfs-file.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsWrite(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *zBuf,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xWrite",
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsResultCode(p, &rc);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_FULL;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_IOERR;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3OsWrite(pFd->pReal, zBuf, iAmt, iOfst);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate an tvfs-file.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xTruncate",
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsResultCode(p, &rc);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3OsTruncate(pFd->pReal, size);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sync an tvfs-file.
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsSync(sqlite3_file *pFile, int flags){
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_SYNC_MASK ){
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zFlags;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch( flags ){
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SQLITE_SYNC_NORMAL:
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zFlags = "normal";
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SQLITE_SYNC_FULL:
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zFlags = "full";
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SQLITE_SYNC_NORMAL|SQLITE_SYNC_DATAONLY:
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zFlags = "normal|dataonly";
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY:
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        zFlags = "full|dataonly";
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert(0);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xSync",
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(zFlags, -1)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsResultCode(p, &rc);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3OsSync(pFd->pReal, flags);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the current file-size of an tvfs-file.
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *p = tvfsGetFd(pFile);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsFileSize(p->pReal, pSize);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock an tvfs-file.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsLock(sqlite3_file *pFile, int eLock){
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *p = tvfsGetFd(pFile);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsLock(p->pReal, eLock);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Unlock an tvfs-file.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsUnlock(sqlite3_file *pFile, int eLock){
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *p = tvfsGetFd(pFile);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsUnlock(p->pReal, eLock);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Check if another file-handle holds a RESERVED lock on an tvfs-file.
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *p = tvfsGetFd(pFile);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsCheckReservedLock(p->pReal, pResOut);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** File control method. For custom operations on an tvfs-file.
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *p = tvfsGetFd(pFile);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsFileControl(p->pReal, op, pArg);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the sector-size in bytes for an tvfs-file.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsSectorSize(sqlite3_file *pFile){
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->iSectorsize>=0 ){
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return p->iSectorsize;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsSectorSize(pFd->pReal);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the device characteristic flags supported by an tvfs-file.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsDeviceCharacteristics(sqlite3_file *pFile){
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->iDevchar>=0 ){
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return p->iDevchar;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsDeviceCharacteristics(pFd->pReal);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open an tvfs file handle.
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsOpen(
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName,
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pOutFlags
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFile *pTestfile = (TestvfsFile *)pFile;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *pId = 0;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pVfs->pAppData;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd = (TestvfsFd *)ckalloc(sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pFd, 0, sizeof(TestvfsFd) + PARENTVFS(pVfs)->szOsFile);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pShm = 0;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pShmId = 0;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->zFilename = zName;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pVfs = pVfs;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pReal = (sqlite3_file *)&pFd[1];
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pTestfile, 0, sizeof(TestvfsFile));
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pTestfile->pFd = pFd;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Evaluate the Tcl script:
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   SCRIPT xOpen FILENAME
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** If the script returns an SQLite error code other than SQLITE_OK, an
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** error is returned to the caller. If it returns SQLITE_OK, the new
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** connection is named "anon". Otherwise, the value returned by the
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** script is used as the connection name.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_ResetResult(p->interp);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( tvfsResultCode(p, &rc) ){
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ) return rc;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pId = Tcl_GetObjResult(p->interp);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (p->mask&TESTVFS_OPEN_MASK) &&  tvfsInjectIoerr(p) ) return SQLITE_IOERR;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( tvfsInjectCantopenerr(p) ) return SQLITE_CANTOPEN;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( tvfsInjectFullerr(p) ) return SQLITE_FULL;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pId ){
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pId = Tcl_NewStringObj("anon", -1);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_IncrRefCount(pId);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pShmId = pId;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_ResetResult(p->interp);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd->pReal, flags, pOutFlags);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFd->pReal->pMethods ){
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_io_methods *pMethods;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nByte;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pVfs->iVersion>1 ){
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nByte = sizeof(sqlite3_io_methods);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nByte = offsetof(sqlite3_io_methods, xShmMap);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pMethods = (sqlite3_io_methods *)ckalloc(nByte);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(pMethods, &tvfs_io_methods, nByte);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pMethods->iVersion = pVfs->iVersion;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pMethods->xShmUnmap = 0;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pMethods->xShmLock = 0;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pMethods->xShmBarrier = 0;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pMethods->xShmMap = 0;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->pMethods = pMethods;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the file located at zPath. If the dirSync argument is true,
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ensure the file-system modifications are synced to disk before
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returning.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pVfs->pAppData;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xDelete",
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsResultCode(p, &rc);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Test for access permissions. Return true if the requested permission
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is available, or false otherwise.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsAccess(
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pResOut
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)pVfs->pAppData;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rc;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zArg = 0;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS";
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE";
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ";
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xAccess",
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( tvfsResultCode(p, &rc) ){
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ) return rc;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_Interp *interp = p->interp;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_OK;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsAccess(PARENTVFS(pVfs), zPath, flags, pResOut);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate buffer zOut with the full canonical pathname corresponding
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to the pathname in zPath. zOut is guaranteed to point to a buffer
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of at least (DEVSYM_MAX_PATHNAME+1) bytes.
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsFullPathname(
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nOut,
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zOut
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_LOAD_EXTENSION
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open the dynamic library located at zPath and return a handle.
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *tvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsDlOpen(PARENTVFS(pVfs), zPath);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate the buffer zErrMsg (size nByte bytes) with a human readable
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** utf-8 string describing the most recent error encountered associated
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with dynamic libraries.
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3OsDlError(PARENTVFS(pVfs), nByte, zErrMsg);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*tvfsDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsDlSym(PARENTVFS(pVfs), p, zSym);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close the dynamic library handle pHandle.
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsDlClose(sqlite3_vfs *pVfs, void *pHandle){
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3OsDlClose(PARENTVFS(pVfs), pHandle);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OMIT_LOAD_EXTENSION */
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate the buffer pointed to by zBufOut with nByte bytes of
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** random data.
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsRandomness(PARENTVFS(pVfs), nByte, zBufOut);
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sleep for nMicro microseconds. Return the number of microseconds
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** actually slept.
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsSleep(sqlite3_vfs *pVfs, int nMicro){
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3OsSleep(PARENTVFS(pVfs), nMicro);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the current time as a Julian Day number in *pTimeOut.
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmOpen(sqlite3_file *pFile){
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;             /* Return code */
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsBuffer *pBuffer;         /* Buffer to open connection to */
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd;                 /* The testvfs file structure */
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd = tvfsGetFd(pFile);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = (Testvfs *)pFd->pVfs->pAppData;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFd->pShmId && pFd->pShm==0 && pFd->pNext==0 );
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Evaluate the Tcl script:
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   SCRIPT xShmOpen FILENAME
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_ResetResult(p->interp);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( tvfsResultCode(p, &rc) ){
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ) return rc;
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( rc==SQLITE_OK );
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Search for a TestvfsBuffer. Create a new one if required. */
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pBuffer ){
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nByte = sizeof(TestvfsBuffer) + strlen(pFd->zFilename) + 1;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBuffer = (TestvfsBuffer *)ckalloc(nByte);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pBuffer, 0, nByte);
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBuffer->zFile = (char *)&pBuffer[1];
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strcpy(pBuffer->zFile, pFd->zFilename);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pBuffer->pNext = p->pBuffer;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pBuffer = pBuffer;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pNext = pBuffer->pFile;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pBuffer->pFile = pFd;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pShm = pBuffer;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsAllocPage(TestvfsBuffer *p, int iPage, int pgsz){
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( iPage<TESTVFS_MAX_PAGES );
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->aPage[iPage]==0 ){
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->aPage[iPage] = (u8 *)ckalloc(pgsz);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(p->aPage[iPage], 0, pgsz);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->pgsz = pgsz;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmMap(
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,            /* Handle open on database file */
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iPage,                      /* Page to retrieve */
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pgsz,                       /* Size of pages */
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isWrite,                    /* True to extend file if necessary */
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void volatile **pp              /* OUT: Mapped memory */
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( 0==pFd->pShm ){
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = tvfsShmOpen(pFile);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_Obj *pArg = Tcl_NewObj();
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_IncrRefCount(pArg);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage));
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xShmMap",
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsResultCode(p, &rc);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_DecrRefCount(pArg);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_IOERR;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && isWrite && !pFd->pShm->aPage[iPage] ){
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsAllocPage(pFd->pShm, iPage, pgsz);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pp = (void volatile *)pFd->pShm->aPage[iPage];
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmLock(
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ofst,
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n,
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nLock;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zLock[80];
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n);
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nLock = strlen(zLock);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( flags & SQLITE_SHM_LOCK ){
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcpy(&zLock[nLock], " lock");
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcpy(&zLock[nLock], " unlock");
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nLock += strlen(&zLock[nLock]);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( flags & SQLITE_SHM_SHARED ){
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcpy(&zLock[nLock], " shared");
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      strcpy(&zLock[nLock], " exclusive");
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xShmLock",
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(zLock, -1)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsResultCode(p, &rc);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_IOERR;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int isLock = (flags & SQLITE_SHM_LOCK);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int isExcl = (flags & SQLITE_SHM_EXCLUSIVE);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u32 mask = (((1<<n)-1) << ofst);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( isLock ){
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestvfsFd *p2;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(p2=pFd->pShm->pFile; p2; p2=p2->pNext){
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( p2==pFd ) continue;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( (p2->excllock&mask) || (isExcl && p2->sharedlock&mask) ){
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rc = SQLITE_BUSY;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( isExcl )  pFd->excllock |= mask;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( !isExcl ) pFd->sharedlock |= mask;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( isExcl )  pFd->excllock &= (~mask);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !isExcl ) pFd->sharedlock &= (~mask);
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void tvfsShmBarrier(sqlite3_file *pFile){
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xShmBarrier",
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tvfsShmUnmap(
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int deleteFlag
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd *pFd = tvfsGetFd(pFile);
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsBuffer *pBuffer = pFd->pShm;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestvfsFd **ppFd;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pBuffer ) return SQLITE_OK;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFd->pShmId && pFd->pShm );
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsExecTcl(p, "xShmUnmap",
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsResultCode(p, &rc);
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext));
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (*ppFd)==pFd );
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ppFd = pFd->pNext;
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pNext = 0;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pBuffer->pFile==0 ){
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestvfsBuffer **pp;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext));
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pp = (*pp)->pNext;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=0; pBuffer->aPage[i]; i++){
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ckfree((char *)pBuffer->aPage[i]);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ckfree((char *)pBuffer);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFd->pShm = 0;
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int testvfs_obj_cmd(
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientData cd,
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)cd;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum DB_enum {
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT,
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR, CMD_CANTOPENERR
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestvfsSubcmd {
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zName;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enum DB_enum eCmd;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } aSubcmd[] = {
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "shm",         CMD_SHM         },
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "delete",      CMD_DELETE      },
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "filter",      CMD_FILTER      },
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "ioerr",       CMD_IOERR       },
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "fullerr",     CMD_FULLERR     },
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "cantopenerr", CMD_CANTOPENERR },
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "script",      CMD_SCRIPT      },
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "devchar",     CMD_DEVCHAR     },
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "sectorsize",  CMD_SECTORSIZE  },
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 0, 0 }
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( objc<2 ){
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( Tcl_GetIndexFromObjStruct(
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        interp, objv[1], aSubcmd, sizeof(aSubcmd[0]), "subcommand", 0, &i)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TCL_ERROR;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_ResetResult(interp);
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( aSubcmd[i].eCmd ){
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_SHM: {
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_Obj *pObj;
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestvfsBuffer *pBuffer;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char *zName;
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc!=3 && objc!=4 ){
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "FILE ?VALUE?");
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zName = ckalloc(p->pParent->mxPathname);
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->pParent->xFullPathname(
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->pParent, Tcl_GetString(objv[2]),
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->pParent->mxPathname, zName
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      );
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( 0==strcmp(pBuffer->zFile, zName) ) break;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ckfree(zName);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !pBuffer ){
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_AppendResult(interp, "no such file: ", Tcl_GetString(objv[2]), 0);
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc==4 ){
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int n;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        u8 *a = Tcl_GetByteArrayFromObj(objv[3], &n);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int pgsz = pBuffer->pgsz;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pgsz==0 ) pgsz = 65536;
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for(i=0; i*pgsz<n; i++){
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          int nByte = pgsz;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tvfsAllocPage(pBuffer, i, pgsz);
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( n-i*pgsz<pgsz ){
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            nByte = n;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          memcpy(pBuffer->aPage[i], &a[i*pgsz], nByte);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pObj = Tcl_NewObj();
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(i=0; pBuffer->aPage[i]; i++){
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int pgsz = pBuffer->pgsz;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( pgsz==0 ) pgsz = 65536;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], pgsz));
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_SetObjResult(interp, pObj);
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_FILTER: {
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static struct VfsMethod {
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char *zName;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int mask;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } vfsmethod [] = {
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xShmOpen",    TESTVFS_SHMOPEN_MASK },
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xShmLock",    TESTVFS_SHMLOCK_MASK },
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xShmUnmap",   TESTVFS_SHMCLOSE_MASK },
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xShmMap",     TESTVFS_SHMMAP_MASK },
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xSync",       TESTVFS_SYNC_MASK },
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xDelete",     TESTVFS_DELETE_MASK },
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xWrite",      TESTVFS_WRITE_MASK },
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xTruncate",   TESTVFS_TRUNCATE_MASK },
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xOpen",       TESTVFS_OPEN_MASK },
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xClose",      TESTVFS_CLOSE_MASK },
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "xAccess",     TESTVFS_ACCESS_MASK },
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_Obj **apElem = 0;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int nElem = 0;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int mask = 0;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc!=3 ){
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "LIST");
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( Tcl_ListObjGetElements(interp, objv[2], &nElem, &apElem) ){
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_ResetResult(interp);
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(i=0; i<nElem; i++){
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int iMethod;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char *zElem = Tcl_GetString(apElem[i]);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for(iMethod=0; iMethod<ArraySize(vfsmethod); iMethod++){
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( strcmp(zElem, vfsmethod[iMethod].zName)==0 ){
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mask |= vfsmethod[iMethod].mask;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( iMethod==ArraySize(vfsmethod) ){
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Tcl_AppendResult(interp, "unknown method: ", zElem, 0);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return TCL_ERROR;
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->mask = mask;
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_SCRIPT: {
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc==3 ){
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int nByte;
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( p->pScript ){
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Tcl_DecrRefCount(p->pScript);
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ckfree((char *)p->apScript);
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->apScript = 0;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->nScript = 0;
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->pScript = 0;
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_GetStringFromObj(objv[2], &nByte);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( nByte>0 ){
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          p->pScript = Tcl_DuplicateObj(objv[2]);
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Tcl_IncrRefCount(p->pScript);
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else if( objc!=2 ){
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_ResetResult(interp);
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( p->pScript ) Tcl_SetObjResult(interp, p->pScript);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** TESTVFS ioerr ?IFAIL PERSIST?
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **   Where IFAIL is an integer and PERSIST is boolean.
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_CANTOPENERR:
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_IOERR:
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_FULLERR: {
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestFaultInject *pTest;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int iRet;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch( aSubcmd[i].eCmd ){
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case CMD_IOERR: pTest = &p->ioerr_err; break;
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case CMD_FULLERR: pTest = &p->full_err; break;
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case CMD_CANTOPENERR: pTest = &p->cantopen_err; break;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default: assert(0);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iRet = pTest->nFail;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pTest->nFail = 0;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pTest->eFault = 0;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pTest->iCnt = 0;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc==4 ){
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int iCnt, iPersist;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iCnt)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         || TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &iPersist)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ){
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return TCL_ERROR;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pTest->eFault = iPersist?FAULT_INJECT_PERSISTENT:FAULT_INJECT_TRANSIENT;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pTest->iCnt = iCnt;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else if( objc!=2 ){
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "?CNT PERSIST?");
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_SetObjResult(interp, Tcl_NewIntObj(iRet));
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_DELETE: {
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_DEVCHAR: {
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct DeviceFlag {
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char *zName;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int iValue;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } aFlag[] = {
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "default",               -1 },
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic",                SQLITE_IOCAP_ATOMIC      },
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic512",             SQLITE_IOCAP_ATOMIC512   },
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic1k",              SQLITE_IOCAP_ATOMIC1K    },
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic2k",              SQLITE_IOCAP_ATOMIC2K    },
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic4k",              SQLITE_IOCAP_ATOMIC4K    },
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic8k",              SQLITE_IOCAP_ATOMIC8K    },
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic16k",             SQLITE_IOCAP_ATOMIC16K   },
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic32k",             SQLITE_IOCAP_ATOMIC32K   },
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "atomic64k",             SQLITE_IOCAP_ATOMIC64K   },
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "sequential",            SQLITE_IOCAP_SEQUENTIAL  },
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "safe_append",           SQLITE_IOCAP_SAFE_APPEND },
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { 0, 0 }
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      };
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_Obj *pRet;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int iFlag;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc>3 ){
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "?ATTR-LIST?");
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc==3 ){
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int j;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int iNew = 0;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_Obj **flags = 0;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int nFlags = 0;
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( Tcl_ListObjGetElements(interp, objv[2], &nFlags, &flags) ){
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return TCL_ERROR;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for(j=0; j<nFlags; j++){
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          int idx = 0;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( Tcl_GetIndexFromObjStruct(interp, flags[j], aFlag,
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sizeof(aFlag[0]), "flag", 0, &idx)
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ){
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return TCL_ERROR;
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( aFlag[idx].iValue<0 && nFlags>1 ){
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            Tcl_AppendResult(interp, "bad flags: ", Tcl_GetString(objv[2]), 0);
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return TCL_ERROR;
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          iNew |= aFlag[idx].iValue;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        p->iDevchar = iNew;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pRet = Tcl_NewObj();
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(iFlag=0; iFlag<sizeof(aFlag)/sizeof(aFlag[0]); iFlag++){
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( p->iDevchar & aFlag[iFlag].iValue ){
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Tcl_ListObjAppendElement(
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              interp, pRet, Tcl_NewStringObj(aFlag[iFlag].zName, -1)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          );
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_SetObjResult(interp, pRet);
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CMD_SECTORSIZE: {
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc>3 ){
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tcl_WrongNumArgs(interp, 2, objv, "?VALUE?");
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( objc==3 ){
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int iNew = 0;
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( Tcl_GetIntFromObj(interp, objv[2], &iNew) ){
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return TCL_ERROR;
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        p->iSectorsize = iNew;
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Tcl_SetObjResult(interp, Tcl_NewIntObj(p->iSectorsize));
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void testvfs_obj_del(ClientData cd){
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p = (Testvfs *)cd;
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->pScript ) Tcl_DecrRefCount(p->pScript);
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs_unregister(p->pVfs);
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ckfree((char *)p->apScript);
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ckfree((char *)p->pVfs);
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ckfree((char *)p);
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Usage:  testvfs VFSNAME ?SWITCHES?
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Switches are:
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   -noshm   BOOLEAN             (True to omit shm methods. Default false)
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   -default BOOLEAN             (True to make the vfs default. Default false)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This command creates two things when it is invoked: an SQLite VFS, and
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a Tcl command. Both are named VFSNAME. The VFS is installed. It is not
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** installed as the default VFS.
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The VFS passes all file I/O calls through to the underlying VFS.
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Whenever the xShmMap method of the VFS
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is invoked, the SCRIPT is executed as follows:
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   SCRIPT xShmMap    FILENAME ID
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The value returned by the invocation of SCRIPT above is interpreted as
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an SQLite error code and returned to SQLite. Either a symbolic
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** "SQLITE_OK" or numeric "0" value may be returned.
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The contents of the shared-memory buffer associated with a given file
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** may be read and set using the following command:
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   VFSNAME shm FILENAME ?NEWVALUE?
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When the xShmLock method is invoked by SQLite, the following script is
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** run:
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   SCRIPT xShmLock    FILENAME ID LOCK
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** where LOCK is of the form "OFFSET NBYTE lock/unlock shared/exclusive"
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int testvfs_cmd(
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientData cd,
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static sqlite3_vfs tvfs_vfs = {
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    2,                            /* iVersion */
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* szOsFile */
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* mxPathname */
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* pNext */
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* zName */
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* pAppData */
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsOpen,                     /* xOpen */
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsDelete,                   /* xDelete */
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsAccess,                   /* xAccess */
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsFullPathname,             /* xFullPathname */
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_LOAD_EXTENSION
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsDlOpen,                   /* xDlOpen */
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsDlError,                  /* xDlError */
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsDlSym,                    /* xDlSym */
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsDlClose,                  /* xDlClose */
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xDlOpen */
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xDlError */
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xDlSym */
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xDlClose */
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OMIT_LOAD_EXTENSION */
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsRandomness,               /* xRandomness */
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsSleep,                    /* xSleep */
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tvfsCurrentTime,              /* xCurrentTime */
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xGetLastError */
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* xCurrentTimeInt64 */
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Testvfs *p;                     /* New object */
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;              /* New VFS */
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zVfs;
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte;                      /* Bytes of space to allocate at p */
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isNoshm = 0;                /* True if -noshm is passed */
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isDefault = 0;              /* True if -default is passed */
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szOsFile = 0;               /* Value passed to -szosfile */
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int mxPathname = -1;            /* Value passed to -mxpathname */
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iVersion = 2;               /* Value passed to -iversion */
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( objc<2 || 0!=(objc%2) ) goto bad_args;
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=2; i<objc; i += 2){
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nSwitch;
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zSwitch;
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSwitch = Tcl_GetStringFromObj(objv[i], &nSwitch);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isNoshm) ){
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( Tcl_GetBooleanFromObj(interp, objv[i+1], &isDefault) ){
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( Tcl_GetIntFromObj(interp, objv[i+1], &szOsFile) ){
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( Tcl_GetIntFromObj(interp, objv[i+1], &mxPathname) ){
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( Tcl_GetIntFromObj(interp, objv[i+1], &iVersion) ){
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return TCL_ERROR;
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else{
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto bad_args;
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( szOsFile<sizeof(TestvfsFile) ){
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    szOsFile = sizeof(TestvfsFile);
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zVfs = Tcl_GetString(objv[1]);
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = sizeof(Testvfs) + strlen(zVfs)+1;
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = (Testvfs *)ckalloc(nByte);
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, nByte);
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->iDevchar = -1;
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->iSectorsize = -1;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create the new object command before querying SQLite for a default VFS
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** to use for 'real' IO operations. This is because creating the new VFS
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** may delete an existing [testvfs] VFS of the same name. If such a VFS
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** is currently the default, the new [testvfs] may end up calling the
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** methods of a deleted object.
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del);
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pParent = sqlite3_vfs_find(0);
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->interp = interp;
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->zName = (char *)&p[1];
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(p->zName, zVfs, strlen(zVfs)+1);
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs));
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs));
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs->pAppData = (void *)p;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs->iVersion = iVersion;
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs->zName = p->zName;
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs->mxPathname = p->pParent->mxPathname;
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( mxPathname>=0 && mxPathname<pVfs->mxPathname ){
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pVfs->mxPathname = mxPathname;
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pVfs->szOsFile = szOsFile;
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pVfs = pVfs;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->isNoshm = isNoshm;
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->mask = TESTVFS_ALL_MASK;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs_register(pVfs, isDefault);
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bad_args:
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?");
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_ERROR;
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Sqlitetestvfs_Init(Tcl_Interp *interp){
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0);
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1411