15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2010 April 7
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)** An example of a simple VFS implementation that omits complex features
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** often not required or not possible on embedded platforms. Also includes
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** code to buffer writes to the journal file, which can be a significant
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** performance improvement on some embedded platforms.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** OVERVIEW
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   The code in this file implements a minimal SQLite VFS that can be
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   used on Linux and other posix-like operating systems. The following
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   system calls are used:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    File-system: access(), unlink(), getcwd()
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    File IO:     open(), read(), write(), fsync(), close(), fstat()
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    Other:       sleep(), usleep(), time()
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   The following VFS features are omitted:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     1. File locking. The user must ensure that there is at most one
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        connection to each database when using this VFS. Multiple
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        connections to a single shared-cache count as a single connection
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        for the purposes of the previous statement.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     2. The loading of dynamic extensions (shared libraries).
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     3. Temporary files. The user must configure SQLite to use in-memory
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        temp files when using this VFS. The easiest way to do this is to
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        compile with:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**          -DSQLITE_TEMP_STORE=3
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     4. File truncation. As of version 3.6.24, SQLite may run without
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        a working xTruncate() call, providing the user does not configure
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        SQLite to use "journal_mode=truncate", or use both
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        "journal_mode=persist" and ATTACHed databases.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   It is assumed that the system uses UNIX-like path-names. Specifically,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   that '/' characters are used to separate path components and that
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   a path-name is a relative path unless it begins with a '/'. And that
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   no UTF-8 encoded paths are greater than 512 bytes in length.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** JOURNAL WRITE-BUFFERING
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   To commit a transaction to the database, SQLite first writes rollback
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   information into the journal file. This usually consists of 4 steps:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     1. The rollback information is sequentially written into the journal
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**        file, starting at the start of the file.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     2. The journal file is synced to disk.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     3. A modification is made to the first few bytes of the journal file.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     4. The journal file is synced to disk again.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   Most of the data is written in step 1 using a series of calls to the
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   VFS xWrite() method. The buffers passed to the xWrite() calls are of
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   various sizes. For example, as of version 3.6.24, when committing a
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   transaction that modifies 3 pages of a database file that uses 4096
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   byte pages residing on a media with 512 byte sectors, SQLite makes
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   eleven calls to the xWrite() method to create the rollback journal,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   as follows:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             Write offset | Bytes written
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             ----------------------------
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                        0            512
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                      512              4
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                      516           4096
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                     4612              4
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                     4616              4
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                     4620           4096
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                     8716              4
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                     8720              4
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                     8724           4096
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                    12820              4
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             ++++++++++++SYNC+++++++++++
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                        0             12
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             ++++++++++++SYNC+++++++++++
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   On many operating systems, this is an efficient way to write to a file.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   However, on some embedded systems that do not cache writes in OS
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   buffers it is much more efficient to write data in blocks that are
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   an integer multiple of the sector-size in size and aligned at the
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   start of a sector.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   To work around this, the code in this file allocates a fixed size
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   buffer of SQLITE_DEMOVFS_BUFFERSZ using sqlite3_malloc() whenever a
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   journal file is opened. It uses the buffer to coalesce sequential
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   writes into aligned SQLITE_DEMOVFS_BUFFERSZ blocks. When SQLite
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   invokes the xSync() method to sync the contents of the file to disk,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   all accumulated data is written out, even if it does not constitute
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   a complete block. This means the actual IO to create the rollback
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   journal for the example transaction above is this:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             Write offset | Bytes written
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             ----------------------------
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                        0           8192
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                     8192           4632
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             ++++++++++++SYNC+++++++++++
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**                        0             12
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**             ++++++++++++SYNC+++++++++++
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   Much more efficient if the underlying OS is not caching write
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   operations.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(SQLITE_TEST) || SQLITE_OS_UNIX
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sqlite3.h>
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/file.h>
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/param.h>
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h>
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Size of the write buffer used by journal files in bytes.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_DEMOVFS_BUFFERSZ
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define SQLITE_DEMOVFS_BUFFERSZ 8192
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The maximum pathname length supported by this VFS.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAXPATHNAME 512
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When using this VFS, the sqlite3_file* handles that SQLite uses are
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** actually pointers to instances of type DemoFile.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct DemoFile DemoFile;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DemoFile {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file base;              /* Base class. Must be first. */
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd;                         /* File descriptor */
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *aBuffer;                  /* Pointer to malloc'd buffer */
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nBuffer;                    /* Valid bytes of data in zBuffer */
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 iBufferOfst;      /* Offset in file of zBuffer[0] */
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write directly to the file passed as the first argument. Even if the
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file has a write-buffer (DemoFile.aBuffer), ignore it.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoDirectWrite(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DemoFile *p,                    /* File handle */
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *zBuf,               /* Buffer containing data to write */
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,                       /* Size of data to write in bytes */
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst              /* File offset to write to */
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  off_t ofst;                     /* Return value from lseek() */
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t nWrite;                  /* Return value from write() */
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ofst = lseek(p->fd, iOfst, SEEK_SET);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( ofst!=iOfst ){
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_WRITE;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nWrite = write(p->fd, zBuf, iAmt);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nWrite!=iAmt ){
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_WRITE;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Flush the contents of the DemoFile.aBuffer buffer to disk. This is a
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** no-op if this particular file does not have a buffer (i.e. it is not
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a journal file) or if the buffer is currently empty.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoFlushBuffer(DemoFile *p){
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->nBuffer ){
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = demoDirectWrite(p, p->aBuffer, p->nBuffer, p->iBufferOfst);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->nBuffer = 0;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoClose(sqlite3_file *pFile){
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DemoFile *p = (DemoFile*)pFile;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = demoFlushBuffer(p);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p->aBuffer);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close(p->fd);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from a file.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoRead(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zBuf,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DemoFile *p = (DemoFile*)pFile;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  off_t ofst;                     /* Return value from lseek() */
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRead;                      /* Return value from read() */
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                         /* Return code from demoFlushBuffer() */
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Flush any data in the write buffer to disk in case this operation
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** is trying to read data the file-region currently cached in the buffer.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** It would be possible to detect this case and possibly save an
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** unnecessary write here, but in practice SQLite will rarely read from
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** a journal file when there is data cached in the write-buffer.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = demoFlushBuffer(p);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ofst = lseek(p->fd, iOfst, SEEK_SET);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( ofst!=iOfst ){
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_READ;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nRead = read(p->fd, zBuf, iAmt);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nRead==iAmt ){
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( nRead>=0 ){
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_SHORT_READ;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_IOERR_READ;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data to a crash-file.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoWrite(
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *zBuf,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DemoFile *p = (DemoFile*)pFile;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->aBuffer ){
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *z = (char *)zBuf;       /* Pointer to remaining data to write */
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int n = iAmt;                 /* Number of bytes at z */
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_int64 i = iOfst;      /* File offset to write to */
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( n>0 ){
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int nCopy;                  /* Number of bytes to copy into buffer */
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* If the buffer is full, or if this data is not being written directly
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** following the data already buffered, flush the buffer. Flushing
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** the buffer is a no-op if it is empty.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( p->nBuffer==SQLITE_DEMOVFS_BUFFERSZ || p->iBufferOfst+p->nBuffer!=i ){
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int rc = demoFlushBuffer(p);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( rc!=SQLITE_OK ){
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return rc;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( p->nBuffer==0 || p->iBufferOfst+p->nBuffer==i );
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->iBufferOfst = i - p->nBuffer;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Copy as much data as possible into the buffer. */
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nCopy = SQLITE_DEMOVFS_BUFFERSZ - p->nBuffer;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( nCopy>n ){
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nCopy = n;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(&p->aBuffer[p->nBuffer], z, nCopy);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->nBuffer += nCopy;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      n -= nCopy;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i += nCopy;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      z += nCopy;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return demoDirectWrite(p, zBuf, iAmt, iOfst);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate a file. This is a no-op for this VFS (see header comments at
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the top of the file).
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoTruncate(sqlite3_file *pFile, sqlite_int64 size){
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( ftruncate(((DemoFile *)pFile)->fd, size) ) return SQLITE_IOERR_TRUNCATE;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sync the contents of the file to the persistent media.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoSync(sqlite3_file *pFile, int flags){
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DemoFile *p = (DemoFile*)pFile;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = demoFlushBuffer(p);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = fsync(p->fd);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (rc==0 ? SQLITE_OK : SQLITE_IOERR_FSYNC);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write the size of the file in bytes to *pSize.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DemoFile *p = (DemoFile*)pFile;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                         /* Return code from fstat() call */
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat sStat;              /* Output of fstat() call */
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Flush the contents of the buffer to disk. As with the flush in the
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** demoRead() method, it would be possible to avoid this and save a write
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** here and there. But in practice this comes up so infrequently it is
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** not worth the trouble.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = demoFlushBuffer(p);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=SQLITE_OK ){
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rc;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = fstat(p->fd, &sStat);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=0 ) return SQLITE_IOERR_FSTAT;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pSize = sStat.st_size;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Locking functions. The xLock() and xUnlock() methods are both no-ops.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The xCheckReservedLock() always indicates that no other process holds
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a reserved lock on the database file. This ensures that if a hot-journal
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file is found in the file-system it is rolled back.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoLock(sqlite3_file *pFile, int eLock){
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoUnlock(sqlite3_file *pFile, int eLock){
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoCheckReservedLock(sqlite3_file *pFile, int *pResOut){
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = 0;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** No xFileControl() verbs are implemented by this VFS.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoFileControl(sqlite3_file *pFile, int op, void *pArg){
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The xSectorSize() and xDeviceCharacteristics() methods. These two
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** may return special values allowing SQLite to optimize file-system
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** access to some extent. But it is also safe to simply return 0.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoSectorSize(sqlite3_file *pFile){
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoDeviceCharacteristics(sqlite3_file *pFile){
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a file handle.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoOpen(
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,              /* VFS */
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName,              /* File to open, or 0 for a temp file */
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,            /* Pointer to DemoFile struct to populate */
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,                      /* Input SQLITE_OPEN_XXX flags */
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pOutFlags                  /* Output SQLITE_OPEN_XXX flags (or NULL) */
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const sqlite3_io_methods demoio = {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                            /* iVersion */
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoClose,                    /* xClose */
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoRead,                     /* xRead */
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoWrite,                    /* xWrite */
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoTruncate,                 /* xTruncate */
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoSync,                     /* xSync */
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoFileSize,                 /* xFileSize */
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoLock,                     /* xLock */
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoUnlock,                   /* xUnlock */
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoCheckReservedLock,        /* xCheckReservedLock */
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoFileControl,              /* xFileControl */
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoSectorSize,               /* xSectorSize */
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoDeviceCharacteristics     /* xDeviceCharacteristics */
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DemoFile *p = (DemoFile*)pFile; /* Populate this structure */
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int oflags = 0;                 /* flags to pass to open() call */
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *aBuf = 0;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zName==0 ){
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags&SQLITE_OPEN_MAIN_JOURNAL ){
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aBuf = (char *)sqlite3_malloc(SQLITE_DEMOVFS_BUFFERSZ);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !aBuf ){
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags&SQLITE_OPEN_EXCLUSIVE ) oflags |= O_EXCL;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags&SQLITE_OPEN_CREATE )    oflags |= O_CREAT;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags&SQLITE_OPEN_READONLY )  oflags |= O_RDONLY;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags&SQLITE_OPEN_READWRITE ) oflags |= O_RDWR;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, sizeof(DemoFile));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->fd = open(zName, oflags, 0600);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->fd<0 ){
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(aBuf);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_CANTOPEN;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->aBuffer = aBuf;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pOutFlags ){
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pOutFlags = flags;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->base.pMethods = &demoio;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the file identified by argument zPath. If the dirSync parameter
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is non-zero, then ensure the file-system modification to delete the
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file has been synced to disk before returning.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                         /* Return code */
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = unlink(zPath);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!=0 && errno==ENOENT ) return SQLITE_OK;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==0 && dirSync ){
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int dfd;                      /* File descriptor open on directory */
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;                        /* Iterator variable */
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char zDir[MAXPATHNAME+1];     /* Name of directory containing file zPath */
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Figure out the directory name from the path of the file deleted. */
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zDir[MAXPATHNAME] = '\0';
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(i=strlen(zDir); i>1 && zDir[i]!='/'; i++);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zDir[i] = '\0';
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Open a file-descriptor on the directory. Sync. Close. */
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dfd = open(zDir, O_RDONLY, 0);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( dfd<0 ){
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = -1;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = fsync(dfd);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      close(dfd);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (rc==0 ? SQLITE_OK : SQLITE_IOERR_DELETE);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef F_OK
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define F_OK 0
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef R_OK
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define R_OK 4
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef W_OK
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define W_OK 2
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Query the file-system to see if the named file exists, is readable or
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is both readable and writable.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoAccess(
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pResOut
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                         /* access() return code */
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eAccess = F_OK;             /* Second argument to access() */
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( flags==SQLITE_ACCESS_EXISTS       /* access(zPath, F_OK) */
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==SQLITE_ACCESS_READ         /* access(zPath, R_OK) */
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==SQLITE_ACCESS_READWRITE    /* access(zPath, R_OK|W_OK) */
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags==SQLITE_ACCESS_READWRITE ) eAccess = R_OK|W_OK;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags==SQLITE_ACCESS_READ )      eAccess = R_OK;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = access(zPath, eAccess);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = (rc==0);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Argument zPath points to a nul-terminated string containing a file path.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If zPath is an absolute path, then it is copied as is into the output
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** buffer. Otherwise, if it is a relative path, then the equivalent full
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** path is written to the output buffer.
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function assumes that paths are UNIX style. Specifically, that:
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   1. Path components are separated by a '/'. and
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   2. Full paths begin with a '/' character.
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoFullPathname(
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,              /* VFS */
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,              /* Input path (possibly a relative path) */
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nPathOut,                   /* Size of output buffer in bytes */
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zPathOut                  /* Pointer to output buffer */
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zDir[MAXPATHNAME+1];
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zPath[0]=='/' ){
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zDir[0] = '\0';
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    getcwd(zDir, sizeof(zDir));
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zDir[MAXPATHNAME] = '\0';
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zPathOut[nPathOut-1] = '\0';
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following four VFS methods:
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   xDlOpen
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   xDlError
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   xDlSym
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   xDlClose
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are supposed to implement the functionality needed by SQLite to load
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** extensions compiled as shared objects. This simple VFS does not support
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this functionality, so the following functions are no-ops.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *demoDlOpen(sqlite3_vfs *pVfs, const char *zPath){
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void demoDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_snprintf(nByte, zErrMsg, "Loadable extensions are not supported");
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zErrMsg[nByte-1] = '\0';
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*demoDlSym(sqlite3_vfs *pVfs, void *pH, const char *z))(void){
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void demoDlClose(sqlite3_vfs *pVfs, void *pHandle){
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Parameter zByte points to a buffer nByte bytes in size. Populate this
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** buffer with pseudo-random data.
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoRandomness(sqlite3_vfs *pVfs, int nByte, char *zByte){
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sleep for at least nMicro microseconds. Return the (approximate) number
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of microseconds slept for.
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoSleep(sqlite3_vfs *pVfs, int nMicro){
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sleep(nMicro / 1000000);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  usleep(nMicro % 1000000);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return nMicro;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Set *pTime to the current UTC time expressed as a Julian day. Return
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLITE_OK if successful, or an error code otherwise.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   http://en.wikipedia.org/wiki/Julian_day
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This implementation is not very good. The current time is rounded to
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** an integer number of seconds. Also, assuming time_t is a signed 32-bit
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** value, it will stop working some time in the year 2038 AD (the so-called
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** "year 2038" problem that afflicts systems that store time this way).
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int demoCurrentTime(sqlite3_vfs *pVfs, double *pTime){
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  time_t t = time(0);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pTime = t/86400.0 + 2440587.5;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function returns a pointer to the VFS implemented in this file.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** To make the VFS available to SQLite:
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   sqlite3_vfs_register(sqlite3_demovfs(), 0);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sqlite3_vfs *sqlite3_demovfs(void){
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static sqlite3_vfs demovfs = {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                            /* iVersion */
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(DemoFile),             /* szOsFile */
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MAXPATHNAME,                  /* mxPathname */
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* pNext */
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "demo",                       /* zName */
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                            /* pAppData */
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoOpen,                     /* xOpen */
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoDelete,                   /* xDelete */
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoAccess,                   /* xAccess */
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoFullPathname,             /* xFullPathname */
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoDlOpen,                   /* xDlOpen */
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoDlError,                  /* xDlError */
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoDlSym,                    /* xDlSym */
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoDlClose,                  /* xDlClose */
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoRandomness,               /* xRandomness */
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoSleep,                    /* xSleep */
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    demoCurrentTime,              /* xCurrentTime */
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &demovfs;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* !defined(SQLITE_TEST) || SQLITE_OS_UNIX */
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <tcl.h>
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_UNIX
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int register_demovfs(
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,              /* Number of arguments */
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]  /* Command arguments */
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs_register(sqlite3_demovfs(), 1);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unregister_demovfs(
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int objc,              /* Number of arguments */
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_Obj *CONST objv[]  /* Command arguments */
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs_unregister(sqlite3_demovfs());
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Register commands with the TCL interpreter.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Sqlitetest_demovfs_Init(Tcl_Interp *interp){
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_CreateObjCommand(interp, "register_demovfs", register_demovfs, 0, 0);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tcl_CreateObjCommand(interp, "unregister_demovfs", unregister_demovfs, 0, 0);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TCL_OK;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int Sqlitetest_demovfs_Init(Tcl_Interp *interp){ return TCL_OK; }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_TEST */
681