source upload

This commit is contained in:
Razor12911
2022-01-17 22:16:47 +02:00
parent 12936d065b
commit 098e8c48de
1778 changed files with 1206749 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
# SQLite3 Database Engine With Encryption
## Reference Only - Do Not Use
This source code is included as reference.
**You should not have to compile the SQLite3 c code by yourself.**
We supply and validate the proper static `.o` `.obj` files within our https://github/synopse repository, or directly from https://synopse.info/files/sqlite3fpc.7z (for FPC) or https://synopse.info/files/sqlite3obj.7z (for Delphi).
## How To Compile The SQlite3 Engine
1. Copy here the latest amalgamation files from https://www.sqlite.org/download.html
2. Run the `patch-and-compile.sh` script to patch main `sqlite3.c` and cross-compile it for FPC
3. Run `c*.bat` to generate the `sqlite3.o` and `sqlite3.obj` for Delphi Win32/Win64
4. Don't forget to tune the expected *SQLite3* version text in `SynSQLite3Static.pas`
## Cross-Compile
Scripts are supplied to cross-compile from Linux to other systems.
It will use either the cross-compiler as installed by `fpcupdeluxe` or you should manually add some packages.
Here are some instructions for Debian/Ubuntu.
### Cross-Compile to Linux i386 from Linux x86_64
Install the following package:
sudo apt install libc6-dev:i386
granted the following has been run beforehand:
dpkg --add-architecture i386
You may also try the `gcc-multilib` package as alternative.
### Cross-Compile To Win32 And Win64
Install the following package:
sudo apt install mingw-w64
### Cross-Compile to Darwin / Linux ARM/AARCH64
Ensure you installed the latest version of the corresponding cross-compilers in `fpcupdeluxe` (in the *Cross* tab), and modify the `*.sh` path if necessary, from its default value:
CROSS=/home/ab/fpcup/cross/bin/$ARCH
## Acknowledgment
Our c wrapper is a cut-down, deeply adapted, version from https://github.com/utelle/SQLite3MultipleCiphers to use our `SynCrypto` unit and ensure compatibily with *bcc32/bcc64* Embarcadero compilers.
Original MIT License - (c) 2006-2020 Ulrich Telle

View File

@@ -0,0 +1,14 @@
LOCAL_PATH := $(call my-dir)
#
# Statically Linked
#
include $(CLEAR_VARS)
LOCAL_MODULE := sqlite3-a
LOCAL_MODULE_FILENAME := libsqlite3
LOCAL_SRC_FILES := ../../sqlite3mc.c
LOCAL_CFLAGS += -w -Wno-error -DSQLITE_ENABLE_FTS3 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -DSQLITE_TEMP_STORE=1
# LOCAL_ALLOW_UNDEFINED_SYMBOLS :=true
include $(BUILD_STATIC_LIBRARY)

View File

@@ -0,0 +1,4 @@
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_PLATFORM := android-21
APP_CPPFLAGS += -fexceptions -frtti
APP_STL := c++_shared

View File

@@ -0,0 +1,5 @@
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_PLATFORM := android-21
APP_CPPFLAGS += -fexceptions -frtti
APP_STL := c++_shared
HOST_TAG64 := windows

View File

@@ -0,0 +1,25 @@
#!/bin/sh
ndk=/home/superdad/Public/android-ndk-r21d
$ndk/ndk-build clean
$ndk/ndk-build all
bindir=./obj/local
targetdir=./../../../static/i386-android
cp $bindir/x86/libsqlite3.a $targetdir/libsqlite3.a
cp $ndk/toolchains/x86-4.9/prebuilt/linux-x86_64/lib/gcc/i686-linux-android/4.9.x/libgcc.a $targetdir/libgcc.a
targetdir=./../../../static/x86_64-android
cp $bindir/x86_64/libsqlite3.a $targetdir/libsqlite3.a
cp $ndk/toolchains/x86_64-4.9/prebuilt/linux-x86_64/lib/gcc/x86_64-linux-android/4.9.x/libgcc.a $targetdir/libgcc.a
targetdir=./../../../static/arm-android
cp $bindir/armeabi-v7a/libsqlite3.a $targetdir/libsqlite3.a
cp $ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a $targetdir/libgcc.a
# cp $ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a/libgcc.a $targetdir/libgcc.a
targetdir=./../../../static/aarch64-android
cp $bindir/arm64-v8a/libsqlite3.a $targetdir/libsqlite3.a
cp $ndk/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a $targetdir/libgcc.a

View File

@@ -0,0 +1,50 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Android sqlite buildscript for Windows
@rem Builds the mORMot sqlite static libraries with the Android NDK
@rem Please set the path towards the NDK
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem set ndk=C:\Users\Public\Documents\Embarcadero\Studio\17.0\PlatformSDKs\android-ndk-r10e
@rem set gccverextension=
@rem set ndk=C:\Users\Alfred\AppData\Local\Android\android-ndk-r19c
@rem set ndk=C:\Users\Alfred\AppData\Local\Android\android-ndk-r20b
set ndk=C:\Users\Alfred\AppData\Local\Android\Sdk\ndk\21.1.6352462
set gccverextension=.x
set path=%ndk%;%path%
@rem echo path
call %ndk%\ndk-build.cmd clean
call %ndk%\ndk-build.cmd all
set bindir=.\obj\local
set targetdir=.\..\..\..\static\i386-android
copy %bindir%\x86\libsqlite3.a %targetdir%\libsqlite3.a
copy %ndk%\toolchains\x86-4.9\prebuilt\windows-x86_64\lib\gcc\i686-linux-android\4.9.x\libgcc.a %targetdir%\libgcc.a
set targetdir=.\..\..\..\static\x86_64-android
copy %bindir%\x86_64\libsqlite3.a %targetdir%\libsqlite3.a
copy %ndk%\toolchains\x86_64-4.9\prebuilt\windows-x86_64\lib\gcc\x86_64-linux-android\4.9.x\libgcc.a %targetdir%\libgcc.a
set targetdir=.\..\..\..\static\arm-android
copy %bindir%\armeabi-v7a\libsqlite3.a %targetdir%\libsqlite3.a
copy %ndk%\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.9.x\libgcc.a %targetdir%\libgcc.a
@rem copy %ndk%\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.9.x\armv7-a\libgcc.a %targetdir%\libgcc.a
set targetdir=.\..\..\..\static\aarch64-android
copy %bindir%\arm64-v8a\libsqlite3.a %targetdir%\libsqlite3.a
copy %ndk%\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\lib\gcc\aarch64-linux-android\4.9.x\libgcc.a %targetdir%\libgcc.a
if "%OS%"=="Windows_NT" endlocal
pause

