/* restore.c - the restore action --------------------------------------*- C -*- * * This file is part of ck, the config keeper * * ----------------------------------------------------------------------------- * * Copyright (C) 2019 Anastasis Grammenos * GPLv3 (see LICENCE for the full notice) * * -------------------------------------------------------------------------- */ #include #include "dblayer.h" #include "ckerrlog.h" ERRLOG(restore); static 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; } static 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_fq_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; } static 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; } int run_RESTORE(UserOpt *opt, Conf *conf) { DB db; if (open_DB(&db, opt)) { return -1; } cklist *from = list_make_new(); cklist *to = list_make_new(); int err_flag = 0; char *arg = list_get(opt->args); if (strcmp(arg, "--all") != 0) { if (program_exists(&db, arg)) { if (restore_configs_exists(&db, conf, arg, from, to)) { hLOG("Restoring links for %s...", arg); } else { err_flag = 1; } } else { ERR("Program %s does not exist", arg); err_flag = 1; } } else { if (restore_all_exist(&db, conf, from, to)) { hLOG("Restoring all links..."); } else { err_flag = 1; } } close_DB(&db); int rc = -1; if (!err_flag) { rc = restore_make_links(from, to); if (rc) { sERR("Restore failed."); } } list_free(from); list_free(to); return rc; } void print_RESTORE_help() { ckhelp("ck restore PROGRAM_NAME"); ckhelp("ck restore --all"); report_help(); }