From 646f00ed04fea2f08a584268d1467b3dc7fc91b9 Mon Sep 17 00:00:00 2001 From: "jk.koo" Date: Fri, 6 Mar 2020 15:49:56 +0900 Subject: [PATCH] Add db integrity check Change-Id: Ie46ee7fe48510d9034455e652a40adb1e84037cf Signed-off-by: jk.koo --- packaging/contacts-service.spec | 2 +- server/ctsvc_schema_recovery.c | 105 ++++++++++++++++++++++++++++------- server/ctsvc_server_group.c | 2 +- server/ctsvc_server_sqlite.c | 118 ++++++++++++++++++++++++++-------------- server/ctsvc_server_sqlite.h | 2 +- server/db/ctsvc_db_schema.h | 5 +- 6 files changed, 168 insertions(+), 66 deletions(-) diff --git a/packaging/contacts-service.spec b/packaging/contacts-service.spec index e5ca4d7..67a3a00 100644 --- a/packaging/contacts-service.spec +++ b/packaging/contacts-service.spec @@ -1,6 +1,6 @@ Name: contacts-service Summary: Contacts Service -Version: 0.13.75 +Version: 0.13.76 Release: 0 Group: Social & Content/Service License: Apache-2.0 diff --git a/server/ctsvc_schema_recovery.c b/server/ctsvc_schema_recovery.c index 17aa3d8..adeb6ac 100644 --- a/server/ctsvc_schema_recovery.c +++ b/server/ctsvc_schema_recovery.c @@ -51,7 +51,7 @@ static inline int __ctsvc_server_remake_db_file() char *errmsg = NULL; sqlite3 *db = NULL; - ret = ctsvc_server_db_open(&db); + ret = ctsvc_server_db_open(&db, NULL); RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret); ret = sqlite3_exec(db, schema_query, NULL, 0, &errmsg); @@ -67,49 +67,114 @@ static inline int __ctsvc_server_remake_db_file() return CONTACTS_ERROR_NONE; } -static int __ctsvc_server_check_table() +static bool need_to_remove = false; +static int __integrity_callback(void *pid, int argc, char **argv, char **notUsed2) { - int ret; + CTS_FN_CALL; + + if (NULL == argv || NULL == argv[0]) { + ERR("Invalid parameter"); + need_to_remove = true; + return -1; + } + + if (0 != strcmp(argv[0], "ok")) { + ERR("integrity_check() Fail(argv[%s])", argv[0]); + need_to_remove = true; + return -1; + } + + DBG("integrity_check done"); + return 0; +} + +static int __ctsvc_server_check_db_integrity(void) +{ + CTS_FN_CALL; + int ret = 0; sqlite3 *db = NULL; - char query[CTS_SQL_MAX_LEN] = {0}; cts_stmt stmt = NULL; + int sqlite_error = SQLITE_OK; - ret = ctsvc_server_db_open(&db); - RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret); + ret = ctsvc_server_db_open(&db, &sqlite_error); + if (CONTACTS_ERROR_NONE != ret) { + /* LCOV_EXCL_START */ + ERR("ctsvc_server_db_open() Fail(%d), sqlite_error(%d)", ret, sqlite_error); + if (SQLITE_ERROR == sqlite_error ||SQLITE_CORRUPT == sqlite_error ||SQLITE_NOTADB == sqlite_error) + return -1; + else + return 0; + /* LCOV_EXCL_STOP */ + } + + ret = sqlite3_exec(db, "pragma integrity_check", __integrity_callback, NULL, NULL); + if (true == need_to_remove || SQLITE_ERROR == ret || SQLITE_CORRUPT == ret || SQLITE_NOTADB == ret) { + /* LCOV_EXCL_START */ + ERR("need_to_remove [%s], ret [%d]", need_to_remove ? "true" : "false", ret); + need_to_remove = false; + return -1; + /* LCOV_EXCL_STOP */ + } - snprintf(query, sizeof(query), - "SELECT name FROM sqlite_master WHERE type='table' AND name='%s'", - CTS_TABLE_CONTACTS); + /* check if table is missing */ + const char *query = "SELECT count(*) FROM sqlite_master WHERE type='table'" + " AND name IN ('persons','addressbooks','contacts','contact_deleteds','cts_version' ," + "'sdn','data','groups','group_deleteds','group_relations','speeddials','favorites','sim_info'," + "'phonelogs','phonelog_stat','contact_stat','activities','activity_photos','search_index','name_lookup','phone_lookup','my_profiles')"; ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); if (SQLITE_OK != ret) { /* LCOV_EXCL_START */ - ERR("sqlite3_prepare_v2(%s) Fail(%s)", query, sqlite3_errmsg(db)); - ctsvc_server_db_close(); - return CONTACTS_ERROR_DB; + ERR("sqlite3_qlite3_prepare_v2() Fail(%d)", ret); + if (SQLITE_ERROR == ret ||SQLITE_CORRUPT == ret ||SQLITE_NOTADB == ret) + return -1; + else + return 0; /* LCOV_EXCL_STOP */ } ret = sqlite3_step(stmt); if (SQLITE_ROW != ret) { /* LCOV_EXCL_START */ - ERR("contacts table does not exist in contacts DB file : %s", sqlite3_errmsg(db)); + ERR("sqlite3_step() Fail(%d)", ret); sqlite3_finalize(stmt); - ctsvc_server_db_close(); - return CTSVC_ERR_NO_TABLE; + if (SQLITE_ERROR == ret ||SQLITE_CORRUPT == ret ||SQLITE_NOTADB == ret) + return -1; + else + return 0; /* LCOV_EXCL_STOP */ } + int get_count = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); - ctsvc_server_db_close(); - return CONTACTS_ERROR_NONE; + + if (get_count != CTS_SCHEMA_TABLE_TOTAL) { + /* LCOV_EXCL_START */ + ERR("Table is missing(expected(%d) but result(%d)", CTS_SCHEMA_TABLE_TOTAL, get_count); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; } int ctsvc_server_check_schema(void) { - if (CTSVC_ERR_NO_DB_FILE == __ctsvc_server_check_db_file()) - __ctsvc_server_remake_db_file(); - else if (CTSVC_ERR_NO_TABLE == __ctsvc_server_check_table()) + if (CONTACTS_ERROR_NONE != __ctsvc_server_check_db_file() + || 0 != __ctsvc_server_check_db_integrity()) + { + ERR("Need to remove and remake db files"); + + ctsvc_server_db_close(); + + if (remove(CTSVC_DB_SHM_FILE) != 0) + ERR("Failed to remove CTSVC_DB_SHM_FILE"); + if (remove(CTSVC_DB_WAL_FILE) != 0) + ERR("Failed to remove CTSVC_DB_WAL_FILE"); + if (remove(CTSVC_DB_PATH) !=0) + ERR("Failed to remove CTSVC_DB_PATH"); + __ctsvc_server_remake_db_file(); + } return CONTACTS_ERROR_NONE; } diff --git a/server/ctsvc_server_group.c b/server/ctsvc_server_group.c index 9c228d3..e7eb4b4 100644 --- a/server/ctsvc_server_group.c +++ b/server/ctsvc_server_group.c @@ -44,7 +44,7 @@ int ctsvc_group_add_contact_in_transaction(int group_id, int contact_id) ret = ctsvc_query_get_first_int_result(query, &exist); if (CONTACTS_ERROR_NONE != ret) { - DBG("ctsvc_query_get_first_int_result fail(%d)"); + DBG("ctsvc_query_get_first_int_result fail(%d)", ret); return ret; } if (1 == exist) { diff --git a/server/ctsvc_server_sqlite.c b/server/ctsvc_server_sqlite.c index 73bcecf..8b21c73 100644 --- a/server/ctsvc_server_sqlite.c +++ b/server/ctsvc_server_sqlite.c @@ -53,51 +53,85 @@ static sqlite3 *server_db; -int ctsvc_server_db_open(sqlite3 **db) +int ctsvc_server_db_open(sqlite3 **db, int *sqlite_error) { CTS_FN_CALL; int ret; if (NULL == server_db) { - ret = db_util_open(CTSVC_DB_PATH, &server_db, 0); - RETVM_IF(ret != SQLITE_OK || NULL == server_db, CONTACTS_ERROR_DB, - "db_util_open() Fail(%d), server_db(%s)", ret, sqlite3_errmsg(server_db)); - - ret = sqlite3_create_function(server_db, "_DATA_DELETE_", 2, SQLITE_UTF8, NULL, - ctsvc_db_data_delete_callback, NULL, NULL); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_function() Fail(%d)", ret); - ret = sqlite3_create_function(server_db, "_DATA_IMAGE_DELETE_", 1, SQLITE_UTF8, NULL, - ctsvc_db_image_delete_callback, NULL, NULL); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_function() Fail(%d)", ret); - ret = sqlite3_create_function(server_db, "_DATA_COMPANY_DELETE_", 1, SQLITE_UTF8, NULL, - ctsvc_db_company_delete_callback, NULL, NULL); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_function() Fail(%d)", ret); + do { + ret = db_util_open(CTSVC_DB_PATH, &server_db, 0); + if (ret != SQLITE_OK || NULL == server_db) { + ERR("db_util_open() Fail(%d), server_db(%s)", ret, sqlite3_errmsg(server_db)); + break; + } + + ret = sqlite3_create_function(server_db, "_DATA_DELETE_", 2, SQLITE_UTF8, NULL, + ctsvc_db_data_delete_callback, NULL, NULL); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_function() Fail(%d)", ret); + break; + } + + ret = sqlite3_create_function(server_db, "_DATA_IMAGE_DELETE_", 1, SQLITE_UTF8, NULL, + ctsvc_db_image_delete_callback, NULL, NULL); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_function() Fail(%d)", ret); + break; + } + + ret = sqlite3_create_function(server_db, "_DATA_COMPANY_DELETE_", 1, SQLITE_UTF8, NULL, + ctsvc_db_company_delete_callback, NULL, NULL); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_function() Fail(%d)", ret); + break; + } + #ifdef ENABLE_LOG_FEATURE - ret = sqlite3_create_function(server_db, "_PHONE_LOG_DELETE_", 1, SQLITE_UTF8, NULL, - ctsvc_db_phone_log_delete_callback, NULL, NULL); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_function() Fail(%d)", ret); + ret = sqlite3_create_function(server_db, "_PHONE_LOG_DELETE_", 1, SQLITE_UTF8, NULL, + ctsvc_db_phone_log_delete_callback, NULL, NULL); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_function() Fail(%d)", ret); + break; + } #endif /* ENABLE_LOG_FEATURE */ - ret = sqlite3_create_function(server_db, "_PERSON_DELETE_", 1, SQLITE_UTF8, NULL, - ctsvc_db_person_delete_callback, NULL, NULL); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_function() Fail(%d)", ret); - ret = sqlite3_create_function(server_db, "_GROUP_DELETE_", 1, SQLITE_UTF8, NULL, - ctsvc_db_group_delete_callback, NULL, NULL); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_function() Fail(%d)", ret); - ret = sqlite3_create_function(server_db, "_NUMBER_COMPARE_", 4, SQLITE_UTF8, NULL, - ctsvc_db_phone_number_equal_callback, NULL, NULL); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_function() Fail(%d)", ret); - ret = sqlite3_create_collation(server_db, "_NAME_SORT_", SQLITE_UTF8, (void *)SQLITE_UTF8, - ctsvc_db_group_name_sort_callback); - RETVM_IF(SQLITE_OK != ret, CONTACTS_ERROR_DB, - "sqlite3_create_collation() Fail(%d)", ret); + + ret = sqlite3_create_function(server_db, "_PERSON_DELETE_", 1, SQLITE_UTF8, NULL, + ctsvc_db_person_delete_callback, NULL, NULL); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_function() Fail(%d)", ret); + break; + } + + ret = sqlite3_create_function(server_db, "_GROUP_DELETE_", 1, SQLITE_UTF8, NULL, + ctsvc_db_group_delete_callback, NULL, NULL); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_function() Fail(%d)", ret); + break; + } + + ret = sqlite3_create_function(server_db, "_NUMBER_COMPARE_", 4, SQLITE_UTF8, NULL, + ctsvc_db_phone_number_equal_callback, NULL, NULL); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_function() Fail(%d)", ret); + break; + } + + ret = sqlite3_create_collation(server_db, "_NAME_SORT_", SQLITE_UTF8, (void *)SQLITE_UTF8, + ctsvc_db_group_name_sort_callback); + if (SQLITE_OK != ret) { + ERR("sqlite3_create_collation() Fail(%d)", ret); + break; + } + } while (0); + + if (ret != SQLITE_OK || NULL == server_db) { + if (sqlite_error) + *sqlite_error = ret; + return CONTACTS_ERROR_DB; + } } + if (db) *db = server_db; return CONTACTS_ERROR_NONE; @@ -190,7 +224,7 @@ int ctsvc_server_update_sort(int prev_sort_primary, int prev_sort_secondary, int char *errmsg = NULL; char query[CTS_SQL_MIN_LEN] = {0}; - ret = ctsvc_server_db_open(&db); + ret = ctsvc_server_db_open(&db, NULL); RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret); ret = ctsvc_server_begin_trans(); @@ -329,7 +363,7 @@ int ctsvc_server_insert_sdn_contact(const char *name, const char *number, sqlite3_stmt *stmt = NULL; char query[CTS_SQL_MIN_LEN] = {0}; - ret = ctsvc_server_db_open(&db); + ret = ctsvc_server_db_open(&db, NULL); RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_server_db_open() Fail(%d)", ret); snprintf(query, sizeof(query), "INSERT INTO %s(name, number, sim_slot_no) VALUES(?, ?, ?)", @@ -370,7 +404,7 @@ int ctsvc_server_delete_sdn_contact(int sim_slot_no) sqlite3_stmt *stmt = NULL; char query[CTS_SQL_MAX_LEN] = {0}; - ret = ctsvc_server_db_open(&db); + ret = ctsvc_server_db_open(&db, NULL); RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "helper_db_open() Fail(%d)", ret); if (sim_slot_no < 0) @@ -411,7 +445,7 @@ int ctsvc_server_update_collation() ctsvc_db_set_status(CONTACTS_DB_STATUS_CHANGING_COLLATION); - ret = ctsvc_server_db_open(&db); + ret = ctsvc_server_db_open(&db, NULL); if (CONTACTS_ERROR_NONE != ret) { /* LCOV_EXCL_START */ ERR("ctsvc_server_db_open() Fail(%d)", ret); @@ -699,7 +733,7 @@ int ctsvc_server_update_sort_name() ctsvc_db_set_status(CONTACTS_DB_STATUS_CHANGING_COLLATION); - ret = ctsvc_server_db_open(&db); + ret = ctsvc_server_db_open(&db, NULL); if (CONTACTS_ERROR_NONE != ret) { /* LCOV_EXCL_START */ ERR("ctsvc_server_db_open() Fail(%d)", ret); diff --git a/server/ctsvc_server_sqlite.h b/server/ctsvc_server_sqlite.h index d8faaa3..d5c4d1c 100644 --- a/server/ctsvc_server_sqlite.h +++ b/server/ctsvc_server_sqlite.h @@ -21,7 +21,7 @@ #include -int ctsvc_server_db_open(sqlite3 **db); +int ctsvc_server_db_open(sqlite3 **db, int *sqlite_error); int ctsvc_server_db_close(void); int ctsvc_server_update_sort(int prev_sort_primary, int prev_sort_secondary, int new_sort_primary, int new_sort_secondary); int ctsvc_server_insert_sdn_contact(const char *name, const char *number, int sim_slot_no); diff --git a/server/db/ctsvc_db_schema.h b/server/db/ctsvc_db_schema.h index 00d14e6..8439a2c 100644 --- a/server/db/ctsvc_db_schema.h +++ b/server/db/ctsvc_db_schema.h @@ -22,13 +22,16 @@ #include #define CTSVC_DB_PATH tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db") +#define CTSVC_DB_SHM_FILE tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db-shm") +#define CTSVC_DB_WAL_FILE tzplatform_mkpath(TZ_USER_DB, "privacy/.contacts-svc.db-wal") /* For Security */ #define CTS_SECURITY_FILE_GROUP 5000 #define CTS_SECURITY_DEFAULT_PERMISSION 0666 #define CTS_SECURITY_DIR_DEFAULT_PERMISSION 0770 -#define CTS_SCHEMA_TABLE_TOTAL 10 +/* MUST MACTH table count */ +#define CTS_SCHEMA_TABLE_TOTAL 22 /* DB Tables */ #define CTS_TABLE_PERSONS "persons" -- 2.7.4