Home | History | Annotate | Download | only in src
      1 /*
      2 ** 2007 September 14
      3 **
      4 ** The author disclaims copyright to this source code.  In place of
      5 ** a legal notice, here is a blessing:
      6 **
      7 **    May you do good and not evil.
      8 **    May you find forgiveness for yourself and forgive others.
      9 **    May you share freely, never taking more than you give.
     10 **
     11 *************************************************************************
     12 **
     13 ** OVERVIEW:
     14 **
     15 **   This file contains some example code demonstrating how the SQLite
     16 **   vfs feature can be used to have SQLite operate directly on an
     17 **   embedded media, without using an intermediate file system.
     18 **
     19 **   Because this is only a demo designed to run on a workstation, the
     20 **   underlying media is simulated using a regular file-system file. The
     21 **   size of the file is fixed when it is first created (default size 10 MB).
     22 **   From SQLite's point of view, this space is used to store a single
     23 **   database file and the journal file.
     24 **
     25 **   Any statement journal created is stored in volatile memory obtained
     26 **   from sqlite3_malloc(). Any attempt to create a temporary database file
     27 **   will fail (SQLITE_IOERR). To prevent SQLite from attempting this,
     28 **   it should be configured to store all temporary database files in
     29 **   main memory (see pragma "temp_store" or the SQLITE_TEMP_STORE compile
     30 **   time option).
     31 **
     32 ** ASSUMPTIONS:
     33 **
     34 **   After it has been created, the blob file is accessed using the
     35 **   following three functions only:
     36 **
     37 **       mediaRead();            - Read a 512 byte block from the file.
     38 **       mediaWrite();           - Write a 512 byte block to the file.
     39 **       mediaSync();            - Tell the media hardware to sync.
     40 **
     41 **   It is assumed that these can be easily implemented by any "real"
     42 **   media vfs driver adapting this code.
     43 **
     44 ** FILE FORMAT:
     45 **
     46 **   The basic principle is that the "database file" is stored at the
     47 **   beginning of the 10 MB blob and grows in a forward direction. The
     48 **   "journal file" is stored at the end of the 10MB blob and grows
     49 **   in the reverse direction. If, during a transaction, insufficient
     50 **   space is available to expand either the journal or database file,
     51 **   an SQLITE_FULL error is returned. The database file is never allowed
     52 **   to consume more than 90% of the blob space. If SQLite tries to
     53 **   create a file larger than this, SQLITE_FULL is returned.
     54 **
     55 **   No allowance is made for "wear-leveling", as is required by.
     56 **   embedded devices in the absence of equivalent hardware features.
     57 **
     58 **   The first 512 block byte of the file is reserved for storing the
     59 **   size of the "database file". It is updated as part of the sync()
     60 **   operation. On startup, it can only be trusted if no journal file
     61 **   exists. If a journal-file does exist, then it stores the real size
     62 **   of the database region. The second and subsequent blocks store the
     63 **   actual database content.
     64 **
     65 **   The size of the "journal file" is not stored persistently in the
     66 **   file. When the system is running, the size of the journal file is
     67 **   stored in volatile memory. When recovering from a crash, this vfs
     68 **   reports a very large size for the journal file. The normal journal
     69 **   header and checksum mechanisms serve to prevent SQLite from
     70 **   processing any data that lies past the logical end of the journal.
     71 **
     72 **   When SQLite calls OsDelete() to delete the journal file, the final
     73 **   512 bytes of the blob (the area containing the first journal header)
     74 **   are zeroed.
     75 **
     76 ** LOCKING:
     77 **
     78 **   File locking is a no-op. Only one connection may be open at any one
     79 **   time using this demo vfs.
     80 */
     81 
     82 #include "sqlite3.h"
     83 #include <assert.h>
     84 #include <string.h>
     85 
     86 /*
     87 ** Maximum pathname length supported by the fs backend.
     88 */
     89 #define BLOCKSIZE 512
     90 #define BLOBSIZE 10485760
     91 
     92 /*
     93 ** Name used to identify this VFS.
     94 */
     95 #define FS_VFS_NAME "fs"
     96 
     97 typedef struct fs_real_file fs_real_file;
     98 struct fs_real_file {
     99   sqlite3_file *pFile;
    100   const char *zName;
    101   int nDatabase;              /* Current size of database region */
    102   int nJournal;               /* Current size of journal region */
    103   int nBlob;                  /* Total size of allocated blob */
    104   int nRef;                   /* Number of pointers to this structure */
    105   fs_real_file *pNext;
    106   fs_real_file **ppThis;
    107 };
    108 
    109 typedef struct fs_file fs_file;
    110 struct fs_file {
    111   sqlite3_file base;
    112   int eType;
    113   fs_real_file *pReal;
    114 };
    115 
    116 typedef struct tmp_file tmp_file;
    117 struct tmp_file {
    118   sqlite3_file base;
    119   int nSize;
    120   int nAlloc;
    121   char *zAlloc;
    122 };
    123 
    124 /* Values for fs_file.eType. */
    125 #define DATABASE_FILE   1
    126 #define JOURNAL_FILE    2
    127 
    128 /*
    129 ** Method declarations for fs_file.
    130 */
    131 static int fsClose(sqlite3_file*);
    132 static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
    133 static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
    134 static int fsTruncate(sqlite3_file*, sqlite3_int64 size);
    135 static int fsSync(sqlite3_file*, int flags);
    136 static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
    137 static int fsLock(sqlite3_file*, int);
    138 static int fsUnlock(sqlite3_file*, int);
    139 static int fsCheckReservedLock(sqlite3_file*, int *pResOut);
    140 static int fsFileControl(sqlite3_file*, int op, void *pArg);
    141 static int fsSectorSize(sqlite3_file*);
    142 static int fsDeviceCharacteristics(sqlite3_file*);
    143 
    144 /*
    145 ** Method declarations for tmp_file.
    146 */
    147 static int tmpClose(sqlite3_file*);
    148 static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
    149 static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
    150 static int tmpTruncate(sqlite3_file*, sqlite3_int64 size);
    151 static int tmpSync(sqlite3_file*, int flags);
    152 static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize);
    153 static int tmpLock(sqlite3_file*, int);
    154 static int tmpUnlock(sqlite3_file*, int);
    155 static int tmpCheckReservedLock(sqlite3_file*, int *pResOut);
    156 static int tmpFileControl(sqlite3_file*, int op, void *pArg);
    157 static int tmpSectorSize(sqlite3_file*);
    158 static int tmpDeviceCharacteristics(sqlite3_file*);
    159 
    160 /*
    161 ** Method declarations for fs_vfs.
    162 */
    163 static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
    164 static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);
    165 static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
    166 static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
    167 static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
    168 static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
    169 static void (*fsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
    170 static void fsDlClose(sqlite3_vfs*, void*);
    171 static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
    172 static int fsSleep(sqlite3_vfs*, int microseconds);
    173 static int fsCurrentTime(sqlite3_vfs*, double*);
    174 
    175 
    176 typedef struct fs_vfs_t fs_vfs_t;
    177 struct fs_vfs_t {
    178   sqlite3_vfs base;
    179   fs_real_file *pFileList;
    180   sqlite3_vfs *pParent;
    181 };
    182 
    183 static fs_vfs_t fs_vfs = {
    184   {
    185     1,                                          /* iVersion */
    186     0,                                          /* szOsFile */
    187     0,                                          /* mxPathname */
    188     0,                                          /* pNext */
    189     FS_VFS_NAME,                                /* zName */
    190     0,                                          /* pAppData */
    191     fsOpen,                                     /* xOpen */
    192     fsDelete,                                   /* xDelete */
    193     fsAccess,                                   /* xAccess */
    194     fsFullPathname,                             /* xFullPathname */
    195     fsDlOpen,                                   /* xDlOpen */
    196     fsDlError,                                  /* xDlError */
    197     fsDlSym,                                    /* xDlSym */
    198     fsDlClose,                                  /* xDlClose */
    199     fsRandomness,                               /* xRandomness */
    200     fsSleep,                                    /* xSleep */
    201     fsCurrentTime,                              /* xCurrentTime */
    202     0                                           /* xCurrentTimeInt64 */
    203   },
    204   0,                                            /* pFileList */
    205   0                                             /* pParent */
    206 };
    207 
    208 static sqlite3_io_methods fs_io_methods = {
    209   1,                            /* iVersion */
    210   fsClose,                      /* xClose */
    211   fsRead,                       /* xRead */
    212   fsWrite,                      /* xWrite */
    213   fsTruncate,                   /* xTruncate */
    214   fsSync,                       /* xSync */
    215   fsFileSize,                   /* xFileSize */
    216   fsLock,                       /* xLock */
    217   fsUnlock,                     /* xUnlock */
    218   fsCheckReservedLock,          /* xCheckReservedLock */
    219   fsFileControl,                /* xFileControl */
    220   fsSectorSize,                 /* xSectorSize */
    221   fsDeviceCharacteristics,      /* xDeviceCharacteristics */
    222   0,                            /* xShmMap */
    223   0,                            /* xShmLock */
    224   0,                            /* xShmBarrier */
    225   0                             /* xShmUnmap */
    226 };
    227 
    228 
    229 static sqlite3_io_methods tmp_io_methods = {
    230   1,                            /* iVersion */
    231   tmpClose,                     /* xClose */
    232   tmpRead,                      /* xRead */
    233   tmpWrite,                     /* xWrite */
    234   tmpTruncate,                  /* xTruncate */
    235   tmpSync,                      /* xSync */
    236   tmpFileSize,                  /* xFileSize */
    237   tmpLock,                      /* xLock */
    238   tmpUnlock,                    /* xUnlock */
    239   tmpCheckReservedLock,         /* xCheckReservedLock */
    240   tmpFileControl,               /* xFileControl */
    241   tmpSectorSize,                /* xSectorSize */
    242   tmpDeviceCharacteristics,     /* xDeviceCharacteristics */
    243   0,                            /* xShmMap */
    244   0,                            /* xShmLock */
    245   0,                            /* xShmBarrier */
    246   0                             /* xShmUnmap */
    247 };
    248 
    249 /* Useful macros used in several places */
    250 #define MIN(x,y) ((x)<(y)?(x):(y))
    251 #define MAX(x,y) ((x)>(y)?(x):(y))
    252 
    253 
    254 /*
    255 ** Close a tmp-file.
    256 */
    257 static int tmpClose(sqlite3_file *pFile){
    258   tmp_file *pTmp = (tmp_file *)pFile;
    259   sqlite3_free(pTmp->zAlloc);
    260   return SQLITE_OK;
    261 }
    262 
    263 /*
    264 ** Read data from a tmp-file.
    265 */
    266 static int tmpRead(
    267   sqlite3_file *pFile,
    268   void *zBuf,
    269   int iAmt,
    270   sqlite_int64 iOfst
    271 ){
    272   tmp_file *pTmp = (tmp_file *)pFile;
    273   if( (iAmt+iOfst)>pTmp->nSize ){
    274     return SQLITE_IOERR_SHORT_READ;
    275   }
    276   memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt);
    277   return SQLITE_OK;
    278 }
    279 
    280 /*
    281 ** Write data to a tmp-file.
    282 */
    283 static int tmpWrite(
    284   sqlite3_file *pFile,
    285   const void *zBuf,
    286   int iAmt,
    287   sqlite_int64 iOfst
    288 ){
    289   tmp_file *pTmp = (tmp_file *)pFile;
    290   if( (iAmt+iOfst)>pTmp->nAlloc ){
    291     int nNew = 2*(iAmt+iOfst+pTmp->nAlloc);
    292     char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew);
    293     if( !zNew ){
    294       return SQLITE_NOMEM;
    295     }
    296     pTmp->zAlloc = zNew;
    297     pTmp->nAlloc = nNew;
    298   }
    299   memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt);
    300   pTmp->nSize = MAX(pTmp->nSize, iOfst+iAmt);
    301   return SQLITE_OK;
    302 }
    303 
    304 /*
    305 ** Truncate a tmp-file.
    306 */
    307 static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){
    308   tmp_file *pTmp = (tmp_file *)pFile;
    309   pTmp->nSize = MIN(pTmp->nSize, size);
    310   return SQLITE_OK;
    311 }
    312 
    313 /*
    314 ** Sync a tmp-file.
    315 */
    316 static int tmpSync(sqlite3_file *pFile, int flags){
    317   return SQLITE_OK;
    318 }
    319 
    320 /*
    321 ** Return the current file-size of a tmp-file.
    322 */
    323 static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
    324   tmp_file *pTmp = (tmp_file *)pFile;
    325   *pSize = pTmp->nSize;
    326   return SQLITE_OK;
    327 }
    328 
    329 /*
    330 ** Lock a tmp-file.
    331 */
    332 static int tmpLock(sqlite3_file *pFile, int eLock){
    333   return SQLITE_OK;
    334 }
    335 
    336 /*
    337 ** Unlock a tmp-file.
    338 */
    339 static int tmpUnlock(sqlite3_file *pFile, int eLock){
    340   return SQLITE_OK;
    341 }
    342 
    343 /*
    344 ** Check if another file-handle holds a RESERVED lock on a tmp-file.
    345 */
    346 static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){
    347   *pResOut = 0;
    348   return SQLITE_OK;
    349 }
    350 
    351 /*
    352 ** File control method. For custom operations on a tmp-file.
    353 */
    354 static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){
    355   return SQLITE_OK;
    356 }
    357 
    358 /*
    359 ** Return the sector-size in bytes for a tmp-file.
    360 */
    361 static int tmpSectorSize(sqlite3_file *pFile){
    362   return 0;
    363 }
    364 
    365 /*
    366 ** Return the device characteristic flags supported by a tmp-file.
    367 */
    368 static int tmpDeviceCharacteristics(sqlite3_file *pFile){
    369   return 0;
    370 }
    371 
    372 /*
    373 ** Close an fs-file.
    374 */
    375 static int fsClose(sqlite3_file *pFile){
    376   int rc = SQLITE_OK;
    377   fs_file *p = (fs_file *)pFile;
    378   fs_real_file *pReal = p->pReal;
    379 
    380   /* Decrement the real_file ref-count. */
    381   pReal->nRef--;
    382   assert(pReal->nRef>=0);
    383 
    384   /* When the ref-count reaches 0, destroy the structure */
    385   if( pReal->nRef==0 ){
    386     *pReal->ppThis = pReal->pNext;
    387     if( pReal->pNext ){
    388       pReal->pNext->ppThis = pReal->ppThis;
    389     }
    390     rc = pReal->pFile->pMethods->xClose(pReal->pFile);
    391     sqlite3_free(pReal);
    392   }
    393 
    394   return rc;
    395 }
    396 
    397 /*
    398 ** Read data from an fs-file.
    399 */
    400 static int fsRead(
    401   sqlite3_file *pFile,
    402   void *zBuf,
    403   int iAmt,
    404   sqlite_int64 iOfst
    405 ){
    406   int rc = SQLITE_OK;
    407   fs_file *p = (fs_file *)pFile;
    408   fs_real_file *pReal = p->pReal;
    409   sqlite3_file *pF = pReal->pFile;
    410 
    411   if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase)
    412    || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal)
    413   ){
    414     rc = SQLITE_IOERR_SHORT_READ;
    415   }else if( p->eType==DATABASE_FILE ){
    416     rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
    417   }else{
    418     /* Journal file. */
    419     int iRem = iAmt;
    420     int iBuf = 0;
    421     int ii = iOfst;
    422     while( iRem>0 && rc==SQLITE_OK ){
    423       int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
    424       int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
    425 
    426       rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff);
    427       ii += iRealAmt;
    428       iBuf += iRealAmt;
    429       iRem -= iRealAmt;
    430     }
    431   }
    432 
    433   return rc;
    434 }
    435 
    436 /*
    437 ** Write data to an fs-file.
    438 */
    439 static int fsWrite(
    440   sqlite3_file *pFile,
    441   const void *zBuf,
    442   int iAmt,
    443   sqlite_int64 iOfst
    444 ){
    445   int rc = SQLITE_OK;
    446   fs_file *p = (fs_file *)pFile;
    447   fs_real_file *pReal = p->pReal;
    448   sqlite3_file *pF = pReal->pFile;
    449 
    450   if( p->eType==DATABASE_FILE ){
    451     if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){
    452       rc = SQLITE_FULL;
    453     }else{
    454       rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
    455       if( rc==SQLITE_OK ){
    456         pReal->nDatabase = MAX(pReal->nDatabase, iAmt+iOfst);
    457       }
    458     }
    459   }else{
    460     /* Journal file. */
    461     int iRem = iAmt;
    462     int iBuf = 0;
    463     int ii = iOfst;
    464     while( iRem>0 && rc==SQLITE_OK ){
    465       int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
    466       int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
    467 
    468       if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){
    469         rc = SQLITE_FULL;
    470       }else{
    471         rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff);
    472         ii += iRealAmt;
    473         iBuf += iRealAmt;
    474         iRem -= iRealAmt;
    475       }
    476     }
    477     if( rc==SQLITE_OK ){
    478       pReal->nJournal = MAX(pReal->nJournal, iAmt+iOfst);
    479     }
    480   }
    481 
    482   return rc;
    483 }
    484 
    485 /*
    486 ** Truncate an fs-file.
    487 */
    488 static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){
    489   fs_file *p = (fs_file *)pFile;
    490   fs_real_file *pReal = p->pReal;
    491   if( p->eType==DATABASE_FILE ){
    492     pReal->nDatabase = MIN(pReal->nDatabase, size);
    493   }else{
    494     pReal->nJournal = MIN(pReal->nJournal, size);
    495   }
    496   return SQLITE_OK;
    497 }
    498 
    499 /*
    500 ** Sync an fs-file.
    501 */
    502 static int fsSync(sqlite3_file *pFile, int flags){
    503   fs_file *p = (fs_file *)pFile;
    504   fs_real_file *pReal = p->pReal;
    505   sqlite3_file *pRealFile = pReal->pFile;
    506   int rc = SQLITE_OK;
    507 
    508   if( p->eType==DATABASE_FILE ){
    509     unsigned char zSize[4];
    510     zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
    511     zSize[1] = (pReal->nDatabase&0x00FF0000)>>16;
    512     zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
    513     zSize[3] = (pReal->nDatabase&0x000000FF);
    514     rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
    515   }
    516   if( rc==SQLITE_OK ){
    517     rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY));
    518   }
    519 
    520   return rc;
    521 }
    522 
    523 /*
    524 ** Return the current file-size of an fs-file.
    525 */
    526 static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
    527   fs_file *p = (fs_file *)pFile;
    528   fs_real_file *pReal = p->pReal;
    529   if( p->eType==DATABASE_FILE ){
    530     *pSize = pReal->nDatabase;
    531   }else{
    532     *pSize = pReal->nJournal;
    533   }
    534   return SQLITE_OK;
    535 }
    536 
    537 /*
    538 ** Lock an fs-file.
    539 */
    540 static int fsLock(sqlite3_file *pFile, int eLock){
    541   return SQLITE_OK;
    542 }
    543 
    544 /*
    545 ** Unlock an fs-file.
    546 */
    547 static int fsUnlock(sqlite3_file *pFile, int eLock){
    548   return SQLITE_OK;
    549 }
    550 
    551 /*
    552 ** Check if another file-handle holds a RESERVED lock on an fs-file.
    553 */
    554 static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
    555   *pResOut = 0;
    556   return SQLITE_OK;
    557 }
    558 
    559 /*
    560 ** File control method. For custom operations on an fs-file.
    561 */
    562 static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){
    563   return SQLITE_OK;
    564 }
    565 
    566 /*
    567 ** Return the sector-size in bytes for an fs-file.
    568 */
    569 static int fsSectorSize(sqlite3_file *pFile){
    570   return BLOCKSIZE;
    571 }
    572 
    573 /*
    574 ** Return the device characteristic flags supported by an fs-file.
    575 */
    576 static int fsDeviceCharacteristics(sqlite3_file *pFile){
    577   return 0;
    578 }
    579 
    580 /*
    581 ** Open an fs file handle.
    582 */
    583 static int fsOpen(
    584   sqlite3_vfs *pVfs,
    585   const char *zName,
    586   sqlite3_file *pFile,
    587   int flags,
    588   int *pOutFlags
    589 ){
    590   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
    591   fs_file *p = (fs_file *)pFile;
    592   fs_real_file *pReal = 0;
    593   int eType;
    594   int nName;
    595   int rc = SQLITE_OK;
    596 
    597   if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
    598     tmp_file *p = (tmp_file *)pFile;
    599     memset(p, 0, sizeof(*p));
    600     p->base.pMethods = &tmp_io_methods;
    601     return SQLITE_OK;
    602   }
    603 
    604   eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE);
    605   p->base.pMethods = &fs_io_methods;
    606   p->eType = eType;
    607 
    608   assert(strlen("-journal")==8);
    609   nName = strlen(zName)-((eType==JOURNAL_FILE)?8:0);
    610   pReal=pFsVfs->pFileList;
    611   for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext);
    612 
    613   if( !pReal ){
    614     int real_flags = (flags&~(SQLITE_OPEN_MAIN_DB))|SQLITE_OPEN_TEMP_DB;
    615     sqlite3_int64 size;
    616     sqlite3_file *pRealFile;
    617     sqlite3_vfs *pParent = pFsVfs->pParent;
    618     assert(eType==DATABASE_FILE);
    619 
    620     pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile);
    621     if( !pReal ){
    622       rc = SQLITE_NOMEM;
    623       goto open_out;
    624     }
    625     memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile);
    626     pReal->zName = zName;
    627     pReal->pFile = (sqlite3_file *)(&pReal[1]);
    628 
    629     rc = pParent->xOpen(pParent, zName, pReal->pFile, real_flags, pOutFlags);
    630     if( rc!=SQLITE_OK ){
    631       goto open_out;
    632     }
    633     pRealFile = pReal->pFile;
    634 
    635     rc = pRealFile->pMethods->xFileSize(pRealFile, &size);
    636     if( rc!=SQLITE_OK ){
    637       goto open_out;
    638     }
    639     if( size==0 ){
    640       rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1);
    641       pReal->nBlob = BLOBSIZE;
    642     }else{
    643       unsigned char zS[4];
    644       pReal->nBlob = size;
    645       rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0);
    646       pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3];
    647       if( rc==SQLITE_OK ){
    648         rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4);
    649         if( zS[0] || zS[1] || zS[2] || zS[3] ){
    650           pReal->nJournal = pReal->nBlob;
    651         }
    652       }
    653     }
    654 
    655     if( rc==SQLITE_OK ){
    656       pReal->pNext = pFsVfs->pFileList;
    657       if( pReal->pNext ){
    658         pReal->pNext->ppThis = &pReal->pNext;
    659       }
    660       pReal->ppThis = &pFsVfs->pFileList;
    661       pFsVfs->pFileList = pReal;
    662     }
    663   }
    664 
    665 open_out:
    666   if( pReal ){
    667     if( rc==SQLITE_OK ){
    668       p->pReal = pReal;
    669       pReal->nRef++;
    670     }else{
    671       if( pReal->pFile->pMethods ){
    672         pReal->pFile->pMethods->xClose(pReal->pFile);
    673       }
    674       sqlite3_free(pReal);
    675     }
    676   }
    677   return rc;
    678 }
    679 
    680 /*
    681 ** Delete the file located at zPath. If the dirSync argument is true,
    682 ** ensure the file-system modifications are synced to disk before
    683 ** returning.
    684 */
    685 static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
    686   int rc = SQLITE_OK;
    687   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
    688   fs_real_file *pReal;
    689   sqlite3_file *pF;
    690   int nName = strlen(zPath) - 8;
    691 
    692   assert(strlen("-journal")==8);
    693   assert(strcmp("-journal", &zPath[nName])==0);
    694 
    695   pReal = pFsVfs->pFileList;
    696   for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
    697   if( pReal ){
    698     pF = pReal->pFile;
    699     rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE);
    700     if( rc==SQLITE_OK ){
    701       pReal->nJournal = 0;
    702     }
    703   }
    704   return rc;
    705 }
    706 
    707 /*
    708 ** Test for access permissions. Return true if the requested permission
    709 ** is available, or false otherwise.
    710 */
    711 static int fsAccess(
    712   sqlite3_vfs *pVfs,
    713   const char *zPath,
    714   int flags,
    715   int *pResOut
    716 ){
    717   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
    718   fs_real_file *pReal;
    719   int isJournal = 0;
    720   int nName = strlen(zPath);
    721 
    722   if( flags!=SQLITE_ACCESS_EXISTS ){
    723     sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    724     return pParent->xAccess(pParent, zPath, flags, pResOut);
    725   }
    726 
    727   assert(strlen("-journal")==8);
    728   if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){
    729     nName -= 8;
    730     isJournal = 1;
    731   }
    732 
    733   pReal = pFsVfs->pFileList;
    734   for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
    735 
    736   *pResOut = (pReal && (!isJournal || pReal->nJournal>0));
    737   return SQLITE_OK;
    738 }
    739 
    740 /*
    741 ** Populate buffer zOut with the full canonical pathname corresponding
    742 ** to the pathname in zPath. zOut is guaranteed to point to a buffer
    743 ** of at least (FS_MAX_PATHNAME+1) bytes.
    744 */
    745 static int fsFullPathname(
    746   sqlite3_vfs *pVfs,            /* Pointer to vfs object */
    747   const char *zPath,            /* Possibly relative input path */
    748   int nOut,                     /* Size of output buffer in bytes */
    749   char *zOut                    /* Output buffer */
    750 ){
    751   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    752   return pParent->xFullPathname(pParent, zPath, nOut, zOut);
    753 }
    754 
    755 /*
    756 ** Open the dynamic library located at zPath and return a handle.
    757 */
    758 static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
    759   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    760   return pParent->xDlOpen(pParent, zPath);
    761 }
    762 
    763 /*
    764 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
    765 ** utf-8 string describing the most recent error encountered associated
    766 ** with dynamic libraries.
    767 */
    768 static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
    769   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    770   pParent->xDlError(pParent, nByte, zErrMsg);
    771 }
    772 
    773 /*
    774 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
    775 */
    776 static void (*fsDlSym(sqlite3_vfs *pVfs, void *pH, const char *zSym))(void){
    777   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    778   return pParent->xDlSym(pParent, pH, zSym);
    779 }
    780 
    781 /*
    782 ** Close the dynamic library handle pHandle.
    783 */
    784 static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){
    785   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    786   pParent->xDlClose(pParent, pHandle);
    787 }
    788 
    789 /*
    790 ** Populate the buffer pointed to by zBufOut with nByte bytes of
    791 ** random data.
    792 */
    793 static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
    794   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    795   return pParent->xRandomness(pParent, nByte, zBufOut);
    796 }
    797 
    798 /*
    799 ** Sleep for nMicro microseconds. Return the number of microseconds
    800 ** actually slept.
    801 */
    802 static int fsSleep(sqlite3_vfs *pVfs, int nMicro){
    803   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    804   return pParent->xSleep(pParent, nMicro);
    805 }
    806 
    807 /*
    808 ** Return the current time as a Julian Day number in *pTimeOut.
    809 */
    810 static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
    811   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
    812   return pParent->xCurrentTime(pParent, pTimeOut);
    813 }
    814 
    815 /*
    816 ** This procedure registers the fs vfs with SQLite. If the argument is
    817 ** true, the fs vfs becomes the new default vfs. It is the only publicly
    818 ** available function in this file.
    819 */
    820 int fs_register(void){
    821   if( fs_vfs.pParent ) return SQLITE_OK;
    822   fs_vfs.pParent = sqlite3_vfs_find(0);
    823   fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname;
    824   fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file));
    825   return sqlite3_vfs_register(&fs_vfs.base, 0);
    826 }
    827 
    828 #ifdef SQLITE_TEST
    829   int SqlitetestOnefile_Init() {return fs_register();}
    830 #endif
    831