From 401820e28b74e09bffdeaa25fcf6de518487a433 Mon Sep 17 00:00:00 2001 From: Anastasis Grammenos Date: Sat, 27 Oct 2018 00:49:06 +0300 Subject: restore --- src/actionhelper.c | 43 ++++++++++++++++++++++ src/actionhelper.h | 5 +++ src/actionparser.c | 22 ++++++++++- src/actionparser.h | 1 + src/actions.c | 63 ++++++++++++++++++++++++++++++++ src/dblayer.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dblayer.h | 7 ++++ 7 files changed, 244 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/actionhelper.c b/src/actionhelper.c index ad259a2..0269470 100644 --- a/src/actionhelper.c +++ b/src/actionhelper.c @@ -260,6 +260,36 @@ ListOpt list_make_options(cklist *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)) { + while (1) { + HELP("%s %d %d", list_get(to), util_file_exists(list_get(to), NULL), !util_is_file_link(list_get(to))); + if (util_file_exists(list_get(to), NULL) + || !util_is_file_link(list_get(to))) { + sERR("File %s already exists. Terminating.", list_get(to)); + return -1; + } + if (util_symlink_file(list_get(from), list_get(to))) { + sERR("Failed: %s -> %s", list_get(from), list_get(to)); + return -1; + } + LOG("Linking: %s -> %s", list_get(from), list_get(to)); + HELP("Linking: %s -> %s", list_get(from), list_get(to)); + if (!list_next(from)) { + break; + } + if (!list_next(to)) { + break; + } + } + } + return 0; +} + /*****************/ /* PRINT RESULTS */ /*****************/ @@ -317,6 +347,14 @@ void print_HELP_result(int err) { } } +void print_RESTORE_result(int err) { + if (!err) { + HELP("restore OK"); + return; + } + sERR("restore NOT OK"); +} + void print_INIT_help() { ckhelp("Initialize the database and create the file that holds"); ckhelp("the paths where configurations will be stored."); @@ -406,6 +444,11 @@ void print_HELP_help() { report_help(); } +void print_RESTORE_help() { + ckhelp("Restore help"); + report_help(); +} + void print_conf_help(void) { ckhelp("Set a different ck configuration directory.\n"); ckhelp("This has to be passed before any action or action argument"); diff --git a/src/actionhelper.h b/src/actionhelper.h index bfe0b85..4265691 100644 --- a/src/actionhelper.h +++ b/src/actionhelper.h @@ -53,6 +53,11 @@ extern void edit_print_suggested_configs(DB *db, const char *pName); /********/ extern ListOpt list_make_options(cklist *args); +/***********/ +/* RESTORE */ +/***********/ +extern int restore_make_links(cklist *from, cklist *to); + /************************/ /* PRINT RESULTS & HELP */ /************************/ diff --git a/src/actionparser.c b/src/actionparser.c index 529876e..c4bfbc5 100644 --- a/src/actionparser.c +++ b/src/actionparser.c @@ -24,6 +24,7 @@ const char* const strEDIT[] = {"3", "edit", "e", "-e"}; const char* const strLIST[] = {"5", "list", "ls", "l", "-l", "-ls"}; const char* const strSEARCH[] = {"4", "search", "grep", "s", "-s"}; const char* const strHELP[] = {"5", "help", "h", "-?", "-h", "--help"}; +const char* const strRESTORE[] = {"3", "restore","r", "-r"}; const char* const strConfDir[] = {"2", "config", "-c"}; const char* const strVersion[] = {"2", "version", "--version"}; const char* const strVerbose1[] = {"2", "--verbose", "-v"}; @@ -160,6 +161,18 @@ int parse_HELP(UserOpt *opt) { return 0; } +int parse_RESTORE(UserOpt *opt) { + /* Restore expects 1 to 2 arguments */ + if (optNum < pos + 1 + || optNum > pos + 2) { + opt->err = PERR_RESTORE_WRONG; + return -1; + } + + int arg_num = optNum - pos; + fill_args_list(arg_num, opt); + return 0; +} int parse_vals(UserOpt *opt) { switch (opt->action) { @@ -354,6 +367,9 @@ void print_parser_error(UserOpt *opt) { break; case PERR_HELP_WRONG: sprintf(errStr, "Get help for a ck action.\nUsage: %s action", names); + break; + case PERR_RESTORE_WRONG: + sprintf(errStr, "Restore links of programs.\nUsage: %s {all} | {-p programName}", names); } HELP("%s", errStr); } @@ -373,9 +389,11 @@ void print_parser_help() { get_possible_action_strings(names, CKA_LIST); ckhelp("List configs: \t%s", names); get_possible_action_strings(names, CKA_SEARCH); - ckhelp("Search: \t%s", names); + ckhelp("Search configs: \t%s", names); + get_possible_action_strings(names, CKA_RESTORE); + ckhelp("Restore links: \t%s", names); get_possible_action_strings(names, CKA_HELP); - ckhelp("Actions Help: \t%s", names); + ckhelp("Help: \t%s", names); report_help(); } diff --git a/src/actionparser.h b/src/actionparser.h index d3c97c4..0a28511 100644 --- a/src/actionparser.h +++ b/src/actionparser.h @@ -27,6 +27,7 @@ X(EDIT) \ X(LIST) \ X(SEARCH) \ + X(RESTORE) \ X(HELP) enum ParseErrors { diff --git a/src/actions.c b/src/actions.c index 48a4066..5220864 100644 --- a/src/actions.c +++ b/src/actions.c @@ -300,3 +300,66 @@ int run_HELP(UserOpt *opt, Conf *conf) { } return 1; } + +int run_RESTORE(UserOpt *opt, Conf *conf) { + UNUSED(conf); + DB db = open_DB(opt); + if (db.ptr == NULL) { + if (db.error == SQL_ERR_NO_TABLES) { + ERR("The database file is currupted. Run ck init anew."); + } + return 1; + } + cklist *from = list_make_new(); + cklist *to = list_make_new(); + int err_flag = 0; + if (strcmp(list_get(opt->args), "-p") == 0) { + if (list_next(opt->args)) { + if (program_exists(&db, list_get(opt->args))) { + if (restore_configs_exists(&db, conf, list_get(opt->args), from, to)) { + HELP("Making links for %s", list_get(opt->args)); + } + else { + err_flag = 1; + } + } + else { + ERR("Program %s does not exist", list_get(opt->args)); + err_flag = 1; + } + } + else { + sERR("-p needs a program name"); + err_flag = 1; + } + } + else if (strcmp(list_get(opt->args), "all") == 0) { + if (!list_next(opt->args)) { + if (restore_all_exist(&db, conf, from, to)) { + HELP("Make all links"); + } + else { + err_flag = 1; + } + } + else { + sERR("Wrong argument"); + err_flag = 1; + } + } + else { + sERR("Wrong argument"); + err_flag = 1; + } + close_DB(&db); + if (!err_flag) { + HELP("LINKS"); + int rc = restore_make_links(from, to); + list_free(from); + list_free(to); + return rc; + } + list_free(from); + list_free(to); + return 1; +} diff --git a/src/dblayer.c b/src/dblayer.c index acdf339..33e1682 100644 --- a/src/dblayer.c +++ b/src/dblayer.c @@ -842,3 +842,108 @@ int del_transaction_try(DB *db, char *arg, int conf) { __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; + } + list_add(from, filePath); + list_add(to, /*path*/ (char *)sqlite3_column_text(stmt, 0)); + } + 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 94ef7ea..13ac187 100644 --- a/src/dblayer.h +++ b/src/dblayer.h @@ -81,4 +81,11 @@ extern int list_get_path_program_tree(DB *db, cklist *ckl, int attr); /*******/ extern int del_transaction_try(DB *db, char *arg, int conf); + +/***********/ +/* restore */ +/***********/ + +extern int restore_configs_exists(DB *db, Conf *conf, const char *pName, cklist *from, cklist *to); +extern int restore_all_exist(DB *db, Conf *conf, cklist *from, cklist *to); #endif /* DBLAYER_H */ -- cgit v1.2.3