aboutsummaryrefslogblamecommitdiffstats
path: root/src/dblayer.c
blob: 94af08919122f5ebf6a4a6e7adec7dee143eb41a (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                                

                                             

                                                                                
  
                                          

                                          
                                                                                

                   
                    


                     
 
                                                 
 
                                  
                                                           
                           
                            
                                
 
                       

 

                                   
                           

                                      

 
                                        
                                              
                       
                                

                     
                                                             



                                                                
                                                   

                           
                                                  

                          
                                               













                          

                         

 



                                         
         
                           
 
                                      






                                                             




                                                               

   

                            

 
                                              


                     
                       
                           


                                                      
                                                           

              
                                                         








                                            






                                               
                                             


                     
                       
                          


                                                      
                                                    

              
                                                         








                                            
                                                                            


                     
                       




                                      





                                             
                                                          


                                                      
                                                                   

              
 
                                 
                                            









                                                         

                         
           

 



                                            
 
                       
                                      
 

                                                      

              
 


                                            
   
 
                        

              


                         
 

                                            

                      
                                          
   


            



                                       
 
                       
                               
 


                                                      
   
 
                                 
 

                                            
   


                        
   

                         

 








                                                         
 
                                                                                                      











                                            



                                          



                                        
                         
                                                            






                                                        


                                                               



                                     






                                                     

                 


                                                             
       





                           
            
 





                            
                             













                                                      
/* dblayer.c - Database layer for ck -----------------------------------*- 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(ckdb);

static const char * const DB_FILE_NAME = "/ckdb";

/* figure out the database name */
static void make_db_name(char *ret, const char *confPath) {
  char db_path[STR_L] = "";
  strcpy(db_path, confPath);
  strcat(db_path, DB_FILE_NAME);

  strcpy(ret, db_path);
}

/* Check if the db file exists*/
int db_exists(const UserOpt *opt) {
  char db_path[STR_L] = "";
  make_db_name(db_path, opt->confDir);
  return util_is_file_rw(db_path);
}

/* check if db has the correct tables */
static int check_initialized_DB(sqlite3 *db) {
  char sql[STR_M] = "";
  dbh_fq_select_all_tables(sql);
  sqlite3_stmt *stmt;

  sqlite3_prepare_v2(db, sql, (int)strlen(sql), &stmt, NULL);

  int program_table_ok, config_table_ok, rel_table_ok = 0;
  while (sqlite3_step(stmt) != SQLITE_DONE) {
    const unsigned char *tmpbuf  = sqlite3_column_text(stmt, 1);
    if (strcmp((char *)tmpbuf, TBL_PROGRAM) == 0) {
      program_table_ok = 1;
    }
    if (strcmp((char *)tmpbuf, TBL_CONFIG) == 0) {
      config_table_ok = 1;
    }
    if (strcmp((char *)tmpbuf, TBL_REL) == 0) {
      rel_table_ok = 1;
    }
  }

  if (!program_table_ok
      || !config_table_ok
      || !rel_table_ok ) {
    return 1;
  }

  sqlite3_finalize(stmt);
  return 0;
}

void close_DB(DB *db) {
  sqlite3_close(db->ptr);
}

int open_DB(DB *db, const UserOpt *opt) {
  if (!db || !opt) {
    return -1;
  }
  int rc;
  char db_path[STR_L] = "";

  make_db_name(db_path, opt->confDir);
  rc = sqlite3_open(db_path, &db->ptr);

  if (rc) {
    ERR("%s is not a path to an sqlite3 database.", db_path);
    return -1;
  }

  if (opt->action != CKA_INIT) {
    if (check_initialized_DB(db->ptr)) {
      ERR("The database file is currupted. Run ck init anew.");
      return -1;
    }
  }

  LOG("Opened %s", db_path);
  return 0;
}

int get_program_id(DB *db, const char* name) {
  sqlite3_stmt *stmt;
  int rc;

  char sql[STR_M] = "";
  dhb_fq_find_program(sql);

  rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0);
  if (rc != SQLITE_OK) {
    PRINT_ERR("Error while preparing get_program_id sql.");
    return -2;
  }
  sqlite3_bind_text(stmt, 1, name, (int)strlen(name), 0);
  int id = -1;
  while (sqlite3_step(stmt) == SQLITE_ROW) {
    id = sqlite3_column_int(stmt, 0);
    break;
  }
  sqlite3_finalize(stmt);
  return id;
}

int program_exists(DB *db, const char *pName) {
  if (get_program_id(db, pName) == -1) {
    return 0;
  }
  return 1;
}

int get_config_id(DB *db, const char* path) {
  sqlite3_stmt *stmt;
  int rc;

  char sql[STR_M] = "";
  dhb_fq_find_config(sql);

  rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0);
  if (rc != SQLITE_OK) {
    PRINT_ERR("while preparing get_config_id sql.");
    return -2;
  }
  sqlite3_bind_text(stmt, 1, path, (int)strlen(path), 0);
  int id = -1;
  while (sqlite3_step(stmt) == SQLITE_ROW) {
    id = sqlite3_column_int(stmt, 0);
    break;
  }
  sqlite3_finalize(stmt);
  return id;
}

