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 : : }
|