View File

@@ -0,0 +1,544 @@
/*
** Refactored from https://github.com/utelle/SQLite3MultipleCiphers
** Original MIT License - (c) 2006-2020 Ulrich Telle
*/
/*
** Include a "special" version of the VACUUM command
** (not needed with our fixed page-size algorithm)
*/
// #include "rekeyvacuum.c"
/*
** Include "multi-cipher" algorithms
** (not included in our Synopse-specific encryption)
*/
// #include "cipher_common.h"
SQLITE_API void
sqlite3_activate_see(const char *info)
{
}
/*
** Our Synopse-specific algorithm don't append anything to the page size
*/
SQLITE_PRIVATE int
sqlite3mcGetPageSize(Codec* codec)
{
return codec->m_btShared->pageSize;
}
/*
** Free the encryption data structure associated with a pager instance.
** (called from the modified code in pager.c)
*/
SQLITE_PRIVATE void
sqlite3mcCodecFree(void *pCodecArg)
{
if (pCodecArg)
{
CodecTerm(pCodecArg);
sqlite3_free(pCodecArg);
pCodecArg = NULL;
}
}
SQLITE_PRIVATE void
mcReportCodecError(BtShared* pBt, int error)
{
pBt->pPager->errCode = error;
setGetterMethod(pBt->pPager);
pBt->db->errCode = error;
}
/*
// Encrypt/Decrypt functionality, called by pager.c
*/
SQLITE_PRIVATE void*
sqlite3mcCodec(void* pCodecArg, void* data, Pgno nPageNum, int nMode)
{
int rc = SQLITE_OK;
Codec* codec = NULL;
int pageSize;
if (pCodecArg == NULL)
{
return data;
}
codec = (Codec*) pCodecArg;
if (!CodecIsEncrypted(codec))
{
return data;
}
pageSize = sqlite3mcGetPageSize(codec);
switch(nMode)
{
case 0: /* Undo a "case 7" journal file encryption */
case 2: /* Reload a page */
case 3: /* Load a page */
if (CodecHasReadKey(codec))
{
rc = CodecDecrypt(codec, nPageNum, (unsigned char*) data, pageSize);
if (rc != SQLITE_OK) mcReportCodecError(CodecGetBtShared(codec), rc);
}
break;
case 6: /* Encrypt a page for the main database file */
if (CodecHasWriteKey(codec))
{
unsigned char* pageBuffer = CodecGetPageBuffer(codec);
memcpy(pageBuffer, data, pageSize);
data = pageBuffer;
rc = CodecEncrypt(codec, nPageNum, (unsigned char*) data, pageSize, 1);
if (rc != SQLITE_OK) mcReportCodecError(CodecGetBtShared(codec), rc);
}
break;
case 7: /* Encrypt a page for the journal file */
/* Under normal circumstances, the readkey is the same as the writekey. However,
when the database is being rekeyed, the readkey is not the same as the writekey.
The rollback journal must be written using the original key for the
database file because it is, by nature, a rollback journal.
Therefore, for case 7, when the rollback is being written, always encrypt using
the database's readkey, which is guaranteed to be the same key that was used to
read the original data.
*/
if (CodecHasReadKey(codec))
{
unsigned char* pageBuffer = CodecGetPageBuffer(codec);
memcpy(pageBuffer, data, pageSize);
data = pageBuffer;
rc = CodecEncrypt(codec, nPageNum, (unsigned char*) data, pageSize, 0);
if (rc != SQLITE_OK) mcReportCodecError(CodecGetBtShared(codec), rc);
}
break;
}
return data;
}
/* some prototypes of functions implemented in sqlite3mc_vfs.c */
SQLITE_PRIVATE Codec*
sqlite3mcGetMainCodec(sqlite3* db);
SQLITE_PRIVATE Codec*
sqlite3mcGetCodec(sqlite3* db, const char* zDbName);
SQLITE_PRIVATE void
sqlite3mcSetCodec(sqlite3* db, const char* zFileName, Codec* codec);
SQLITE_PRIVATE int
sqlite3mcCodecAttach(sqlite3* db, int nDb, const char* zPath, const void* zKey, int nKey)
{
/* Attach a key to a database. */
Codec* codec = (Codec*) sqlite3_malloc(sizeof(Codec));
int rc = (codec != NULL) ? CodecInit(codec) : SQLITE_NOMEM;
if (rc != SQLITE_OK)
{
/* Unable to allocate memory for the codec base structure */
return rc;
}
sqlite3_mutex_enter(db->mutex);
CodecSetDb(codec, db);
/* No key specified, could mean either use the main db's encryption or no encryption */
if (zKey == NULL || nKey <= 0)
{
/* No key specified */
if (nDb != 0 && nKey > 0)
{
/* Main database possibly encrypted, no key explicitly given for attached database */
Codec* mainCodec = sqlite3mcGetMainCodec(db);
/* Attached database, therefore use the key of main database, if main database is encrypted */
if (mainCodec != NULL && CodecIsEncrypted(mainCodec))
{
rc = CodecCopyCipher(codec, mainCodec);
if (rc == SQLITE_OK)
{
CodecSetBtree(codec, db->aDb[nDb].pBt);
zPath = sqlite3_db_filename(db, db->aDb[nDb].zDbSName);
sqlite3mcSetCodec(db, zPath, codec);
}
else
{
/* Replicating main codec failed, do not attach incomplete codec */
sqlite3mcCodecFree(codec);
}
}
else
{
/* Main database not encrypted */
sqlite3mcCodecFree(codec);
}
}
else
{
/* Main database not encrypted, no key given for attached database */
sqlite3mcCodecFree(codec);
}
}
else
{
/* Key specified, setup encryption key for database */
CodecSetIsEncrypted(codec, 1);
CodecSetHasReadKey(codec, 1);
CodecSetHasWriteKey(codec, 1);
CodecGenerateReadKey(codec, (char*) zKey, nKey);
CodecCopyKey(codec, 1);
CodecSetBtree(codec, db->aDb[nDb].pBt);
zPath = sqlite3_db_filename(db, db->aDb[nDb].zDbSName);
sqlite3mcSetCodec(db, zPath, codec);
}
sqlite3_mutex_leave(db->mutex);
return rc;
}
SQLITE_PRIVATE void
sqlite3mcCodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey)
{
/*
** The unencrypted password is not stored for security reasons
** therefore always return NULL
** If the main database is encrypted a key length of 1 is returned.
** In that case an attached database will get the same encryption key
** as the main database if no key was explicitly given for the attached database.
*/
Codec* codec = sqlite3mcGetCodec(db, db->aDb[nDb].zDbSName);
int keylen = (codec != NULL && CodecIsEncrypted(codec)) ? 1 : 0;
*zKey = NULL;
*nKey = keylen;
}
SQLITE_API int
sqlite3_rekey_v2(sqlite3 *db, const char *zDbName, const void *zKey, int nKey)
{
/* Changes the encryption key for an existing database. */
int rc = SQLITE_ERROR;
int nPagesize;
Pager* pPager;
Codec* codec;
Btree* pBt;
const char* dbFileName = sqlite3_db_filename(db, zDbName);
int dbIndex = (zDbName) ? sqlite3FindDbName(db, zDbName) : 0;
if (dbIndex < 0)
{
return rc;
}
pBt = db->aDb[dbIndex].pBt;
nPagesize = sqlite3BtreeGetPageSize(pBt);
if (zKey != NULL && nKey < 0)
{
/* Key is zero-terminated string */
nKey = sqlite3Strlen30(zKey);
}
pPager = sqlite3BtreePager(pBt);
codec = sqlite3mcGetCodec(db, zDbName);
if ((zKey == NULL || nKey == 0) && (codec == NULL || !CodecIsEncrypted(codec)))
{
/* Database not encrypted and key not specified, therefore do nothing */
return SQLITE_OK;
}
sqlite3_mutex_enter(db->mutex);
if (codec == NULL || !CodecIsEncrypted(codec))
{
/* Database not encrypted, but key specified, therefore encrypt database */
if (codec == NULL)
{
codec = (Codec*) sqlite3_malloc(sizeof(Codec));
rc = (codec != NULL) ? CodecInit(codec) : SQLITE_NOMEM;
}
if (rc == SQLITE_OK)
{
CodecSetIsEncrypted(codec, 1);
CodecSetHasReadKey(codec, 0); /* Original database is not encrypted */
CodecSetHasWriteKey(codec, 1);
CodecGenerateWriteKey(codec, (char*) zKey, nKey);
CodecSetDb(codec, db);
CodecSetBtree(codec, pBt);
sqlite3mcSetCodec(db, dbFileName, codec);
}
else
{
return rc;
}
}
else if (zKey == NULL || nKey == 0)
{
/* Database encrypted, but key not specified, therefore decrypt database */
/* Keep read key, drop write key */
CodecSetHasWriteKey(codec, 0);
}
else
{
/* Database encrypted and key specified, therefore re-encrypt database with new key */
/* Keep read key, change write key to new key */
CodecGenerateWriteKey(codec, (char*) zKey, nKey);
CodecSetHasWriteKey(codec, 1);
}
/* Start transaction */
#if (SQLITE_VERSION_NUMBER >= 3025000)
rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
#else
rc = sqlite3BtreeBeginTrans(pBt, 1);
#endif
if (!rc)
{
int pageSize = sqlite3BtreeGetPageSize(pBt);
Pgno nSkip = WX_PAGER_MJ_PGNO(pageSize);
#if (SQLITE_VERSION_NUMBER >= 3003014)
DbPage *pPage;
#else
void *pPage;
#endif
Pgno n;
/* Rewrite all pages using the new encryption key (if specified) */
#if (SQLITE_VERSION_NUMBER >= 3007001)
Pgno nPage;
int nPageCount = -1;
sqlite3PagerPagecount(pPager, &nPageCount);
nPage = nPageCount;
#elif (SQLITE_VERSION_NUMBER >= 3006000)
int nPageCount = -1;
int rc = sqlite3PagerPagecount(pPager, &nPageCount);
Pgno nPage = (Pgno) nPageCount;
#elif (SQLITE_VERSION_NUMBER >= 3003014)
Pgno nPage = sqlite3PagerPagecount(pPager);
#else
Pgno nPage = sqlite3pager_pagecount(pPager);
#endif
for (n = 1; rc == SQLITE_OK && n <= nPage; n++)
{
if (n == nSkip) continue;
#if (SQLITE_VERSION_NUMBER >= 3010000)
rc = sqlite3PagerGet(pPager, n, &pPage, 0);
#elif (SQLITE_VERSION_NUMBER >= 3003014)
rc = sqlite3PagerGet(pPager, n, &pPage);
#else
rc = sqlite3pager_get(pPager, n, &pPage);
#endif
if (!rc)
{
#if (SQLITE_VERSION_NUMBER >= 3003014)
rc = sqlite3PagerWrite(pPage);
sqlite3PagerUnref(pPage);
#else
rc = sqlite3pager_write(pPage);
sqlite3pager_unref(pPage);
#endif
}
}
}
if (rc == SQLITE_OK)
{
/* Commit transaction if all pages could be rewritten */
rc = sqlite3BtreeCommit(pBt);
}
if (rc != SQLITE_OK)
{
/* Rollback in case of error */
#if (SQLITE_VERSION_NUMBER >= 3008007)
/* Unfortunately this change was introduced in version 3.8.7.2 which cannot be detected using the SQLITE_VERSION_NUMBER */
/* That is, compilation will fail for version 3.8.7 or 3.8.7.1 ==> Please change manually ... or upgrade to 3.8.7.2 or higher */
sqlite3BtreeRollback(pBt, SQLITE_OK, 0);
#elif (SQLITE_VERSION_NUMBER >= 3007011)
sqlite3BtreeRollback(pbt, SQLITE_OK);
#else
sqlite3BtreeRollback(pbt);
#endif
}
sqlite3_mutex_leave(db->mutex);
if (rc == SQLITE_OK)
{
/* Set read key equal to write key if necessary */
if (CodecHasWriteKey(codec))
{
CodecCopyKey(codec, 0);
CodecSetHasReadKey(codec, 1);
}
else
{
CodecSetIsEncrypted(codec, 0);
}
}
else
{
/* Restore write key if necessary */
if (CodecHasReadKey(codec))
{
CodecCopyKey(codec, 1);
}
else
{
CodecSetIsEncrypted(codec, 0);
}
}
if (!CodecIsEncrypted(codec))
{
/* Remove codec for unencrypted database */
sqlite3mcSetCodec(db, zDbName, NULL);
}
return rc;
}
SQLITE_API int
sqlite3_key_v2(sqlite3 *db, const char *zDbName, const void *zKey, int nKey)
{
int rc = SQLITE_ERROR;
int dbIndex;
if (zKey != NULL && nKey < 0)
{
/* Key is zero-terminated string */
nKey = sqlite3Strlen30(zKey);
}
if ((db != NULL) && (zKey != NULL) && (nKey > 0))
{
const char* dbFileName = sqlite3_db_filename(db, zDbName);
/* The key is only set for the main database, not the temp database */
dbIndex = (zDbName) ? sqlite3FindDbName(db, zDbName) : 0;
if (dbIndex >= 0)
{
rc = sqlite3mcCodecAttach(db, dbIndex, dbFileName, zKey, nKey);
}
else
{
rc = SQLITE_ERROR;
}
}
return rc;
}
SQLITE_API int
sqlite3_key(sqlite3 *db, const void *zKey, int nKey)
{
/* The key is only set for the main database, not the temp database */
return sqlite3_key_v2(db, "main", zKey, nKey);
}
SQLITE_API int
sqlite3_rekey(sqlite3 *db, const void *zKey, int nKey)
{
return sqlite3_rekey_v2(db, "main", zKey, nKey);
}
/*
** Functions called from patched SQLite version
*/
SQLITE_PRIVATE int
sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg)
{
int rc = sqlite3_file_control(db, zDbName, op, pArg);
/* not implemented: handle cipher pragmas */
return rc;
}
/*
** Process URI filename query parameters relevant to the SQLite Encryption
** Extension. Return true if any of the relevant query parameters are
** seen and return false if not.
*/
SQLITE_PRIVATE int
sqlite3mcCodecQueryParameters(sqlite3* db, const char* zDb, const char* zUri)
{
int rc = 1;
const char* zKey;
if ((zKey = sqlite3_uri_parameter(zUri, "hexkey")) != 0 && zKey[0])
{
u8 iByte;
int i;
char zDecoded[40];
for (i = 0, iByte = 0; i < sizeof(zDecoded) * 2 && sqlite3Isxdigit(zKey[i]); i++)
{
iByte = (iByte << 4) + sqlite3HexToInt(zKey[i]);
if ((i & 1) != 0) zDecoded[i / 2] = iByte;
}
sqlite3_key_v2(db, zDb, zDecoded, i / 2);
}
else if ((zKey = sqlite3_uri_parameter(zUri, "key")) != 0)
{
sqlite3_key_v2(db, zDb, zKey, sqlite3Strlen30(zKey));
}
else if ((zKey = sqlite3_uri_parameter(zUri, "textkey")) != 0)
{
sqlite3_key_v2(db, zDb, zKey, -1);
}
else
{
rc = 0;
}
return rc;
}
SQLITE_PRIVATE int
sqlite3mcHandleAttachKey(sqlite3* db, const char* zName, const char* zPath, sqlite3_value* pKey, char** zErrDyn)
{
int rc = SQLITE_OK;
int nKey;
char* zKey;
int keyType = sqlite3_value_type(pKey);
switch (keyType)
{
case SQLITE_INTEGER:
case SQLITE_FLOAT:
/* Invalid data type for key */
*zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
rc = SQLITE_ERROR;
break;
case SQLITE_TEXT:
case SQLITE_BLOB:
/* Key parameter specified in ATTACH statement */
nKey = sqlite3_value_bytes(pKey);
zKey = (char*) sqlite3_value_blob(pKey);
rc = sqlite3mcCodecAttach(db, db->nDb - 1, zPath, zKey, nKey);
break;
case SQLITE_NULL:
/* No key specified. Use the key from URI filename, or if none,
** use the key from the main database. */
if (sqlite3mcCodecQueryParameters(db, zName, zPath) == 0)
{
/* this is buggy and leaks memory - will use the key from main DB anyway
see https://github.com/utelle/SQLite3MultipleCiphers/issues/10
sqlite3mcCodecGetKey(db, 0, (void**) &zKey, &nKey);
if (nKey)
{
rc = sqlite3mcCodecAttach(db, db->nDb - 1, zPath, zKey, nKey);
}
*/
}
break;
}
return rc;
}
SQLITE_PRIVATE int
sqlite3mcHandleMainKey(sqlite3* db, const char* zPath)
{
int rc = SQLITE_OK;
/* Not implemented: implement URI cipher parameters */
return rc;
}

