static void file_exists(sqlite3_context *ctx, int argc, sqlite3_value **argv) { char fpath[MAXPATHLEN]; sqlite3 *db = sqlite3_context_db_handle(ctx); char *path = dirname(sqlite3_db_filename(db, "main")); char cksum[SHA256_DIGEST_LENGTH * 2 +1]; if (argc != 2) { sqlite3_result_error(ctx, "file_exists needs two argument", -1); return; } snprintf(fpath, sizeof(fpath), "%s/%s", path, sqlite3_value_text(argv[0])); if (access(fpath, R_OK) == 0) { sha256_file(fpath, cksum); if (strcmp(cksum, sqlite3_value_text(argv[1])) == 0) sqlite3_result_int(ctx, 1); else sqlite3_result_int(ctx, 0); } else { sqlite3_result_int(ctx, 0); } }
void SqliteDatabase::runWal () { int log = 0, ckpt = 0; int ret = sqlite3_wal_checkpoint_v2 (mConnection, nullptr, SQLITE_CHECKPOINT_PASSIVE, &log, &ckpt); if (ret != SQLITE_OK) { WriteLog ((ret == SQLITE_LOCKED) ? lsTRACE : lsWARNING, SqliteDatabase) << "WAL(" << sqlite3_db_filename (mConnection, "main") << "): error " << ret; } else WriteLog (lsTRACE, SqliteDatabase) << "WAL(" << sqlite3_db_filename (mConnection, "main") << "): frames=" << log << ", written=" << ckpt; { ScopedLockType sl (m_walMutex); walRunning = false; } }
static void reportDbCorruption(Repo& repo, int repoId, const std::string& where) { std::string report = folly::sformat("{} returned SQLITE_CORRUPT.\n", where); auto repoPath = sqlite3_db_filename(repo.dbc(), repo.dbName(repoId)); if (repoPath) { report += folly::sformat("Path: '{}'\n", repoPath); struct stat repoStat; if (stat(repoPath, &repoStat) == 0) { time_t now = time(nullptr); report += folly::sformat("{} bytes, c_age: {}, m_age: {}\n", repoStat.st_size, now - repoStat.st_ctime, now - repoStat.st_mtime); } else { report += "stat() failed\n"; } } else { report += "sqlite3_db_filename() returned nullptr\n"; } // Use raw SQLite here because we just want to hit the raw DB itself. sqlite3_exec(repo.dbc(), folly::sformat( "PRAGMA {}.integrity_check(4);", repo.dbName(repoId)).c_str(), [](void* _report, int columns, char** text, char** names) { std::string& report = *reinterpret_cast<std::string*>(_report); for (int column = 0; column < columns; ++column) { report += folly::sformat("Integrity Check ({}): {}\n", column, text[column]); } return 0; }, &report, nullptr); Logger::Error(report); }
int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) { u32 meta; int rc = 0; int command_idx = 0; int password_sz; int saved_flags; int saved_nChange; int saved_nTotalChange; void (*saved_xTrace)(void*,const char*); Db *pDb = 0; sqlite3 *db = ctx->pBt->db; const char *db_filename = sqlite3_db_filename(db, "main"); char *migrated_db_filename = sqlite3_mprintf("%s-migrated", db_filename); char *pragma_hmac_off = "PRAGMA cipher_use_hmac = OFF;"; char *pragma_4k_kdf_iter = "PRAGMA kdf_iter = 4000;"; char *pragma_1x_and_4k; char *set_user_version; char *key; int key_sz; int user_version = 0; int upgrade_1x_format = 0; int upgrade_4k_format = 0; static const unsigned char aCopy[] = { BTREE_SCHEMA_VERSION, 1, /* Add one to the old schema cookie */ BTREE_DEFAULT_CACHE_SIZE, 0, /* Preserve the default page cache size */ BTREE_TEXT_ENCODING, 0, /* Preserve the text encoding */ BTREE_USER_VERSION, 0, /* Preserve the user version */ BTREE_APPLICATION_ID, 0, /* Preserve the application id */ }; key_sz = ctx->read_ctx->pass_sz + 1; key = sqlcipher_malloc(key_sz); memset(key, 0, key_sz); memcpy(key, ctx->read_ctx->pass, ctx->read_ctx->pass_sz); if(db_filename){ const char* commands[5]; char *attach_command = sqlite3_mprintf("ATTACH DATABASE '%s-migrated' as migrate KEY '%q';", db_filename, key); int rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, "", &user_version); if(rc == SQLITE_OK){ CODEC_TRACE(("No upgrade required - exiting\n")); goto exit; } // Version 2 - check for 4k with hmac format rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_4k_kdf_iter, &user_version); if(rc == SQLITE_OK) { CODEC_TRACE(("Version 2 format found\n")); upgrade_4k_format = 1; } // Version 1 - check both no hmac and 4k together pragma_1x_and_4k = sqlite3_mprintf("%s%s", pragma_hmac_off, pragma_4k_kdf_iter); rc = sqlcipher_check_connection(db_filename, key, ctx->read_ctx->pass_sz, pragma_1x_and_4k, &user_version); sqlite3_free(pragma_1x_and_4k); if(rc == SQLITE_OK) { CODEC_TRACE(("Version 1 format found\n")); upgrade_1x_format = 1; upgrade_4k_format = 1; } if(upgrade_1x_format == 0 && upgrade_4k_format == 0) { CODEC_TRACE(("Upgrade format not determined\n")); goto handle_error; } set_user_version = sqlite3_mprintf("PRAGMA migrate.user_version = %d;", user_version); commands[0] = upgrade_4k_format == 1 ? pragma_4k_kdf_iter : ""; commands[1] = upgrade_1x_format == 1 ? pragma_hmac_off : ""; commands[2] = attach_command; commands[3] = "SELECT sqlcipher_export('migrate');"; commands[4] = set_user_version; for(command_idx = 0; command_idx < ArraySize(commands); command_idx++){ const char *command = commands[command_idx]; if(strcmp(command, "") == 0){ continue; } rc = sqlite3_exec(db, command, NULL, NULL, NULL); if(rc != SQLITE_OK){ break; } } sqlite3_free(attach_command); sqlite3_free(set_user_version); sqlcipher_free(key, key_sz); if(rc == SQLITE_OK){ Btree *pDest; Btree *pSrc; int i = 0; if( !db->autoCommit ){ CODEC_TRACE(("cannot migrate from within a transaction")); goto handle_error; } if( db->nVdbeActive>1 ){ CODEC_TRACE(("cannot migrate - SQL statements in progress")); goto handle_error; } /* Save the current value of the database flags so that it can be ** restored before returning. Then set the writable-schema flag, and ** disable CHECK and foreign key constraints. */ saved_flags = db->flags; saved_nChange = db->nChange; saved_nTotalChange = db->nTotalChange; saved_xTrace = db->xTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin; db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder); db->xTrace = 0; pDest = db->aDb[0].pBt; pDb = &(db->aDb[db->nDb-1]); pSrc = pDb->pBt; rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL); rc = sqlite3BtreeBeginTrans(pSrc, 2); rc = sqlite3BtreeBeginTrans(pDest, 2); assert( 1==sqlite3BtreeIsInTrans(pDest) ); assert( 1==sqlite3BtreeIsInTrans(pSrc) ); sqlite3CodecGetKey(db, db->nDb - 1, (void**)&key, &password_sz); sqlite3CodecAttach(db, 0, key, password_sz); sqlite3pager_get_codec(pDest->pBt->pPager, (void**)&ctx); ctx->skip_read_hmac = 1; for(i=0; i<ArraySize(aCopy); i+=2){ sqlite3BtreeGetMeta(pSrc, aCopy[i], &meta); rc = sqlite3BtreeUpdateMeta(pDest, aCopy[i], meta+aCopy[i+1]); if( NEVER(rc!=SQLITE_OK) ) goto handle_error; } rc = sqlite3BtreeCopyFile(pDest, pSrc); ctx->skip_read_hmac = 0; if( rc!=SQLITE_OK ) goto handle_error; rc = sqlite3BtreeCommit(pDest); db->flags = saved_flags; db->nChange = saved_nChange; db->nTotalChange = saved_nTotalChange; db->xTrace = saved_xTrace; db->autoCommit = 1; if( pDb ){ sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; } sqlite3ResetAllSchemasOfConnection(db); remove(migrated_db_filename); sqlite3_free(migrated_db_filename); } else { CODEC_TRACE(("*** migration failure** \n\n")); } } goto exit; handle_error: CODEC_TRACE(("An error occurred attempting to migrate the database\n")); rc = SQLITE_ERROR; exit: return rc; }
static void trace_callback(void * arg, const char * query) { CallbackData * d = static_cast<CallbackData*>(arg); std::string n(sqlite3_db_filename(d->db_, "main")); d->tortured_databases_.push_back(n); }