xref: /sqlite-3.40.0/src/test_onefile.c (revision 8a29dfde)
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 TEMP_STORE compile time
30 **   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*);
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*);
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);
166 static int fsGetTempname(sqlite3_vfs*, int nOut, char *zOut);
167 static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
168 static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
169 static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
170 static void *fsDlSym(sqlite3_vfs*,void*, const char *zSymbol);
171 static void fsDlClose(sqlite3_vfs*, void*);
172 static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
173 static int fsSleep(sqlite3_vfs*, int microseconds);
174 static int fsCurrentTime(sqlite3_vfs*, double*);
175 
176 
177 typedef struct fs_vfs_t fs_vfs_t;
178 struct fs_vfs_t {
179   sqlite3_vfs base;
180   fs_real_file *pFileList;
181   sqlite3_vfs *pParent;
182 };
183 
184 static fs_vfs_t fs_vfs = {
185   {
186     1,                                          /* iVersion */
187     0,                                          /* szOsFile */
188     0,                                          /* mxPathname */
189     0,                                          /* pNext */
190     FS_VFS_NAME,                                /* zName */
191     0,                                          /* pAppData */
192     fsOpen,                                     /* xOpen */
193     fsDelete,                                   /* xDelete */
194     fsAccess,                                   /* xAccess */
195     fsGetTempname,                              /* xGetTempName */
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){
340   return SQLITE_OK;
341 }
342 
343 /*
344 ** File control method. For custom operations on a tmp-file.
345 */
346 static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){
347   return SQLITE_OK;
348 }
349 
350 /*
351 ** Return the sector-size in bytes for a tmp-file.
352 */
353 static int tmpSectorSize(sqlite3_file *pFile){
354   return 0;
355 }
356 
357 /*
358 ** Return the device characteristic flags supported by a tmp-file.
359 */
360 static int tmpDeviceCharacteristics(sqlite3_file *pFile){
361   return 0;
362 }
363 
364 /*
365 ** Close an fs-file.
366 */
367 static int fsClose(sqlite3_file *pFile){
368   int rc = SQLITE_OK;
369   fs_file *p = (fs_file *)pFile;
370   fs_real_file *pReal = p->pReal;
371 
372   /* Decrement the real_file ref-count. */
373   pReal->nRef--;
374   assert(pReal->nRef>=0);
375 
376   /* When the ref-count reaches 0, destroy the structure */
377   if( pReal->nRef==0 ){
378     *pReal->ppThis = pReal->pNext;
379     if( pReal->pNext ){
380       pReal->pNext->ppThis = pReal->ppThis;
381     }
382     rc = pReal->pFile->pMethods->xClose(pReal->pFile);
383     sqlite3_free(pReal);
384   }
385 
386   return rc;
387 }
388 
389 /*
390 ** Read data from an fs-file.
391 */
392 static int fsRead(
393   sqlite3_file *pFile,
394   void *zBuf,
395   int iAmt,
396   sqlite_int64 iOfst
397 ){
398   int rc = SQLITE_OK;
399   fs_file *p = (fs_file *)pFile;
400   fs_real_file *pReal = p->pReal;
401   sqlite3_file *pF = pReal->pFile;
402 
403   if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase)
404    || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal)
405   ){
406     rc = SQLITE_IOERR_SHORT_READ;
407   }else if( p->eType==DATABASE_FILE ){
408     rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
409   }else{
410     /* Journal file. */
411     int iRem = iAmt;
412     int iBuf = 0;
413     int ii = iOfst;
414     while( iRem>0 && rc==SQLITE_OK ){
415       int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
416       int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
417 
418       rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff);
419       ii += iRealAmt;
420       iBuf += iRealAmt;
421       iRem -= iRealAmt;
422     }
423   }
424 
425   return rc;
426 }
427 
428 /*
429 ** Write data to an fs-file.
430 */
431 static int fsWrite(
432   sqlite3_file *pFile,
433   const void *zBuf,
434   int iAmt,
435   sqlite_int64 iOfst
436 ){
437   int rc = SQLITE_OK;
438   fs_file *p = (fs_file *)pFile;
439   fs_real_file *pReal = p->pReal;
440   sqlite3_file *pF = pReal->pFile;
441 
442   if( p->eType==DATABASE_FILE ){
443     if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){
444       rc = SQLITE_FULL;
445     }else{
446       rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
447       if( rc==SQLITE_OK ){
448         pReal->nDatabase = MAX(pReal->nDatabase, iAmt+iOfst);
449       }
450     }
451   }else{
452     /* Journal file. */
453     int iRem = iAmt;
454     int iBuf = 0;
455     int ii = iOfst;
456     while( iRem>0 && rc==SQLITE_OK ){
457       int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
458       int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
459 
460       if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){
461         rc = SQLITE_FULL;
462       }else{
463         rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff);
464         ii += iRealAmt;
465         iBuf += iRealAmt;
466         iRem -= iRealAmt;
467       }
468     }
469     if( rc==SQLITE_OK ){
470       pReal->nJournal = MAX(pReal->nJournal, iAmt+iOfst);
471     }
472   }
473 
474   return rc;
475 }
476 
477 /*
478 ** Truncate an fs-file.
479 */
480 static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){
481   fs_file *p = (fs_file *)pFile;
482   fs_real_file *pReal = p->pReal;
483   if( p->eType==DATABASE_FILE ){
484     pReal->nDatabase = MIN(pReal->nDatabase, size);
485   }else{
486     pReal->nJournal = MIN(pReal->nJournal, size);
487   }
488   return SQLITE_OK;
489 }
490 
491 /*
492 ** Sync an fs-file.
493 */
494 static int fsSync(sqlite3_file *pFile, int flags){
495   fs_file *p = (fs_file *)pFile;
496   fs_real_file *pReal = p->pReal;
497   sqlite3_file *pRealFile = pReal->pFile;
498   int rc = SQLITE_OK;
499 
500   if( p->eType==DATABASE_FILE ){
501     unsigned char zSize[4];
502     zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
503     zSize[1] = (pReal->nDatabase&0x00FF0000)>>16;
504     zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
505     zSize[3] = (pReal->nDatabase&0x000000FF);
506     rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
507   }
508   if( rc==SQLITE_OK ){
509     rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY));
510   }
511 
512   return rc;
513 }
514 
515 /*
516 ** Return the current file-size of an fs-file.
517 */
518 static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
519   fs_file *p = (fs_file *)pFile;
520   fs_real_file *pReal = p->pReal;
521   if( p->eType==DATABASE_FILE ){
522     *pSize = pReal->nDatabase;
523   }else{
524     *pSize = pReal->nJournal;
525   }
526   return SQLITE_OK;
527 }
528 
529 /*
530 ** Lock an fs-file.
531 */
532 static int fsLock(sqlite3_file *pFile, int eLock){
533   return SQLITE_OK;
534 }
535 
536 /*
537 ** Unlock an fs-file.
538 */
539 static int fsUnlock(sqlite3_file *pFile, int eLock){
540   return SQLITE_OK;
541 }
542 
543 /*
544 ** Check if another file-handle holds a RESERVED lock on an fs-file.
545 */
546 static int fsCheckReservedLock(sqlite3_file *pFile){
547   return 0;
548 }
549 
550 /*
551 ** File control method. For custom operations on an fs-file.
552 */
553 static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){
554   return SQLITE_OK;
555 }
556 
557 /*
558 ** Return the sector-size in bytes for an fs-file.
559 */
560 static int fsSectorSize(sqlite3_file *pFile){
561   return BLOCKSIZE;
562 }
563 
564 /*
565 ** Return the device characteristic flags supported by an fs-file.
566 */
567 static int fsDeviceCharacteristics(sqlite3_file *pFile){
568   return 0;
569 }
570 
571 /*
572 ** Open an fs file handle.
573 */
574 static int fsOpen(
575   sqlite3_vfs *pVfs,
576   const char *zName,
577   sqlite3_file *pFile,
578   int flags,
579   int *pOutFlags
580 ){
581   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
582   fs_file *p = (fs_file *)pFile;
583   fs_real_file *pReal = 0;
584   int eType;
585   int nName;
586   int rc = SQLITE_OK;
587 
588   if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
589     tmp_file *p = (tmp_file *)pFile;
590     memset(p, 0, sizeof(*p));
591     p->base.pMethods = &tmp_io_methods;
592     return SQLITE_OK;
593   }
594 
595   eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE);
596   p->base.pMethods = &fs_io_methods;
597   p->eType = eType;
598 
599   assert(strlen("-journal")==8);
600   nName = strlen(zName)-((eType==JOURNAL_FILE)?8:0);
601   pReal=pFsVfs->pFileList;
602   for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext);
603 
604   if( !pReal ){
605     sqlite3_int64 size;
606     sqlite3_file *pRealFile;
607     sqlite3_vfs *pParent = pFsVfs->pParent;
608     assert(eType==DATABASE_FILE);
609 
610     pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile);
611     if( !pReal ){
612       rc = SQLITE_NOMEM;
613       goto open_out;
614     }
615     memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile);
616     pReal->zName = zName;
617     pReal->pFile = (sqlite3_file *)(&pReal[1]);
618 
619     rc = pParent->xOpen(pParent, zName, pReal->pFile, flags, pOutFlags);
620     if( rc!=SQLITE_OK ){
621       goto open_out;
622     }
623     pRealFile = pReal->pFile;
624 
625     rc = pRealFile->pMethods->xFileSize(pRealFile, &size);
626     if( rc!=SQLITE_OK ){
627       goto open_out;
628     }
629     if( size==0 ){
630       rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1);
631       pReal->nBlob = BLOBSIZE;
632     }else{
633       unsigned char zS[4];
634       pReal->nBlob = size;
635       rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0);
636       pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3];
637       if( rc==SQLITE_OK ){
638         rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4);
639         if( zS[0] || zS[1] || zS[2] || zS[3] ){
640           pReal->nJournal = pReal->nBlob;
641         }
642       }
643     }
644 
645     if( rc==SQLITE_OK ){
646       pReal->pNext = pFsVfs->pFileList;
647       if( pReal->pNext ){
648         pReal->pNext->ppThis = &pReal->pNext;
649       }
650       pReal->ppThis = &pFsVfs->pFileList;
651       pFsVfs->pFileList = pReal;
652     }
653   }
654 
655 open_out:
656   if( pReal ){
657     if( rc==SQLITE_OK ){
658       p->pReal = pReal;
659       pReal->nRef++;
660     }else{
661       if( pReal->pFile->pMethods ){
662         pReal->pFile->pMethods->xClose(pReal->pFile);
663       }
664       sqlite3_free(pReal);
665     }
666   }
667   return rc;
668 }
669 
670 /*
671 ** Delete the file located at zPath. If the dirSync argument is true,
672 ** ensure the file-system modifications are synced to disk before
673 ** returning.
674 */
675 static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
676   int rc = SQLITE_OK;
677   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
678   fs_real_file *pReal;
679   sqlite3_file *pF;
680   int nName = strlen(zPath) - 8;
681 
682   assert(strlen("-journal")==8);
683   assert(strcmp("-journal", &zPath[nName])==0);
684 
685   pReal = pFsVfs->pFileList;
686   for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
687   if( pReal ){
688     pF = pReal->pFile;
689     rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE);
690     if( rc==SQLITE_OK ){
691       pReal->nJournal = 0;
692     }
693   }
694   return rc;
695 }
696 
697 /*
698 ** Test for access permissions. Return true if the requested permission
699 ** is available, or false otherwise.
700 */
701 static int fsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){
702   fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
703   fs_real_file *pReal;
704   int isJournal = 0;
705   int nName = strlen(zPath);
706 
707   if( flags!=SQLITE_ACCESS_EXISTS ){
708     sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
709     return pParent->xAccess(pParent, zPath, flags);
710   }
711 
712   assert(strlen("-journal")==8);
713   if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){
714     nName -= 8;
715     isJournal = 1;
716   }
717 
718   pReal = pFsVfs->pFileList;
719   for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
720   if( !pReal ) return 0;
721   return ((!isJournal||pReal->nJournal>0)?1:0);
722 }
723 
724 /*
725 ** Populate buffer zBufOut with a pathname suitable for use as a
726 ** temporary file. zBufOut is guaranteed to point to a buffer of
727 ** at least (FS_MAX_PATHNAME+1) bytes.
728 */
729 static int fsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){
730   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
731   return pParent->xGetTempname(pParent, nBufOut, zBufOut);
732 }
733 
734 /*
735 ** Populate buffer zOut with the full canonical pathname corresponding
736 ** to the pathname in zPath. zOut is guaranteed to point to a buffer
737 ** of at least (FS_MAX_PATHNAME+1) bytes.
738 */
739 static int fsFullPathname(
740   sqlite3_vfs *pVfs,            /* Pointer to vfs object */
741   const char *zPath,            /* Possibly relative input path */
742   int nOut,                     /* Size of output buffer in bytes */
743   char *zOut                    /* Output buffer */
744 ){
745   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
746   return pParent->xFullPathname(pParent, zPath, nOut, zOut);
747 }
748 
749 /*
750 ** Open the dynamic library located at zPath and return a handle.
751 */
752 static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
753   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
754   return pParent->xDlOpen(pParent, zPath);
755 }
756 
757 /*
758 ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
759 ** utf-8 string describing the most recent error encountered associated
760 ** with dynamic libraries.
761 */
762 static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
763   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
764   pParent->xDlError(pParent, nByte, zErrMsg);
765 }
766 
767 /*
768 ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
769 */
770 static void *fsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
771   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
772   return pParent->xDlSym(pParent, pHandle, zSymbol);
773 }
774 
775 /*
776 ** Close the dynamic library handle pHandle.
777 */
778 static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){
779   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
780   pParent->xDlClose(pParent, pHandle);
781 }
782 
783 /*
784 ** Populate the buffer pointed to by zBufOut with nByte bytes of
785 ** random data.
786 */
787 static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
788   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
789   return pParent->xRandomness(pParent, nByte, zBufOut);
790 }
791 
792 /*
793 ** Sleep for nMicro microseconds. Return the number of microseconds
794 ** actually slept.
795 */
796 static int fsSleep(sqlite3_vfs *pVfs, int nMicro){
797   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
798   return pParent->xSleep(pParent, nMicro);
799 }
800 
801 /*
802 ** Return the current time as a Julian Day number in *pTimeOut.
803 */
804 static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
805   sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
806   return pParent->xCurrentTime(pParent, pTimeOut);
807 }
808 
809 /*
810 ** This procedure registers the fs vfs with SQLite. If the argument is
811 ** true, the fs vfs becomes the new default vfs. It is the only publicly
812 ** available function in this file.
813 */
814 int fs_register(){
815   if( fs_vfs.pParent ) return SQLITE_OK;
816   fs_vfs.pParent = sqlite3_vfs_find(0);
817   fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname;
818   fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file));
819   return sqlite3_vfs_register(&fs_vfs.base, 0);
820 }
821 
822 #ifdef SQLITE_TEST
823   int SqlitetestOnefile_Init() {return fs_register();}
824 #endif
825