View File

@@ -0,0 +1,18 @@
@echo off
attrib -r ..\sqlite3.obj
del ..\sqlite3.obj
set bcc=d:\dev\DelphiXE7
rem set bcc=d:\dev\bcc
echo ---------------------------------------------------
echo Compiling for Delphi Win32 using %bcc%
%bcc%\bin\bcc32 -6 -Oi -O2 -c -d -u- sqlite3mc.c
copy sqlite3mc.obj ..\sqlite3.obj
del sqlite3mc.obj
attrib +r ..\sqlite3.obj
rem pause

View File

@@ -0,0 +1,17 @@
@echo off
attrib -r ..\sqlite3.o
del ..\sqlite3.o
set bcc=d:\dev\DelphiXE7
rem set bcc=d:\Dev\bcc64ce
echo ---------------------------------------------------
echo Compiling for Delphi Win64 using %bcc%
%bcc%\bin\bcc64 -isystem "%bcc%\include" -isystem "%bcc%\include\windows\sdk" -isystem "%bcc%\include\dinkumware64" -isystem "%bcc%\include\windows\crtl" -O2 -c -DWIN64 sqlite3mc.c
copy sqlite3mc.o ..\sqlite3.o
del sqlite3mc.o
attrib +r ..\sqlite3.o
rem pause

