| Index: third_party/sqlite/src/ext/misc/memvfs.c
|
| diff --git a/third_party/sqlite/src/ext/misc/memvfs.c b/third_party/sqlite/src/ext/misc/memvfs.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..62a8a033d7de14cf1073023e4366ca6619418187
|
| --- /dev/null
|
| +++ b/third_party/sqlite/src/ext/misc/memvfs.c
|
| @@ -0,0 +1,491 @@
|
| +/*
|
| +** 2016-09-07
|
| +**
|
| +** The author disclaims copyright to this source code. In place of
|
| +** a legal notice, here is a blessing:
|
| +**
|
| +** May you do good and not evil.
|
| +** May you find forgiveness for yourself and forgive others.
|
| +** May you share freely, never taking more than you give.
|
| +**
|
| +******************************************************************************
|
| +**
|
| +** This is an in-memory read-only VFS implementation. The application
|
| +** supplies a block of memory which is the database file, and this VFS
|
| +** uses that block of memory.
|
| +**
|
| +** Because there is no place to store journals and no good way to lock
|
| +** the "file", this VFS is read-only.
|
| +**
|
| +** USAGE:
|
| +**
|
| +** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336", &db,
|
| +** SQLITE_OPEN_READONLY | SQLITE_OPEN_URI,
|
| +** "memvfs");
|
| +**
|
| +** The ptr= and sz= query parameters are required or the open will fail.
|
| +** The ptr= parameter gives the memory address of the buffer holding the
|
| +** read-only database and sz= gives the size of the database. The parameter
|
| +** values may be in hexadecimal or decimal. The filename is ignored.
|
| +*/
|
| +#include <sqlite3ext.h>
|
| +SQLITE_EXTENSION_INIT1
|
| +#include <string.h>
|
| +#include <assert.h>
|
| +
|
| +
|
| +/*
|
| +** Forward declaration of objects used by this utility
|
| +*/
|
| +typedef struct sqlite3_vfs MemVfs;
|
| +typedef struct MemFile MemFile;
|
| +
|
| +/* Access to a lower-level VFS that (might) implement dynamic loading,
|
| +** access to randomness, etc.
|
| +*/
|
| +#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
|
| +
|
| +/* An open file */
|
| +struct MemFile {
|
| + sqlite3_file base; /* IO methods */
|
| + sqlite3_int64 sz; /* Size of the file */
|
| + unsigned char *aData; /* content of the file */
|
| +};
|
| +
|
| +/*
|
| +** Methods for MemFile
|
| +*/
|
| +static int memClose(sqlite3_file*);
|
| +static int memRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
| +static int memWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
|
| +static int memTruncate(sqlite3_file*, sqlite3_int64 size);
|
| +static int memSync(sqlite3_file*, int flags);
|
| +static int memFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
| +static int memLock(sqlite3_file*, int);
|
| +static int memUnlock(sqlite3_file*, int);
|
| +static int memCheckReservedLock(sqlite3_file*, int *pResOut);
|
| +static int memFileControl(sqlite3_file*, int op, void *pArg);
|
| +static int memSectorSize(sqlite3_file*);
|
| +static int memDeviceCharacteristics(sqlite3_file*);
|
| +static int memShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
|
| +static int memShmLock(sqlite3_file*, int offset, int n, int flags);
|
| +static void memShmBarrier(sqlite3_file*);
|
| +static int memShmUnmap(sqlite3_file*, int deleteFlag);
|
| +static int memFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
|
| +static int memUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
|
| +
|
| +/*
|
| +** Methods for MemVfs
|
| +*/
|
| +static int memOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
| +static int memDelete(sqlite3_vfs*, const char *zName, int syncDir);
|
| +static int memAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
| +static int memFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
| +static void *memDlOpen(sqlite3_vfs*, const char *zFilename);
|
| +static void memDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
|
| +static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
|
| +static void memDlClose(sqlite3_vfs*, void*);
|
| +static int memRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
| +static int memSleep(sqlite3_vfs*, int microseconds);
|
| +static int memCurrentTime(sqlite3_vfs*, double*);
|
| +static int memGetLastError(sqlite3_vfs*, int, char *);
|
| +static int memCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
| +
|
| +static sqlite3_vfs mem_vfs = {
|
| + 2, /* iVersion */
|
| + 0, /* szOsFile (set when registered) */
|
| + 1024, /* mxPathname */
|
| + 0, /* pNext */
|
| + "memvfs", /* zName */
|
| + 0, /* pAppData (set when registered) */
|
| + memOpen, /* xOpen */
|
| + memDelete, /* xDelete */
|
| + memAccess, /* xAccess */
|
| + memFullPathname, /* xFullPathname */
|
| + memDlOpen, /* xDlOpen */
|
| + memDlError, /* xDlError */
|
| + memDlSym, /* xDlSym */
|
| + memDlClose, /* xDlClose */
|
| + memRandomness, /* xRandomness */
|
| + memSleep, /* xSleep */
|
| + memCurrentTime, /* xCurrentTime */
|
| + memGetLastError, /* xGetLastError */
|
| + memCurrentTimeInt64 /* xCurrentTimeInt64 */
|
| +};
|
| +
|
| +static const sqlite3_io_methods mem_io_methods = {
|
| + 3, /* iVersion */
|
| + memClose, /* xClose */
|
| + memRead, /* xRead */
|
| + memWrite, /* xWrite */
|
| + memTruncate, /* xTruncate */
|
| + memSync, /* xSync */
|
| + memFileSize, /* xFileSize */
|
| + memLock, /* xLock */
|
| + memUnlock, /* xUnlock */
|
| + memCheckReservedLock, /* xCheckReservedLock */
|
| + memFileControl, /* xFileControl */
|
| + memSectorSize, /* xSectorSize */
|
| + memDeviceCharacteristics, /* xDeviceCharacteristics */
|
| + memShmMap, /* xShmMap */
|
| + memShmLock, /* xShmLock */
|
| + memShmBarrier, /* xShmBarrier */
|
| + memShmUnmap, /* xShmUnmap */
|
| + memFetch, /* xFetch */
|
| + memUnfetch /* xUnfetch */
|
| +};
|
| +
|
| +
|
| +
|
| +/*
|
| +** Close an mem-file.
|
| +**
|
| +** The pData pointer is owned by the application, so there is nothing
|
| +** to free.
|
| +*/
|
| +static int memClose(sqlite3_file *pFile){
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Read data from an mem-file.
|
| +*/
|
| +static int memRead(
|
| + sqlite3_file *pFile,
|
| + void *zBuf,
|
| + int iAmt,
|
| + sqlite_int64 iOfst
|
| +){
|
| + MemFile *p = (MemFile *)pFile;
|
| + memcpy(zBuf, p->aData+iOfst, iAmt);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Write data to an mem-file.
|
| +*/
|
| +static int memWrite(
|
| + sqlite3_file *pFile,
|
| + const void *z,
|
| + int iAmt,
|
| + sqlite_int64 iOfst
|
| +){
|
| + return SQLITE_READONLY;
|
| +}
|
| +
|
| +/*
|
| +** Truncate an mem-file.
|
| +*/
|
| +static int memTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
| + return SQLITE_READONLY;
|
| +}
|
| +
|
| +/*
|
| +** Sync an mem-file.
|
| +*/
|
| +static int memSync(sqlite3_file *pFile, int flags){
|
| + return SQLITE_READONLY;
|
| +}
|
| +
|
| +/*
|
| +** Return the current file-size of an mem-file.
|
| +*/
|
| +static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
| + MemFile *p = (MemFile *)pFile;
|
| + *pSize = p->sz;
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Lock an mem-file.
|
| +*/
|
| +static int memLock(sqlite3_file *pFile, int eLock){
|
| + return SQLITE_READONLY;
|
| +}
|
| +
|
| +/*
|
| +** Unlock an mem-file.
|
| +*/
|
| +static int memUnlock(sqlite3_file *pFile, int eLock){
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Check if another file-handle holds a RESERVED lock on an mem-file.
|
| +*/
|
| +static int memCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
| + *pResOut = 0;
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** File control method. For custom operations on an mem-file.
|
| +*/
|
| +static int memFileControl(sqlite3_file *pFile, int op, void *pArg){
|
| + MemFile *p = (MemFile *)pFile;
|
| + int rc = SQLITE_NOTFOUND;
|
| + if( op==SQLITE_FCNTL_VFSNAME ){
|
| + *(char**)pArg = sqlite3_mprintf("mem(%p,%lld)", p->aData, p->sz);
|
| + rc = SQLITE_OK;
|
| + }
|
| + return rc;
|
| +}
|
| +
|
| +/*
|
| +** Return the sector-size in bytes for an mem-file.
|
| +*/
|
| +static int memSectorSize(sqlite3_file *pFile){
|
| + return 1024;
|
| +}
|
| +
|
| +/*
|
| +** Return the device characteristic flags supported by an mem-file.
|
| +*/
|
| +static int memDeviceCharacteristics(sqlite3_file *pFile){
|
| + return SQLITE_IOCAP_IMMUTABLE;
|
| +}
|
| +
|
| +/* Create a shared memory file mapping */
|
| +static int memShmMap(
|
| + sqlite3_file *pFile,
|
| + int iPg,
|
| + int pgsz,
|
| + int bExtend,
|
| + void volatile **pp
|
| +){
|
| + return SQLITE_READONLY;
|
| +}
|
| +
|
| +/* Perform locking on a shared-memory segment */
|
| +static int memShmLock(sqlite3_file *pFile, int offset, int n, int flags){
|
| + return SQLITE_READONLY;
|
| +}
|
| +
|
| +/* Memory barrier operation on shared memory */
|
| +static void memShmBarrier(sqlite3_file *pFile){
|
| + return;
|
| +}
|
| +
|
| +/* Unmap a shared memory segment */
|
| +static int memShmUnmap(sqlite3_file *pFile, int deleteFlag){
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/* Fetch a page of a memory-mapped file */
|
| +static int memFetch(
|
| + sqlite3_file *pFile,
|
| + sqlite3_int64 iOfst,
|
| + int iAmt,
|
| + void **pp
|
| +){
|
| + MemFile *p = (MemFile *)pFile;
|
| + *pp = (void*)(p->aData + iOfst);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/* Release a memory-mapped page */
|
| +static int memUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Open an mem file handle.
|
| +*/
|
| +static int memOpen(
|
| + sqlite3_vfs *pVfs,
|
| + const char *zName,
|
| + sqlite3_file *pFile,
|
| + int flags,
|
| + int *pOutFlags
|
| +){
|
| + MemFile *p = (MemFile*)pFile;
|
| + memset(p, 0, sizeof(*p));
|
| + if( (flags & SQLITE_OPEN_MAIN_DB)==0 ) return SQLITE_CANTOPEN;
|
| + p->aData = (unsigned char*)sqlite3_uri_int64(zName,"ptr",0);
|
| + if( p->aData==0 ) return SQLITE_CANTOPEN;
|
| + p->sz = sqlite3_uri_int64(zName,"sz",0);
|
| + if( p->sz<0 ) return SQLITE_CANTOPEN;
|
| + pFile->pMethods = &mem_io_methods;
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Delete the file located at zPath. If the dirSync argument is true,
|
| +** ensure the file-system modifications are synced to disk before
|
| +** returning.
|
| +*/
|
| +static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
| + return SQLITE_READONLY;
|
| +}
|
| +
|
| +/*
|
| +** Test for access permissions. Return true if the requested permission
|
| +** is available, or false otherwise.
|
| +*/
|
| +static int memAccess(
|
| + sqlite3_vfs *pVfs,
|
| + const char *zPath,
|
| + int flags,
|
| + int *pResOut
|
| +){
|
| + /* The spec says there are three possible values for flags. But only
|
| + ** two of them are actually used */
|
| + assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE );
|
| + if( flags==SQLITE_ACCESS_READWRITE ){
|
| + *pResOut = 0;
|
| + }else{
|
| + *pResOut = 1;
|
| + }
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Populate buffer zOut with the full canonical pathname corresponding
|
| +** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
| +** of at least (INST_MAX_PATHNAME+1) bytes.
|
| +*/
|
| +static int memFullPathname(
|
| + sqlite3_vfs *pVfs,
|
| + const char *zPath,
|
| + int nOut,
|
| + char *zOut
|
| +){
|
| + sqlite3_snprintf(nOut, zOut, "%s", zPath);
|
| + return SQLITE_OK;
|
| +}
|
| +
|
| +/*
|
| +** Open the dynamic library located at zPath and return a handle.
|
| +*/
|
| +static void *memDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
| + return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
|
| +}
|
| +
|
| +/*
|
| +** Populate the buffer zErrMsg (size nByte bytes) with a human readable
|
| +** utf-8 string describing the most recent error encountered associated
|
| +** with dynamic libraries.
|
| +*/
|
| +static void memDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
| + ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
|
| +}
|
| +
|
| +/*
|
| +** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
|
| +*/
|
| +static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
|
| + return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
|
| +}
|
| +
|
| +/*
|
| +** Close the dynamic library handle pHandle.
|
| +*/
|
| +static void memDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
| + ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
|
| +}
|
| +
|
| +/*
|
| +** Populate the buffer pointed to by zBufOut with nByte bytes of
|
| +** random data.
|
| +*/
|
| +static int memRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
| + return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
|
| +}
|
| +
|
| +/*
|
| +** Sleep for nMicro microseconds. Return the number of microseconds
|
| +** actually slept.
|
| +*/
|
| +static int memSleep(sqlite3_vfs *pVfs, int nMicro){
|
| + return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
|
| +}
|
| +
|
| +/*
|
| +** Return the current time as a Julian Day number in *pTimeOut.
|
| +*/
|
| +static int memCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
| + return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
|
| +}
|
| +
|
| +static int memGetLastError(sqlite3_vfs *pVfs, int a, char *b){
|
| + return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
|
| +}
|
| +static int memCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
| + return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
|
| +}
|
| +
|
| +#ifdef MEMVFS_TEST
|
| +/*
|
| +** memload(FILENAME)
|
| +**
|
| +** This an SQL function used to help in testing the memvfs VFS. The
|
| +** function reads the content of a file into memory and then returns
|
| +** a string that gives the locate and size of the in-memory buffer.
|
| +*/
|
| +#include <stdio.h>
|
| +static void memvfsMemloadFunc(
|
| + sqlite3_context *context,
|
| + int argc,
|
| + sqlite3_value **argv
|
| +){
|
| + unsigned char *p;
|
| + sqlite3_int64 sz;
|
| + FILE *in;
|
| + const char *zFilename = (const char*)sqlite3_value_text(argv[0]);
|
| + char zReturn[100];
|
| +
|
| + if( zFilename==0 ) return;
|
| + in = fopen(zFilename, "rb");
|
| + if( in==0 ) return;
|
| + fseek(in, 0, SEEK_END);
|
| + sz = ftell(in);
|
| + rewind(in);
|
| + p = sqlite3_malloc( sz );
|
| + if( p==0 ){
|
| + fclose(in);
|
| + sqlite3_result_error_nomem(context);
|
| + return;
|
| + }
|
| + fread(p, sz, 1, in);
|
| + fclose(in);
|
| + sqlite3_snprintf(sizeof(zReturn),zReturn,"ptr=%lld&sz=%lld",
|
| + (sqlite3_int64)p, sz);
|
| + sqlite3_result_text(context, zReturn, -1, SQLITE_TRANSIENT);
|
| +}
|
| +/* Called for each new database connection */
|
| +static int memvfsRegister(
|
| + sqlite3 *db,
|
| + const char **pzErrMsg,
|
| + const struct sqlite3_api_routines *pThunk
|
| +){
|
| + return sqlite3_create_function(db, "memload", 1, SQLITE_UTF8, 0,
|
| + memvfsMemloadFunc, 0, 0);
|
| +}
|
| +#endif /* MEMVFS_TEST */
|
| +
|
| +
|
| +#ifdef _WIN32
|
| +__declspec(dllexport)
|
| +#endif
|
| +/*
|
| +** This routine is called when the extension is loaded.
|
| +** Register the new VFS.
|
| +*/
|
| +int sqlite3_memvfs_init(
|
| + sqlite3 *db,
|
| + char **pzErrMsg,
|
| + const sqlite3_api_routines *pApi
|
| +){
|
| + int rc = SQLITE_OK;
|
| + SQLITE_EXTENSION_INIT2(pApi);
|
| + mem_vfs.pAppData = sqlite3_vfs_find(0);
|
| + mem_vfs.szOsFile = sizeof(MemFile);
|
| + rc = sqlite3_vfs_register(&mem_vfs, 1);
|
| +#ifdef MEMVFS_TEST
|
| + if( rc==SQLITE_OK ){
|
| + rc = sqlite3_auto_extension((void(*)(void))memvfsRegister);
|
| + }
|
| +#endif
|
| + if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
|
| + return rc;
|
| +}
|
|
|