Skip to content

Commit 4bc6ba0

Browse files
Initial work on a PRAGMA cipher_migrate
Swapping of the Btree meta data is not working properly now.
1 parent 6cd1fdf commit 4bc6ba0

3 files changed

Lines changed: 82 additions & 0 deletions

File tree

src/crypto.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c
8989

9090
CODEC_TRACE(("codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx));
9191

92+
if( sqlite3StrICmp(zLeft, "cipher_migrate")==0 && !zRight ){
93+
if(ctx){
94+
char *migrate_status = sqlite3_mprintf("%d", sqlcipher_codec_ctx_migrate(ctx));
95+
codec_vdbe_return_static_string(pParse, "sqlcipher_migrate", migrate_status);
96+
sqlite3_free(migrate_status);
97+
}
98+
} else
9299
if( sqlite3StrICmp(zLeft, "cipher_provider")==0 && !zRight ){
93100
if(ctx) { codec_vdbe_return_static_string(pParse, "cipher_provider",
94101
sqlcipher_codec_get_cipher_provider(ctx));

src/crypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag);
209209
int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag, int for_ctx);
210210

211211
const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx);
212+
int sqlcipher_codec_ctx_migrate(codec_ctx *ctx);
212213
#endif
213214
#endif
214215
/* END SQLCIPHER */

src/crypto_impl.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,5 +867,79 @@ const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx) {
867867
return ctx->read_ctx->provider->get_provider_name(ctx->read_ctx);
868868
}
869869

870+
int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
871+
u32 meta;
872+
int rc = 0;
873+
int command_idx = 0;
874+
sqlite3 *db = ctx->pBt->db;
875+
const char *db_filename = sqlite3_db_filename(db, "main");
876+
const char *migrated_db_filename = sqlite3_mprintf("%s-migrated", db_filename);
877+
const char *key = ctx->read_ctx->pass;
878+
int db_idx = db->nDb;
879+
CODEC_TRACE(("current database count:%d\n", db_idx));
880+
if(db_filename){
881+
char *attach_command = sqlite3_mprintf("ATTACH DATABASE '%s-migrated' as migrate KEY '%s';",
882+
db_filename, key);
883+
const char *commands[] = {
884+
"PRAGMA kdf_iter = '4000';",
885+
attach_command,
886+
"SELECT sqlcipher_export('migrate');",
887+
};
888+
for(command_idx = 0; command_idx < ArraySize(commands); command_idx++){
889+
const char *command = commands[command_idx];
890+
rc = sqlite3_exec(db, command, NULL, NULL, NULL);
891+
if(rc != SQLITE_OK){
892+
break;
893+
}
894+
}
895+
sqlite3_free(attach_command);
896+
if(rc == SQLITE_OK){
897+
898+
static const unsigned char aCopy[] = {
899+
BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */
900+
BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */
901+
BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */
902+
BTREE_USER_VERSION, 0, /* Preserve the user version */
903+
BTREE_APPLICATION_ID, 0, /* Preserve the application id */
904+
};
905+
906+
CODEC_TRACE(("current database count:%d\n", db->nDb));
907+
Btree *pDest = db->aDb[0].pBt;
908+
Btree *pSrc = db->aDb[db->nDb-1].pBt;
909+
910+
CODEC_TRACE(("pSrc is '%p'\n", (void*)pSrc));
911+
CODEC_TRACE(("pDest is '%p'\n", (void*)pDest));
912+
913+
//rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
914+
rc = sqlite3BtreeBeginTrans(pSrc, 2);
915+
rc = sqlite3BtreeBeginTrans(pDest, 2);
916+
917+
assert( 1==sqlite3BtreeIsInTrans(pDest) );
918+
assert( 1==sqlite3BtreeIsInTrans(pSrc) );
919+
920+
CODEC_TRACE(("before metadata copy\n"));
921+
int i = 0;
922+
for(i=0; i<ArraySize(aCopy); i+=2){
923+
sqlite3BtreeGetMeta(pSrc, aCopy[i], &meta);
924+
rc = sqlite3BtreeUpdateMeta(pDest, aCopy[i], meta+aCopy[i+1]);
925+
if( NEVER(rc!=SQLITE_OK) ) goto handle_error;
926+
}
927+
rc = sqlite3BtreeCopyFile(pSrc, pDest);
928+
if( rc!=SQLITE_OK ) goto handle_error;
929+
rc = sqlite3BtreeCommit(pDest);
930+
rc = sqlite3_exec(db, "DETACH DATABASE migrate;", NULL, NULL, NULL);
931+
remove(migrated_db_filename);
932+
}
933+
sqlite3_free(migrated_db_filename);
934+
}
935+
goto exit;
936+
937+
handle_error:
938+
CODEC_TRACE(("An error occurred\n"));
939+
940+
exit:
941+
return rc;
942+
}
943+
870944
#endif
871945
/* END SQLCIPHER */

0 commit comments

Comments
 (0)