diff options
Diffstat (limited to 'src/add.c')
-rw-r--r-- | src/add.c | 287 |
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; +} |