aboutsummaryrefslogblamecommitdiffstats
path: root/src/restore.c
blob: 426e8033b697d924dbdaa56276aedadf3ccbb487 (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                                                

                   
                    



                     
                                                         






                                              
                                               


























                                                                           
                                                                                                    

















































                                                                                             
                                                                            
















                                                                            








                                           




                                                             

            



                     
                                            


                   


                                                 

          


                   













                                      

                                    

                
/* restore.c - the restore action --------------------------------------*- 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 "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_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;
}

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();
}