aboutsummaryrefslogtreecommitdiffstats
path: root/src/add.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/add.c')
-rw-r--r--src/add.c287
1 files changed, 287 insertions, 0 deletions
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;
+}