xref: /sqlite-3.40.0/src/test_onefile.c (revision 6b017cc6)
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,                                          /* xRename */
203     0                                           /* xCurrentTimeInt64 */
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   0,                            /* xShmOpen */
224   0,                            /* xShmLock */
225   0,                            /* xShmMap */
226   0,                            /* xShmBarrier */
227   0                             /* xShmClose */
228 };
229 
230 
231 static sqlite3_io_methods tmp_io_methods = {
232   1,                            /* iVersion */
233   tmpClose,                     /* xClose */
234   tmpRead,                      /* xRead */
235   tmpWrite,                     /* xWrite */
236   tmpTruncate,                  /* xTruncate */
237   tmpSync,                      /* xSync */
238   tmpFileSize,                  /* xFileSize */
239   tmpLock,                      /* xLock */
240   tmpUnlock,                    /* xUnlock */
241   tmpCheckReservedLock,         /* xCheckReservedLock */
242   tmpFileControl,               /* xFileControl */
243   tmpSectorSize,                /* xSectorSize */
244   tmpDeviceCharacteristics,     /* xDeviceCharacteristics */
245   0,                            /* xShmOpen */
246   0,                            /* xShmLock */
247   0,                            /* xShmMap */
248   0,                            /* xShmBarrier */
249   0                             /* xShmClose */
250 };
251 
252 /* Useful macros used in several places */
253 #define MIN(x,y) ((x)<(y)?(x):(y))
254 #define MAX(x,y) ((x)>(y)?(x):(y))
255 
256 
257 /*
258 ** Close a tmp-file.
259 */
260 static int tmpClose(sqlite3_file *pFile){
261   tmp_file *pTmp = (tmp_file *)pFile;
262   sqlite3_free(pTmp->zAlloc);
263   return SQLITE_OK;
264 }
265 
266 /*
267 ** Read data from a tmp-file.
268 */
269 static int tmpRead(
270   sqlite3_file *pFile,
271   void *zBuf,
272   int iAmt,
273   sqlite_int64 iOfst
274 ){
275   tmp_file *pTmp = (tmp_file *)pFile;
276   if( (iAmt+iOfst)>pTmp->nSize ){
277     return SQLITE_IOERR_SHORT_READ;
278   }
279   memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt);
280   return SQLITE_OK;
281 }
282 
283 /*
284 ** Write data to a tmp-file.
285 */
286 static int tmpWrite(
287   sqlite3_file *pFile,
288   const void *zBuf,
289   int iAmt,
290   sqlite_int64 iOfst
291 ){
292   tmp_file *pTmp = (tmp_file *)pFile;
293   if( (iAmt+iOfst)>pTmp->nAlloc ){
294     int nNew = 2*(iAmt+iOfst+pTmp->nAlloc);
295     char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew);
296     if( !zNew ){
297       return SQLITE_NOMEM;
298     }
299     pTmp->zAlloc = zNew;
300     pTmp->nAlloc = nNew;
301   }
302   memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt);
303   pTmp->nSize = MAX(pTmp->nSize, iOfst+iAmt);
304   return SQLITE_OK;
305 }
306 
307 /*
308 ** Truncate a tmp-file.
309 */
310 static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){
311   tmp_file *pTmp = (tmp_file *)pFile;
312   pTmp->nSize = MIN(pTmp->nSize, size);
313   return SQLITE_OK;
314 }
315 
316 /*
317 ** Sync a tmp-file.
318 */
319 static int tmpSync(sqlite3_file *pFile, int flags){
320   return SQLITE_OK;
321 }
322 
323 /*
324 ** Return the current file-size of a tmp-file.
325 */
326 static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
327   tmp_file *pTmp = (tmp_file *)pFile;
328   *pSize = pTmp->nSize;
329   return SQLITE_OK;
330 }
331 
332 /*
333 ** Lock a tmp-file.
334 */
335 static int tmpLock(sqlite3_file *pFile, int eLock){
336   return SQLITE_OK;
337 }
338 
339 /*
340 ** Unlock a tmp-file.
341 */
342 static int tmpUnlock(sqlite3_file *pFile, int eLock){
343   return SQLITE_OK;
344 }
345 
346 /*
347 ** Check if another file-handle holds a RESERVED lock on a tmp-file.
348 */
349 static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){
350   *pResOut = 0;
351   return SQLITE_OK;
352 }
353 
354 /*
355 ** File control method. For custom operations on a tmp-file.
356 */
357 static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){
358   return SQLITE_OK;
359 }
360 
361 /*
362 ** Return the sector-size in bytes for a tmp-file.
363 */
364 static int tmpSectorSize(sqlite3_file *pFile){
365   return 0;
366 }
367 
368 /*
369 ** Return the device characteristic flags supported by a tmp-file.
370 */
371 static int tmpDeviceCharacteristics(sqlite3_file *pFile){
372   return 0;
373 }
374 
375 /*
376 ** Close an fs-file.
377 */
378 static int fsClose(sqlite3_file *pFile){
379   int rc = SQLITE_OK;
380   fs_file *p = (fs_file *)pFile;
381   fs_real_file *pReal = p->pReal;
382 
383   /* Decrement the real_file ref-count. */
384   pReal->nRef--;
385   assert(pReal->nRef>=0);
386 
387   /* When the ref-count reaches 0, destroy the structure */
388   if( pReal->nRef==0 ){
389     *pReal->ppThis = pReal->pNext;
390     if( pReal->pNext ){
391       pReal->pNext->ppThis = pReal->ppThis;
392     }
393     rc = pReal->pFile->pMethods->xClose(pReal->pFile);
394     sqlite3_free(pReal);
395   }
396 
397   return rc;
398 }
399 
400 /*
401 ** Read data from an fs-file.
402 */
403 static int fsRead(
404   sqlite3_file *pFile,
405   void *zBuf,
406   int iAmt,
407   sqlite_int64 iOfst
408 ){
409   int rc = SQLITE_OK;
410   fs_file *p = (fs_file *)pFile;
411   fs_real_file *pReal = p->pReal;
412   sqlite3_file *pF = pReal->pFile;
413 
414   if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase)
415    || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal)
416   ){
417     rc = SQLITE_IOERR_SHORT_READ;
418   }else if( p->eType==DATABASE_FILE ){
419     rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
420   }else{
421     /* Journal file. */
422     int iRem = iAmt;
423     int iBuf = 0;
424     int ii = iOfst;
425     while( iRem>0 && rc==SQLITE_OK ){
426       int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
427       int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
428 
429       rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff);
430       ii += iRealAmt;
431       iBuf += iRealAmt;
432       iRem -= iRealAmt;
433     }
434   }
435 
436   return rc;
437 }
438 
439 /*
440 ** Write data to an fs-file.
441 */
442 static int fsWrite(
443   sqlite3_file *pFile,
444   const void *zBuf,
445   int iAmt,
446   sqlite_int64 iOfst
447 ){
448   int rc = SQLITE_OK;
449   fs_file *p = (fs_file *)pFile;
450   fs_real_file *pReal = p->pReal;
451   sqlite3_file *pF = pReal->pFile;
452 
453   if( p->eType==DATABASE_FILE ){
454     if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){
455       rc = SQLITE_FULL;
456     }else{
457       rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
458       if( rc==SQLITE_OK ){
459         pReal->nDatabase = MAX(pReal->nDatabase, iAmt+iOfst);
460       }
461     }
462   }else{
463     /* Journal file. */
464     int iRem = iAmt;
465     int iBuf = 0;
466     int ii = iOfst;
467     while( iRem>0 && rc==SQLITE_OK ){
468       int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
469       int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
470 
471       if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){
472         rc = SQLITE_FULL;
473       }else{
474         rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff);
475         ii += iRealAmt;
476         iBuf += iRealAmt;
477         iRem -= iRealAmt;
478       }
479     }
480     if( rc==SQLITE_OK ){
481       pReal->nJournal = MAX(pReal->nJournal, iAmt+iOfst);
482     }
483   }
484 
485   return rc;
486 }
487 
488 /*
489 ** Truncate an fs-file.
490 */
491 static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){
492   fs_file *p = (fs_file *)pFile;
493   fs_real_file *pReal = p->pReal;
494   if( p->eType==DATABASE_FILE ){
495     pReal->nDatabase = MIN(pReal->nDatabase, size);
496   }else{
497     pReal->nJournal = MIN(pReal->nJournal, size);
498   }
499   return SQLITE_OK;
500 }
501 
502 /*
503 ** Sync an fs-file.
504 */
505 static int fsSync(sqlite3_file *pFile, int flags){
506   fs_file *p = (fs_file *)pFile;
507   fs_real_file *pReal = p->pReal;
508   sqlite3_file *pRealFile = pReal->pFile;
509   int rc = SQLITE_OK;
510 
511   if( p->eType==DATABASE_FILE ){
512     unsigned char zSize[4];
513     zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
514     zSize[1] = (pReal->nDatabase&0x00FF0000)>>16;
515     zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
516     zSize[3] = (pReal->nDatabase&0x000000FF);
517     rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
518   }
519   if( rc==SQLITE_OK ){
520     rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY));
521   }
522 
523   return rc;
524 }
525 
526 /*
527 ** Return the current file-size of an fs-file.
528 */
529 static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
530   fs_file *p = (fs_file *)pFile;
531   fs_real_file *pReal = p->pReal;
532   if( p->eType==DATABASE_FILE ){
533     *pSize = pReal->nDatabase;
534   }else{
535     *pSize = pReal->nJournal;
536   }
537   return SQLITE_OK;
538 }
539 
540 /*
541 ** Lock an fs-file.
542 */
543 static int fsLock(sqlite3_file *pFile, int eLock){
544   return SQLITE_OK;
545 }
546 
547 /*
548 ** Unlock an fs-file.
549 */
550 static int fsUnlock(sqlite3_file *pFile, int eLock){
551   return SQLITE_OK;
552 }
553 
554 /*
555 ** Check if another file-handle holds a RESERVED lock on an fs-file.
556 */
557 static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
558   *pResOut = 0;
559   return SQLITE_OK;
560 }
561 
562 /*
563 ** File control method. For custom operations on an fs-file.
564 */
565 static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){
566   return SQLITE_OK;
567 }
568 
569 /*
570 ** Return the sector-size in bytes for an fs-file.
571 */
572 static int fsSectorSize(sqlite3_file *pFile){
573   return BLOCKSIZE;
574 }
575 
576 /*
577 ** Return the device characteristic flags supported by an fs-file.
578 */
579 static int fsDeviceCharacteristics(sqlite3_file *pFile){
580   return 0;
581 }
582 
583 /*
584 ** Open an fs file handle.
585 */
586 static int fsOpen(
587   sqlite3_vfs *pVfs,
588   const char *zName,
589   sqlite3_file *pFile,
590   int flags,
591   int *pOutFlags
592 ){
593   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
594   fs_file *p = (fs_file *)pFile;
595   fs_real_file *pReal = 0;
596   int eType;
597   int nName;
598   int rc = SQLITE_OK;
599 
600   if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
601     tmp_file *p = (tmp_file *)pFile;
602     memset(p, 0, sizeof(*p));
603     p->base.pMethods = &tmp_io_methods;
604     return SQLITE_OK;
605   }
606 
607   eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE);
608   p->base.pMethods = &fs_io_methods;
609   p->eType = eType;
610 
611   assert(strlen("-journal")==8);
612   nName = strlen(zName)-((eType==JOURNAL_FILE)?8:0);
613   pReal=pFsVfs->pFileList;
614   for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext);
615 
616   if( !pReal ){
617     int real_flags = (flags&~(SQLITE_OPEN_MAIN_DB))|SQLITE_OPEN_TEMP_DB;
618     sqlite3_int64 size;
619     sqlite3_file *pRealFile;
620     sqlite3_vfs *pParent = pFsVfs->pParent;
621     assert(eType==DATABASE_FILE);
622 
623     pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile);
624     if( !pReal ){
625       rc = SQLITE_NOMEM;
626       goto open_out;
627     }
628     memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile);
629     pReal->zName = zName;
630     pReal->pFile = (sqlite3_file *)(&pReal[1]);
631 
632     rc = pParent->xOpen(pParent, zName, pReal->pFile, real_flags, pOutFlags);
633     if( rc!=SQLITE_OK ){
634       goto open_out;
635     }
636     pRealFile = pReal->pFile;
637 
638     rc = pRealFile->pMethods->xFileSize(pRealFile, &size);
639     if( rc!=SQLITE_OK ){
640       goto open_out;
641     }
642     if( size==0 ){
643       rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1);
644       pReal->nBlob = BLOBSIZE;
645     }else{
646       unsigned char zS[4];
647       pReal->nBlob = size;
648       rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0);
649       pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3];
650       if( rc==SQLITE_OK ){
651         rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4);
652         if( zS[0] || zS[1] || zS[2] || zS[3] ){
653           pReal->nJournal = pReal->nBlob;
654         }
655       }
656     }
657 
658     if( rc==SQLITE_OK ){
659       pReal->pNext = pFsVfs->pFileList;
660       if( pReal->pNext ){
661         pReal->pNext->ppThis = &pReal->pNext;
662       }
663       pReal->ppThis = &pFsVfs->pFileList;
664       pFsVfs->pFileList = pReal;
665     }
666   }
667 
668 open_out:
669   if( pReal ){
670     if( rc==SQLITE_OK ){
671       p->pReal = pReal;
672       pReal->nRef++;
673     }else{
674       if( pReal->pFile->pMethods ){
675         pReal->pFile->pMethods->xClose(pReal->pFile);
676       }
677       sqlite3_free(pReal);
678     }
679   }
680   return rc;
681 }
682 
683 /*
684 ** Delete the file located at zPath. If the dirSync argument is true,
685 ** ensure the file-system modifications are synced to disk before
686 ** returning.
687 */
688 static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
689   int rc = SQLITE_OK;
690   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
691   fs_real_file *pReal;
692   sqlite3_file *pF;
693   int nName = strlen(zPath) - 8;
694 
695   assert(strlen("-journal")==8);
696   assert(strcmp("-journal", &zPath[nName])==0);
697 
698   pReal = pFsVfs->pFileList;
699   for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
700   if( pReal ){
701     pF = pReal->pFile;
702     rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE);
703     if( rc==SQLITE_OK ){
704       pReal->nJournal = 0;
705     }
706   }
707   return rc;
708 }
709 
710 /*
711 ** Test for access permissions. Return true if the requested permission
712 ** is available, or false otherwise.
713 */
714 static int fsAccess(
715   sqlite3_vfs *pVfs,
716   const char *zPath,
717   int flags,
718   int *pResOut
719 ){
720   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
721   fs_real_file *pReal;
722   int isJournal = 0;
723   int nName = strlen(zPath);
724 
725   if( flags!=SQLITE_ACCESS_EXISTS ){
726     sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
727     return pParent->xAccess(pParent, zPath, flags, pResOut);
728   }
729 
730   assert(strlen("-journal")==8);
731   if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){
732     nName -= 8;
733     isJournal = 1;
734   }
735 
736   pReal = pFsVfs->pFileList;
737   for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
738 
739   *pResOut = (pReal && (!isJournal || pReal->nJournal>0));
740   return SQLITE_OK;
741 }
742 
743 /*
744 ** Populate buffer zOut with the full canonical pathname corresponding
745 ** to the pathname in zPath. zOut is guaranteed to point to a buffer
746 ** of at least (FS_MAX_PATHNAME+1) bytes.
747 */
748 static int fsFullPathname(
749   sqlite3_vfs *pVfs,            /* Pointer to vfs object */
750   const char *zPath,            /* Possibly relative input path */
751   int nOut,                     /* Size of output buffer in bytes */
752   char *zOut                    /* Output buffer */
753 ){
754   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
755   return pParent->xFullPathname(pParent, zPath, nOut, zOut);
756 }
757 
758 /*
759 ** Open the dynamic library located at zPath and return a handle.
760 */
761 static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
762   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
763   return pParent->xDlOpen(pParent, zPath);
764 }
765 
766 /*
767 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
768 ** utf-8 string describing the most recent error encountered associated
769 ** with dynamic libraries.
770 */
771 static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
772   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
773   pParent->xDlError(pParent, nByte, zErrMsg);
774 }
775 
776 /*
777 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
778 */
779 static void (*fsDlSym(sqlite3_vfs *pVfs, void *pH, const char *zSym))(void){
780   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
781   return pParent->xDlSym(pParent, pH, zSym);
782 }
783 
784 /*
785 ** Close the dynamic library handle pHandle.
786 */
787 static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){
788   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
789   pParent->xDlClose(pParent, pHandle);
790 }
791 
792 /*
793 ** Populate the buffer pointed to by zBufOut with nByte bytes of
794 ** random data.
795 */
796 static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
797   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
798   return pParent->xRandomness(pParent, nByte, zBufOut);
799 }
800 
801 /*
802 ** Sleep for nMicro microseconds. Return the number of microseconds
803 ** actually slept.
804 */
805 static int fsSleep(sqlite3_vfs *pVfs, int nMicro){
806   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
807   return pParent->xSleep(pParent, nMicro);
808 }
809 
810 /*
811 ** Return the current time as a Julian Day number in *pTimeOut.
812 */
813 static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
814   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
815   return pParent->xCurrentTime(pParent, pTimeOut);
816 }
817 
818 /*
819 ** This procedure registers the fs vfs with SQLite. If the argument is
820 ** true, the fs vfs becomes the new default vfs. It is the only publicly
821 ** available function in this file.
822 */
823 int fs_register(void){
824   if( fs_vfs.pParent ) return SQLITE_OK;
825   fs_vfs.pParent = sqlite3_vfs_find(0);
826   fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname;
827   fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file));
828   return sqlite3_vfs_register(&fs_vfs.base, 0);
829 }
830 
831 #ifdef SQLITE_TEST
832   int SqlitetestOnefile_Init() {return fs_register();}
833 #endif
834