diff options
-rw-r--r-- | CMakeLists.txt | 16 | ||||
-rw-r--r-- | src/actionhelper.c | 373 | ||||
-rw-r--r-- | src/actionhelper.h | 68 | ||||
-rw-r--r-- | src/actions.c | 78 | ||||
-rw-r--r-- | src/actions.h | 25 | ||||
-rw-r--r-- | src/add.c | 287 | ||||
-rw-r--r-- | src/ck.c | 3 | ||||
-rw-r--r-- | src/ckerrlog.c | 2 | ||||
-rw-r--r-- | src/ckutil.c | 14 | ||||
-rw-r--r-- | src/ckutil.h | 6 | ||||
-rw-r--r-- | src/clparser.c | 2 | ||||
-rw-r--r-- | src/dblayer.c | 830 | ||||
-rw-r--r-- | src/dblayer.h | 55 | ||||
-rw-r--r-- | src/delete.c | 176 | ||||
-rw-r--r-- | src/edit.c | 91 | ||||
-rw-r--r-- | src/init.c | 62 | ||||
-rw-r--r-- | src/list.c | 206 | ||||
-rw-r--r-- | src/queries.c (renamed from src/dbhelper.c) | 4 | ||||
-rw-r--r-- | src/queries.h (renamed from src/dbhelper.h) | 2 | ||||
-rw-r--r-- | src/restore.c | 114 | ||||
-rw-r--r-- | test/05_restore | 46 |
21 files changed, 1186 insertions, 1274 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d88de5..65490cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ project(ck C) # version set(ck_MAJOR_VERSION 0) set(ck_MINOR_VERSION 9) -set(ck_PATCH_VERSION 1) +set(ck_PATCH_VERSION 2) # Feature test macros set(FEATURE_TEST_MACROS "-D_DEFAULT_SOURCE") @@ -57,22 +57,26 @@ set(ckUnitTest_src ${UNIT_TEST_DIR}/ck-test.c) set(ckLib_src ${SRC_DIR}/clparser.c ${SRC_DIR}/actions.c - ${SRC_DIR}/actionhelper.c ${SRC_DIR}/confparser.c ${SRC_DIR}/dblayer.c - ${SRC_DIR}/dbhelper.c + ${SRC_DIR}/queries.c ${SRC_DIR}/ckutil.c ${SRC_DIR}/cklist.c ${SRC_DIR}/ckerrlog.c + ${SRC_DIR}/init.c + ${SRC_DIR}/add.c + ${SRC_DIR}/delete.c + ${SRC_DIR}/edit.c + ${SRC_DIR}/list.c + ${SRC_DIR}/restore.c ) set(ckLib_hdr ${SRC_DIR}/clparser.h ${SRC_DIR}/actions.h - ${SRC_DIR}/actionhelper.h ${SRC_DIR}/confparser.h ${SRC_DIR}/dblayer.h - ${SRC_DIR}/dbhelper.h + ${SRC_DIR}/queries.h ${SRC_DIR}/ckutil.h ${SRC_DIR}/cklist.h ${SRC_DIR}/ckinfo.h @@ -123,8 +127,8 @@ if (CK_TESTS) configure_file(${TEST_DIR}/01_add ${BIN_TEST_DIR}/01_add @ONLY) configure_file(${TEST_DIR}/02_list ${BIN_TEST_DIR}/02_list @ONLY) configure_file(${TEST_DIR}/03_delete ${BIN_TEST_DIR}/03_delete @ONLY) - configure_file(${TEST_DIR}/03_delete ${BIN_TEST_DIR}/03_delete @ONLY) configure_file(${TEST_DIR}/04_search ${BIN_TEST_DIR}/04_search @ONLY) + configure_file(${TEST_DIR}/05_restore ${BIN_TEST_DIR}/05_restore @ONLY) # test-ck configure_file(${RES_DIR}/test-ck test-ck @ONLY) endif() diff --git a/src/actionhelper.c b/src/actionhelper.c deleted file mode 100644 index 6cc37bd..0000000 --- a/src/actionhelper.c +++ /dev/null @@ -1,373 +0,0 @@ -/* actionhelper.c - helper routines for ck actions --------------------*- C -*- - * - * This file is part of ck, the config keeper - * - * ----------------------------------------------------------------------------- - * - * Copyright (C) 2018 Anastasis Grammenos - * GPLv3 (see LICENCE for the full notice) - * - * -------------------------------------------------------------------------- */ -#include <libgen.h> - -#include "actionhelper.h" -#include "confparser.h" -#include "ckerrlog.h" - -ERRLOG(action); - -char add_err[STR_M] = ""; - -int add_err_message(char *err) { - if (!str_is_empty(add_err)) { - if (err) { - strcpy(err, add_err); - } - return 1; - } - return 0; -} - -void link_config(const AddOpt *opt, const char* newPath) { - printf("Linking %s -> %s\n", newPath, opt->confPath); - if (util_symlink_file(newPath, opt->confPath) != 0) { - strcpy(add_err, "Could not link file."); - } -} - -int move_config(const AddOpt *opt, char *progDir, char *ret) { - char newPath[STR_L] = ""; - char *tmp = strdup(opt->confPath); - str_join_dirname_with_basename(newPath, progDir, basename(tmp)); - free(tmp); - if (util_file_exists(newPath, NULL)) { - strcpy(add_err, "File already exists");\ - return -1; - } - strcpy(ret, newPath); - printf("Moving %s -> %s\n", opt->confPath, newPath); - if (util_move_file(opt->confPath, newPath) != 0) { - strcpy(add_err, "Could not move file."); - return -1; - } - return 0; -} - -AddOpt add_make_options(cklist *args) { - list_rewind(args); - /* since we are here, the first two arguments must exist */ - AddOpt addOpt = { - .progName = list_get(args), - .secret = 0, - .prime = 0, - .err = ADD_NO_ERR - }; - - list_next(args); - if (!util_is_file_rw(list_get(args)) - || !util_is_file_link(list_get(args))) { - addOpt.err = ADD_ERR_WRONG_CONFIG; - return addOpt; - } - realpath(list_get(args), addOpt.confPath); - - while (list_next(args)) { - if (strcmp(list_get(args), "-s") == 0 && addOpt.secret == 0) { - addOpt.secret = 1; - } else if (strcmp(list_get(args), "-p") == 0 && addOpt.prime == 0) { - addOpt.prime = 1; - } else { - addOpt.err = ADD_ERR_WRONG_FLAGS; - return addOpt; - } - } - list_rewind(args); - return addOpt; -} - -void add_print_opts(AddOpt *opt) { - printf("Program:\t%s\nConfig:\t\t%s\n", opt->progName, opt->confPath); - if (opt->prime && opt->secret) { - printf("Options:\tsecret, primary\n"); - } else if (opt->prime) { - printf("Options:\tprimary\n"); - } else if (opt->secret) { - printf("Options:\tsecret\n"); - } -} - -void get_or_make_program_dir(const AddOpt *opt, const Conf *conf, char *ret) { - char tmp[STR_L] = ""; - str_join_dirname_with_basename(tmp, opt->secret ? conf->scrt_dir : conf->vc_dir, opt->progName); - if (!util_file_exists(tmp, NULL)) { - util_mkdir(tmp); - } - strcpy(ret, tmp); -} - -void add_make_link(const AddOpt *opt, const Conf *conf) { - char progDir[STR_L] = ""; - get_or_make_program_dir(opt, conf, progDir); - char newPath[STR_L] = ""; - move_config(opt, progDir, newPath); - if (add_err_message(NULL)) { - return; - } - link_config(opt, newPath); - if (add_err_message(NULL)) { - return; - } -} - -void edit_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 init_create_config_file(UserOpt *opt) { - char absVCdir[STR_L] = ""; - if (!util_file_exists(list_get_at(opt->args, 0), absVCdir)) { - ERR("Version control directory: %s does not exist.", list_get_at(opt->args, 0)); - return 1; - } - - char absSRdir[STR_L] = ""; - if (!util_file_exists(list_get_at(opt->args, 1), absSRdir)) { - ERR("Secret directory: %s does not exist.", list_get_at(opt->args, 1)); - return 1; - } - - if (!util_file_exists(opt->confDir, NULL)) { - util_mkdir(opt->confDir); - } - - char confName[STR_L] = ""; - make_config_name(confName, opt->confDir); - FILE *f; - if ((f = fopen(confName, "w")) == NULL) { - return 1; - } - - char tmp[STR_L] = ""; - strcpy(tmp, "version_control_dir = "); - strcat(tmp, absVCdir); - strcat(tmp, "\n"); - fputs(tmp, f); - - strcpy(tmp, "secret_dir = "); - strcat(tmp, absSRdir); - strcat(tmp, "\n"); - fputs(tmp, f); - - strcpy(tmp, "home_dir = "); - strcat(tmp, getenv("HOME")); - strcat(tmp, "\n"); - fputs(tmp, f); - - fclose(f); - return 0; -} - -ListOpt list_make_options(cklist *args) { - list_rewind(args); - ListOpt listOpt = { - ._lt = LT_TREE, - ._lst = LST_PLAIN, - .pName = NULL, - .attr = 0, - .bName = 0, - .err = 0 - }; - - if (list_size(args)) { - do { - if (strcmp(list_get(args), "-a") == 0) { - listOpt.attr = 1; - continue; - } - if (strcmp(list_get(args), "-b") == 0) { - listOpt.bName = 1; - continue; - } - if (strcmp(list_get(args), "-t") == 0) { - if (!list_next(args)) { - listOpt.err = 1; - break; - } - if (strcmp(list_get(args), "plain") == 0) { - listOpt._lst = LST_PLAIN; - } - else if (strcmp(list_get(args), "lisp") == 0) { - listOpt._lst = LST_LISP; - } - else if (strcmp(list_get(args), "python") == 0) { - listOpt._lst = LST_PYTHON; - } - else { - listOpt.err = 1; - } - } - else if (strcmp(list_get(args), "paths") == 0) { - listOpt._lt = LT_PATH; - } - else if (strcmp(list_get(args), "programs") == 0) { - listOpt._lt = LT_PROGRAM; - } - else if (strcmp(list_get(args), "tree") == 0) { - listOpt._lt = LT_TREE; - } - else if (strcmp(list_get(args), "ckconf") == 0) { - listOpt._lt = LT_CKCONF; - } - else if (strcmp(list_get(args), "-p") == 0) { - if (list_next(args)) { - listOpt._lt = LT_PROG_CONFS; - listOpt.pName = list_get(args); - } - else { - listOpt.err = 1; - break; - } - } - else { - listOpt.err = 1; - } - } while(list_next(args)); - } - list_rewind(args); - return listOpt; -} - -int restore_make_links(cklist *from, cklist *to) { - list_rewind(from); - list_rewind(to); - if (list_size(from) > 0 - && list_size(to) > 0 - && list_size(from) == list_size(to)) { - do { - if (util_file_exists(list_get(to), NULL) - || !util_is_file_link(list_get(to))) { - ERR("File %s already exists.", list_get(to)); - sERR("No links were created."); - return -1; - } - } while (list_next(to)); - list_rewind(to); - while (1) { - if (util_symlink_file(list_get(from), list_get(to))) { - ERR("FATAL could not link %s -> %s", list_get(from), list_get(to)); - sERR("Process stopping."); - return -1; - } - hLOG("Linking: %s -> %s", list_get(from), list_get(to)); - if (util_own_grp_copy(list_get(to), list_get(from))) { - return -1; - } - if (!list_next(from)) { - break; - } - if (!list_next(to)) { - break; - } - } - } - return 0; -} - -/*****************/ -/* PRINT RESULTS */ -/*****************/ - -void print_INIT_result(int err) { - if (!err) { - hLOG("Initialized empty ckdb."); - } -} - -void print_ADD_result(int err) { - if (!err) { - hLOG("ckdb updated succesfully."); - return; - } - sERR("Could not complete add transaction."); -} - -void print_DEL_result(int err) { - if (!err) { - hLOG("ckdb updated succesfully."); - return; - } - sERR("Could not complete delete transaction."); -} - -void print_EDIT_result(int err) { - UNUSED(err); -} - -void print_LIST_result(int err) { - UNUSED(err); -} - -void print_SEARCH_result(int err) { - UNUSED(err); -} - -void print_HELP_result(int err) { - UNUSED(err); -} - -void print_RESTORE_result(int err) { - UNUSED(err); -} - -void print_INIT_help() { - HELP("ck init VERSION_CONTROL_DIR SECRET_DIR"); -} - -void print_ADD_help() { - HELP("ck add PROGRAM_NAME CONFIG_PATH [-p] [-s]"); -} - -void print_DEL_help() { - HELP("ck delete PROGRAM_NAME [CONFIG_BASENAME]"); -} - -void print_EDIT_help() { - HELP("ck edit PROGRAM_NAME [CONFIG_BASENAME]"); -} - -void print_LIST_help() { - ckhelp("ck list tree [-a] [-b]"); - ckhelp("ck list -p PROGRAM_NAME [-t list-type] [-a] [-b]"); - ckhelp("ck list programs [-t list-type] [-a] [-b]"); - ckhelp("ck list paths [-t list-type] [-a] [-b]"); - ckhelp("ck list ckconf"); - report_help(); -} - -void print_SEARCH_help() { - HELP("ck search SEARCH_TERM"); -} - -void print_HELP_help() { - HELP("ck help action"); -} - -void print_RESTORE_help() { - ckhelp("ck restore -p PROGRAM_NAME"); - ckhelp("ck restore all"); - report_help(); -} - -void print_conf_help(void) { - HELP("ck [-v|--verbose] [-c|--config DIR] action [...]"); -} - -void print_verbose_help(void) { - HELP("ck [-v|--verbose] [-c|--config DIR] action [...]"); -} diff --git a/src/actionhelper.h b/src/actionhelper.h deleted file mode 100644 index f7da0dd..0000000 --- a/src/actionhelper.h +++ /dev/null @@ -1,68 +0,0 @@ -/* actionhelper.h - helper routines for ck actions --------------------*- C -*- - * - * This file is part of ck, the config keeper - * - * ----------------------------------------------------------------------------- - * - * Copyright (C) 2018 Anastasis Grammenos - * GPLv3 (see LICENCE for the full notice) - * - * ----------------------------------------------------------------------------- - * - * Here reside helper routines for the actions. - * - * -------------------------------------------------------------------------- */ -#ifndef ACTIONHELPER_H -#define ACTIONHELPER_H - -#include "actions.h" -#include "ckutil.h" -#include "cklist.h" -#include "dblayer.h" - -/********/ -/* INIT */ -/********/ - -int init_create_config_file(UserOpt *opt); - -/*******/ -/* ADD */ -/*******/ - -/* if add_err is set, return true - * along with a copy of the error message. - * Pass NULL if you don't care about the message */ -int add_err_message(char *err); -AddOpt add_make_options(cklist *args); -void add_print_opts(AddOpt *opt); -void add_make_link(const AddOpt *opt, const Conf *conf); - -/********/ -/* EDIT */ -/********/ -void edit_print_suggested_configs(DB *db, const char *pName); - -/********/ -/* LIST */ -/********/ -ListOpt list_make_options(cklist *args); - -/***********/ -/* RESTORE */ -/***********/ -int restore_make_links(cklist *from, cklist *to); - -/************************/ -/* PRINT RESULTS & HELP */ -/************************/ -#define X(ACTION) \ - void print_##ACTION##_result(int err); \ - void print_##ACTION##_help(void); -CK_ACTIONS -#undef X - -void print_conf_help(void); -void print_verbose_help(void); - -#endif /* ACTIONHELPER_H */ diff --git a/src/actions.c b/src/actions.c index 882fa30..c977aee 100644 --- a/src/actions.c +++ b/src/actions.c @@ -8,10 +8,7 @@ * GPLv3 (see LICENCE for the full notice) * * -------------------------------------------------------------------------- */ -#include "actions.h" -#include "actionhelper.h" #include "dblayer.h" -#include "ckutil.h" #include "cklist.h" #include "ckerrlog.h" @@ -28,10 +25,12 @@ int run_INIT(UserOpt * opt, Conf *conf) { return -1; } DB db; - if (!init_make_DB(&db, opt)) { - init_make_tables(&db); + if (open_DB(&db, opt)) { + return -1; } + init_make_tables(&db); sqlite3_close(db.ptr); + hLOG("Initialized empty ckdb."); return 0; } @@ -56,15 +55,14 @@ int run_ADD(UserOpt * opt, Conf *conf) { if (add_transaction_try(&db, &addOpt, conf->home_dir)) { goto error; } - add_make_link(&addOpt, conf); - char err[STR_M] = ""; - if (add_err_message(err)) { - PRINT_ERR(err); + if (add_make_link(&addOpt, conf)) { error: close_DB(&db); + sERR("Could not complete add transaction."); return -1; } close_DB(&db); + hLOG("ckdb updated succesfully."); return 0; } @@ -93,11 +91,16 @@ int run_DEL(UserOpt * opt, Conf *conf) { rc = del_transaction_try(&db, pName, cName); if (rc) { HELP("Program %s doesn't have a config named %s", pName, cName); - edit_print_suggested_configs(&db, pName); + print_suggested_configs(&db, pName); } } error: close_DB(&db); + if (!rc) { + hLOG("ckdb updated succesfully."); + } else { + sERR("Could not complete delete transaction."); + } return rc; } @@ -131,7 +134,7 @@ int run_EDIT(UserOpt *opt, Conf *conf) { /* If the program has many configs */ else { HELP("Ambiguous config. Please type the config name after the program."); - edit_print_suggested_configs(&db, pName); + print_suggested_configs(&db, pName); goto error; } } @@ -141,7 +144,7 @@ int run_EDIT(UserOpt *opt, Conf *conf) { char *cName = list_get(opt->args); if (edit_get_config(&db, pName, confName, cName, &secret)) { ERR("Program %s doesn't have a config named %s", pName, cName); - edit_print_suggested_configs(&db, pName); + print_suggested_configs(&db, pName); goto error; } } @@ -360,3 +363,54 @@ int run_RESTORE(UserOpt *opt, Conf *conf) { list_free(to); return rc; } + +/**************/ +/* PRINT HELP */ +/**************/ + +void print_INIT_help() { + HELP("ck init VERSION_CONTROL_DIR SECRET_DIR"); +} + +void print_ADD_help() { + HELP("ck add PROGRAM_NAME CONFIG_PATH [-p] [-s]"); +} + +void print_DEL_help() { + HELP("ck delete PROGRAM_NAME [CONFIG_BASENAME]"); +} + +void print_EDIT_help() { + HELP("ck edit PROGRAM_NAME [CONFIG_BASENAME]"); +} + +void print_LIST_help() { + ckhelp("ck list tree [-a] [-b]"); + ckhelp("ck list -p PROGRAM_NAME [-t list-type] [-a] [-b]"); + ckhelp("ck list programs [-t list-type] [-a] [-b]"); + ckhelp("ck list paths [-t list-type] [-a] [-b]"); + ckhelp("ck list ckconf"); + report_help(); +} + +void print_SEARCH_help() { + HELP("ck search SEARCH_TERM"); +} + +void print_HELP_help() { + HELP("ck help action"); +} + +void print_RESTORE_help() { + ckhelp("ck restore -p PROGRAM_NAME"); + ckhelp("ck restore all"); + report_help(); +} + +void print_conf_help(void) { + HELP("ck [-v|--verbose] [-c|--config DIR] action [...]"); +} + +void print_verbose_help(void) { + HELP("ck [-v|--verbose] [-c|--config DIR] action [...]"); +} diff --git a/src/actions.h b/src/actions.h index d261cc6..2015538 100644 --- a/src/actions.h +++ b/src/actions.h @@ -67,4 +67,29 @@ struct ListOptions { int err; }; +/* init.c */ +int init_create_config_file(UserOpt *opt); + +/* add.c */ +AddOpt add_make_options(cklist *args); +void add_print_opts(AddOpt *opt); +int add_make_link(const AddOpt *opt, const Conf *conf); + +/* list.c */ +ListOpt list_make_options(cklist *args); + +/* restore.c */ +int restore_make_links(cklist *from, cklist *to); + +/************************/ +/* PRINT RESULTS & HELP */ +/************************/ +#define X(ACTION) \ + void print_##ACTION##_help(void); +CK_ACTIONS +#undef X + +void print_conf_help(void); +void print_verbose_help(void); + #endif /* ACTIONS_H */ diff --git a/src/add.c b/src/add.c new file mode 100644 index 0000000..f7a49bf --- /dev/null +++ b/src/add.c @@ -0,0 +1,287 @@ +#include <libgen.h> + +#include "actions.h" +#include "dblayer.h" +#include "queries.h" +#include "ckerrlog.h" + +ERRLOG(add); + +static int get_next_valid_id_from_table(DB *db, const char* tableName) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dbh_form_query_select_id_from(sql, tableName); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -1; + } + sqlite3_bind_text(stmt, 1, tableName, (int)strlen(tableName), 0); + + int id = 0; + while (sqlite3_step(stmt) == SQLITE_ROW) { + int a = sqlite3_column_int(stmt, 0); + if (a != id) { + break; + } + id++; + } + sqlite3_finalize(stmt); + return id; +} + +static int insert_to_program_table(DB *db, const char *name) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_L] = ""; + dbh_form_query_insert_program(sql); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + ERR("while preparing insert to program sql."); + db->error = SQL_ERR_SQLITE; + return -1; + } + int id = get_next_valid_id_from_table(db, TBL_PROGRAM); + if (id == -1) { + db->error = SQL_ERR_SQLITE; + return -1; + } + sqlite3_bind_int(stmt, 1, id); + sqlite3_bind_text(stmt, 2, name, (int)strlen(name), 0); + if (sqlite3_step(stmt) != SQLITE_DONE) { + ERR("while excecuting insert to program sql."); + db->error = SQL_ERR_SQLITE; + return -1; + } + sqlite3_finalize(stmt); + return id; +} + +static int insert_to_config_table(DB *db, const char *path, const int secret, const int prime) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_L] = ""; + dbh_form_query_insert_config(sql); + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + ERR("Error while preparing insert to config sql."); + db->error = SQL_ERR_SQLITE; + return -1; + } + int id = get_next_valid_id_from_table(db, TBL_CONFIG); + if (id == -1) { + db->error = SQL_ERR_SQLITE; + return -1; + } + sqlite3_bind_int(stmt, 1, id); + sqlite3_bind_text(stmt, 2, path, (int)strlen(path), 0); + sqlite3_bind_int(stmt, 3, secret); + sqlite3_bind_int(stmt, 4, prime); + if (sqlite3_step(stmt) != SQLITE_DONE) { + ERR("Error while excecuting insert to config sql."); + db->error = SQL_ERR_SQLITE; + return-1; + } + sqlite3_finalize(stmt); + return id; +} + +static int add_get_or_insert_config_to_db(DB *db, const int pid, const char *path, const int secret, const int prime, const char *home) { + char tpath[STR_L] = ""; + if (!swap_home_with_tilde(tpath, path, home)) { + strcpy(tpath, path); + } + int cid = get_config_id(db, tpath); + if (cid == -2) { + db->error = SQL_ERR_SQLITE; + return -1; + } + /* If config doesnt exist insert it and return it's cid */ + if (cid == -1) { + if (program_has_primary_config(db, pid, NULL, NULL) && prime) { + db->error = SQL_ERR_PRIMARY_REDEFINITION; + return -1; + } + return insert_to_config_table(db, tpath, secret, prime); + } + + /* If it exist it means the user has inserted the same path twice */ + db->error = SQL_CONFIG_PATH_EXISTS; + return -1; +} + +static int add_get_or_insert_program_to_db(DB *db, const char *name) { + int pid = get_program_id(db, name); + if (pid == -2) { + db->error = SQL_ERR_SQLITE; + return -1; + } + if (pid == -1) { + return insert_to_program_table(db, name); + } + return pid; +} + +static int add_basename_exists(DB *db, const char *pName, const char *path) { + cklist *baseNames = list_make_new(); + get_program_paths(db, baseNames, pName, 1 /*basename */, 0, NULL); + char *tmp = strdup(path); + int rc = list_exists(baseNames, basename(tmp)); + free(tmp); + list_free(baseNames); + return rc; +} + +static int add_insert_relationship(DB *db, const int pid, const int cid) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dhb_form_query_insert_relationship(sql); + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + db->error = SQL_ERR_SQLITE; + ERR("while preparing insert to rel sql."); + return -1; + } + sqlite3_bind_int(stmt, 1, pid); + sqlite3_bind_int(stmt, 2, cid); + if (sqlite3_step(stmt) != SQLITE_DONE) { + db->error = SQL_ERR_SQLITE; + ERR("while excecuting insert to rel sql."); + return-1; + } + sqlite3_finalize(stmt); + return 1; +} + +int add_transaction_try(DB *db, const AddOpt * const opt, const char *home) { + __BEGIN_TRANSACTION__ + int pid = add_get_or_insert_program_to_db(db, opt->progName); + if (db->error == SQL_ERR_SQLITE) { + ERR("Could not insert program to db."); + return 1; + } + if (add_basename_exists(db, opt->progName, opt->confPath)) { + ERR("Cannot have two configs with the same basename, for the same program."); + return 1; + } + int cid = add_get_or_insert_config_to_db(db, pid, opt->confPath, opt->secret, opt->prime, home); + if (db->error == SQL_ERR_SQLITE) { + ERR("Could not insert config to db."); + return 1; + } + else if (db->error == SQL_CONFIG_PATH_EXISTS) { + ERR("This config already exists in the database."); + return 1; + } + else if (db->error == SQL_ERR_PRIMARY_REDEFINITION) { + ERR("This program already has a primary config."); + return 1; + } + add_insert_relationship(db, pid, cid); + if (db->error == SQL_ERR_SQLITE) { + ERR("rel update failed\n"); + return 1; + } + __END_TRANSACTION__ + + return 0; +} + +static int link_config(const AddOpt *opt, const char* newPath) { + hLOG("Linking %s -> %s\n", newPath, opt->confPath); + if (util_symlink_file(newPath, opt->confPath) != 0) { + ERR("Could not link file."); + return -1; + } + return 0; +} + +static int move_config(const AddOpt *opt, char *progDir, char *ret) { + char newPath[STR_L] = ""; + char *tmp = strdup(opt->confPath); + str_join_dirname_with_basename(newPath, progDir, basename(tmp)); + free(tmp); + if (util_file_exists(newPath, NULL)) { + ERR("File already exists"); + return -1; + } + strcpy(ret, newPath); + hLOG("Moving %s -> %s\n", opt->confPath, newPath); + if (util_move_file(opt->confPath, newPath) != 0) { + ERR("Could not move file."); + return -1; + } + return 0; +} + +AddOpt add_make_options(cklist *args) { + list_rewind(args); + /* since we are here, the first two arguments must exist */ + AddOpt addOpt = { + .progName = list_get(args), + .secret = 0, + .prime = 0, + .err = ADD_NO_ERR + }; + + list_next(args); + if (!util_is_file_rw(list_get(args)) + || !util_is_file_link(list_get(args))) { + addOpt.err = ADD_ERR_WRONG_CONFIG; + return addOpt; + } + realpath(list_get(args), addOpt.confPath); + + while (list_next(args)) { + if (strcmp(list_get(args), "-s") == 0 && addOpt.secret == 0) { + addOpt.secret = 1; + } else if (strcmp(list_get(args), "-p") == 0 && addOpt.prime == 0) { + addOpt.prime = 1; + } else { + addOpt.err = ADD_ERR_WRONG_FLAGS; + return addOpt; + } + } + list_rewind(args); + return addOpt; +} + +void add_print_opts(AddOpt *opt) { + printf("Program:\t%s\nConfig:\t\t%s\n", opt->progName, opt->confPath); + if (opt->prime && opt->secret) { + printf("Options:\tsecret, primary\n"); + } else if (opt->prime) { + printf("Options:\tprimary\n"); + } else if (opt->secret) { + printf("Options:\tsecret\n"); + } +} + +static void get_or_make_program_dir(const AddOpt *opt, const Conf *conf, char *ret) { + char tmp[STR_L] = ""; + str_join_dirname_with_basename(tmp, opt->secret ? conf->scrt_dir : conf->vc_dir, opt->progName); + if (!util_file_exists(tmp, NULL)) { + util_mkdir(tmp); + } + strcpy(ret, tmp); +} + +int add_make_link(const AddOpt *opt, const Conf *conf) { + char progDir[STR_L] = ""; + get_or_make_program_dir(opt, conf, progDir); + char newPath[STR_L] = ""; + if (move_config(opt, progDir, newPath)) { + return -1; + } + if (link_config(opt, newPath)) { + return -1; + } + return 0; +} @@ -28,7 +28,7 @@ * * -------------------------------------------------------------------------- */ -#include "actionhelper.h" +#include "actions.h" #include "dblayer.h" #include "cklist.h" #include "ckutil.h" @@ -68,7 +68,6 @@ int main(int argc, const char **argv) { #define X(ACTION) \ case CKA_##ACTION: \ rc = run_##ACTION(&opt, &conf); \ - print_##ACTION##_result(rc); \ break; CK_ACTIONS #undef X diff --git a/src/ckerrlog.c b/src/ckerrlog.c index fab18b0..cf5a6e8 100644 --- a/src/ckerrlog.c +++ b/src/ckerrlog.c @@ -44,7 +44,7 @@ void log_command(int argc,const char* argv[]) { void add_ ## stream ## _with_delim(const char *delim, \ const char *txt, \ va_list args) { \ - char tmp[STR_L] = ""; \ + char tmp[STR_L] = ""; \ vsprintf(tmp, txt, args); \ if (stream) { \ list_add(stream, tmp); \ diff --git a/src/ckutil.c b/src/ckutil.c index fde5e24..2b807de 100644 --- a/src/ckutil.c +++ b/src/ckutil.c @@ -228,3 +228,17 @@ int y_or_n_prompt() { } return 0; } + +void decorate_entry(char *entry, int secret, int primary, const char *path) { + if (primary) { + strcat(entry, " [p]"); + } + + if (secret) { + strcat(entry, " [s]"); + } + /* root */ + if (util_is_link_owned_by_root(path)) { + strcat(entry, " [root]"); + } +} diff --git a/src/ckutil.h b/src/ckutil.h index d29b302..60d715f 100644 --- a/src/ckutil.h +++ b/src/ckutil.h @@ -49,11 +49,11 @@ /* Create the config name to be used when storing a new config to * the VC or SCRT dir */ void str_make_ck_config_name(char *ret, const char *path, - const char *progName); + const char *progName); /* Joins the two strings into ret, with a '/' in between */ void str_join_dirname_with_basename(char *ret, const char *path, - const char *progName); + const char *progName); /* Returns 1 if str contains only whitespace, or nothing, * else returns 0. */ @@ -99,4 +99,6 @@ int util_is_link_owned_by_root(const char *link); /* yes is 1, no is 0 */ int y_or_n_prompt(); + +void decorate_entry(char *entry, int secret, int primary, const char *path); #endif // CKUTIL_H diff --git a/src/clparser.c b/src/clparser.c index 6dbd62a..ba73db0 100644 --- a/src/clparser.c +++ b/src/clparser.c @@ -13,7 +13,7 @@ #include "confparser.h" #include "ckinfo.h" #include "ckerrlog.h" -#include "actionhelper.h" +#include "actions.h" ERRLOG(parser); diff --git a/src/dblayer.c b/src/dblayer.c index a6e6193..12be997 100644 --- a/src/dblayer.c +++ b/src/dblayer.c @@ -11,16 +11,16 @@ #include <libgen.h> #include "dblayer.h" -#include "dbhelper.h" +#include "queries.h" #include "ckutil.h" #include "ckerrlog.h" ERRLOG(ckdb); -const char * const DB_FILE_NAME = "/ckdb"; +static const char * const DB_FILE_NAME = "/ckdb"; /* figure out the database name */ -void make_db_name(char *ret, const char *confPath) { +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); @@ -36,7 +36,7 @@ int db_exists(const UserOpt *opt) { } /* check if db has the correct tables */ -int check_initialized_DB(sqlite3 *db) { +static int check_initialized_DB(sqlite3 *db) { char sql[STR_M] = ""; dbh_form_query_select_all_tables(sql); sqlite3_stmt *stmt; @@ -67,14 +67,6 @@ int check_initialized_DB(sqlite3 *db) { return 0; } -DB empty_DB(SqlError err) { - return (DB){ .ptr = NULL, .error = err }; -} - -DB new_DB(sqlite3 *db) { - return (DB){ .ptr = db, .error = SQL_NO_ERR }; -} - void close_DB(DB *db) { sqlite3_close(db->ptr); } @@ -94,149 +86,17 @@ int open_DB(DB *db, const UserOpt *opt) { return -1; } - if (check_initialized_DB(db->ptr)) { - ERR("The database file is currupted. Run ck init anew."); - 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 init_make_DB(DB *db, const UserOpt *opt) { - char db_path[STR_L] = ""; - int rc; - - make_db_name(db_path, opt->confDir); - rc = sqlite3_open(db_path, &db->ptr); - if (rc != SQLITE_OK) { - return -1; - } - - return 0; -} - -void init_make_tables(DB *db) { - char sql[STR_L] = ""; - dbh_form_query_make_tables(sql); - - int rc = sqlite3_exec(db->ptr, sql, 0, 0, 0); - if (rc != SQLITE_OK ) { - PRINT_ERR("Could not create empty db."); - db->error = SQL_ERR_SQLITE; - return; - } -} - -int get_next_valid_id_from_table(DB *db, const char* tableName) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dbh_form_query_select_id_from(sql, tableName); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -1; - } - sqlite3_bind_text(stmt, 1, tableName, (int)strlen(tableName), 0); - - int id = 0; - while (sqlite3_step(stmt) == SQLITE_ROW) { - int a = sqlite3_column_int(stmt, 0); - if (a != id) { - break; - } - id++; - } - sqlite3_finalize(stmt); - return id; -} - -int insert_to_program_table(DB *db, const char *name) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_L] = ""; - dbh_form_query_insert_program(sql); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - PRINT_ERR("while preparing insert to program sql."); - db->error = SQL_ERR_SQLITE; - return -1; - } - int id = get_next_valid_id_from_table(db, TBL_PROGRAM); - if (id == -1) { - db->error = SQL_ERR_SQLITE; - return -1; - } - sqlite3_bind_int(stmt, 1, id); - sqlite3_bind_text(stmt, 2, name, (int)strlen(name), 0); - if (sqlite3_step(stmt) != SQLITE_DONE) { - PRINT_ERR("while excecuting insert to program sql."); - db->error = SQL_ERR_SQLITE; - return -1; - } - sqlite3_finalize(stmt); - return id; -} - -int insert_to_config_table(DB *db, const char *path, const int secret, const int prime) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_L] = ""; - dbh_form_query_insert_config(sql); - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - PRINT_ERR("Error while preparing insert to config sql."); - db->error = SQL_ERR_SQLITE; - return -1; - } - int id = get_next_valid_id_from_table(db, TBL_CONFIG); - if (id == -1) { - db->error = SQL_ERR_SQLITE; - return -1; - } - sqlite3_bind_int(stmt, 1, id); - sqlite3_bind_text(stmt, 2, path, (int)strlen(path), 0); - sqlite3_bind_int(stmt, 3, secret); - sqlite3_bind_int(stmt, 4, prime); - if (sqlite3_step(stmt) != SQLITE_DONE) { - PRINT_ERR("Error while excecuting insert to config sql."); - db->error = SQL_ERR_SQLITE; - return-1; - } - sqlite3_finalize(stmt); - return id; -} - -int insert_to_rel_table(DB *db, const int pid, const int cid) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dhb_form_query_insert_relationship(sql); - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - db->error = SQL_ERR_SQLITE; - PRINT_ERR("while preparing insert to rel sql."); - return -1; - } - sqlite3_bind_int(stmt, 1, pid); - sqlite3_bind_int(stmt, 2, cid); - if (sqlite3_step(stmt) != SQLITE_DONE) { - db->error = SQL_ERR_SQLITE; - PRINT_ERR("while excecuting insert to rel sql."); - return-1; - } - sqlite3_finalize(stmt); - return 1; -} - -/* Returns -2 or error, -1 if program doesn't exist - * else the program ID */ int get_program_id(DB *db, const char* name) { sqlite3_stmt *stmt; int rc; @@ -288,12 +148,6 @@ int get_config_id(DB *db, const char* path) { return id; } -int add_insert_relationship(DB *db, const int pid, const int cid) { - // do checks - return insert_to_rel_table(db, pid, cid); -} - -/* Returns the path of the found config via *ret */ int program_has_primary_config(DB *db, const int pid, char *ret, int *sec) { sqlite3_stmt *stmt; int rc; @@ -335,185 +189,75 @@ int program_has_primary_config(DB *db, const int pid, char *ret, int *sec) { return 0; } -int add_get_or_insert_config_to_db(DB *db, const int pid, const char *path, const int secret, const int prime, const char *home) { - char tpath[STR_L] = ""; - if (!swap_home_with_tilde(tpath, path, home)) { - strcpy(tpath, path); - } - int cid = get_config_id(db, tpath); - if (cid == -2) { - db->error = SQL_ERR_SQLITE; - return -1; - } - /* If config doesnt exist insert it and return it's cid */ - if (cid == -1) { - if (program_has_primary_config(db, pid, NULL, NULL) && prime) { - db->error = SQL_ERR_PRIMARY_REDEFINITION; - return -1; - } - return insert_to_config_table(db, tpath, secret, prime); - } +int get_program_relations(DB *db, int pid) { + int count = -1; + sqlite3_stmt *stmt; + int rc; - /* If it exist it means the user has inserted the same path twice */ - db->error = SQL_CONFIG_PATH_EXISTS; - return -1; -} + char sql[STR_M] = ""; + dbh_form_query_count_program_relations(sql); -int add_get_or_insert_program_to_db(DB *db, const char *name) { - int pid = get_program_id(db, name); - if (pid == -2) { - db->error = SQL_ERR_SQLITE; + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { return -1; } - if (pid == -1) { - return insert_to_program_table(db, name); - } - return pid; -} -int add_basename_exists(DB *db, const char *pName, const char *path) { - cklist *baseNames = list_make_new(); - get_program_paths(db, baseNames, pName, 1 /*basename */, 0, NULL); - char *tmp = strdup(path); - int rc = list_exists(baseNames, basename(tmp)); - free(tmp); - list_free(baseNames); - return rc; -} - -int add_transaction_try(DB *db, const AddOpt * const opt, const char *home) { - __BEGIN_TRANSACTION__ - int pid = add_get_or_insert_program_to_db(db, opt->progName); - if (db->error == SQL_ERR_SQLITE) { - PRINT_ERR("Could not insert program to db.\n"); - return 1; - } - if (add_basename_exists(db, opt->progName, opt->confPath)) { - ERR("Cannot have two configs with the same basename, for the same program."); - return 1; - } - int cid = add_get_or_insert_config_to_db(db, pid, opt->confPath, opt->secret, opt->prime, home); - if (db->error == SQL_ERR_SQLITE) { - PRINT_ERR("Could not insert config to db.\n"); - return 1; - } - else if (db->error == SQL_CONFIG_PATH_EXISTS) { - PRINT_ERR("This config already exists in the database.\n"); - return 1; - } - else if (db->error == SQL_ERR_PRIMARY_REDEFINITION) { - PRINT_ERR("This program already has a primary config.\n"); - return 1; - } - add_insert_relationship(db, pid, cid); - if (db->error == SQL_ERR_SQLITE) { - PRINT_ERR("rel update failed\n"); - return 1; + sqlite3_bind_int(stmt, 1, pid); + while (sqlite3_step(stmt) == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); } - __END_TRANSACTION__ - return 0; -} - -int edit_get_prime_config_from_program(DB *db, char *pName, char *ret, int *secret) { - int pid = get_program_id(db, pName); - /* error */ - if (pid == -2) { + 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) { - char path[STR_M] = ""; - if (program_has_primary_config(db, pid, path, secret) == 1) { - if (!str_is_empty(path)) { - if (ret) { - str_make_ck_config_name(ret, path, pName); - } - return 0; - } - } + return get_program_relations(db, pid); } - - /* No prime config found */ return -1; } -int edit_get_config(DB *db, const char *pName, char *ret, const char *cName, int *sec) { - 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); - 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); +int get_pid_from_cid(DB *db, int cid) { + int pid = -1; + sqlite3_stmt *stmt; + int rc; - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - sqlite3_bind_int(stmt, 1, pid); - if (rc != SQLITE_OK) { - return -2; - } + char sql[STR_M] = ""; + dbh_form_query_get_pid_from_cid(sql); - int flag = -1; - while (sqlite3_step(stmt) == SQLITE_ROW) { - char confName[STR_M] = ""; - if (cName) { - char *tmp = strdup((char *)sqlite3_column_text(stmt, 0)); - if (strcmp(cName, basename(tmp)) == 0) { - flag = 0; - str_make_ck_config_name(confName, (char *)sqlite3_column_text(stmt, 0), pName); - strcpy(ret, confName); - if (sec) { - *sec = sqlite3_column_int(stmt, 1); - } - } - free(tmp); - break; - } - else { - /* Since we are here, it means there is only 1 config for the selected program */ - flag = 0; - str_make_ck_config_name(confName, (char *)sqlite3_column_text(stmt, 0), pName); - strcpy(ret, confName); - if (sec) { - *sec = sqlite3_column_int(stmt, 1); - } - break; - } - } - sqlite3_finalize(stmt); - return flag; + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -1; } - return -1; -} -static void decorate_entry(char *entry, int secret, int primary, const char *path) { - if (primary) { - strcat(entry, " [p]"); - } + sqlite3_bind_int(stmt, 1, cid); - if (secret) { - strcat(entry, " [s]"); + while (sqlite3_step(stmt) == SQLITE_ROW) { + pid = sqlite3_column_int(stmt, 0); } - /* root */ - if (util_is_link_owned_by_root(path)) { - strcat(entry, " [root]"); + + 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); @@ -573,471 +317,3 @@ int get_program_paths(DB *db, cklist *ckl, const char* pName, int bname, int att } return -1; } - -int list_get_paths(DB *db, cklist *ckl, int bName, int attr, const char *home) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dbh_form_query_select_paths_with_attributes(sql); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -2; - } - - while (sqlite3_step(stmt) == SQLITE_ROW) { - char *tmp = strdup((char *)sqlite3_column_text(stmt, 0)); - char path[STR_L] = ""; - if (bName) { - strcat(path, basename(tmp)); - } - else { - char tpath[STR_L] = ""; - if (swap_tilde_with_home(tpath, tmp, home)) { - strcat(path, tpath); - } - else { - strcat(path, tmp); - } - } - free(tmp); - if (attr) { - decorate_entry(path, sqlite3_column_int(stmt, 1), - sqlite3_column_int(stmt, 2), - (char *)sqlite3_column_text(stmt, 0)); - } - list_add(ckl, path); - } - sqlite3_finalize(stmt); - - return 1; -} - -int list_get_programs(DB *db, cklist *ckl) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dbh_form_query_select_programs(sql); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -2; - } - - while (sqlite3_step(stmt) == SQLITE_ROW) { - list_add(ckl, (char *)sqlite3_column_text(stmt, 0)); - } - sqlite3_finalize(stmt); - - return 1; -} - -int list_get_path_program_tree(DB *db, cklist *ckl, int bName, int attr, const char *home) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dbh_form_query_select_programs(sql); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -2; - } - - while (sqlite3_step(stmt) == SQLITE_ROW) { - char programName[STR_M] = ""; - strcat(programName, (char *)sqlite3_column_text(stmt, 0)); - strcat(programName, ":"); - list_add(ckl, programName); - sqlite3_stmt *stmt2; - int rc2; - - char sql2[STR_L] = ""; - - 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_NAME); - - dbh_form_query_select_from_joined_eq(sql2, selection, condition); - - rc2 = sqlite3_prepare_v2(db->ptr, sql2, -1, &stmt2, 0); - if (rc2 != SQLITE_OK) { - return -2; - } - - sqlite3_bind_text(stmt2, 1, (char *)sqlite3_column_text(stmt, 0), -1, 0); - while (sqlite3_step(stmt2) == SQLITE_ROW) { - char treePath[STR_L] = "|- "; - char *tmp = strdup((char *)sqlite3_column_text(stmt2, 0)); - if (bName) { - strcat(treePath, basename(tmp)); - } - else { - char tpath[STR_L] = ""; - if (swap_tilde_with_home(tpath, tmp, home)) { - strcat(treePath, tpath); - } - else { - strcat(treePath, tmp); - } - } - free(tmp); - if (attr) { - decorate_entry(treePath, sqlite3_column_int(stmt2, 1), - sqlite3_column_int(stmt2, 2), - (char *)sqlite3_column_text(stmt2, 0)); - } - list_add(ckl, treePath); - } - sqlite3_finalize(stmt2); - } - sqlite3_finalize(stmt); - - return 1; -} - -int delete_prog(DB *db, int pid) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dbh_form_query_delete_x_from_y(sql, COL_PROGRAM_ID, TBL_PROGRAM); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -1; - } - sqlite3_bind_int(stmt, 1, pid); - sqlite3_step(stmt); - if (rc != SQLITE_OK) { - return -1; - } - - sqlite3_finalize(stmt); - return 0; -} - -int delete_conf(DB *db, int cid) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dbh_form_query_delete_x_from_y(sql, COL_CONFIG_ID, TBL_CONFIG); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -1; - } - sqlite3_bind_int(stmt, 1, cid); - sqlite3_step(stmt); - if (rc != SQLITE_OK) { - return -1; - } - - sqlite3_finalize(stmt); - return 0; -} - -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; -} - -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; -} - -/* Removes the relationship of `cid` with the corresponding program. - * Returns the program's pid on succes, negative integer otherwise. - */ -int remove_conf_rel(DB *db, int cid) { - sqlite3_stmt *stmt; - int rc; - - int pid = get_pid_from_cid(db, cid); - - char sql[STR_M] = ""; - dbh_form_query_delete_x_from_y(sql, COL_REL_CONFIG_ID, TBL_REL); - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -1; - } - sqlite3_bind_int(stmt, 1, cid); - sqlite3_step(stmt); - if (rc != SQLITE_OK) { - return -1; - } - - sqlite3_finalize(stmt); - - return pid; -} - -int remove_all_configs(DB *db, int pid) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_M] = ""; - dbh_form_query_select_from_joined_eq(sql, COL_REL_CONFIG_ID, COL_REL_PROGRAM_ID); - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return -2; - } - - sqlite3_bind_int(stmt, 1, pid); - - while (sqlite3_step(stmt) == SQLITE_ROW) { - delete_conf(db, sqlite3_column_int(stmt, 0)); - remove_conf_rel(db, sqlite3_column_int(stmt, 0)); - } - sqlite3_finalize(stmt); - - return 0; -} - -int get_cid_from_pname_and_basename(DB *db, const char *pName, const char *cBaseName) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_L] = ""; - char selection[STR_M] = TBL_CONFIG; - strcat(selection, "."); - strcat(selection, COL_CONFIG_ID); - strcat(selection, ", "); - strcat(selection, COL_CONFIG_PATH); - - char condition[STR_M] = TBL_PROGRAM; - strcat(condition, "."); - strcat(condition, COL_PROGRAM_NAME); - - dbh_form_query_select_from_joined_eq(sql, selection, condition); - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - ERR("while preparing get_cid_from_pname_and_basename"); - db->error = SQL_ERR_SQLITE; - return -1; - } - - sqlite3_bind_text(stmt, 1, pName, -1, 0); - int _cid = -1; - while (sqlite3_step(stmt) == SQLITE_ROW) { - if (strcmp(cBaseName, basename((char *)sqlite3_column_text(stmt, 1))) == 0) { - _cid = sqlite3_column_int(stmt, 0); - break; - } - } - sqlite3_finalize(stmt); - return _cid; -} - -int del_transaction_try(DB *db, const char *pName, const char *cBaseName) { - __BEGIN_TRANSACTION__ - int pid = -1; - if (cBaseName) { - // del conf - int cid = get_cid_from_pname_and_basename(db, pName, cBaseName); - if (cid < 0) { - ERR("Config %s doesn't exist in the database.", cBaseName); - return -1; - } - if (delete_conf(db, cid)) { - ERR("Could not delete config %s from db.", cBaseName); - return -1; - } - // handle relations - pid = remove_conf_rel(db, cid); - HELP("Deleted %s config: %s", pName, cBaseName); - if (get_program_relations(db, pid) > 0) { - goto end; - } - } - else { - pid = get_program_id(db, pName); - } - if (pid < 0) { - ERR("Program not found in the db."); - return -1; - } - /* If we are deleting a program we should delete everything that - * refferences it (configs and relationships) */ - if (!cBaseName) { - remove_all_configs(db, pid); - } - if(delete_prog(db, pid)) { - ERR("Could not delete program %s from db.", pName); - return -1; - } - HELP("Deleted program %s", pName); - end: - __END_TRANSACTION__ - return 0; -} - -int restore_program(DB *db, Conf *conf, const char *pName) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_L] = ""; - - char selection[STR_M] = COL_CONFIG_PATH; - strcat(selection, ","); - strcat(selection, COL_CONFIG_SECRET); - - char condition[STR_M] = TBL_PROGRAM; - strcat(condition, "."); - strcat(condition, COL_PROGRAM_NAME); - - dbh_form_query_select_from_joined_eq(sql, selection, condition); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return 0; - } - - sqlite3_bind_text(stmt, 1, pName, -1, 0); - int err_flag = 0; - while (sqlite3_step(stmt) == SQLITE_ROW) { - int secret = sqlite3_column_int(stmt, 1); - char filePath[STR_L] = ""; - strcpy(filePath, secret ? conf->scrt_dir : conf->vc_dir); - strcat(filePath, "/"); - strcat(filePath, pName); - strcat(filePath, "/"); - strcat(filePath, basename((char *)sqlite3_column_text(stmt, 0))); - if (!util_is_file_rw(filePath)) { - sERR("%s does not exist or is not accessible.", filePath); - err_flag = 1; - } - } - sqlite3_finalize(stmt); - return err_flag; -} - -int restore_configs_exists(DB *db, Conf *conf, const char *pName, cklist *from, cklist *to) { - sqlite3_stmt *stmt; - int rc; - - char sql[STR_L] = ""; - - char selection[STR_M] = COL_CONFIG_PATH; - strcat(selection, ","); - strcat(selection, COL_CONFIG_SECRET); - - char condition[STR_M] = TBL_PROGRAM; - strcat(condition, "."); - strcat(condition, COL_PROGRAM_NAME); - - dbh_form_query_select_from_joined_eq(sql, selection, condition); - - rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - return 0; - } - - sqlite3_bind_text(stmt, 1, pName, -1, 0); - int err_flag = 0; - while (sqlite3_step(stmt) == SQLITE_ROW) { - char filePath[STR_L] = ""; - strcpy(filePath, /*secret*/ sqlite3_column_int(stmt, 1) ? conf->scrt_dir : conf->vc_dir); - strcat(filePath, "/"); - strcat(filePath, pName); - if (!util_is_dir(filePath)) { - sERR("%s is not a directory.", filePath); - err_flag = 1; - break; - } - strcat(filePath, "/"); - strcat(filePath, basename(/*path*/ (char *)sqlite3_column_text(stmt, 0))); - if (!util_is_file_rw(filePath)) { - sERR("%s does not exist or is not accessible.", filePath); - err_flag = 1; - break; - } - list_add(from, filePath); - char tpath[STR_L] = ""; - if (!swap_tilde_with_home(tpath, (char *)sqlite3_column_text(stmt, 0), conf->home_dir)) { - strcpy(tpath, (char *)sqlite3_column_text(stmt, 0)); - } - list_add(to, tpath); - } - sqlite3_finalize(stmt); - return !err_flag; -} - -int restore_all_exist(DB *db, Conf *conf, cklist *from, cklist *to) { - cklist *programs = list_make_new(); - if (list_get_programs(db, programs) != 1) { - ERR("No programs in ckdb"); - list_free(programs); - return 0; - } - int err_flag = 0; - if (list_size(programs) > 0) { - do { - if (!restore_configs_exists(db, conf, list_get(programs), from, to)) { - err_flag = 1; - } - } while(list_next(programs)); - } - list_free(programs); - return !err_flag; -} diff --git a/src/dblayer.h b/src/dblayer.h index 2e42ad0..c830a94 100644 --- a/src/dblayer.h +++ b/src/dblayer.h @@ -35,57 +35,54 @@ struct DBstruct { SqlError error; }; -int db_exists(const UserOpt *opt); - /* Open the db file. On fail return null pointer to db->ptr * and the corresponding SQL error (NO_DB_FILE | NO_TABLES)*/ int open_DB(DB *db, const UserOpt *opt); - void close_DB(DB *db); +int db_exists(const UserOpt *opt); + + +/**********************************/ int program_exists(DB *db, const char *pName); int get_program_paths(DB *db, cklist *ckl, const char* pName, int bName, int attr, const char *home); +int get_config_number(DB *db, char *pName); +int get_program_relations(DB *db, int pid); +/* Returns the path of the found config via *ret */ +int program_has_primary_config(DB *db, const int pid, char *ret, int *sec); -/********/ -/* init */ -/********/ +/* Returns -2 or error, -1 if program doesn't exist + * else the program ID */ +int get_config_id(DB *db, const char* path); -/* Create the tables required for the ckdb */ -void init_make_tables(DB *db); -int init_make_DB(DB *db, const UserOpt *opt); +/* Returns -2 or error, -1 if program doesn't exist + * else the config ID */ +int get_program_id(DB *db, const char* name); + +int get_pid_from_cid(DB *db, int cid); -/*******/ -/* add */ -/*******/ +void print_suggested_configs(DB *db, const char *pName); +/* init.c */ +void init_make_tables(DB *db); + +/* add.c */ /* Returns 1 in error, 0 otherwise */ int add_transaction_try(DB *db, const AddOpt * const opt, const char *home); -/********/ -/* edit */ -/********/ - +/* edit.c */ int edit_get_prime_config_from_program(DB *db, char *pName, char *ret, int *secret); -int get_config_number(DB *db, char *pName); int edit_get_config(DB *db, const char *pName, char *ret, const char *cName, int *sec); -/********/ -/* list */ -/********/ - +/* list.c */ int list_get_paths(DB *db, cklist *ckl, int bName, int attr, const char *home); int list_get_programs(DB *db, cklist *ckl); int list_get_path_program_tree(DB *db, cklist *ckl, int bName, int attr, const char *home); -/*******/ -/* del */ -/*******/ - +/* delete.c */ int del_transaction_try(DB *db, const char *pName, const char *cBaseName); -/***********/ -/* restore */ -/***********/ - +/* restore.c */ int restore_configs_exists(DB *db, Conf *conf, const char *pName, cklist *from, cklist *to); int restore_all_exist(DB *db, Conf *conf, cklist *from, cklist *to); + #endif /* DBLAYER_H */ diff --git a/src/delete.c b/src/delete.c new file mode 100644 index 0000000..ce7017f --- /dev/null +++ b/src/delete.c @@ -0,0 +1,176 @@ +#include <libgen.h> + +#include "actions.h" +#include "dblayer.h" +#include "queries.h" +#include "ckerrlog.h" + +ERRLOG(delete); + +static int delete_prog(DB *db, int pid) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dbh_form_query_delete_x_from_y(sql, COL_PROGRAM_ID, TBL_PROGRAM); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -1; + } + sqlite3_bind_int(stmt, 1, pid); + sqlite3_step(stmt); + if (rc != SQLITE_OK) { + return -1; + } + + sqlite3_finalize(stmt); + return 0; +} + +static int delete_conf(DB *db, int cid) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dbh_form_query_delete_x_from_y(sql, COL_CONFIG_ID, TBL_CONFIG); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -1; + } + sqlite3_bind_int(stmt, 1, cid); + sqlite3_step(stmt); + if (rc != SQLITE_OK) { + return -1; + } + + sqlite3_finalize(stmt); + return 0; +} + +/* Removes the relationship of `cid` with the corresponding program. + * Returns the program's pid on succes, negative integer otherwise. + */ +static int remove_conf_rel(DB *db, int cid) { + sqlite3_stmt *stmt; + int rc; + + int pid = get_pid_from_cid(db, cid); + + char sql[STR_M] = ""; + dbh_form_query_delete_x_from_y(sql, COL_REL_CONFIG_ID, TBL_REL); + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -1; + } + sqlite3_bind_int(stmt, 1, cid); + sqlite3_step(stmt); + if (rc != SQLITE_OK) { + return -1; + } + + sqlite3_finalize(stmt); + + return pid; +} + +static int remove_all_configs(DB *db, int pid) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dbh_form_query_select_from_joined_eq(sql, COL_REL_CONFIG_ID, COL_REL_PROGRAM_ID); + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -2; + } + + sqlite3_bind_int(stmt, 1, pid); + + while (sqlite3_step(stmt) == SQLITE_ROW) { + delete_conf(db, sqlite3_column_int(stmt, 0)); + remove_conf_rel(db, sqlite3_column_int(stmt, 0)); + } + sqlite3_finalize(stmt); + + return 0; +} + +static int get_cid_from_pname_and_basename(DB *db, const char *pName, const char *cBaseName) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_L] = ""; + char selection[STR_M] = TBL_CONFIG; + strcat(selection, "."); + strcat(selection, COL_CONFIG_ID); + strcat(selection, ", "); + strcat(selection, COL_CONFIG_PATH); + + char condition[STR_M] = TBL_PROGRAM; + strcat(condition, "."); + strcat(condition, COL_PROGRAM_NAME); + + dbh_form_query_select_from_joined_eq(sql, selection, condition); + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + ERR("while preparing get_cid_from_pname_and_basename"); + db->error = SQL_ERR_SQLITE; + return -1; + } + + sqlite3_bind_text(stmt, 1, pName, -1, 0); + int _cid = -1; + while (sqlite3_step(stmt) == SQLITE_ROW) { + if (strcmp(cBaseName, basename((char *)sqlite3_column_text(stmt, 1))) == 0) { + _cid = sqlite3_column_int(stmt, 0); + break; + } + } + sqlite3_finalize(stmt); + return _cid; +} + +int del_transaction_try(DB *db, const char *pName, const char *cBaseName) { + __BEGIN_TRANSACTION__ + int pid = -1; + if (cBaseName) { + // del conf + int cid = get_cid_from_pname_and_basename(db, pName, cBaseName); + if (cid < 0) { + ERR("Config %s doesn't exist in the database.", cBaseName); + return -1; + } + if (delete_conf(db, cid)) { + ERR("Could not delete config %s from db.", cBaseName); + return -1; + } + // handle relations + pid = remove_conf_rel(db, cid); + HELP("Deleted %s config: %s", pName, cBaseName); + if (get_program_relations(db, pid) > 0) { + goto end; + } + } + else { + pid = get_program_id(db, pName); + } + if (pid < 0) { + ERR("Program not found in the db."); + return -1; + } + /* If we are deleting a program we should delete everything that + * refferences it (configs and relationships) */ + if (!cBaseName) { + remove_all_configs(db, pid); + } + if(delete_prog(db, pid)) { + ERR("Could not delete program %s from db.", pName); + return -1; + } + HELP("Deleted program %s", pName); + end: + __END_TRANSACTION__ + return 0; +} diff --git a/src/edit.c b/src/edit.c new file mode 100644 index 0000000..1058d45 --- /dev/null +++ b/src/edit.c @@ -0,0 +1,91 @@ +#include <libgen.h> + +#include "actions.h" +#include "dblayer.h" +#include "queries.h" +#include "ckerrlog.h" + +int edit_get_prime_config_from_program(DB *db, char *pName, char *ret, int *secret) { + int pid = get_program_id(db, pName); + /* error */ + if (pid == -2) { + return -1; + } + + /* program exists */ + if (pid > -1) { + char path[STR_M] = ""; + if (program_has_primary_config(db, pid, path, secret) == 1) { + if (!str_is_empty(path)) { + if (ret) { + str_make_ck_config_name(ret, path, pName); + } + return 0; + } + } + } + + /* No prime config found */ + return -1; +} + +int edit_get_config(DB *db, const char *pName, char *ret, const char *cName, int *sec) { + 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); + 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; + } + + int flag = -1; + while (sqlite3_step(stmt) == SQLITE_ROW) { + char confName[STR_M] = ""; + if (cName) { + char *tmp = strdup((char *)sqlite3_column_text(stmt, 0)); + if (strcmp(cName, basename(tmp)) == 0) { + flag = 0; + str_make_ck_config_name(confName, (char *)sqlite3_column_text(stmt, 0), pName); + strcpy(ret, confName); + if (sec) { + *sec = sqlite3_column_int(stmt, 1); + } + } + free(tmp); + break; + } + else { + /* Since we are here, it means there is only 1 config for the selected program */ + flag = 0; + str_make_ck_config_name(confName, (char *)sqlite3_column_text(stmt, 0), pName); + strcpy(ret, confName); + if (sec) { + *sec = sqlite3_column_int(stmt, 1); + } + break; + } + } + sqlite3_finalize(stmt); + return flag; + } + return -1; +} diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..e38a6f5 --- /dev/null +++ b/src/init.c @@ -0,0 +1,62 @@ +#include "actions.h" +#include "dblayer.h" +#include "queries.h" +#include "ckerrlog.h" + +ERRLOG(init); + +int init_create_config_file(UserOpt *opt) { + char absVCdir[STR_L] = ""; + if (!util_file_exists(list_get_at(opt->args, 0), absVCdir)) { + ERR("Version control directory: %s does not exist.", list_get_at(opt->args, 0)); + return 1; + } + + char absSRdir[STR_L] = ""; + if (!util_file_exists(list_get_at(opt->args, 1), absSRdir)) { + ERR("Secret directory: %s does not exist.", list_get_at(opt->args, 1)); + return 1; + } + + if (!util_file_exists(opt->confDir, NULL)) { + util_mkdir(opt->confDir); + } + + char confName[STR_L] = ""; + make_config_name(confName, opt->confDir); + FILE *f; + if ((f = fopen(confName, "w")) == NULL) { + return 1; + } + + char tmp[STR_L] = ""; + strcpy(tmp, "version_control_dir = "); + strcat(tmp, absVCdir); + strcat(tmp, "\n"); + fputs(tmp, f); + + strcpy(tmp, "secret_dir = "); + strcat(tmp, absSRdir); + strcat(tmp, "\n"); + fputs(tmp, f); + + strcpy(tmp, "home_dir = "); + strcat(tmp, getenv("HOME")); + strcat(tmp, "\n"); + fputs(tmp, f); + + fclose(f); + return 0; +} + +void init_make_tables(DB *db) { + char sql[STR_L] = ""; + dbh_form_query_make_tables(sql); + + int rc = sqlite3_exec(db->ptr, sql, 0, 0, 0); + if (rc != SQLITE_OK ) { + PRINT_ERR("Could not create empty db."); + db->error = SQL_ERR_SQLITE; + return; + } +} diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..105c101 --- /dev/null +++ b/src/list.c @@ -0,0 +1,206 @@ +#include <libgen.h> + +#include "actions.h" +#include "dblayer.h" +#include "queries.h" +#include "ckerrlog.h" + +ListOpt list_make_options(cklist *args) { + list_rewind(args); + ListOpt listOpt = { + ._lt = LT_TREE, + ._lst = LST_PLAIN, + .pName = NULL, + .attr = 0, + .bName = 0, + .err = 0 + }; + + if (list_size(args)) { + do { + if (strcmp(list_get(args), "-a") == 0) { + listOpt.attr = 1; + continue; + } + if (strcmp(list_get(args), "-b") == 0) { + listOpt.bName = 1; + continue; + } + if (strcmp(list_get(args), "-t") == 0) { + if (!list_next(args)) { + listOpt.err = 1; + break; + } + if (strcmp(list_get(args), "plain") == 0) { + listOpt._lst = LST_PLAIN; + } + else if (strcmp(list_get(args), "lisp") == 0) { + listOpt._lst = LST_LISP; + } + else if (strcmp(list_get(args), "python") == 0) { + listOpt._lst = LST_PYTHON; + } + else { + listOpt.err = 1; + } + } + else if (strcmp(list_get(args), "paths") == 0) { + listOpt._lt = LT_PATH; + } + else if (strcmp(list_get(args), "programs") == 0) { + listOpt._lt = LT_PROGRAM; + } + else if (strcmp(list_get(args), "tree") == 0) { + listOpt._lt = LT_TREE; + } + else if (strcmp(list_get(args), "ckconf") == 0) { + listOpt._lt = LT_CKCONF; + } + else if (strcmp(list_get(args), "-p") == 0) { + if (list_next(args)) { + listOpt._lt = LT_PROG_CONFS; + listOpt.pName = list_get(args); + } + else { + listOpt.err = 1; + break; + } + } + else { + listOpt.err = 1; + } + } while(list_next(args)); + } + list_rewind(args); + return listOpt; +} + +int list_get_paths(DB *db, cklist *ckl, int bName, int attr, const char *home) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dbh_form_query_select_paths_with_attributes(sql); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -2; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + char *tmp = strdup((char *)sqlite3_column_text(stmt, 0)); + char path[STR_L] = ""; + if (bName) { + strcat(path, basename(tmp)); + } + else { + char tpath[STR_L] = ""; + if (swap_tilde_with_home(tpath, tmp, home)) { + strcat(path, tpath); + } + else { + strcat(path, tmp); + } + } + free(tmp); + if (attr) { + decorate_entry(path, sqlite3_column_int(stmt, 1), + sqlite3_column_int(stmt, 2), + (char *)sqlite3_column_text(stmt, 0)); + } + list_add(ckl, path); + } + sqlite3_finalize(stmt); + + return 1; +} + +int list_get_programs(DB *db, cklist *ckl) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dbh_form_query_select_programs(sql); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -2; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + list_add(ckl, (char *)sqlite3_column_text(stmt, 0)); + } + sqlite3_finalize(stmt); + + return 1; +} + +int list_get_path_program_tree(DB *db, cklist *ckl, int bName, int attr, const char *home) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_M] = ""; + dbh_form_query_select_programs(sql); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return -2; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + char programName[STR_M] = ""; + strcat(programName, (char *)sqlite3_column_text(stmt, 0)); + strcat(programName, ":"); + list_add(ckl, programName); + sqlite3_stmt *stmt2; + int rc2; + + char sql2[STR_L] = ""; + + 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_NAME); + + dbh_form_query_select_from_joined_eq(sql2, selection, condition); + + rc2 = sqlite3_prepare_v2(db->ptr, sql2, -1, &stmt2, 0); + if (rc2 != SQLITE_OK) { + return -2; + } + + sqlite3_bind_text(stmt2, 1, (char *)sqlite3_column_text(stmt, 0), -1, 0); + while (sqlite3_step(stmt2) == SQLITE_ROW) { + char treePath[STR_L] = "|- "; + char *tmp = strdup((char *)sqlite3_column_text(stmt2, 0)); + if (bName) { + strcat(treePath, basename(tmp)); + } + else { + char tpath[STR_L] = ""; + if (swap_tilde_with_home(tpath, tmp, home)) { + strcat(treePath, tpath); + } + else { + strcat(treePath, tmp); + } + } + free(tmp); + if (attr) { + decorate_entry(treePath, sqlite3_column_int(stmt2, 1), + sqlite3_column_int(stmt2, 2), + (char *)sqlite3_column_text(stmt2, 0)); + } + list_add(ckl, treePath); + } + sqlite3_finalize(stmt2); + } + sqlite3_finalize(stmt); + + return 1; +} diff --git a/src/dbhelper.c b/src/queries.c index 9de780e..0c56cc1 100644 --- a/src/dbhelper.c +++ b/src/queries.c @@ -1,4 +1,4 @@ -/* dbhelper.c - Database layer for ck -----------------------------------*- C -*- +/* queries.c - Database stuff for ck -----------------------------------*- C -*- * * This file is part of ck, the config keeper * @@ -8,7 +8,7 @@ * GPLv3 (see LICENCE for the full notice) * * -------------------------------------------------------------------------- */ -#include "dbhelper.h" +#include "queries.h" void dbh_form_query_make_tables(char *query) { char tmp[STR_L] = "CREATE TABLE "; diff --git a/src/dbhelper.h b/src/queries.h index 31559cc..d4c3ae0 100644 --- a/src/dbhelper.h +++ b/src/queries.h @@ -1,4 +1,4 @@ -/* dbhelper.h - Database layer for ck ----------------------------------*- C -*- +/* queries.h - Database stuff for ck -----------------------------------*- C -*- * * This file is part of ck, the config keeper * diff --git a/src/restore.c b/src/restore.c new file mode 100644 index 0000000..c90cb82 --- /dev/null +++ b/src/restore.c @@ -0,0 +1,114 @@ +#include <libgen.h> + +#include "actions.h" +#include "dblayer.h" +#include "queries.h" +#include "ckerrlog.h" + +ERRLOG(restore); + +int restore_make_links(cklist *from, cklist *to) { + list_rewind(from); + list_rewind(to); + if (list_size(from) > 0 + && list_size(to) > 0 + && list_size(from) == list_size(to)) { + do { + if (util_file_exists(list_get(to), NULL) + || !util_is_file_link(list_get(to))) { + ERR("File %s already exists.", list_get(to)); + sERR("No links were created."); + return -1; + } + } while (list_next(to)); + list_rewind(to); + while (1) { + if (util_symlink_file(list_get(from), list_get(to))) { + ERR("FATAL could not link %s -> %s", list_get(from), list_get(to)); + sERR("Process stopping."); + return -1; + } + hLOG("Linking: %s -> %s", list_get(from), list_get(to)); + if (util_own_grp_copy(list_get(to), list_get(from))) { + return -1; + } + if (!list_next(from)) { + break; + } + if (!list_next(to)) { + break; + } + } + } + return 0; +} + +int restore_configs_exists(DB *db, Conf *conf, const char *pName, cklist *from, cklist *to) { + sqlite3_stmt *stmt; + int rc; + + char sql[STR_L] = ""; + + char selection[STR_M] = COL_CONFIG_PATH; + strcat(selection, ","); + strcat(selection, COL_CONFIG_SECRET); + + char condition[STR_M] = TBL_PROGRAM; + strcat(condition, "."); + strcat(condition, COL_PROGRAM_NAME); + + dbh_form_query_select_from_joined_eq(sql, selection, condition); + + rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + return 0; + } + + sqlite3_bind_text(stmt, 1, pName, -1, 0); + int err_flag = 0; + while (sqlite3_step(stmt) == SQLITE_ROW) { + char filePath[STR_L] = ""; + strcpy(filePath, /*secret*/ sqlite3_column_int(stmt, 1) ? conf->scrt_dir : conf->vc_dir); + strcat(filePath, "/"); + strcat(filePath, pName); + if (!util_is_dir(filePath)) { + sERR("%s is not a directory.", filePath); + err_flag = 1; + break; + } + strcat(filePath, "/"); + strcat(filePath, basename(/*path*/ (char *)sqlite3_column_text(stmt, 0))); + if (!util_is_file_rw(filePath)) { + sERR("%s does not exist or is not accessible.", filePath); + err_flag = 1; + break; + } + list_add(from, filePath); + char tpath[STR_L] = ""; + if (!swap_tilde_with_home(tpath, (char *)sqlite3_column_text(stmt, 0), conf->home_dir)) { + strcpy(tpath, (char *)sqlite3_column_text(stmt, 0)); + } + list_add(to, tpath); + } + sqlite3_finalize(stmt); + return !err_flag; +} + +int restore_all_exist(DB *db, Conf *conf, cklist *from, cklist *to) { + cklist *programs = list_make_new(); + if (list_get_programs(db, programs) != 1) { + ERR("No programs in ckdb"); + list_free(programs); + return 0; + } + int err_flag = 0; + if (list_size(programs) > 0) { + do { + if (!restore_configs_exists(db, conf, list_get(programs), from, to)) { + err_flag = 1; + } + } while(list_next(programs)); + } + list_free(programs); + return !err_flag; +} diff --git a/test/05_restore b/test/05_restore new file mode 100644 index 0000000..b27ed35 --- /dev/null +++ b/test/05_restore @@ -0,0 +1,46 @@ +#!/bin/bash + +init restore + +# setup test configs +path1=$BIN/test1.conf +path2=$BIN/test2.conf +path3=$BIN/test3.conf +path4=$BIN/test4.conf + +add_config prog1 $path1 +add_config prog1 $path2 + +add_config prog2 $path3 +add_config prog2 $path4 + +# delete prog1 links +rm $path1 $path2 + +# restore them +exec $BIN/ck -c $BIN restore -p prog1 > /dev/null & +wait $! + +for i in $($BIN/ck -c $BIN list -p prog1); do + if [[ ! -L "$i" ]]; then + err "Couldn't restore path $i" + exit 1 + fi +done + +## delete all links +rm $path1 $path2 $path3 $path4 + +# restore all +exec $BIN/ck -c $BIN restore all > /dev/null & +wait $! + +for i in $($BIN/ck -c $BIN list paths); do + if [[ ! -L "$i" ]]; then + err "Couldn't restore path $i" + exit 1 + fi +done + +clear_tests +echo -e $PASS |