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