15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2007 September 14
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)** OVERVIEW:
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   This file contains some example code demonstrating how the SQLite
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   vfs feature can be used to have SQLite operate directly on an
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   embedded media, without using an intermediate file system.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   Because this is only a demo designed to run on a workstation, the
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   underlying media is simulated using a regular file-system file. The
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   size of the file is fixed when it is first created (default size 10 MB).
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   From SQLite's point of view, this space is used to store a single
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   database file and the journal file.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   Any statement journal created is stored in volatile memory obtained
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   from sqlite3_malloc(). Any attempt to create a temporary database file
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   will fail (SQLITE_IOERR). To prevent SQLite from attempting this,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   it should be configured to store all temporary database files in
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   main memory (see pragma "temp_store" or the SQLITE_TEMP_STORE compile
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   time option).
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ASSUMPTIONS:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   After it has been created, the blob file is accessed using the
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   following three functions only:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       mediaRead();            - Read a 512 byte block from the file.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       mediaWrite();           - Write a 512 byte block to the file.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**       mediaSync();            - Tell the media hardware to sync.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   It is assumed that these can be easily implemented by any "real"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   media vfs driver adapting this code.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** FILE FORMAT:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   The basic principle is that the "database file" is stored at the
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   beginning of the 10 MB blob and grows in a forward direction. The
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   "journal file" is stored at the end of the 10MB blob and grows
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   in the reverse direction. If, during a transaction, insufficient
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   space is available to expand either the journal or database file,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   an SQLITE_FULL error is returned. The database file is never allowed
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   to consume more than 90% of the blob space. If SQLite tries to
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   create a file larger than this, SQLITE_FULL is returned.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   No allowance is made for "wear-leveling", as is required by.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   embedded devices in the absence of equivalent hardware features.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   The first 512 block byte of the file is reserved for storing the
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   size of the "database file". It is updated as part of the sync()
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   operation. On startup, it can only be trusted if no journal file
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   exists. If a journal-file does exist, then it stores the real size
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   of the database region. The second and subsequent blocks store the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   actual database content.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   The size of the "journal file" is not stored persistently in the
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   file. When the system is running, the size of the journal file is
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   stored in volatile memory. When recovering from a crash, this vfs
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   reports a very large size for the journal file. The normal journal
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   header and checksum mechanisms serve to prevent SQLite from
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   processing any data that lies past the logical end of the journal.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   When SQLite calls OsDelete() to delete the journal file, the final
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   512 bytes of the blob (the area containing the first journal header)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   are zeroed.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** LOCKING:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   File locking is a no-op. Only one connection may be open at any one
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   time using this demo vfs.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqlite3.h"
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Maximum pathname length supported by the fs backend.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BLOCKSIZE 512
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BLOBSIZE 10485760
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Name used to identify this VFS.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FS_VFS_NAME "fs"
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct fs_real_file fs_real_file;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fs_real_file {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nDatabase;              /* Current size of database region */
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nJournal;               /* Current size of journal region */
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nBlob;                  /* Total size of allocated blob */
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRef;                   /* Number of pointers to this structure */
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pNext;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file **ppThis;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct fs_file fs_file;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fs_file {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file base;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eType;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct tmp_file tmp_file;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct tmp_file {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file base;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nSize;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nAlloc;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zAlloc;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Values for fs_file.eType. */
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DATABASE_FILE   1
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define JOURNAL_FILE    2
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Method declarations for fs_file.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsClose(sqlite3_file*);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsTruncate(sqlite3_file*, sqlite3_int64 size);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsSync(sqlite3_file*, int flags);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsLock(sqlite3_file*, int);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsUnlock(sqlite3_file*, int);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsCheckReservedLock(sqlite3_file*, int *pResOut);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsFileControl(sqlite3_file*, int op, void *pArg);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsSectorSize(sqlite3_file*);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsDeviceCharacteristics(sqlite3_file*);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Method declarations for tmp_file.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpClose(sqlite3_file*);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpTruncate(sqlite3_file*, sqlite3_int64 size);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpSync(sqlite3_file*, int flags);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpLock(sqlite3_file*, int);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpUnlock(sqlite3_file*, int);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpCheckReservedLock(sqlite3_file*, int *pResOut);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpFileControl(sqlite3_file*, int op, void *pArg);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpSectorSize(sqlite3_file*);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpDeviceCharacteristics(sqlite3_file*);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Method declarations for fs_vfs.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*fsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void fsDlClose(sqlite3_vfs*, void*);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsSleep(sqlite3_vfs*, int microseconds);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsCurrentTime(sqlite3_vfs*, double*);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct fs_vfs_t fs_vfs_t;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct fs_vfs_t {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs base;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pFileList;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static fs_vfs_t fs_vfs = {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1,                                          /* iVersion */
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                          /* szOsFile */
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                          /* mxPathname */
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                          /* pNext */
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FS_VFS_NAME,                                /* zName */
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                                          /* pAppData */
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsOpen,                                     /* xOpen */
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsDelete,                                   /* xDelete */
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsAccess,                                   /* xAccess */
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsFullPathname,                             /* xFullPathname */
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsDlOpen,                                   /* xDlOpen */
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsDlError,                                  /* xDlError */
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsDlSym,                                    /* xDlSym */
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsDlClose,                                  /* xDlClose */
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsRandomness,                               /* xRandomness */
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsSleep,                                    /* xSleep */
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fsCurrentTime,                              /* xCurrentTime */
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0                                           /* xCurrentTimeInt64 */
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  },
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                                            /* pFileList */
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0                                             /* pParent */
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_io_methods fs_io_methods = {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                            /* iVersion */
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsClose,                      /* xClose */
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsRead,                       /* xRead */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsWrite,                      /* xWrite */
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsTruncate,                   /* xTruncate */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsSync,                       /* xSync */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsFileSize,                   /* xFileSize */
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsLock,                       /* xLock */
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsUnlock,                     /* xUnlock */
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsCheckReservedLock,          /* xCheckReservedLock */
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsFileControl,                /* xFileControl */
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsSectorSize,                 /* xSectorSize */
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fsDeviceCharacteristics,      /* xDeviceCharacteristics */
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                            /* xShmMap */
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                            /* xShmLock */
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                            /* xShmBarrier */
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0                             /* xShmUnmap */
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static sqlite3_io_methods tmp_io_methods = {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,                            /* iVersion */
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpClose,                     /* xClose */
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpRead,                      /* xRead */
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpWrite,                     /* xWrite */
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpTruncate,                  /* xTruncate */
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpSync,                      /* xSync */
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpFileSize,                  /* xFileSize */
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpLock,                      /* xLock */
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpUnlock,                    /* xUnlock */
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpCheckReservedLock,         /* xCheckReservedLock */
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpFileControl,               /* xFileControl */
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpSectorSize,                /* xSectorSize */
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmpDeviceCharacteristics,     /* xDeviceCharacteristics */
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                            /* xShmMap */
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                            /* xShmLock */
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,                            /* xShmBarrier */
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0                             /* xShmUnmap */
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Useful macros used in several places */
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MIN(x,y) ((x)<(y)?(x):(y))
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX(x,y) ((x)>(y)?(x):(y))
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a tmp-file.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpClose(sqlite3_file *pFile){
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_file *pTmp = (tmp_file *)pFile;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pTmp->zAlloc);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from a tmp-file.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpRead(
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zBuf,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_file *pTmp = (tmp_file *)pFile;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (iAmt+iOfst)>pTmp->nSize ){
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_SHORT_READ;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data to a tmp-file.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpWrite(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *zBuf,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_file *pTmp = (tmp_file *)pFile;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (iAmt+iOfst)>pTmp->nAlloc ){
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nNew = 2*(iAmt+iOfst+pTmp->nAlloc);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !zNew ){
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pTmp->zAlloc = zNew;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pTmp->nAlloc = nNew;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pTmp->nSize = MAX(pTmp->nSize, iOfst+iAmt);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate a tmp-file.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_file *pTmp = (tmp_file *)pFile;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pTmp->nSize = MIN(pTmp->nSize, size);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sync a tmp-file.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpSync(sqlite3_file *pFile, int flags){
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the current file-size of a tmp-file.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_file *pTmp = (tmp_file *)pFile;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pSize = pTmp->nSize;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock a tmp-file.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpLock(sqlite3_file *pFile, int eLock){
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Unlock a tmp-file.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpUnlock(sqlite3_file *pFile, int eLock){
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Check if another file-handle holds a RESERVED lock on a tmp-file.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = 0;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** File control method. For custom operations on a tmp-file.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the sector-size in bytes for a tmp-file.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpSectorSize(sqlite3_file *pFile){
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the device characteristic flags supported by a tmp-file.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int tmpDeviceCharacteristics(sqlite3_file *pFile){
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close an fs-file.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsClose(sqlite3_file *pFile){
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_file *p = (fs_file *)pFile;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal = p->pReal;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Decrement the real_file ref-count. */
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pReal->nRef--;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(pReal->nRef>=0);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* When the ref-count reaches 0, destroy the structure */
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pReal->nRef==0 ){
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pReal->ppThis = pReal->pNext;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pReal->pNext ){
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->pNext->ppThis = pReal->ppThis;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = pReal->pFile->pMethods->xClose(pReal->pFile);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pReal);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from an fs-file.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsRead(
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zBuf,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_file *p = (fs_file *)pFile;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal = p->pReal;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pF = pReal->pFile;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_IOERR_SHORT_READ;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( p->eType==DATABASE_FILE ){
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Journal file. */
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iRem = iAmt;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iBuf = 0;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ii = iOfst;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( iRem>0 && rc==SQLITE_OK ){
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ii += iRealAmt;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iBuf += iRealAmt;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iRem -= iRealAmt;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data to an fs-file.
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsWrite(
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *zBuf,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iAmt,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite_int64 iOfst
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_file *p = (fs_file *)pFile;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal = p->pReal;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pF = pReal->pFile;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->eType==DATABASE_FILE ){
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_FULL;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pReal->nDatabase = MAX(pReal->nDatabase, iAmt+iOfst);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Journal file. */
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iRem = iAmt;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iBuf = 0;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ii = iOfst;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( iRem>0 && rc==SQLITE_OK ){
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_FULL;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ii += iRealAmt;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iBuf += iRealAmt;
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iRem -= iRealAmt;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->nJournal = MAX(pReal->nJournal, iAmt+iOfst);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate an fs-file.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_file *p = (fs_file *)pFile;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal = p->pReal;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->eType==DATABASE_FILE ){
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pReal->nDatabase = MIN(pReal->nDatabase, size);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pReal->nJournal = MIN(pReal->nJournal, size);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sync an fs-file.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsSync(sqlite3_file *pFile, int flags){
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_file *p = (fs_file *)pFile;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal = p->pReal;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pRealFile = pReal->pFile;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->eType==DATABASE_FILE ){
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char zSize[4];
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSize[1] = (pReal->nDatabase&0x00FF0000)>>16;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zSize[3] = (pReal->nDatabase&0x000000FF);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==SQLITE_OK ){
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY));
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the current file-size of an fs-file.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_file *p = (fs_file *)pFile;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal = p->pReal;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p->eType==DATABASE_FILE ){
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pSize = pReal->nDatabase;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pSize = pReal->nJournal;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock an fs-file.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsLock(sqlite3_file *pFile, int eLock){
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Unlock an fs-file.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsUnlock(sqlite3_file *pFile, int eLock){
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Check if another file-handle holds a RESERVED lock on an fs-file.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = 0;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** File control method. For custom operations on an fs-file.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the sector-size in bytes for an fs-file.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsSectorSize(sqlite3_file *pFile){
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return BLOCKSIZE;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the device characteristic flags supported by an fs-file.
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsDeviceCharacteristics(sqlite3_file *pFile){
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open an fs file handle.
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsOpen(
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName,
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pFile,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pOutFlags
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_file *p = (fs_file *)pFile;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal = 0;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eType;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nName;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp_file *p = (tmp_file *)pFile;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(p, 0, sizeof(*p));
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p->base.pMethods = &tmp_io_methods;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->base.pMethods = &fs_io_methods;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->eType = eType;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(strlen("-journal")==8);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nName = strlen(zName)-((eType==JOURNAL_FILE)?8:0);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pReal=pFsVfs->pFileList;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !pReal ){
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int real_flags = (flags&~(SQLITE_OPEN_MAIN_DB))|SQLITE_OPEN_TEMP_DB;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_int64 size;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_file *pRealFile;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_vfs *pParent = pFsVfs->pParent;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(eType==DATABASE_FILE);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !pReal ){
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto open_out;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile);
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pReal->zName = zName;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pReal->pFile = (sqlite3_file *)(&pReal[1]);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = pParent->xOpen(pParent, zName, pReal->pFile, real_flags, pOutFlags);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto open_out;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pRealFile = pReal->pFile;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = pRealFile->pMethods->xFileSize(pRealFile, &size);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto open_out;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( size==0 ){
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->nBlob = BLOBSIZE;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned char zS[4];
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->nBlob = size;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3];
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( zS[0] || zS[1] || zS[2] || zS[3] ){
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pReal->nJournal = pReal->nBlob;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->pNext = pFsVfs->pFileList;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pReal->pNext ){
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pReal->pNext->ppThis = &pReal->pNext;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->ppThis = &pFsVfs->pFileList;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFsVfs->pFileList = pReal;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)open_out:
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pReal ){
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->pReal = pReal;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->nRef++;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pReal->pFile->pMethods ){
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pReal->pFile->pMethods->xClose(pReal->pFile);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(pReal);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the file located at zPath. If the dirSync argument is true,
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** ensure the file-system modifications are synced to disk before
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returning.
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *pF;
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nName = strlen(zPath) - 8;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(strlen("-journal")==8);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(strcmp("-journal", &zPath[nName])==0);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pReal = pFsVfs->pFileList;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pReal ){
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pF = pReal->pFile;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pReal->nJournal = 0;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Test for access permissions. Return true if the requested permission
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is available, or false otherwise.
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsAccess(
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pResOut
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_real_file *pReal;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isJournal = 0;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nName = strlen(zPath);
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags!=SQLITE_ACCESS_EXISTS ){
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pParent->xAccess(pParent, zPath, flags, pResOut);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(strlen("-journal")==8);
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nName -= 8;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isJournal = 1;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pReal = pFsVfs->pFileList;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = (pReal && (!isJournal || pReal->nJournal>0));
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate buffer zOut with the full canonical pathname corresponding
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to the pathname in zPath. zOut is guaranteed to point to a buffer
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of at least (FS_MAX_PATHNAME+1) bytes.
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsFullPathname(
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath,            /* Possibly relative input path */
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nOut,                     /* Size of output buffer in bytes */
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zOut                    /* Output buffer */
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pParent->xFullPathname(pParent, zPath, nOut, zOut);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open the dynamic library located at zPath and return a handle.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pParent->xDlOpen(pParent, zPath);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate the buffer zErrMsg (size nByte bytes) with a human readable
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** utf-8 string describing the most recent error encountered associated
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with dynamic libraries.
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pParent->xDlError(pParent, nByte, zErrMsg);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void (*fsDlSym(sqlite3_vfs *pVfs, void *pH, const char *zSym))(void){
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pParent->xDlSym(pParent, pH, zSym);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close the dynamic library handle pHandle.
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pParent->xDlClose(pParent, pHandle);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Populate the buffer pointed to by zBufOut with nByte bytes of
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** random data.
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pParent->xRandomness(pParent, nByte, zBufOut);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sleep for nMicro microseconds. Return the number of microseconds
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** actually slept.
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsSleep(sqlite3_vfs *pVfs, int nMicro){
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pParent->xSleep(pParent, nMicro);
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the current time as a Julian Day number in *pTimeOut.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pParent->xCurrentTime(pParent, pTimeOut);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This procedure registers the fs vfs with SQLite. If the argument is
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** true, the fs vfs becomes the new default vfs. It is the only publicly
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** available function in this file.
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int fs_register(void){
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( fs_vfs.pParent ) return SQLITE_OK;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_vfs.pParent = sqlite3_vfs_find(0);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file));
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3_vfs_register(&fs_vfs.base, 0);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int SqlitetestOnefile_Init() {return fs_register();}
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
831