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