LCOV - code coverage report
Current view: top level - src - db_validate_paths.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.7 % 95 70
Test Date: 2026-01-12 05:34:38 Functions: 100.0 % 1 1

            Line data    Source code
       1              : #include "precizer.h"
       2              : 
       3              : /**
       4              :  * @brief Validates path consistency between database records and provided config variables
       5              :  *
       6              :  * @details This function performs validation of paths by comparing paths stored
       7              :  * in the database against paths provided as config variables. The validation
       8              :  * process involves:
       9              :  *
      10              :  * 1. Checking if paths stored in database match paths passed as config variables
      11              :  * 2. Warning user about potential data loss if paths mismatch
      12              :  * 3. Handling forced path updates when --force flag is used
      13              :  *
      14              :  * The function supports several operational modes:
      15              :  * - Normal mode: Validates paths and prevents updates if mismatch detected
      16              :  * - Force mode: Allows path updates even when mismatches are detected
      17              :  * - Compare mode: Skips validation entirely
      18              :  *
      19              :  * Database operations:
      20              :  * - Queries existing paths from database
      21              :  * - Creates temporary tables for tracking mismatched paths
      22              :  * - Performs path prefix comparisons
      23              :  *
      24              :  * @note This function is crucial for preventing accidental data loss by ensuring
      25              :  * path consistency before performing database operations.
      26              :  *
      27              :  * @warning Using --force flag can lead to loss or replacement of file and
      28              :  * checksum information if used incorrectly.
      29              :  *
      30              :  * Error handling:
      31              :  * - Memory allocation failures
      32              :  * - SQLite preparation and execution errors
      33              :  * - Path mismatch detection
      34              :  *
      35              :  * @provide Return Status code indicating operation result:
      36              :  *         - SUCCESS (0): Paths are valid or force flag is used
      37              :  *         - FAILURE (1): Path mismatch detected without force flag
      38              :  *                       or database operation error occurred
      39              :  */
      40          186 : Return db_validate_paths(void)
      41              : {
      42              :         /// The status that will be passed to return() before exiting.
      43              :         /// By default, the function worked without errors.
      44          186 :         Return status = SUCCESS;
      45              : 
      46              :         // Don't do anything
      47          186 :         if(config->compare == true)
      48              :         {
      49           32 :                 return(status);
      50              :         }
      51              : 
      52              :         /* Interrupt the function smoothly */
      53              :         /* Interrupt when Ctrl+C */
      54          154 :         if(global_interrupt_flag == true)
      55              :         {
      56            0 :                 provide(status);
      57              :         }
      58              : 
      59          154 :         sqlite3_stmt *select_stmt = NULL;
      60          154 :         sqlite3_stmt *insert_stmt = NULL;
      61          154 :         int rc = 0;
      62              : 
      63          154 :         bool paths_are_equal = true;
      64              : 
      65          154 :         create(char,select_sql);
      66              : 
      67              :         // Create the SQL request
      68          154 :         if(config->paths[0] != NULL)
      69              :         {
      70          154 :                 char const *sql_1 = "SELECT ID FROM paths WHERE prefix NOT IN (";
      71              : 
      72          154 :                 status = concat_literal(select_sql,sql_1);
      73              : 
      74          154 :                 if(SUCCESS != status)
      75              :                 {
      76            0 :                         del(select_sql);
      77            0 :                         provide(status);
      78              :                 }
      79              : 
      80          308 :                 for(int i = 0; config->paths[i]; i++)
      81              :                 {
      82          154 :                         create(char,path);
      83              : 
      84          154 :                         run(db_sql_wrap_string(path,config->paths[i]));
      85              : 
      86          154 :                         run(concat_literal(select_sql,getcstring(path)));
      87              : 
      88          154 :                         del(path);
      89              : 
      90          154 :                         if(SUCCESS != status)
      91              :                         {
      92            0 :                                 del(select_sql);
      93            0 :                                 provide(status);
      94              :                         }
      95              : 
      96              :                         // Not the last path in the array
      97          154 :                         if(config->paths[i + 1] != 0)
      98              :                         {
      99              :                                 /* Concatenate with the comma character "," */
     100            0 :                                 status = concat_literal(select_sql,",");
     101              : 
     102            0 :                                 if(SUCCESS != status)
     103              :                                 {
     104            0 :                                         del(select_sql);
     105            0 :                                         provide(status);
     106              :                                 }
     107              :                         }
     108              :                 }
     109              : 
     110              :                 /* Close the string that contains SQL request */
     111              : 
     112              :                 /* Concatenate with the ");" characters */
     113          154 :                 status = concat_literal(select_sql,");");
     114              : 
     115          154 :                 if(SUCCESS != status)
     116              :                 {
     117            0 :                         del(select_sql);
     118            0 :                         provide(status);
     119              :                 }
     120              :         }
     121              : 
     122          154 :         rc = sqlite3_prepare_v2(config->db,getstring(select_sql),-1,&select_stmt,NULL);
     123              : 
     124          154 :         if(SQLITE_OK != rc)
     125              :         {
     126            0 :                 log_sqlite_error(config->db,rc,NULL,"Can't prepare select statement %s",getstring(select_sql));
     127            0 :                 status = FAILURE;
     128              :         }
     129              : 
     130          154 :         if(SUCCESS == status)
     131              :         {
     132          312 :                 while(SQLITE_ROW == (rc = sqlite3_step(select_stmt)))
     133              :                 {
     134            4 :                         sqlite3_int64 path_ID = -1;
     135              : 
     136            4 :                         path_ID = sqlite3_column_int64(select_stmt,0);
     137              : 
     138            4 :                         if(path_ID != -1)
     139              :                         {
     140            4 :                                 paths_are_equal = false;
     141              : 
     142            4 :                                 const char *insert_sql = "INSERT INTO runtime_paths_id.the_path_id_does_not_exists (path_id) VALUES (?1);";
     143              : 
     144            4 :                                 rc = sqlite3_prepare_v2(config->db,insert_sql,-1,&insert_stmt,NULL);
     145              : 
     146            4 :                                 if(SQLITE_OK != rc)
     147              :                                 {
     148            0 :                                         log_sqlite_error(config->db,rc,NULL,"Can't prepare insert statement");
     149            0 :                                         status = FAILURE;
     150              :                                 }
     151              : 
     152            4 :                                 if(SUCCESS == status)
     153              :                                 {
     154            4 :                                         rc = sqlite3_bind_int64(insert_stmt,1,path_ID);
     155              : 
     156            4 :                                         if(SQLITE_OK != rc)
     157              :                                         {
     158            0 :                                                 log_sqlite_error(config->db,rc,NULL,"Error binding value in insert");
     159            0 :                                                 status = FAILURE;
     160              :                                         }
     161              :                                 }
     162              : 
     163            4 :                                 if(SUCCESS == status)
     164              :                                 {
     165              :                                         /* Execute SQL statement */
     166            4 :                                         if(sqlite3_step(insert_stmt) != SQLITE_DONE)
     167              :                                         {
     168            0 :                                                 log_sqlite_error(config->db,rc,NULL,"Insert statement didn't return DONE");
     169            0 :                                                 status = FAILURE;
     170              :                                         }
     171              :                                 }
     172              : 
     173            4 :                                 sqlite3_finalize(insert_stmt);
     174              :                         }
     175              :                 }
     176              : 
     177          154 :                 if(SQLITE_DONE != rc)
     178              :                 {
     179            0 :                         log_sqlite_error(config->db,rc,NULL,"Select statement didn't finish with DONE");
     180            0 :                         status = FAILURE;
     181              :                 }
     182              :         }
     183              : 
     184          154 :         del(select_sql);
     185              : 
     186          154 :         sqlite3_finalize(select_stmt);
     187              : 
     188          154 :         if(SUCCESS == status)
     189              :         {
     190              :                 /* If the primary database was just created */
     191          154 :                 if(config->db_primary_file_exists == false && config->compare == false)
     192              :                 {
     193           78 :                         slog(TRACE,"The brand new database has just been created. No need to verify the paths stored in the database against those passed as command-line arguments\n");
     194           78 :                         provide(status);
     195              : 
     196              :                 } else {
     197              : 
     198           76 :                         if(paths_are_equal == true)
     199              :                         {
     200           72 :                                 slog(TRACE,"The paths written against the database and the paths passed as arguments are completely identical\n");
     201              :                         } else {
     202            4 :                                 slog(EVERY,"The paths passed as arguments differ from those saved in the database. File paths and checksum information may be lost!\n");
     203              : 
     204            4 :                                 if(!(rational_logger_mode & SILENT))
     205              :                                 {
     206            4 :                                         slog(EVERY,"Paths saved in the database:\n");
     207              : 
     208              :                                         sqlite3_stmt *stmt;
     209            4 :                                         int rc_stmt = 0;
     210            4 :                                         char const *sql = "SELECT prefix FROM paths;";
     211              : 
     212            4 :                                         rc_stmt = sqlite3_prepare_v2(config->db,sql,-1,&stmt,NULL);
     213              : 
     214            4 :                                         if(SQLITE_OK != rc_stmt)
     215              :                                         {
     216            0 :                                                 log_sqlite_error(config->db,rc_stmt,NULL,"Can't prepare select statement %s",sql);
     217            0 :                                                 status = FAILURE;
     218              :                                         }
     219              : 
     220            4 :                                         if(SUCCESS == status)
     221              :                                         {
     222            8 :                                                 while(SQLITE_ROW == (rc_stmt = sqlite3_step(stmt)))
     223              :                                                 {
     224            4 :                                                         const char *prefix = (const char *)sqlite3_column_text(stmt,0);
     225              : 
     226            4 :                                                         slog(EVERY|UNDECOR,"%s\n",prefix);
     227              :                                                 }
     228              : 
     229            4 :                                                 if(SQLITE_DONE != rc_stmt)
     230              :                                                 {
     231            0 :                                                         log_sqlite_error(config->db,rc_stmt,NULL,"Select statement didn't finish with DONE");
     232            0 :                                                         status = FAILURE;
     233              :                                                 }
     234              :                                         }
     235              : 
     236            4 :                                         sqlite3_finalize(stmt);
     237              :                                 }
     238              : 
     239            4 :                                 if(config->force == true)
     240              :                                 {
     241            2 :                                         if(!(rational_logger_mode & SILENT))
     242              :                                         {
     243            2 :                                                 slog(EVERY,"The " BOLD "--force" RESET " option has been used, so the following paths will be written to the %s:\n",config->db_file_name);
     244              : 
     245            4 :                                                 for(int i = 0; config->paths[i]; i++)
     246              :                                                 {
     247            2 :                                                         slog(EVERY|UNDECOR,"%s\n",config->paths[i]);
     248              :                                                 }
     249              :                                         }
     250              :                                 } else {
     251            2 :                                         slog(EVERY,"Use the " BOLD "--force" RESET " option only when the PATHS stored in the database need"
     252              :                                                 " to be updated. Warning: If this option is used incorrectly, file and checksum information"
     253              :                                                 " in the database may be lost or completely replaced with different values.\n");
     254            2 :                                         status = WARNING;
     255              :                                 }
     256              :                         }
     257              :                 }
     258              :         }
     259              : 
     260           76 :         provide(status);
     261              : }
        

Generated by: LCOV version 2.0-1