int program_has_primary_config(DB *db, const int pid, char *ret, int *sec) {
  sqlite3_stmt *stmt;
  int rc;

  char sql[STR_L] = "";

  char condition[STR_S] = TBL_PROGRAM;
  strcat(condition, ".");
  strcat(condition, COL_PROGRAM_ID);

  char selection[STR_M] = COL_CONFIG_PRIMARY;
  strcat(selection, ", ");
  strcat(selection, COL_CONFIG_PATH);
  strcat(selection, ", ");
  strcat(selection, COL_CONFIG_SECRET);

  dbh_fq_select_from_joined_eq(sql, selection, condition);

  rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0);
  if (rc != SQLITE_OK) {
    PRINT_ERR("whinnle preparing program_has_primary_exists sql.");
    return -2;
  }

  sqlite3_bind_int(stmt, 1, pid);
  while (sqlite3_step(stmt) == SQLITE_ROW) {
    if (sqlite3_column_int(stmt, 0) == 1) {
      if (ret) {
        strcpy(ret,(char *)sqlite3_column_text(stmt, 1));
      }
      if (sec) {
        *sec = sqlite3_column_int(stmt, 2);
      }
      sqlite3_finalize(stmt);
      return 1;
    }
  }
  sqlite3_finalize(stmt);
  return 0;
}

int get_program_relations(DB *db, int pid) {
  int count = -1;
  sqlite3_stmt *stmt;
  int rc;

  char sql[STR_M] = "";
  dbh_fq_count_program_relations(sql);

  rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0);
  if (rc != SQLITE_OK) {
    return -1;
  }

  sqlite3_bind_int(stmt, 1, pid);
  while (sqlite3_step(stmt) == SQLITE_ROW) {
    count = sqlite3_column_int(stmt, 0);
  }

  if (rc != SQLITE_OK) {
    return -1;
  }
  sqlite3_finalize(stmt);
  return count;
}

int get_config_number(DB *db, char* pName) {
  int pid = get_program_id(db, pName);
  /* program exists */
  if (pid > -1) {
    return get_program_relations(db, pid);
  }
  return -1;
}

int get_pid_from_cid(DB *db, int cid) {
  int pid = -1;
  sqlite3_stmt *stmt;
  int rc;

  char sql[STR_M] = "";
  dbh_fq_get_pid_from_cid(sql);

  rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0);
  if (rc != SQLITE_OK) {
    return -1;
  }

  sqlite3_bind_int(stmt, 1, cid);

  while (sqlite3_step(stmt) == SQLITE_ROW) {
    pid = sqlite3_column_int(stmt, 0);
  }

  if (rc != SQLITE_OK) {
    return -1;
  }
  sqlite3_finalize(stmt);
  return pid;
}

void print_suggested_configs(DB *db, const char *pName) {
  char name[STR_M] = "";
  strcat(name, pName);
  strcat(name, ":");
  cklist *paths = list_make_and_add(name);
  get_program_paths(db, paths, pName, 1, 0, NULL);
  list_print(paths);
  list_free(paths);
}

int get_program_paths(DB *db, cklist *ckl, const char* pName, int bname, int attr, const char *home) {
  int pid = get_program_id(db, pName);
  /* error */
  if (pid == -2) {
    return -1;
  }

  /* program exists */
  if (pid > -1) {
    sqlite3_stmt *stmt;
    int rc;

    char selection[STR_M] = COL_CONFIG_PATH;
    strcat(selection, ",");
    strcat(selection, COL_CONFIG_SECRET);
    strcat(selection, ",");
    strcat(selection, COL_CONFIG_PRIMARY);
    char condition[STR_M] = TBL_PROGRAM;
    strcat(condition, ".");
    strcat(condition, COL_PROGRAM_ID);

    char sql[STR_L] = "";
    dbh_fq_select_from_joined_eq(sql, selection, condition);

    rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0);
    sqlite3_bind_int(stmt, 1, pid);
    if (rc != SQLITE_OK) {
      return -2;
    }

    while (sqlite3_step(stmt) == SQLITE_ROW) {
      char *tmp = strdup((char *)sqlite3_column_text(stmt, 0));
      char entry[STR_M] = "";
      if (bname) {
        strcat(entry, basename(tmp));
      }
      else {
        char tpath[STR_L] = "";
        if (swap_tilde_with_home(tpath, tmp, home)) {
          strcat(entry, tpath);
        }
        else {
          strcat(entry, tmp);
        }
      }
      if (attr) {
        decorate_entry(entry, sqlite3_column_int(stmt, 1),
                       sqlite3_column_int(stmt, 2),
                       (char *)sqlite3_column_text(stmt, 0));
      }
      list_add(ckl, entry);
      free(tmp);
    }
    sqlite3_finalize(stmt);
    return 0;
  }
  return -1;
}

int secret_enabled(DB *db) {
  sqlite3_stmt *stmt;
  int rc;

  char sql[STR_M] = "";
  dbh_fq_secret_enabled(sql);

  rc = sqlite3_prepare_v2(db->ptr, sql, -1, &stmt, 0);
  if (rc != SQLITE_OK) {
    ERR("while preparing secret_enabled sql.");
    return -2;
  }
  int enabled = 1;
  while (sqlite3_step(stmt) == SQLITE_ROW) {
    enabled = sqlite3_column_int(stmt, 0);
    break;
  }
  sqlite3_finalize(stmt);
  return enabled;
}