modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/test_onefile.c (about)

     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 = (int)(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 = (int)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 = (int)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 = (int)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 = (int)MAX(pReal->nDatabase, iAmt+iOfst);
   457        }
   458      }
   459    }else{
   460      /* Journal file. */
   461      int iRem = iAmt;
   462      int iBuf = 0;
   463      int ii = (int)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 = (int)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 = (int)MIN(pReal->nDatabase, size);
   493    }else{
   494      pReal->nJournal = (int)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] = (unsigned char)((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 *p2 = (tmp_file *)pFile;
   599      memset(p2, 0, sizeof(*p2));
   600      p2->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 = (int)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 = (int)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 = (int)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 = (int)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