Branch data Line data Source code
1 : : #include "precizer.h"
2 : :
3 : : /**
4 : : * @brief Validate stored DB path prefixes against current CLI PATH arguments
5 : : *
6 : : * @details Skips validation in compare mode. When the primary database has just
7 : : * been created, no stored-path comparison is needed. Otherwise the function
8 : : * finds DB prefixes that are missing from the current PATH arguments, stores
9 : : * their IDs in `the_path_id_does_not_exists`, and reports the mismatch to the
10 : : * user
11 : : *
12 : : * If mismatches are found and `--force` is not enabled, the function returns
13 : : * `WARNING` so the caller can stop before replacing stored path metadata. When
14 : : * `--force` is enabled, execution continues and the new PATH arguments may be
15 : : * written to the database
16 : : *
17 : : * @warning Using `--force` incorrectly can replace path, file, and checksum
18 : : * metadata in the database
19 : : *
20 : : * @return `SUCCESS` when paths match or forced path replacement is allowed,
21 : : * `WARNING` when mismatches are found without `--force`, or `FAILURE`
22 : : * on SQLite or memory errors
23 : : */
24 : 381 : Return db_validate_paths(void)
25 : : {
26 : : /* Status returned by this function through provide()
27 : : Default value assumes successful completion */
28 : 381 : Return status = SUCCESS;
29 : :
30 : : // Don't do anything
31 [ + + ]: 381 : if(config->compare == true)
32 : : {
33 : 112 : provide(status);
34 : : }
35 : :
36 : : /* Interrupt the function smoothly */
37 : : /* Interrupt when Ctrl+C */
38 [ - + ]: 269 : if(global_interrupt_flag == true)
39 : : {
40 : 0 : provide(status);
41 : : }
42 : :
43 : 269 : sqlite3_stmt *select_stmt = NULL;
44 : 269 : sqlite3_stmt *insert_stmt = NULL;
45 : 269 : int rc = 0;
46 : :
47 : 269 : bool paths_are_equal = true;
48 : :
49 : 269 : create(char,select_sql);
50 : :
51 : : // Create the SQL request
52 [ + - ]: 269 : if(config->paths[0] != NULL)
53 : : {
54 : 269 : char const *sql_1 = "SELECT ID FROM paths WHERE prefix NOT IN (";
55 : :
56 : 269 : status = concat_literal(select_sql,sql_1);
57 : :
58 [ - + ]: 269 : if(SUCCESS != status)
59 : : {
60 : 0 : del(select_sql);
61 : 0 : provide(status);
62 : : }
63 : :
64 [ + + ]: 538 : for(int i = 0; config->paths[i]; i++)
65 : : {
66 : 269 : create(char,path);
67 : :
68 [ + - - + ]: 269 : run(db_sql_wrap_string(path,config->paths[i]));
69 : :
70 [ + - - + ]: 269 : run(concat_literal(select_sql,getcstring(path)));
71 : :
72 : 269 : del(path);
73 : :
74 [ - + ]: 269 : if(SUCCESS != status)
75 : : {
76 : 0 : del(select_sql);
77 : 0 : provide(status);
78 : : }
79 : :
80 : : // Not the last path in the array
81 [ - + ]: 269 : if(config->paths[i + 1] != 0)
82 : : {
83 : : /* Concatenate with the comma character "," */
84 : 0 : status = concat_literal(select_sql,",");
85 : :
86 [ # # ]: 0 : if(SUCCESS != status)
87 : : {
88 : 0 : del(select_sql);
89 : 0 : provide(status);
90 : : }
91 : : }
92 : : }
93 : :
94 : : /* Close the string that contains SQL request */
95 : :
96 : : /* Concatenate with the ");" characters */
97 : 269 : status = concat_literal(select_sql,");");
98 : :
99 [ - + ]: 269 : if(SUCCESS != status)
100 : : {
101 : 0 : del(select_sql);
102 : 0 : provide(status);
103 : : }
104 : : }
105 : :
106 : 269 : rc = sqlite3_prepare_v2(config->db,getcstring(select_sql),-1,&select_stmt,NULL);
107 : :
108 [ - + ]: 269 : if(SQLITE_OK != rc)
109 : : {
110 : 0 : log_sqlite_error(config->db,rc,NULL,"Can't prepare select statement %s",getcstring(select_sql));
111 : 0 : status = FAILURE;
112 : : }
113 : :
114 [ + - ]: 269 : if(SUCCESS == status)
115 : : {
116 [ + + ]: 542 : while(SQLITE_ROW == (rc = sqlite3_step(select_stmt)))
117 : : {
118 : 4 : sqlite3_int64 path_ID = -1;
119 : :
120 : 4 : path_ID = sqlite3_column_int64(select_stmt,0);
121 : :
122 [ - + ]: 4 : if(path_ID != -1)
123 : : {
124 : 4 : paths_are_equal = false;
125 : :
126 : 4 : const char *insert_sql = "INSERT INTO the_path_id_does_not_exists (path_id) VALUES (?1);";
127 : :
128 : 4 : rc = sqlite3_prepare_v2(config->db,insert_sql,-1,&insert_stmt,NULL);
129 : :
130 [ - + ]: 4 : if(SQLITE_OK != rc)
131 : : {
132 : 0 : log_sqlite_error(config->db,rc,NULL,"Can't prepare insert statement");
133 : 0 : status = FAILURE;
134 : : }
135 : :
136 [ + - ]: 4 : if(SUCCESS == status)
137 : : {
138 : 4 : rc = sqlite3_bind_int64(insert_stmt,1,path_ID);
139 : :
140 [ - + ]: 4 : if(SQLITE_OK != rc)
141 : : {
142 : 0 : log_sqlite_error(config->db,rc,NULL,"Error binding value in insert");
143 : 0 : status = FAILURE;
144 : : }
145 : : }
146 : :
147 [ + - ]: 4 : if(SUCCESS == status)
148 : : {
149 : : /* Execute SQL statement */
150 : 4 : rc = sqlite3_step(insert_stmt);
151 : :
152 [ - + ]: 4 : if(rc != SQLITE_DONE)
153 : : {
154 : 0 : log_sqlite_error(config->db,rc,NULL,"Insert statement didn't return DONE");
155 : 0 : status = FAILURE;
156 : : }
157 : : }
158 : :
159 : 4 : sqlite3_finalize(insert_stmt);
160 : : }
161 : : }
162 : :
163 [ - + ]: 269 : if(SQLITE_DONE != rc)
164 : : {
165 : 0 : log_sqlite_error(config->db,rc,NULL,"Select statement didn't finish with DONE");
166 : 0 : status = FAILURE;
167 : : }
168 : : }
169 : :
170 : 269 : del(select_sql);
171 : :
172 : 269 : sqlite3_finalize(select_stmt);
173 : :
174 [ + - ]: 269 : if(SUCCESS == status)
175 : : {
176 : : /* If the primary database was just created */
177 [ + + + - ]: 269 : if(config->db_primary_file_exists == false && config->compare == false)
178 : : {
179 : 159 : 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");
180 : 159 : provide(status);
181 : :
182 : : } else {
183 : :
184 [ + + ]: 110 : if(paths_are_equal == true)
185 : : {
186 : 106 : slog(TRACE,"The paths written against the database and the paths passed as arguments are completely identical\n");
187 : : } else {
188 : 4 : slog(EVERY,"The paths passed as arguments differ from those saved in the database. File paths and checksum information may be lost!\n");
189 : :
190 [ + - ]: 4 : if(!(rational_logger_mode & SILENT))
191 : : {
192 : 4 : slog(EVERY,"Paths saved in the database:\n");
193 : :
194 : : sqlite3_stmt *stmt;
195 : 4 : int rc_stmt = 0;
196 : 4 : char const *sql = "SELECT prefix FROM paths;";
197 : :
198 : 4 : rc_stmt = sqlite3_prepare_v2(config->db,sql,-1,&stmt,NULL);
199 : :
200 [ - + ]: 4 : if(SQLITE_OK != rc_stmt)
201 : : {
202 : 0 : log_sqlite_error(config->db,rc_stmt,NULL,"Can't prepare select statement %s",sql);
203 : 0 : status = FAILURE;
204 : : }
205 : :
206 [ + - ]: 4 : if(SUCCESS == status)
207 : : {
208 [ + + ]: 8 : while(SQLITE_ROW == (rc_stmt = sqlite3_step(stmt)))
209 : : {
210 : 4 : const char *prefix = (const char *)sqlite3_column_text(stmt,0);
211 : :
212 : 4 : slog(EVERY|UNDECOR,"%s\n",prefix);
213 : : }
214 : :
215 [ - + ]: 4 : if(SQLITE_DONE != rc_stmt)
216 : : {
217 : 0 : log_sqlite_error(config->db,rc_stmt,NULL,"Select statement didn't finish with DONE");
218 : 0 : status = FAILURE;
219 : : }
220 : : }
221 : :
222 : 4 : sqlite3_finalize(stmt);
223 : : }
224 : :
225 [ + + ]: 4 : if(config->force == true)
226 : : {
227 [ + - ]: 2 : if(!(rational_logger_mode & SILENT))
228 : : {
229 : 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));
230 : :
231 [ + + ]: 4 : for(int i = 0; config->paths[i]; i++)
232 : : {
233 : 2 : slog(EVERY|UNDECOR,"%s\n",config->paths[i]);
234 : : }
235 : : }
236 : : } else {
237 : 2 : slog(EVERY,"Use the " BOLD "--force" RESET " option only when the PATHS stored in the database need"
238 : : " to be updated. Warning: If this option is used incorrectly, file and checksum information"
239 : : " in the database may be lost or completely replaced with different values.\n");
240 : 2 : status = WARNING;
241 : : }
242 : : }
243 : : }
244 : : }
245 : :
246 : 110 : provide(status);
247 : : }
|