/* dblayer.c - Database layer for ck -----------------------------------*- C -*- * * This file is part of ck, the config keeper * * ----------------------------------------------------------------------------- * * Copyright (C) 2018 Anastasis Grammenos * GPLv3 (see LICENCE for the full notice) * * -------------------------------------------------------------------------- */ #include #include "dblayer.h" #include "ckerrlog.h" ERRLOG(ckdb); static const char * const DB_FILE_NAME = "/ckdb"; /* figure out the database name */ static void make_db_name(char *ret, const char *confPath) { char db_path[STR_L] = ""; strcpy(db_path, confPath); strcat(db_path, DB_FILE_NAME); strcpy(ret, db_path); } /* Check if the db file exists*/ int db_exists(const UserOpt *opt) { char db_path[STR_L] = ""; make_db_name(db_path, opt->confDir); return util_is_file_rw(db_path); } /* check if db has the correct tables */ static int check_initialized_DB(sqlite3 *db) { char sql[STR_M] = ""; dbh_form_query_select_all_tables(sql); sqlite3_stmt *stmt; sqlite3_prepare_v2(db, sql, (int)strlen(sql), &stmt, NULL); int program_table_ok, config_table_ok, rel_table_ok = 0; while (sqlite3_step(stmt) != SQLITE_DONE) { const unsigned char *tmpbuf = sqlite3_column_text(stmt, 1); if (strcmp((char *)tmpbuf, TBL_PROGRAM) == 0) { program_table_ok = 1; } if (strcmp((char *)tmpbuf, TBL_CONFIG) == 0) { config_table_ok = 1; } if (strcmp((char *)tmpbuf, TBL_REL) == 0) { rel_table_ok = 1; } } if (!program_table_ok || !config_table_ok || !rel_table_ok ) { return 1; } sqlite3_finalize(stmt); return 0; } void close_DB(DB *db) { sqlite3_close(db->ptr); } int open_DB(DB *db, const UserOpt *opt) { if (!db || !opt) { return -1; } int rc; char db_path[STR_L] = ""; make_db_name(db_path, opt->confDir); rc = sqlite3_open(db_path, &db->ptr); if (rc) { ERR("%s is not a path to an sqlite3 database.", db_path); return -1; } if (opt->action != CKA_INIT) { if (check_initialized_DB(db->ptr)) { ERR("The database file is currupted. Run ck init anew."); return -1; } } LOG("Opened %s", db_path); return 0; } int get_program_id(DB *db, const char* name) { sqlite3_stmt *stmt; int rc; char sql[STR_M] = ""; dhb_form_query_find_program(sql); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { PRINT_ERR("Error while preparing get_program_id sql."); return -2; } sqlite3_bind_text(stmt, 1, name, (int)strlen(name), 0); int id = -1; while (sqlite3_step(stmt) == SQLITE_ROW) { id = sqlite3_column_int(stmt, 0); break; } sqlite3_finalize(stmt); return id; } int program_exists(DB *db, const char *pName) { if (get_program_id(db, pName) == -1) { return 0; } return 1; } int get_config_id(DB *db, const char* path) { sqlite3_stmt *stmt; int rc; char sql[STR_M] = ""; dhb_form_query_find_config(sql); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { PRINT_ERR("while preparing get_config_id sql."); return -2; } sqlite3_bind_text(stmt, 1, path, (int)strlen(path), 0); int id = -1; while (sqlite3_step(stmt) == SQLITE_ROW) { id = sqlite3_column_int(stmt, 0); break; } sqlite3_finalize(stmt); return id; } int program_has_primary_config(DB *db, const int pid, char *ret, int *sec) { sqlite3_stmt *stmt; int rc; char sql[STR_L] = ""; char condition[STR_S] = TBL_PROGRAM; strcat(condition, "."); strcat(condition, COL_PROGRAM_ID); char selection[STR_M] = COL_CONFIG_PRIMARY; strcat(selection, ", "); strcat(selection, COL_CONFIG_PATH); strcat(selection, ", "); strcat(selection, COL_CONFIG_SECRET); dbh_form_query_select_from_joined_eq(sql, selection, condition); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { PRINT_ERR("whinnle preparing program_has_primary_exists sql."); return -2; } sqlite3_bind_int(stmt, 1, pid); while (sqlite3_step(stmt) == SQLITE_ROW) { if (sqlite3_column_int(stmt, 0) == 1) { if (ret) { strcpy(ret,(char *)sqlite3_column_text(stmt, 1)); } if (sec) { *sec = sqlite3_column_int(stmt, 2); } sqlite3_finalize(stmt); return 1; } } sqlite3_finalize(stmt); return 0; } int get_program_relations(DB *db, int pid) { int count = -1; sqlite3_stmt *stmt; int rc; char sql[STR_M] = ""; dbh_form_query_count_program_relations(sql); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { return -1; } sqlite3_bind_int(stmt, 1, pid); while (sqlite3_step(stmt) == SQLITE_ROW) { count = sqlite3_column_int(stmt, 0); } if (rc != SQLITE_OK) { return -1; } sqlite3_finalize(stmt); return count; } int get_config_number(DB *db, char* pName) { int pid = get_program_id(db, pName); /* program exists */ if (pid > -1) { return get_program_relations(db, pid); } return -1; } int get_pid_from_cid(DB *db, int cid) { int pid = -1; sqlite3_stmt *stmt; int rc; char sql[STR_M] = ""; dbh_form_query_get_pid_from_cid(sql); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { return -1; } sqlite3_bind_int(stmt, 1, cid); while (sqlite3_step(stmt) == SQLITE_ROW) { pid = sqlite3_column_int(stmt, 0); } if (rc != SQLITE_OK) { return -1; } sqlite3_finalize(stmt); return pid; } void print_suggested_configs(DB *db, const char *pName) { char name[STR_M] = ""; strcat(name, pName); strcat(name, ":"); cklist *paths = list_make_and_add(name); get_program_paths(db, paths, pName, 1, 0, NULL); list_print(paths); list_free(paths); } int get_program_paths(DB *db, cklist *ckl, const char* pName, int bname, int attr, const char *home) { int pid = get_program_id(db, pName); /* error */ if (pid == -2) { return -1; } /* program exists */ if (pid > -1) { sqlite3_stmt *stmt; int rc; char selection[STR_M] = COL_CONFIG_PATH; strcat(selection, ","); strcat(selection, COL_CONFIG_SECRET); strcat(selection, ","); strcat(selection, COL_CONFIG_PRIMARY); char condition[STR_M] = TBL_PROGRAM; strcat(condition, "."); strcat(condition, COL_PROGRAM_ID); char sql[STR_L] = ""; dbh_form_query_select_from_joined_eq(sql, selection, condition); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); sqlite3_bind_int(stmt, 1, pid); if (rc != SQLITE_OK) { return -2; } while (sqlite3_step(stmt) == SQLITE_ROW) { char *tmp = strdup((char *)sqlite3_column_text(stmt, 0)); char entry[STR_M] = ""; if (bname) { strcat(entry, basename(tmp)); } else { char tpath[STR_L] = ""; if (swap_tilde_with_home(tpath, tmp, home)) { strcat(entry, tpath); } else { strcat(entry, tmp); } } if (attr) { decorate_entry(entry, sqlite3_column_int(stmt, 1), sqlite3_column_int(stmt, 2), (char *)sqlite3_column_text(stmt, 0)); } list_add(ckl, entry); free(tmp); } sqlite3_finalize(stmt); return 0; } return -1; } int secret_enabled(DB *db) { sqlite3_stmt *stmt; int rc; char sql[STR_M] = ""; dbh_form_query_secret_enabled(sql); rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); if (rc != SQLITE_OK) { ERR("while preparing secret_enabled sql."); return -2; } int enabled = 1; while (sqlite3_step(stmt) == SQLITE_ROW) { enabled = sqlite3_column_int(stmt, 0); break; } sqlite3_finalize(stmt); return enabled; }