/* 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 <libgen.h>
#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();
}