View File

@@ -0,0 +1,17 @@
#!/bin/sh
ARCH=aarch64-linux
CROSS=/home/ab/fpcup/cross/bin/$ARCH
GCC=$CROSS/$ARCH-gcc
DST=../../static/$ARCH/sqlite3.o
rm $DST
rm sqlite3-$ARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $ARCH using $GCC
$GCC -static -O1 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$ARCH.o
cp sqlite3-$ARCH.o $DST

View File

@@ -0,0 +1,17 @@
#!/bin/sh
ARCH=arm-linux
CROSS=/home/ab/fpcup/cross/bin/$ARCH
GCC=$CROSS/arm-linux-gnueabihf-gcc
DST=../../static/$ARCH/sqlite3.o
rm $DST
rm sqlite3-$ARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $ARCH using $GCC
$GCC -static -O1 -marm -march=armv7-a+fp -I$CROSS/include -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -D__ARM_PCS_VFP -mfloat-abi=hard -c sqlite3mc.c -o sqlite3-$ARCH.o
cp sqlite3-$ARCH.o $DST

View File

@@ -0,0 +1,19 @@
#!/bin/sh
ARCH=i386-darwin
DST=../../static/$ARCH/sqlite3.o
CROSS=/home/ab/fpcup/cross
SDK=$CROSS/lib/x86-darwin/MacOSX10.11.sdk\usr
GCC=$CROSS/bin/x86-darwin/i386-apple-darwin15
rm $DST
rm sqlite3-$ARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $ARCH using $GCC
$GCC-clang -static -target i386-apple-darwin15 -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -I$SDK/include -c sqlite3mc.c -o sqlite3-$ARCH.o
cp sqlite3-$ARCH.o $DST
$GCC-libtool -static sqlite3-$ARCH.o -o ../../static/$ARCH/libsqlite3.a

