static int prv_bind_triple_update(sqlite3_stmt *statement, const char *key, const char *prop, const char *value) { int sqlerr; DMC_ERR_MANAGE; sqlerr = sqlite3_bind_text(statement, 1, key, -1, SQLITE_STATIC); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_bind_text(statement, 2, prop, -1, SQLITE_STATIC); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_bind_text(statement, 3, value, -1, SQLITE_STATIC); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_step(statement); if (sqlerr == SQLITE_OK) DMC_ERR = DMC_ERR_IO; else if (sqlerr != SQLITE_DONE) DMC_ERR = map_sqlite3_error(sqlerr); DMC_ON_ERR: sqlite3_reset(statement); sqlite3_clear_bindings(statement); return DMC_ERR; }
static int prv_open_database(const char *datastore, int flags, dmsettings **handle) { DMC_ERR_MANAGE; dmsettings *settings; int sqlerr; DMC_FAIL_NULL(settings, malloc(sizeof(*settings)), DMC_ERR_OOM); memset(settings, 0, sizeof(*settings)); sqlerr = sqlite3_open_v2(datastore, &settings->db_handle, flags, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_busy_timeout(settings->db_handle, DMSETTINGS_BUSY_TIMEOUT); DMC_FAIL(map_sqlite3_error(sqlerr)); *handle = settings; return DMC_ERR_NONE; DMC_ON_ERR: free(settings); return DMC_ERR; }
static int prv_bind_double_query(sqlite3_stmt *statement, const char *key, const char *param) { int sqlerr; DMC_ERR_MANAGE; sqlerr = sqlite3_bind_text(statement, 1, key, -1, SQLITE_STATIC); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_bind_text(statement, 2, param, -1, SQLITE_STATIC); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_step(statement); if (sqlerr == SQLITE_OK) DMC_ERR = DMC_ERR_IO; else if (sqlerr == SQLITE_DONE) DMC_ERR = DMC_ERR_NOT_FOUND; else if (sqlerr != SQLITE_ROW) DMC_ERR = map_sqlite3_error(sqlerr); DMC_ON_ERR: return DMC_ERR; }
static int prv_delete_generic(dmsettings *handle, const char *key, const char *parent) { DMC_ERR_MANAGE; DMC_FAIL(prv_bind_double_update(handle->stmt_delete_explicit, key, key)); if (sqlite3_changes(handle->db_handle) <= 0) DMC_FAIL_FORCE(DMC_ERR_NOT_FOUND); DMC_FAIL(prv_bind_double_update(handle->stmt_delete_meta, key, key)); if (parent) { DMC_ERR = dmsettings_create_dir(handle, parent); if (DMC_ERR != DMC_ERR_ALREADY_EXISTS) DMC_FAIL(DMC_ERR); else DMC_ERR = DMC_ERR_NONE; } DMC_ON_ERR: return DMC_ERR; }
static int prv_find_children(dmsettings *handle, const char *key, dmc_ptr_array *children) { DMC_ERR_MANAGE; const char *full_child; char *child_copy = NULL; unsigned int i; int sqlerr; for (i = 1; i <= 3; ++i) { sqlerr = sqlite3_bind_text(handle->stmt_find_children, i, key, -1, SQLITE_STATIC); DMC_FAIL(map_sqlite3_error(sqlerr)); } sqlerr = sqlite3_step(handle->stmt_find_children); if (sqlerr == SQLITE_OK) DMC_FAIL_FORCE(DMC_ERR_IO); while (sqlerr == SQLITE_ROW) { full_child = (const char *) sqlite3_column_text(handle->stmt_find_children, 0); if (full_child) DMC_FAIL(prv_process_child(full_child, children, &child_copy)); sqlerr = sqlite3_step(handle->stmt_find_children); } if (sqlerr != SQLITE_DONE) DMC_FAIL_FORCE(sqlerr); if (child_copy) { DMC_FAIL(dmc_ptr_array_append(children, child_copy)); child_copy = NULL; } DMC_ON_ERR: if (child_copy) free(child_copy); sqlite3_reset(handle->stmt_find_children); sqlite3_clear_bindings(handle->stmt_find_children); return DMC_ERR; }
int dmsettings_get_meta(dmsettings *handle, const char *key, const char *prop, char **value) { DMC_ERR_MANAGE; const char *text_sqlite3; char *text_copy; DMC_FAIL(prv_bind_double_query(handle->stmt_get_meta, key, prop)); text_sqlite3 = (const char*) sqlite3_column_text(handle->stmt_get_meta, 0); if (text_sqlite3) DMC_FAIL_NULL(text_copy, strdup(text_sqlite3), DMC_ERR_OOM); else DMC_FAIL_FORCE(DMC_ERR_NOT_FOUND); *value = text_copy; DMC_ON_ERR: sqlite3_reset(handle->stmt_get_meta); sqlite3_clear_bindings(handle->stmt_get_meta); return DMC_ERR; }
int dmsettings_open_database(const char *datastore, dmsettings **handle) { DMC_ERR_MANAGE; dmsettings *settings; DMC_FAIL(prv_open_database(datastore, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, &settings)); DMC_FAIL_LABEL(prv_create_database(settings), db_opened); DMC_FAIL_LABEL(prv_create_ro_queries(settings), db_opened); DMC_FAIL_LABEL(prv_create_rw_queries(settings), db_opened); settings->can_write = true; *handle = settings; return DMC_ERR_NONE; db_opened: dmsettings_close(settings); DMC_ON_ERR: return DMC_ERR; }
static int prv_process_child(const char *new_child, dmc_ptr_array *children, char **child_copy) { DMC_ERR_MANAGE; const char *child; uintptr_t name_length; if ((child = strchr(new_child, '/'))) name_length = child - new_child; else name_length = strlen(new_child); if (*child_copy) { if (strncmp(new_child, *child_copy, name_length)) { DMC_FAIL(dmc_ptr_array_append(children, *child_copy)); DMC_FAIL_NULL(*child_copy, strndup(new_child, name_length), DMC_ERR_OOM); } } else DMC_FAIL_NULL(*child_copy, strndup(new_child, name_length), DMC_ERR_OOM); DMC_ON_ERR: return DMC_ERR; }
static int prv_create_database(dmsettings *handle) { DMC_ERR_MANAGE; DMC_FAIL(map_sqlite3_error(sqlite3_exec(handle->db_handle, DM_SETTINGS_CREATE_DATA, NULL, NULL, NULL))); DMC_FAIL(map_sqlite3_error(sqlite3_exec(handle->db_handle, DM_SETTINGS_CREATE_META, NULL, NULL, NULL))); DMC_ON_ERR: return DMC_ERR; }
int dmsettings_delete(dmsettings *handle, const char *key) { DMC_ERR_MANAGE; char *parent = NULL; const char *parent_path = NULL; char *tok; if (!key) DMC_FAIL_FORCE(DMC_ERR_BAD_ARGS); if (!handle->can_write) DMC_FAIL_FORCE(DMC_ERR_DENIED); DMC_FAIL_NULL(parent, strdup(key), DMC_ERR_OOM); tok = strrchr(parent,'/'); if (tok) { *tok = 0; if (strchr(parent,'/')) parent_path = parent; } /* * If parent_path is not NULL then we need to ensure that this node * exists in the explicit table. Otherwise the act of deleting a node * will delete some of its ancestors as well. */ if (handle->transaction_in_progress) DMC_FAIL(prv_delete_in_transaction(handle, key, parent_path)); else DMC_FAIL(prv_delete_out_transaction(handle, key, parent_path)); DMC_ON_ERR: free(parent); return DMC_ERR; }
int dmsettings_get_children(dmsettings *handle, const char *key, dmc_ptr_array *children) { DMC_ERR_MANAGE; if (!key) DMC_FAIL_FORCE(DMC_ERR_BAD_ARGS); DMC_FAIL(prv_find_children(handle, key, children)); DMC_ON_ERR: return DMC_ERR; }
int dmsettings_set_value(dmsettings* handle, const char* key, const char* value) { DMC_ERR_MANAGE; dmsettings_settings_type type; if (!key || !value) DMC_FAIL_FORCE(DMC_ERR_BAD_ARGS); if (!handle->can_write) DMC_FAIL_FORCE(DMC_ERR_DENIED); /* This check is necessary otherwise the db could become corrupted */ DMC_FAIL(dmsettings_exists(handle, key, &type)); if (type == DMSETTINGS_TYPE_DIR) DMC_FAIL_FORCE(DMC_ERR_DENIED); DMC_FAIL(prv_bind_double_update(handle->stmt_set_value, key, value)); DMC_ON_ERR: return DMC_ERR; }
int dmsettings_exists(dmsettings *handle, const char *key, dmsettings_settings_type *type) { DMC_ERR_MANAGE; bool exists; if (!key) DMC_FAIL_FORCE(DMC_ERR_BAD_ARGS); DMC_FAIL(prv_exists_setting(handle, key, &exists)); if (exists) *type = DMSETTINGS_TYPE_VALUE; else { DMC_FAIL(prv_exists(handle, key, &exists)); *type = exists ? DMSETTINGS_TYPE_DIR : DMSETTINGS_TYPE_NOT_EXISTS; } DMC_ON_ERR: return DMC_ERR; }
int dmsettings_create_dir(dmsettings *handle, const char *key) { DMC_ERR_MANAGE; dmsettings_settings_type type; if (!key) DMC_FAIL_FORCE(DMC_ERR_BAD_ARGS); if (!handle->can_write) DMC_FAIL_FORCE(DMC_ERR_DENIED); /* This check is necessary otherwise the db could become corrupted */ DMC_FAIL(dmsettings_exists(handle, key, &type)); if (type != DMSETTINGS_TYPE_NOT_EXISTS) DMC_FAIL_FORCE(DMC_ERR_ALREADY_EXISTS); DMC_FAIL(prv_bind_double_update(handle->stmt_set_value, key, NULL)); DMC_ON_ERR: return DMC_ERR; }
static int prv_exists(dmsettings *handle, const char *key, bool *exists) { DMC_ERR_MANAGE; DMC_FAIL(prv_bind_double_query(handle->stmt_exists, key, key)); *exists = sqlite3_column_int(handle->stmt_exists, 0) ? true : false; DMC_ON_ERR: sqlite3_reset(handle->stmt_exists); sqlite3_clear_bindings(handle->stmt_exists); return DMC_ERR; }
static int prv_create_ro_queries(dmsettings *handle) { DMC_ERR_MANAGE; int sqlerr; sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_EXISTS_SETTING, -1, &handle->stmt_exists_setting, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_EXISTS, -1, &handle->stmt_exists, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_FIND_CHILDREN, -1, &handle->stmt_find_children, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_GET_VALUE, -1, &handle->stmt_get_value, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_GET_META, -1, &handle->stmt_get_meta, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); DMC_ON_ERR: return DMC_ERR; }
int dmsettings_begin_transaction(dmsettings *handle) { DMC_ERR_MANAGE; if (handle->transaction_in_progress) DMC_FAIL_FORCE(DMC_ERR_TRANSACTION_IN_PROGRESS); if (!handle->can_write) DMC_FAIL_FORCE(DMC_ERR_DENIED); DMC_FAIL(prv_exec_simple_cmd(handle->stmt_begin_transaction)); handle->transaction_in_progress = true; DMC_ON_ERR: return DMC_ERR; }
int dmsettings_open_readonly(dmsettings **handle) { DMC_ERR_MANAGE; dmsettings *settings; DMC_FAIL(prv_open_database(DM_SETTINGS_DATABASE, SQLITE_OPEN_READONLY, &settings)); DMC_FAIL_LABEL(prv_create_ro_queries(settings), db_opened); settings->can_write = false; *handle = settings; return DMC_ERR_NONE; db_opened: dmsettings_close(settings); DMC_ON_ERR: return DMC_ERR; }
static int prv_delete_out_transaction(dmsettings *handle, const char *key, const char *parent) { DMC_ERR_MANAGE; DMC_FAIL(dmsettings_begin_transaction(handle)); DMC_FAIL_LABEL(prv_delete_generic(handle, key, parent), cancel_transaction); DMC_FAIL_LABEL(dmsettings_commit_transaction(handle), cancel_transaction); return DMC_ERR_NONE; cancel_transaction: (void) dmsettings_cancel_transaction(handle); DMC_ON_ERR: return DMC_ERR; }
static int prv_delete_in_transaction(dmsettings *handle, const char *key, const char *parent) { DMC_ERR_MANAGE; DMC_FAIL(prv_exec_simple_cmd(handle->stmt_savepoint_set)); DMC_FAIL_LABEL(prv_delete_generic(handle, key, parent), cancel_transaction); DMC_FAIL_LABEL(prv_exec_simple_cmd(handle->stmt_savepoint_commit), cancel_transaction); return DMC_ERR_NONE; cancel_transaction: prv_exec_simple_cmd(handle->stmt_savepoint_cancel); DMC_ON_ERR: return DMC_ERR; }
int get_server_account(mo_mgr_t * iMgr, char * serverID, accountDesc_t ** accountP) { DMC_ERR_MANAGE; char * accMoUri = NULL; char * accountUri = NULL; char * uri = NULL; char * subUri = NULL; dmtree_node_t node; int code; memset(&node, 0, sizeof(dmtree_node_t)); DMC_FAIL(momgr_find_subtree(iMgr, NULL, DMACC_MO_URN, "ServerID", serverID, &accountUri)); DMC_FAIL_NULL(*accountP, malloc(sizeof(accountDesc_t)), OMADM_SYNCML_ERROR_DEVICE_FULL); memset(*accountP, 0, sizeof(accountDesc_t)); (*accountP)->dmtree_uri = accountUri; accountUri = NULL; DMC_FAIL_NULL(node.uri, strdup("./DevInfo/DevId"), OMADM_SYNCML_ERROR_DEVICE_FULL); DMC_FAIL(momgr_get_value(iMgr, &node)); (*accountP)->id = dmtree_node_as_string(&node); dmtree_node_clean(&node, true); // TODO handle IPv4 and IPv6 cases DMC_FAIL_NULL(uri, str_cat_2((*accountP)->dmtree_uri, "/AppAddr"), OMADM_SYNCML_ERROR_DEVICE_FULL); DMC_FAIL(momgr_find_subtree(iMgr, uri, NULL, "AddrType", "URI", &subUri)); free(uri); uri = NULL; DMC_FAIL_NULL(node.uri, str_cat_2(subUri, "/Addr"), OMADM_SYNCML_ERROR_DEVICE_FULL); DMC_FAIL(momgr_get_value(iMgr, &node)); (*accountP)->server_uri = dmtree_node_as_string(&node); dmtree_node_clean(&node, true); free(subUri); subUri = NULL; // TODO handle OBEX and HTTP authentification levels DMC_FAIL_NULL(uri, str_cat_2((*accountP)->dmtree_uri, "/AppAuth"), OMADM_SYNCML_ERROR_DEVICE_FULL); code = momgr_find_subtree(iMgr, uri, NULL, "AAuthLevel", "CLCRED", &subUri); switch (code) { case OMADM_SYNCML_ERROR_NONE: DMC_FAIL_NULL((*accountP)->toServerCred, malloc(sizeof(authDesc_t)), OMADM_SYNCML_ERROR_DEVICE_FULL); DMC_FAIL(prv_fill_credentials(iMgr, subUri, (*accountP)->toServerCred)); break; case OMADM_SYNCML_ERROR_NOT_FOUND: break; default: DMC_FAIL(code); } free(subUri); subUri = NULL; code = momgr_find_subtree(iMgr, uri, NULL, "AAuthLevel", "SRVCRED", &subUri); switch (code) { case OMADM_SYNCML_ERROR_NONE: DMC_FAIL_NULL((*accountP)->toClientCred, malloc(sizeof(authDesc_t)), OMADM_SYNCML_ERROR_DEVICE_FULL); DMC_FAIL(prv_fill_credentials(iMgr, subUri, (*accountP)->toClientCred)); break; case OMADM_SYNCML_ERROR_NOT_FOUND: break; default: DMC_FAIL(code); } free(subUri); subUri = NULL; DMC_ON_ERR: if (accMoUri) free(accMoUri); if (accountUri) free(accountUri); if (uri) free(uri); if (subUri) free(subUri); dmtree_node_clean(&node, true); return DMC_ERR; }
static int prv_create_rw_queries(dmsettings *handle) { DMC_ERR_MANAGE; int sqlerr; sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_SET_VALUE, -1, &handle->stmt_set_value, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_SET_META, -1, &handle->stmt_set_meta, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_BEGIN_TRANSACTION, -1, &handle->stmt_begin_transaction, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_COMMIT_TRANSACTION, -1, &handle->stmt_commit_transaction, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_CANCEL_TRANSACTION, -1, &handle->stmt_cancel_transaction, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_DELETE_EXPLICIT, -1, &handle->stmt_delete_explicit, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_DELETE_META, -1, &handle->stmt_delete_meta, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_SAVEPOINT_SET, -1, &handle->stmt_savepoint_set, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_SAVEPOINT_CANCEL, -1, &handle->stmt_savepoint_cancel, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); sqlerr = sqlite3_prepare_v2(handle->db_handle, DM_SETTINGS_SAVEPOINT_COMMIT, -1, &handle->stmt_savepoint_commit, NULL); DMC_FAIL(map_sqlite3_error(sqlerr)); DMC_ON_ERR: return DMC_ERR; }