test_onefile.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  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. #include "sqlite3.h"
  82. #include <assert.h>
  83. #include <string.h>
  84. /*
  85. ** Maximum pathname length supported by the fs backend.
  86. */
  87. #define BLOCKSIZE 512
  88. #define BLOBSIZE 10485760
  89. /*
  90. ** Name used to identify this VFS.
  91. */
  92. #define FS_VFS_NAME "fs"
  93. typedef struct fs_real_file fs_real_file;
  94. struct fs_real_file {
  95. sqlite3_file *pFile;
  96. const char *zName;
  97. int nDatabase; /* Current size of database region */
  98. int nJournal; /* Current size of journal region */
  99. int nBlob; /* Total size of allocated blob */
  100. int nRef; /* Number of pointers to this structure */
  101. fs_real_file *pNext;
  102. fs_real_file **ppThis;
  103. };
  104. typedef struct fs_file fs_file;
  105. struct fs_file {
  106. sqlite3_file base;
  107. int eType;
  108. fs_real_file *pReal;
  109. };
  110. typedef struct tmp_file tmp_file;
  111. struct tmp_file {
  112. sqlite3_file base;
  113. int nSize;
  114. int nAlloc;
  115. char *zAlloc;
  116. };
  117. /* Values for fs_file.eType. */
  118. #define DATABASE_FILE 1
  119. #define JOURNAL_FILE 2
  120. /*
  121. ** Method declarations for fs_file.
  122. */
  123. static int fsClose(sqlite3_file*);
  124. static int fsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
  125. static int fsWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
  126. static int fsTruncate(sqlite3_file*, sqlite3_int64 size);
  127. static int fsSync(sqlite3_file*, int flags);
  128. static int fsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
  129. static int fsLock(sqlite3_file*, int);
  130. static int fsUnlock(sqlite3_file*, int);
  131. static int fsCheckReservedLock(sqlite3_file*, int *pResOut);
  132. static int fsFileControl(sqlite3_file*, int op, void *pArg);
  133. static int fsSectorSize(sqlite3_file*);
  134. static int fsDeviceCharacteristics(sqlite3_file*);
  135. /*
  136. ** Method declarations for tmp_file.
  137. */
  138. static int tmpClose(sqlite3_file*);
  139. static int tmpRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
  140. static int tmpWrite(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
  141. static int tmpTruncate(sqlite3_file*, sqlite3_int64 size);
  142. static int tmpSync(sqlite3_file*, int flags);
  143. static int tmpFileSize(sqlite3_file*, sqlite3_int64 *pSize);
  144. static int tmpLock(sqlite3_file*, int);
  145. static int tmpUnlock(sqlite3_file*, int);
  146. static int tmpCheckReservedLock(sqlite3_file*, int *pResOut);
  147. static int tmpFileControl(sqlite3_file*, int op, void *pArg);
  148. static int tmpSectorSize(sqlite3_file*);
  149. static int tmpDeviceCharacteristics(sqlite3_file*);
  150. /*
  151. ** Method declarations for fs_vfs.
  152. */
  153. static int fsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
  154. static int fsDelete(sqlite3_vfs*, const char *zName, int syncDir);
  155. static int fsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
  156. static int fsFullPathname(sqlite3_vfs*, const char *zName, int nOut,char *zOut);
  157. static void *fsDlOpen(sqlite3_vfs*, const char *zFilename);
  158. static void fsDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
  159. static void (*fsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
  160. static void fsDlClose(sqlite3_vfs*, void*);
  161. static int fsRandomness(sqlite3_vfs*, int nByte, char *zOut);
  162. static int fsSleep(sqlite3_vfs*, int microseconds);
  163. static int fsCurrentTime(sqlite3_vfs*, double*);
  164. typedef struct fs_vfs_t fs_vfs_t;
  165. struct fs_vfs_t {
  166. sqlite3_vfs base;
  167. fs_real_file *pFileList;
  168. sqlite3_vfs *pParent;
  169. };
  170. static fs_vfs_t fs_vfs = {
  171. {
  172. 1, /* iVersion */
  173. 0, /* szOsFile */
  174. 0, /* mxPathname */
  175. 0, /* pNext */
  176. FS_VFS_NAME, /* zName */
  177. 0, /* pAppData */
  178. fsOpen, /* xOpen */
  179. fsDelete, /* xDelete */
  180. fsAccess, /* xAccess */
  181. fsFullPathname, /* xFullPathname */
  182. fsDlOpen, /* xDlOpen */
  183. fsDlError, /* xDlError */
  184. fsDlSym, /* xDlSym */
  185. fsDlClose, /* xDlClose */
  186. fsRandomness, /* xRandomness */
  187. fsSleep, /* xSleep */
  188. fsCurrentTime, /* xCurrentTime */
  189. 0 /* xCurrentTimeInt64 */
  190. },
  191. 0, /* pFileList */
  192. 0 /* pParent */
  193. };
  194. static sqlite3_io_methods fs_io_methods = {
  195. 1, /* iVersion */
  196. fsClose, /* xClose */
  197. fsRead, /* xRead */
  198. fsWrite, /* xWrite */
  199. fsTruncate, /* xTruncate */
  200. fsSync, /* xSync */
  201. fsFileSize, /* xFileSize */
  202. fsLock, /* xLock */
  203. fsUnlock, /* xUnlock */
  204. fsCheckReservedLock, /* xCheckReservedLock */
  205. fsFileControl, /* xFileControl */
  206. fsSectorSize, /* xSectorSize */
  207. fsDeviceCharacteristics, /* xDeviceCharacteristics */
  208. 0, /* xShmMap */
  209. 0, /* xShmLock */
  210. 0, /* xShmBarrier */
  211. 0 /* xShmUnmap */
  212. };
  213. static sqlite3_io_methods tmp_io_methods = {
  214. 1, /* iVersion */
  215. tmpClose, /* xClose */
  216. tmpRead, /* xRead */
  217. tmpWrite, /* xWrite */
  218. tmpTruncate, /* xTruncate */
  219. tmpSync, /* xSync */
  220. tmpFileSize, /* xFileSize */
  221. tmpLock, /* xLock */
  222. tmpUnlock, /* xUnlock */
  223. tmpCheckReservedLock, /* xCheckReservedLock */
  224. tmpFileControl, /* xFileControl */
  225. tmpSectorSize, /* xSectorSize */
  226. tmpDeviceCharacteristics, /* xDeviceCharacteristics */
  227. 0, /* xShmMap */
  228. 0, /* xShmLock */
  229. 0, /* xShmBarrier */
  230. 0 /* xShmUnmap */
  231. };
  232. /* Useful macros used in several places */
  233. #define MIN(x,y) ((x)<(y)?(x):(y))
  234. #define MAX(x,y) ((x)>(y)?(x):(y))
  235. /*
  236. ** Close a tmp-file.
  237. */
  238. static int tmpClose(sqlite3_file *pFile){
  239. tmp_file *pTmp = (tmp_file *)pFile;
  240. sqlite3_free(pTmp->zAlloc);
  241. return SQLITE_OK;
  242. }
  243. /*
  244. ** Read data from a tmp-file.
  245. */
  246. static int tmpRead(
  247. sqlite3_file *pFile,
  248. void *zBuf,
  249. int iAmt,
  250. sqlite_int64 iOfst
  251. ){
  252. tmp_file *pTmp = (tmp_file *)pFile;
  253. if( (iAmt+iOfst)>pTmp->nSize ){
  254. return SQLITE_IOERR_SHORT_READ;
  255. }
  256. memcpy(zBuf, &pTmp->zAlloc[iOfst], iAmt);
  257. return SQLITE_OK;
  258. }
  259. /*
  260. ** Write data to a tmp-file.
  261. */
  262. static int tmpWrite(
  263. sqlite3_file *pFile,
  264. const void *zBuf,
  265. int iAmt,
  266. sqlite_int64 iOfst
  267. ){
  268. tmp_file *pTmp = (tmp_file *)pFile;
  269. if( (iAmt+iOfst)>pTmp->nAlloc ){
  270. int nNew = (int)(2*(iAmt+iOfst+pTmp->nAlloc));
  271. char *zNew = sqlite3_realloc(pTmp->zAlloc, nNew);
  272. if( !zNew ){
  273. return SQLITE_NOMEM;
  274. }
  275. pTmp->zAlloc = zNew;
  276. pTmp->nAlloc = nNew;
  277. }
  278. memcpy(&pTmp->zAlloc[iOfst], zBuf, iAmt);
  279. pTmp->nSize = (int)MAX(pTmp->nSize, iOfst+iAmt);
  280. return SQLITE_OK;
  281. }
  282. /*
  283. ** Truncate a tmp-file.
  284. */
  285. static int tmpTruncate(sqlite3_file *pFile, sqlite_int64 size){
  286. tmp_file *pTmp = (tmp_file *)pFile;
  287. pTmp->nSize = (int)MIN(pTmp->nSize, size);
  288. return SQLITE_OK;
  289. }
  290. /*
  291. ** Sync a tmp-file.
  292. */
  293. static int tmpSync(sqlite3_file *pFile, int flags){
  294. return SQLITE_OK;
  295. }
  296. /*
  297. ** Return the current file-size of a tmp-file.
  298. */
  299. static int tmpFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  300. tmp_file *pTmp = (tmp_file *)pFile;
  301. *pSize = pTmp->nSize;
  302. return SQLITE_OK;
  303. }
  304. /*
  305. ** Lock a tmp-file.
  306. */
  307. static int tmpLock(sqlite3_file *pFile, int eLock){
  308. return SQLITE_OK;
  309. }
  310. /*
  311. ** Unlock a tmp-file.
  312. */
  313. static int tmpUnlock(sqlite3_file *pFile, int eLock){
  314. return SQLITE_OK;
  315. }
  316. /*
  317. ** Check if another file-handle holds a RESERVED lock on a tmp-file.
  318. */
  319. static int tmpCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  320. *pResOut = 0;
  321. return SQLITE_OK;
  322. }
  323. /*
  324. ** File control method. For custom operations on a tmp-file.
  325. */
  326. static int tmpFileControl(sqlite3_file *pFile, int op, void *pArg){
  327. return SQLITE_OK;
  328. }
  329. /*
  330. ** Return the sector-size in bytes for a tmp-file.
  331. */
  332. static int tmpSectorSize(sqlite3_file *pFile){
  333. return 0;
  334. }
  335. /*
  336. ** Return the device characteristic flags supported by a tmp-file.
  337. */
  338. static int tmpDeviceCharacteristics(sqlite3_file *pFile){
  339. return 0;
  340. }
  341. /*
  342. ** Close an fs-file.
  343. */
  344. static int fsClose(sqlite3_file *pFile){
  345. int rc = SQLITE_OK;
  346. fs_file *p = (fs_file *)pFile;
  347. fs_real_file *pReal = p->pReal;
  348. /* Decrement the real_file ref-count. */
  349. pReal->nRef--;
  350. assert(pReal->nRef>=0);
  351. /* When the ref-count reaches 0, destroy the structure */
  352. if( pReal->nRef==0 ){
  353. *pReal->ppThis = pReal->pNext;
  354. if( pReal->pNext ){
  355. pReal->pNext->ppThis = pReal->ppThis;
  356. }
  357. rc = pReal->pFile->pMethods->xClose(pReal->pFile);
  358. sqlite3_free(pReal);
  359. }
  360. return rc;
  361. }
  362. /*
  363. ** Read data from an fs-file.
  364. */
  365. static int fsRead(
  366. sqlite3_file *pFile,
  367. void *zBuf,
  368. int iAmt,
  369. sqlite_int64 iOfst
  370. ){
  371. int rc = SQLITE_OK;
  372. fs_file *p = (fs_file *)pFile;
  373. fs_real_file *pReal = p->pReal;
  374. sqlite3_file *pF = pReal->pFile;
  375. if( (p->eType==DATABASE_FILE && (iAmt+iOfst)>pReal->nDatabase)
  376. || (p->eType==JOURNAL_FILE && (iAmt+iOfst)>pReal->nJournal)
  377. ){
  378. rc = SQLITE_IOERR_SHORT_READ;
  379. }else if( p->eType==DATABASE_FILE ){
  380. rc = pF->pMethods->xRead(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
  381. }else{
  382. /* Journal file. */
  383. int iRem = iAmt;
  384. int iBuf = 0;
  385. int ii = (int)iOfst;
  386. while( iRem>0 && rc==SQLITE_OK ){
  387. int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
  388. int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
  389. rc = pF->pMethods->xRead(pF, &((char *)zBuf)[iBuf], iRealAmt, iRealOff);
  390. ii += iRealAmt;
  391. iBuf += iRealAmt;
  392. iRem -= iRealAmt;
  393. }
  394. }
  395. return rc;
  396. }
  397. /*
  398. ** Write data to an fs-file.
  399. */
  400. static int fsWrite(
  401. sqlite3_file *pFile,
  402. const 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. if( p->eType==DATABASE_FILE ){
  411. if( (iAmt+iOfst+BLOCKSIZE)>(pReal->nBlob-pReal->nJournal) ){
  412. rc = SQLITE_FULL;
  413. }else{
  414. rc = pF->pMethods->xWrite(pF, zBuf, iAmt, iOfst+BLOCKSIZE);
  415. if( rc==SQLITE_OK ){
  416. pReal->nDatabase = (int)MAX(pReal->nDatabase, iAmt+iOfst);
  417. }
  418. }
  419. }else{
  420. /* Journal file. */
  421. int iRem = iAmt;
  422. int iBuf = 0;
  423. int ii = (int)iOfst;
  424. while( iRem>0 && rc==SQLITE_OK ){
  425. int iRealOff = pReal->nBlob - BLOCKSIZE*((ii/BLOCKSIZE)+1) + ii%BLOCKSIZE;
  426. int iRealAmt = MIN(iRem, BLOCKSIZE - (iRealOff%BLOCKSIZE));
  427. if( iRealOff<(pReal->nDatabase+BLOCKSIZE) ){
  428. rc = SQLITE_FULL;
  429. }else{
  430. rc = pF->pMethods->xWrite(pF, &((char *)zBuf)[iBuf], iRealAmt,iRealOff);
  431. ii += iRealAmt;
  432. iBuf += iRealAmt;
  433. iRem -= iRealAmt;
  434. }
  435. }
  436. if( rc==SQLITE_OK ){
  437. pReal->nJournal = (int)MAX(pReal->nJournal, iAmt+iOfst);
  438. }
  439. }
  440. return rc;
  441. }
  442. /*
  443. ** Truncate an fs-file.
  444. */
  445. static int fsTruncate(sqlite3_file *pFile, sqlite_int64 size){
  446. fs_file *p = (fs_file *)pFile;
  447. fs_real_file *pReal = p->pReal;
  448. if( p->eType==DATABASE_FILE ){
  449. pReal->nDatabase = (int)MIN(pReal->nDatabase, size);
  450. }else{
  451. pReal->nJournal = (int)MIN(pReal->nJournal, size);
  452. }
  453. return SQLITE_OK;
  454. }
  455. /*
  456. ** Sync an fs-file.
  457. */
  458. static int fsSync(sqlite3_file *pFile, int flags){
  459. fs_file *p = (fs_file *)pFile;
  460. fs_real_file *pReal = p->pReal;
  461. sqlite3_file *pRealFile = pReal->pFile;
  462. int rc = SQLITE_OK;
  463. if( p->eType==DATABASE_FILE ){
  464. unsigned char zSize[4];
  465. zSize[0] = (pReal->nDatabase&0xFF000000)>>24;
  466. zSize[1] = (pReal->nDatabase&0x00FF0000)>>16;
  467. zSize[2] = (pReal->nDatabase&0x0000FF00)>>8;
  468. zSize[3] = (pReal->nDatabase&0x000000FF);
  469. rc = pRealFile->pMethods->xWrite(pRealFile, zSize, 4, 0);
  470. }
  471. if( rc==SQLITE_OK ){
  472. rc = pRealFile->pMethods->xSync(pRealFile, flags&(~SQLITE_SYNC_DATAONLY));
  473. }
  474. return rc;
  475. }
  476. /*
  477. ** Return the current file-size of an fs-file.
  478. */
  479. static int fsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  480. fs_file *p = (fs_file *)pFile;
  481. fs_real_file *pReal = p->pReal;
  482. if( p->eType==DATABASE_FILE ){
  483. *pSize = pReal->nDatabase;
  484. }else{
  485. *pSize = pReal->nJournal;
  486. }
  487. return SQLITE_OK;
  488. }
  489. /*
  490. ** Lock an fs-file.
  491. */
  492. static int fsLock(sqlite3_file *pFile, int eLock){
  493. return SQLITE_OK;
  494. }
  495. /*
  496. ** Unlock an fs-file.
  497. */
  498. static int fsUnlock(sqlite3_file *pFile, int eLock){
  499. return SQLITE_OK;
  500. }
  501. /*
  502. ** Check if another file-handle holds a RESERVED lock on an fs-file.
  503. */
  504. static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  505. *pResOut = 0;
  506. return SQLITE_OK;
  507. }
  508. /*
  509. ** File control method. For custom operations on an fs-file.
  510. */
  511. static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){
  512. return SQLITE_OK;
  513. }
  514. /*
  515. ** Return the sector-size in bytes for an fs-file.
  516. */
  517. static int fsSectorSize(sqlite3_file *pFile){
  518. return BLOCKSIZE;
  519. }
  520. /*
  521. ** Return the device characteristic flags supported by an fs-file.
  522. */
  523. static int fsDeviceCharacteristics(sqlite3_file *pFile){
  524. return 0;
  525. }
  526. /*
  527. ** Open an fs file handle.
  528. */
  529. static int fsOpen(
  530. sqlite3_vfs *pVfs,
  531. const char *zName,
  532. sqlite3_file *pFile,
  533. int flags,
  534. int *pOutFlags
  535. ){
  536. fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
  537. fs_file *p = (fs_file *)pFile;
  538. fs_real_file *pReal = 0;
  539. int eType;
  540. int nName;
  541. int rc = SQLITE_OK;
  542. if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
  543. tmp_file *p = (tmp_file *)pFile;
  544. memset(p, 0, sizeof(*p));
  545. p->base.pMethods = &tmp_io_methods;
  546. return SQLITE_OK;
  547. }
  548. eType = ((flags&(SQLITE_OPEN_MAIN_DB))?DATABASE_FILE:JOURNAL_FILE);
  549. p->base.pMethods = &fs_io_methods;
  550. p->eType = eType;
  551. assert(strlen("-journal")==8);
  552. nName = (int)strlen(zName)-((eType==JOURNAL_FILE)?8:0);
  553. pReal=pFsVfs->pFileList;
  554. for(; pReal && strncmp(pReal->zName, zName, nName); pReal=pReal->pNext);
  555. if( !pReal ){
  556. int real_flags = (flags&~(SQLITE_OPEN_MAIN_DB))|SQLITE_OPEN_TEMP_DB;
  557. sqlite3_int64 size;
  558. sqlite3_file *pRealFile;
  559. sqlite3_vfs *pParent = pFsVfs->pParent;
  560. assert(eType==DATABASE_FILE);
  561. pReal = (fs_real_file *)sqlite3_malloc(sizeof(*pReal)+pParent->szOsFile);
  562. if( !pReal ){
  563. rc = SQLITE_NOMEM;
  564. goto open_out;
  565. }
  566. memset(pReal, 0, sizeof(*pReal)+pParent->szOsFile);
  567. pReal->zName = zName;
  568. pReal->pFile = (sqlite3_file *)(&pReal[1]);
  569. rc = pParent->xOpen(pParent, zName, pReal->pFile, real_flags, pOutFlags);
  570. if( rc!=SQLITE_OK ){
  571. goto open_out;
  572. }
  573. pRealFile = pReal->pFile;
  574. rc = pRealFile->pMethods->xFileSize(pRealFile, &size);
  575. if( rc!=SQLITE_OK ){
  576. goto open_out;
  577. }
  578. if( size==0 ){
  579. rc = pRealFile->pMethods->xWrite(pRealFile, "\0", 1, BLOBSIZE-1);
  580. pReal->nBlob = BLOBSIZE;
  581. }else{
  582. unsigned char zS[4];
  583. pReal->nBlob = (int)size;
  584. rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, 0);
  585. pReal->nDatabase = (zS[0]<<24)+(zS[1]<<16)+(zS[2]<<8)+zS[3];
  586. if( rc==SQLITE_OK ){
  587. rc = pRealFile->pMethods->xRead(pRealFile, zS, 4, pReal->nBlob-4);
  588. if( zS[0] || zS[1] || zS[2] || zS[3] ){
  589. pReal->nJournal = pReal->nBlob;
  590. }
  591. }
  592. }
  593. if( rc==SQLITE_OK ){
  594. pReal->pNext = pFsVfs->pFileList;
  595. if( pReal->pNext ){
  596. pReal->pNext->ppThis = &pReal->pNext;
  597. }
  598. pReal->ppThis = &pFsVfs->pFileList;
  599. pFsVfs->pFileList = pReal;
  600. }
  601. }
  602. open_out:
  603. if( pReal ){
  604. if( rc==SQLITE_OK ){
  605. p->pReal = pReal;
  606. pReal->nRef++;
  607. }else{
  608. if( pReal->pFile->pMethods ){
  609. pReal->pFile->pMethods->xClose(pReal->pFile);
  610. }
  611. sqlite3_free(pReal);
  612. }
  613. }
  614. return rc;
  615. }
  616. /*
  617. ** Delete the file located at zPath. If the dirSync argument is true,
  618. ** ensure the file-system modifications are synced to disk before
  619. ** returning.
  620. */
  621. static int fsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  622. int rc = SQLITE_OK;
  623. fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
  624. fs_real_file *pReal;
  625. sqlite3_file *pF;
  626. int nName = (int)strlen(zPath) - 8;
  627. assert(strlen("-journal")==8);
  628. assert(strcmp("-journal", &zPath[nName])==0);
  629. pReal = pFsVfs->pFileList;
  630. for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
  631. if( pReal ){
  632. pF = pReal->pFile;
  633. rc = pF->pMethods->xWrite(pF, "\0\0\0\0", 4, pReal->nBlob-BLOCKSIZE);
  634. if( rc==SQLITE_OK ){
  635. pReal->nJournal = 0;
  636. }
  637. }
  638. return rc;
  639. }
  640. /*
  641. ** Test for access permissions. Return true if the requested permission
  642. ** is available, or false otherwise.
  643. */
  644. static int fsAccess(
  645. sqlite3_vfs *pVfs,
  646. const char *zPath,
  647. int flags,
  648. int *pResOut
  649. ){
  650. fs_vfs_t *pFsVfs = (fs_vfs_t *)pVfs;
  651. fs_real_file *pReal;
  652. int isJournal = 0;
  653. int nName = (int)strlen(zPath);
  654. if( flags!=SQLITE_ACCESS_EXISTS ){
  655. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  656. return pParent->xAccess(pParent, zPath, flags, pResOut);
  657. }
  658. assert(strlen("-journal")==8);
  659. if( nName>8 && strcmp("-journal", &zPath[nName-8])==0 ){
  660. nName -= 8;
  661. isJournal = 1;
  662. }
  663. pReal = pFsVfs->pFileList;
  664. for(; pReal && strncmp(pReal->zName, zPath, nName); pReal=pReal->pNext);
  665. *pResOut = (pReal && (!isJournal || pReal->nJournal>0));
  666. return SQLITE_OK;
  667. }
  668. /*
  669. ** Populate buffer zOut with the full canonical pathname corresponding
  670. ** to the pathname in zPath. zOut is guaranteed to point to a buffer
  671. ** of at least (FS_MAX_PATHNAME+1) bytes.
  672. */
  673. static int fsFullPathname(
  674. sqlite3_vfs *pVfs, /* Pointer to vfs object */
  675. const char *zPath, /* Possibly relative input path */
  676. int nOut, /* Size of output buffer in bytes */
  677. char *zOut /* Output buffer */
  678. ){
  679. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  680. return pParent->xFullPathname(pParent, zPath, nOut, zOut);
  681. }
  682. /*
  683. ** Open the dynamic library located at zPath and return a handle.
  684. */
  685. static void *fsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
  686. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  687. return pParent->xDlOpen(pParent, zPath);
  688. }
  689. /*
  690. ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
  691. ** utf-8 string describing the most recent error encountered associated
  692. ** with dynamic libraries.
  693. */
  694. static void fsDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
  695. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  696. pParent->xDlError(pParent, nByte, zErrMsg);
  697. }
  698. /*
  699. ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
  700. */
  701. static void (*fsDlSym(sqlite3_vfs *pVfs, void *pH, const char *zSym))(void){
  702. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  703. return pParent->xDlSym(pParent, pH, zSym);
  704. }
  705. /*
  706. ** Close the dynamic library handle pHandle.
  707. */
  708. static void fsDlClose(sqlite3_vfs *pVfs, void *pHandle){
  709. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  710. pParent->xDlClose(pParent, pHandle);
  711. }
  712. /*
  713. ** Populate the buffer pointed to by zBufOut with nByte bytes of
  714. ** random data.
  715. */
  716. static int fsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
  717. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  718. return pParent->xRandomness(pParent, nByte, zBufOut);
  719. }
  720. /*
  721. ** Sleep for nMicro microseconds. Return the number of microseconds
  722. ** actually slept.
  723. */
  724. static int fsSleep(sqlite3_vfs *pVfs, int nMicro){
  725. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  726. return pParent->xSleep(pParent, nMicro);
  727. }
  728. /*
  729. ** Return the current time as a Julian Day number in *pTimeOut.
  730. */
  731. static int fsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
  732. sqlite3_vfs *pParent = ((fs_vfs_t *)pVfs)->pParent;
  733. return pParent->xCurrentTime(pParent, pTimeOut);
  734. }
  735. /*
  736. ** This procedure registers the fs vfs with SQLite. If the argument is
  737. ** true, the fs vfs becomes the new default vfs. It is the only publicly
  738. ** available function in this file.
  739. */
  740. int fs_register(void){
  741. if( fs_vfs.pParent ) return SQLITE_OK;
  742. fs_vfs.pParent = sqlite3_vfs_find(0);
  743. fs_vfs.base.mxPathname = fs_vfs.pParent->mxPathname;
  744. fs_vfs.base.szOsFile = MAX(sizeof(tmp_file), sizeof(fs_file));
  745. return sqlite3_vfs_register(&fs_vfs.base, 0);
  746. }
  747. #ifdef SQLITE_TEST
  748. int SqlitetestOnefile_Init() {return fs_register();}
  749. #endif