aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/sqlite/unix/sqlite-3.5.1/src/test_onefile.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/sqlite/unix/sqlite-3.5.1/src/test_onefile.c')
-rw-r--r--libraries/sqlite/unix/sqlite-3.5.1/src/test_onefile.c825
1 files changed, 825 insertions, 0 deletions
diff --git a/libraries/sqlite/unix/sqlite-3.5.1/src/test_onefile.c b/libraries/sqlite/unix/sqlite-3.5.1/src/test_onefile.c
new file mode 100644
index 0000000..d7e19de
--- /dev/null
+++ b/libraries/sqlite/unix/sqlite-3.5.1/src/test_onefile.c
@@ -0,0 +1,825 @@
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
97typedef struct fs_real_file fs_real_file;
98struct 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
109typedef struct fs_file fs_file;
110struct fs_file {
111 sqlite3_file base;
112 int eType;
113 fs_real_file *pReal;
114};
115
116typedef struct tmp_file tmp_file;
117struct 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*/
131static int fsClose(sqlite3_file*);
132static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
133static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
134static int fsTruncate(sqlite3_file*, sqlite3_int64 size);
135static int fsSync(sqlite3_file*, int flags);
136static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
137static int fsLock(sqlite3_file*, int);
138static int fsUnlock(sqlite3_file*, int);
139static int fsCheckReservedLock(sqlite3_file*);
140static int fsFileControl(sqlite3_file*, int op, void *pArg);
141static int fsSectorSize(sqlite3_file*);
142static int fsDeviceCharacteristics(sqlite3_file*);
143
144/*
145** Method declarations for tmp_file.
146*/
147static int tmpClose(sqlite3_file*);
148static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
149static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
150static int tmpTruncate(sqlite3_file*, sqlite3_int64 size);
151static int tmpSync(sqlite3_file*, int flags);
152static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize);
153static int tmpLock(sqlite3_file*, int);
154static int tmpUnlock(sqlite3_file*, int);
155static int tmpCheckReservedLock(sqlite3_file*);
156static int tmpFileControl(sqlite3_file*, int op, void *pArg);
157static int tmpSectorSize(sqlite3_file*);
158static int tmpDeviceCharacteristics(sqlite3_file*);
159
160/*
161** Method declarations for fs_vfs.
162*/
163static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
164static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);
165static int fsAccess(sqlite3_vfs*, const char *zName, int flags);
166static int fsGetTempname(sqlite3_vfs*, int nOut, char *zOut);
167static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
168static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
169static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
170static void *fsDlSym(sqlite3_vfs*,void*, const char *zSymbol);
171static void fsDlClose(sqlite3_vfs*, void*);
172static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
173static int fsSleep(sqlite3_vfs*, int microseconds);
174static int fsCurrentTime(sqlite3_vfs*, double*);
175
176
177typedef struct fs_vfs_t fs_vfs_t;
178struct fs_vfs_t {
179 sqlite3_vfs base;
180 fs_real_file *pFileList;
181 sqlite3_vfs *pParent;
182};
183
184static 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
209static 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
226static 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*/
250static 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*/
259static 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*/
276static 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*/
300static 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*/
309static 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*/
316static 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*/
325static int tmpLock(sqlite3_file *pFile, int eLock){
326 return SQLITE_OK;
327}
328
329/*
330** Unlock a tmp-file.
331*/
332static 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*/
339static int tmpCheckReservedLock(sqlite3_file *pFile){
340 return SQLITE_OK;
341}
342
343/*
344** File control method. For custom operations on a tmp-file.
345*/
346static 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*/
353static int tmpSectorSize(sqlite3_file *pFile){
354 return 0;
355}
356
357/*
358** Return the device characteristic flags supported by a tmp-file.
359*/
360static int tmpDeviceCharacteristics(sqlite3_file *pFile){
361 return 0;
362}
363
364/*
365** Close an fs-file.
366*/
367static 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*/
392static 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*/
431static 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*/
480static 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*/
494static 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*/
518static 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*/
532static int fsLock(sqlite3_file *pFile, int eLock){
533 return SQLITE_OK;
534}
535
536/*
537** Unlock an fs-file.
538*/
539static 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*/
546static int fsCheckReservedLock(sqlite3_file *pFile){
547 return 0;
548}
549
550/*
551** File control method. For custom operations on an fs-file.
552*/
553static 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*/
560static int fsSectorSize(sqlite3_file *pFile){
561 return BLOCKSIZE;
562}
563
564/*
565** Return the device characteristic flags supported by an fs-file.
566*/
567static int fsDeviceCharacteristics(sqlite3_file *pFile){
568 return 0;
569}
570
571/*
572** Open an fs file handle.
573*/
574static 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
655open_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*/
675static 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*/
701static 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*/
729static 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*/
739static 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*/
752static 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*/
762static 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*/
770static 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*/
778static 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*/
787static 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*/
796static 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*/
804static 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*/
814int 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