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-03-01 04:31:48 Functions: 100.0 % 1 1
Branches: 60.0 % 70 42

             Branch data     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                 :         303 : Return db_validate_paths(void)
      41                 :             : {
      42                 :             :         /* Status returned by this function through provide()
      43                 :             :            Default value assumes successful completion */
      44                 :         303 :         Return status = SUCCESS;
      45                 :             : 
      46                 :             :         // Don't do anything
      47         [ +  + ]:         303 :         if(config->compare == true)
      48                 :             :         {
      49                 :          70 :                 provide(status);
      50                 :             :         }
      51                 :             : 
      52                 :             :         /* Interrupt the function smoothly */
      53                 :             :         /* Interrupt when Ctrl+C */
      54         [ -  + ]:         233 :         if(global_interrupt_flag == true)
      55                 :             :         {
      56                 :           0 :                 provide(status);
      57                 :             :         }
      58                 :             : 
      59                 :         233 :         sqlite3_stmt *select_stmt = NULL;
      60                 :         233 :         sqlite3_stmt *insert_stmt = NULL;
      61                 :         233 :         int rc = 0;
      62                 :             : 
      63                 :         233 :         bool paths_are_equal = true;
      64                 :             : 
      65                 :         233 :         create(char,select_sql);
      66                 :             : 
      67                 :             :         // Create the SQL request
      68         [ +  - ]:         233 :         if(config->paths[0] != NULL)
      69                 :             :         {
      70                 :         233 :                 char const *sql_1 = "SELECT ID FROM paths WHERE prefix NOT IN (";
      71                 :             : 
      72                 :         233 :                 status = concat_literal(select_sql,sql_1);
      73                 :             : 
      74         [ -  + ]:         233 :                 if(SUCCESS != status)
      75                 :             :                 {
      76                 :           0 :                         del(select_sql);
      77                 :           0 :                         provide(status);
      78                 :             :                 }
      79                 :             : 
      80         [ +  + ]:         466 :                 for(int i = 0; config->paths[i]; i++)
      81                 :             :                 {
      82                 :         233 :                         create(char,path);
      83                 :             : 
      84   [ +  -  -  + ]:         233 :                         run(db_sql_wrap_string(path,config->paths[i]));
      85                 :             : 
      86   [ +  -  -  + ]:         233 :                         run(concat_literal(select_sql,getcstring(path)));
      87                 :             : 
      88                 :         233 :                         del(path);
      89                 :             : 
      90         [ -  + ]:         233 :                         if(SUCCESS != status)
      91                 :             :                         {
      92                 :           0 :                                 del(select_sql);
      93                 :           0 :                                 provide(status);
      94                 :             :                         }
      95                 :             : 
      96                 :             :                         // Not the last path in the array
      97         [ -  + ]:         233 :                         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                 :         233 :                 status = concat_literal(select_sql,");");
     114                 :             : 
     115         [ -  + ]:         233 :                 if(SUCCESS != status)
     116                 :             :                 {
     117                 :           0 :                         del(select_sql);
     118                 :           0 :                         provide(status);
     119                 :             :                 }
     120                 :             :         }
     121                 :             : 
     122                 :         233 :         rc = sqlite3_prepare_v2(config->db,getstring(select_sql),-1,&select_stmt,NULL);
     123                 :             : 
     124         [ -  + ]:         233 :         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         [ +  - ]:         233 :         if(SUCCESS == status)
     131                 :             :         {
     132         [ +  + ]:         470 :                 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 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         [ -  + ]:         233 :                 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                 :         233 :         del(select_sql);
     185                 :             : 
     186                 :         233 :         sqlite3_finalize(select_stmt);
     187                 :             : 
     188         [ +  - ]:         233 :         if(SUCCESS == status)
     189                 :             :         {
     190                 :             :                 /* If the primary database was just created */
     191   [ +  +  +  - ]:         233 :                 if(config->db_primary_file_exists == false && config->compare == false)
     192                 :             :                 {
     193                 :         125 :                         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                 :         125 :                         provide(status);
     195                 :             : 
     196                 :             :                 } else {
     197                 :             : 
     198         [ +  + ]:         108 :                         if(paths_are_equal == true)
     199                 :             :                         {
     200                 :         104 :                                 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",confstr(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                 :         108 :         provide(status);
     261                 :             : }
        

Generated by: LCOV version 2.0-1