View File

@@ -0,0 +1,17 @@
#!/bin/sh
FPCARCH=i386-freebsd
FPCARCHVERSION=12
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
DST=../../static/$FPCARCH/sqlite3.o
rm $DST
rm sqlite3-$FPCARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $FPCARCH using $GCC
$GCC -static -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
cp sqlite3-$FPCARCH.o $DST

View File

@@ -0,0 +1,20 @@
@echo off
rem Use FpcUpDeluxe cross-compiler toolchain since native GCC generates dependency on newer libc version (e.g. compiled on Ubuntu 20.04 can't link on Ubuntu 18.04).
set FPCARCH=i386-linux
set GCCPATH=d:\fpcup\__win\bin\%FPCARCH%
set GCC=%FPCARCH%-gcc
set DST=..\..\static\%FPCARCH%\sqlite3.o
set path=%path%;%GCCPATH%
del %DST%
del sqlite3-%FPCARCH%.o
echo.
echo ---------------------------------------------------
echo Compiling for FPC on %FPCARCH% using %GCC%
%GCC% -static -w -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-%FPCARCH%.o
copy sqlite3-%FPCARCH%.o %DST%
rem pause

View File

@@ -0,0 +1,15 @@
#!/bin/sh
FPCARCH=i386-linux
GCC=gcc-7
DST=../../static/$FPCARCH/sqlite3.o
rm $DST
rm sqlite3-$FPCARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $FPCARCH using $GCC
$GCC -static -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
cp sqlite3-$FPCARCH.o $DST

View File

@@ -0,0 +1,17 @@
#!/bin/sh
FPCARCH=i386-openbsd
FPCARCHVERSION=
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
DST=../../static/$FPCARCH/sqlite3.o
rm $DST
rm sqlite3-$FPCARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $FPCARCH using $GCC
$GCC -static -O2 -m32 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
cp sqlite3-$FPCARCH.o $DST

View File

@@ -0,0 +1,15 @@
#!/bin/sh
ARCH=i386-win32
GCC=i686-w64-mingw32-gcc
DST=../../static/$ARCH/sqlite3.o
rm $DST
rm sqlite3-$ARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $ARCH using $GCC
$GCC -O2 -m32 -DWIN32 -DNDEBUG -D_WINDOWS -c sqlite3mc.c -o sqlite3-$ARCH.o
cp sqlite3-$ARCH.o $DST

View File

@@ -0,0 +1,19 @@
#!/bin/sh
ARCH=x86_64-darwin
DST=../../static/$ARCH/sqlite3.o
CROSS=/home/ab/fpcup/cross
SDK=$CROSS/lib/x86-darwin/MacOSX10.11.sdk\usr
GCC=$CROSS/bin/x86-darwin/x86_64-apple-darwin15
rm $DST
rm sqlite3-$ARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $ARCH using $GCC
$GCC-clang -static -target x86_64-apple-darwin15 -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -I$SDK/include -c sqlite3mc.c -o sqlite3-$ARCH.o
cp sqlite3-$ARCH.o $DST
$GCC-libtool -static sqlite3-$ARCH.o -o ../../static/$ARCH/libsqlite3.a

View File

@@ -0,0 +1,17 @@
#!/bin/sh
FPCARCH=x86_64-freebsd
FPCARCHVERSION=12
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
DST=../../static/$FPCARCH/sqlite3.o
rm $DST
rm sqlite3-$FPCARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $FPCARCH using $GCC
$GCC -static -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
cp sqlite3-$FPCARCH.o $DST

View File

@@ -0,0 +1,20 @@
@echo off
rem Use FpcUpDeluxe cross-compiler toolchain since native GCC generates dependency on newer libc version (e.g. compiled on Ubuntu 20.04 can't link on Ubuntu 18.04).
set FPCARCH=x86_64-linux
set GCCPATH=d:\fpcup\__win\bin\%FPCARCH%
set GCC=%FPCARCH%-gcc
set DST=..\..\static\%FPCARCH%\sqlite3.o
set path=%path%;%GCCPATH%
del %DST%
del sqlite3-%FPCARCH%.o
echo.
echo ---------------------------------------------------
echo Compiling for FPC on %FPCARCH% using %GCC%
%GCC% -static -w -O2 -fno-pic -fno-stack-protector -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-%FPCARCH%.o
copy sqlite3-%FPCARCH%.o %DST%
rem pause

View File

@@ -0,0 +1,15 @@
#!/bin/sh
FPCARCH=x86_64-linux
GCC=gcc-7
DST=../../static/$FPCARCH/sqlite3.o
rm $DST
rm sqlite3-$FPCARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $FPCARCH using $GCC
$GCC -static -fno-pic -fno-stack-protector -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
cp sqlite3-$FPCARCH.o $DST

View File

@@ -0,0 +1,17 @@
#!/bin/sh
FPCARCH=x86_64-openbsd
FPCARCHVERSION=
CROSS=/home/ab/fpcup/cross/bin/$FPCARCH
GCC=$CROSS/$FPCARCH$FPCARCHVERSION-gcc
DST=../../static/$FPCARCH/sqlite3.o
rm $DST
rm sqlite3-$FPCARCH.o
echo
echo ---------------------------------------------------
echo Compiling for FPC on $FPCARCH using $GCC
$GCC -static -O2 -m64 -DNDEBUG -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -c sqlite3mc.c -o sqlite3-$FPCARCH.o
cp sqlite3-$FPCARCH.o $DST

View File

@@ -0,0 +1,27 @@
#!/bin/sh
ARCH=x86_64-win64
GCC=x86_64-w64-mingw32-gcc
STATIC=../../static/$ARCH
DST=$STATIC/sqlite3.o
rm $DST
rm sqlite3-$ARCH.o
echo
echo ---------------------------------------------------
echo Compiling static for FPC on $ARCH using $GCC
$GCC -O2 -static -DWIN64 -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -m64 -DNDEBUG -D_WINDOWS -c sqlite3mc.c -o sqlite3-$ARCH.o
cp sqlite3-$ARCH.o $DST
DLL=sqlite3-64.dll
rm $DLL
rm $STATIC/$DLL
echo
echo ---------------------------------------------------
echo Compiling $DLL using $GCC
$GCC -O2 -shared -DSQLITE_MMAP_READWRITE -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS4 -DDSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_DESERIALIZE -DWIN64 -DNDEBUG -D_WINDOWS -D_USRDLL -DNO_TCL -D_CRT_SECURE_NO_DEPRECATE -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_THREADSAFE=1 -DTEMP_STORE=1 -m64 sqlite3.c -o $DLL -Wl,--out-implib,libsqlite3-64.a
cp $DLL $STATIC
cp libsqlite3-64.a $STATIC

View File

@@ -0,0 +1,51 @@
#!/bin/sh
echo Patch SQLite3 sources
rm sqlite3patched.c
./patchsqlite3.sh >sqlite3patched.c
# ./compile-fpc-i386-linux.sh
# ./compile-fpc-x86_64-linux.sh
echo
echo Use Wine BC++ compilers for Delphi Win32/Win64
wine cmd /c compile-delphi-win32.bat
wine cmd /c compile-delphi-win64.bat
echo
echo Use Wine fpcupdeluxe cross-compilers for FPC Linux i386/x64
wine cmd /c compile-fpc-i386-linux.bat
wine cmd /c compile-fpc-x86_64-linux.bat
echo
echo Use Native cross-compilers for FPC Win32/Win64
./compile-fpc-i386-win32.sh
./compile-fpc-x86_64-win64.sh
echo
echo Use Native fpcupdeluxe cross-compilers for FPC Darwin
./compile-fpc-i386-darwin.sh
./compile-fpc-x86_64-darwin.sh
echo
echo Use Native fpcupdeluxe cross-compilers for FPC Linux arm/aarch64-linux
./compile-fpc-arm-linux.sh
./compile-fpc-aarch64-linux.sh
echo
echo Use Native fpcupdeluxe cross-compilers for FPC FreeBSD i386/x64
./compile-fpc-i386-freebsd.sh
./compile-fpc-x86_64-freebsd.sh
echo
echo Use Native fpcupdeluxe cross-compilers for FPC OpenBSD i386/x64
./compile-fpc-i386-openbsd.sh
./compile-fpc-x86_64-openbsd.sh

View File

@@ -0,0 +1,22 @@
#!/bin/sh
# Generate patched sqlite3.c from SQLite3 amalgamation and write it to stdout.
# Usage: ./script/patchsqlite3.sh sqlite3.c >sqlite3patched.c
INPUT="$([ "$#" -eq 1 ] && echo "$1" || echo "sqlite3.c")"
if ! [ -f "$INPUT" ]; then
echo "Usage: $0 <SQLITE3_AMALGAMATION>" >&2
echo " e.g.: $0 sqlite3.c" >&2
exit 1
fi
die() {
echo "[-]" "$@" >&2
exit 2
}
# 1) Intercept VFS pragma handling
# 2) Add handling of KEY parameter in ATTACH statements
sed 's/sqlite3_file_control\(.*SQLITE_FCNTL_PRAGMA\)/sqlite3mcFileControlPragma\1/' "$INPUT" \
| sed '/\#endif \/\* SQLITE3\_H \*\//a \ \n\/\* Function prototypes of SQLite3 Multiple Ciphers \*\/\nSQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*);\nSQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);\nSQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*);' \
| sed '/sqlite3_free_filename( zPath );/i \\n \/\* Handle KEY parameter. \*\/\n if( rc==SQLITE_OK ){\n rc = sqlite3mcHandleAttachKey(db, zName, zPath, argv[2], &zErrDyn);\n }' \
| sed '/sqlite3_free_filename(zOpen);/i \\n \/\* Handle encryption related URI parameters. \*\/\n if( rc==SQLITE_OK ){\n rc = sqlite3mcHandleMainKey(db, zOpen);\n }'

View File

@@ -0,0 +1,269 @@
/*
** Wrapper around SQlite3 amalgamation file with proper options and code
**
** Please download and put sqlite3.c in amalgamation/ sub-folder
** from https://sqlite.org/download.html
** then run ./patch.sh
*/
/*
** Define all symbols expected by SynSQLite3Static.pas
**
** See also https://www.sqlite.org/compile.html#recommended_compile_time_options
*/
#define SQLITE_DEFAULT_MEMSTATUS 0
// don't need any debug here, and don't even define sqlite3_status()
#define SQLITE_THREADSAFE 1
// assuming multi-thread safety is made by caller - in our framework, there is
// only one thread using the database connection at the same time, but there could
// be multiple database connection at the same time (previous was 0 could be unsafe)
// - this option is also needed by codecext.c
#define SQLITE_OMIT_SHARED_CACHE 1
// no need of shared cache in a threadsafe calling model
#define SQLITE_OMIT_AUTOINIT 1
// sqlite3_initialize() is done in unit initialization -> no AUTOINIT
#define SQLITE_OMIT_DEPRECATED 1
// spare some code size
#define SQLITE_LIKE_DOESNT_MATCH_BLOBS 1
// historical function, never used
#define SQLITE_ENABLE_FTS3 1
#define SQLITE_ENABLE_FTS3_PARENTHESIS 1
#define SQLITE_ENABLE_FTS4 1
#define SQLITE_ENABLE_FTS5 1
// enable all FTS engines
#define SQLITE_ENABLE_RBU 1
// "Resumable Bulk Update" (or OTA) is not used/published yet
#define SQLITE_ENABLE_JSON1 1
// add JSON extension
#define SQLITE_MAX_EXPR_DEPTH 0
// no SQL depth limit, since we trust the input and expect the best performance
#define SQLITE_OMIT_LOAD_EXTENSION 1
// we don't need/allow extension in an embedded engine
#define SQLITE_OMIT_COMPILEOPTION_DIAGS 1
// we don't need Compilation Options Diagnostics in our embedded engine
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
// we don't need sqlite3_progress_handler() API function
#define SQLITE_ENABLE_RTREE 1
// the RTREE extension is now (from v.1.8/3.7) compiled into the engine
#define SQLITE_ENABLE_DESERIALIZE
// enables sqlite3_serialize() and sqlite3_deserialize()
/*
** Define function for extra initilization
**
** The extra initialization function registers an extension function
** which will be automatically executed for each new database connection.
*/
#define SQLITE_EXTRA_INIT sqlite3mc_initialize
#define SQLITE_EXTRA_SHUTDOWN sqlite3mc_terminate
/*
** Compile the official SQLite3 amalgamation file
*/
#if defined(__BORLANDC__)
#define __STDC__ 1
#endif
#if defined(__BORLANDC__)
#undef __STDC__
#endif
#include "sqlite3patched.c"
// to be downloaded from https://sqlite.org/download.html
// then execute ./patch.sh to apply Codec patches
/*
** Handle Database Ciphering
** adapted from https://github.com/utelle/SQLite3MultipleCiphers patches
** wxWindows Library Licence, Version 3.1
*/
/*
** Define the Codec types as needed by codecext.c
**
*/
#define WX_PAGER_MJ_PGNO(x) ((PENDING_BYTE/(x))+1)
// ATTENTION: Macro similar to that in pager.c
#define KEYLENGTH 304
// match maximum possible AESContextSize, with 8 bytes alignment
// We embed two SynCrypto's TAES objects in the Codec struct
typedef struct _Codec
{
/* Defined if this DB is encrypted */
int m_isEncrypted;
/* Read cipher */
int m_hasReadKey;
unsigned char m_readKey[KEYLENGTH];
/* Write cipher */
int m_hasWriteKey;
unsigned char m_writeKey[KEYLENGTH];
/* Pointers to DB and its B-trees */
sqlite3* m_db;
Btree* m_bt;
BtShared* m_btShared;
/* Temporary memory buffer used during AES process */
unsigned char m_page[SQLITE_MAX_PAGE_SIZE + 24];
} Codec;
static int CodecInit(Codec* codec)
{
int rc = SQLITE_OK;
if (codec != NULL)
{
codec->m_isEncrypted = 0;
codec->m_hasReadKey = 0;
codec->m_hasWriteKey = 0;
codec->m_db = 0;
codec->m_bt = 0;
codec->m_btShared = 0;
}
else
{
rc = SQLITE_NOMEM;
}
return rc;
}
static void CodecCopyKey(Codec* codec, int read2write)
{
if (read2write)
{
memcpy(&codec->m_writeKey, &codec->m_readKey, KEYLENGTH);
}
else
{
memcpy(&codec->m_readKey, &codec->m_writeKey, KEYLENGTH);
}
}
static int CodecCopyCipher(Codec* codec, Codec* other)
{
codec->m_isEncrypted = other->m_isEncrypted;
codec->m_hasReadKey = other->m_hasReadKey;
codec->m_hasWriteKey = other->m_hasWriteKey;
memcpy(&codec->m_readKey, &other->m_readKey, KEYLENGTH);
memcpy(&codec->m_writeKey, &other->m_writeKey, KEYLENGTH);
return SQLITE_OK;
}
// implemented in pascal using SynCrypto optimized AES functions
extern void CodecGenerateReadKey(Codec* codec, char* userPassword, int passwordLength);
extern void CodecGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength);
extern int CodecEncrypt(Codec* codec, int page, unsigned char* data, int len, int useWriteKey);
extern int CodecDecrypt(Codec* codec, int page, unsigned char* data, int len);
extern int CodecTerm(Codec* codec);
// used by SynSQlite3Static to retrieve the PAES members from a given codec
unsigned char* CodecGetReadKey(Codec* codec)
{
return codec->m_readKey;
}
unsigned char* CodecGetWriteKey(Codec* codec)
{
return codec->m_writeKey;
}
static void CodecSetIsEncrypted(Codec* codec, int isEncrypted)
{
codec->m_isEncrypted = isEncrypted;
}
static void CodecSetHasReadKey(Codec* codec, int hasReadKey)
{
codec->m_hasReadKey = hasReadKey;
}
static void CodecSetHasWriteKey(Codec* codec, int hasWriteKey)
{
codec->m_hasWriteKey = hasWriteKey;
}
static int CodecIsEncrypted(Codec* codec)
{
return codec->m_isEncrypted;
}
static int CodecHasReadKey(Codec* codec)
{
return codec->m_hasReadKey;
}
static int CodecHasWriteKey(Codec* codec)
{
return codec->m_hasWriteKey;
}
static void CodecSetDb(Codec* codec, sqlite3* db)
{
codec->m_db = db;
}
static void CodecSetBtree(Codec* codec, Btree* bt)
{
codec->m_bt = bt;
codec->m_btShared = bt->pBt;
}
static Btree* CodecGetBtree(Codec* codec)
{
return codec->m_bt;
}
static BtShared* CodecGetBtShared(Codec* codec)
{
return codec->m_btShared;
}
static unsigned char* CodecGetPageBuffer(Codec* codec)
{
return &codec->m_page[4];
}
#include "codecext.c"
/*
** Multi cipher VFS
*/
SQLITE_API const char* sqlite3mc_vfs_name();
SQLITE_API void sqlite3mc_vfs_terminate();
SQLITE_API int sqlite3mc_vfs_initialize(sqlite3_vfs* vfsDefault, int makeDefault);
#include "sqlite3mc_vfs.c"
int
sqlite3mc_initialize(const char* arg)
{
int rc = SQLITE_OK;
sqlite3_vfs* vfsDefault;
/*
** Initialize and register MultiCipher VFS as default VFS
** if it isn't already registered
*/
if (sqlite3_vfs_find(sqlite3mc_vfs_name()) == NULL)
{
vfsDefault = sqlite3_vfs_find("unix-excl");
/* WAL requires unix-excl so we force it as default on posix */
if (vfsDefault == NULL)
{
vfsDefault = sqlite3_vfs_find(NULL);
}
rc = sqlite3mc_vfs_initialize(vfsDefault, 1);
}
return rc;
}
void
sqlite3mc_terminate(void)
{
sqlite3mc_vfs_terminate();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
/*
** Name: sqlite3mc_vfs.h
** Purpose: Header file for VFS of SQLite3 Multiple Ciphers support
** Author: Ulrich Telle
** Created: 2020-03-01
** Copyright: (c) 2020 Ulrich Telle
** License: MIT
*/
#ifndef SQLITE3MC_VFS_H_
#include <stdlib.h>
#include <stdint.h>
SQLITE_API const char* sqlite3mc_vfs_name();
SQLITE_API void sqlite3mc_vfs_terminate();
SQLITE_API int sqlite3mc_vfs_initialize(sqlite3_vfs* vfsDefault, int makeDefault);
#endif /* SQLITE3MC_VFS_H_ */