Branch data Line data Source code
1 : : #include "precizer.h"
2 : : #include <errno.h>
3 : :
4 : : /**
5 : : * @brief Check whether an unavailable file must be reported as a lock violation
6 : : *
7 : : * @param[in] relative_path Relative path descriptor from the database
8 : : * @param[in] access_status Current unavailable status for the path
9 : : *
10 : : * @return Return status code:
11 : : * - SUCCESS|YES: A checksum-locked unavailable violation was reported
12 : : * - SUCCESS|NO: No checksum-locked unavailable violation was reported
13 : : * - FAILURE|YES: A checksum-locked unavailable violation was detected, but reporting failed
14 : : * - FAILURE|NO: Lock-checksum evaluation or reporting failed
15 : : */
16 : 63 : static Return db_check_locked_unavailable_violation(
17 : : const memory *relative_path,
18 : : const FileAccessStatus access_status)
19 : : {
20 : : /* This function was reviewed line by line by a human and is not AI-generated
21 : : Any change to this function requires separate explicit approval */
22 : :
23 : : /* Status returned by this function through provide()
24 : : Default value assumes successful completion */
25 : 63 : Return status = SUCCESS;
26 : :
27 : 63 : bool locked_unavailable_violation = false;
28 : :
29 : : /*
30 : : * YES means the unavailable path is checksum-locked, so it must be reported as a violation.
31 : : * NO means the path is not checksum-locked, so this unavailable state is not a lock violation
32 : : */
33 : 63 : if(ask(path_check_locked_checksum(relative_path)))
34 : : {
35 : 12 : status = show_locked_checksum_unavailable_violation(relative_path,
36 : : access_status,
37 : : NULL,
38 : : NULL);
39 : :
40 : 12 : locked_unavailable_violation = true;
41 : : }
42 : :
43 [ + + ]: 63 : if(locked_unavailable_violation == true)
44 : : {
45 : 12 : status |= YES;
46 : :
47 : : } else {
48 : 51 : status |= NO;
49 : : }
50 : :
51 : 63 : provide(status);
52 : : }
53 : :
54 : : /**
55 : : * @brief Keep checksum-locked rows even when --db-drop-ignored matched them
56 : : *
57 : : * The function checks the locked path relative to an already opened root
58 : : * directory. An unavailable locked path is reported and kept
59 : : *
60 : : * @param[in] root_directory_fd Open descriptor for the root directory. Used
61 : : * as the base for the relative access check
62 : : * @param[in] relative_path Relative path descriptor from the database
63 : : * @param[out] locked_unavailable_violation_out Set to true when this call reported a locked unavailable path
64 : : *
65 : : * @return Return status code:
66 : : * - SUCCESS|YES: The row must stay in the DB
67 : : * - SUCCESS|NO: The row does not need checksum-lock preservation
68 : : * - FAILURE|NO: Validation, lock-checksum evaluation, or reporting failed
69 : : */
70 : 90 : static Return db_preserve_locked_ignored_record(
71 : : const int root_directory_fd,
72 : : const memory *relative_path,
73 : : bool *locked_unavailable_violation_out)
74 : : {
75 : : /* This changed function requires a new line-by-line human review before it is considered trusted */
76 : :
77 : : /* Status returned by this function through provide()
78 : : Default value assumes successful completion */
79 : 90 : Return status = SUCCESS;
80 : :
81 [ - + ]: 90 : if(locked_unavailable_violation_out == NULL)
82 : : {
83 : 0 : provide(FAILURE | NO);
84 : : }
85 : :
86 : 90 : *locked_unavailable_violation_out = false;
87 : :
88 : 90 : bool keep_locked_record = false;
89 : :
90 : : /*
91 : : * YES means the ignored DB row is checksum-locked and must be checked for preservation.
92 : : * NO means the row is not checksum-locked, so this helper does not preserve it
93 : : */
94 : 90 : if(ask(path_check_locked_checksum(relative_path)))
95 : : {
96 : : /*
97 : : * Check the path relative to the open root directory without
98 : : * constructing an absolute path
99 : : */
100 : 16 : FileAccessStatus access_status = file_check_access(
101 : : root_directory_fd,
102 : : relative_path,
103 : : R_OK);
104 : :
105 [ + - + + ]: 16 : if(SUCCESS == status && access_status != FILE_ACCESS_ALLOWED)
106 : : {
107 : : /*
108 : : * YES means the unavailable checksum-locked row was reported as a violation.
109 : : * NO means no violation was reported for this unavailable row
110 : : */
111 : 6 : if(ask(db_check_locked_unavailable_violation(relative_path,access_status)))
112 : : {
113 : 6 : *locked_unavailable_violation_out = true;
114 : : }
115 : :
116 : : }
117 : :
118 [ + - ]: 16 : if(TRIUMPH & status)
119 : : {
120 : 16 : keep_locked_record = true;
121 : : }
122 : : }
123 : :
124 [ + + ]: 90 : if(keep_locked_record == true)
125 : : {
126 : 16 : status |= YES;
127 : :
128 : : } else {
129 : 74 : status |= NO;
130 : : }
131 : :
132 : 90 : provide(status);
133 : : }
134 : :
135 : : /**
136 : : * @brief Remove stale file records from the primary database after an update
137 : : *
138 : : * @details
139 : : * The function walks through file records stored in the primary database and
140 : : * decides whether each row should remain there
141 : : *
142 : : * One root prefix is retrieved from the `paths` table and opened once. Every
143 : : * file row is checked relative to that same directory descriptor. The current
144 : : * cleanup path therefore requires the database to describe a single root and
145 : : * does not distinguish file rows belonging to different stored roots
146 : : *
147 : : * A row can be removed when the file is no longer present on disk, when it is
148 : : * inaccessible or its access check fails and `--db-drop-inaccessible` is active,
149 : : * or when the path is ignored and `--db-drop-ignored` is enabled. Ignored rows
150 : : * are otherwise kept outside missing-file cleanup, except checksum-locked rows
151 : : * that must still report unavailable protected files
152 : : *
153 : : * If the root cannot be opened for any reason, its cleanup is skipped without
154 : : * changing file rows or returning an error. This prevents a temporary root
155 : : * access problem from being mistaken for missing or inaccessible files
156 : : *
157 : : * Checksum-locked paths are file paths matched by a `--lock-checksum` pattern.
158 : : * Their stored checksums serve as protected integrity references, so cleanup
159 : : * must not silently remove their database rows when the files cannot be verified
160 : : * If a locked file is missing or unavailable, the function keeps the database
161 : : * row, reports the violation, and returns a warning instead of deleting it
162 : : * A NULL `files.relative_path` value violates the database contract and stops
163 : : * cleanup with `FAILURE`
164 : : *
165 : : * In `--compare` mode, or when `--update` is not active, the function exits
166 : : * without performing cleanup
167 : : * In `--dry-run` mode it evaluates the same cleanup decisions without deleting
168 : : * rows from the database or starting a write transaction
169 : : *
170 : : * Real deletions share one transaction for the entire cleanup, without timed
171 : : * commits. Normal completion and graceful interruption commit the deletions
172 : : * already performed. A technical error rolls back this cleanup transaction;
173 : : * previously committed traversal results remain intact
174 : : *
175 : : * @return Return status code:
176 : : * - SUCCESS: Cleanup completed without lock-checksum warnings
177 : : * - WARNING: One or more unavailable checksum-locked paths were found
178 : : * - FAILURE: Cleanup was interrupted by an internal error
179 : : */
180 : 628 : Return db_delete_missing_metadata(void)
181 : : {
182 : : /* Status returned by this function through provide()
183 : : Default value assumes successful completion */
184 : 628 : Return status = SUCCESS;
185 : :
186 : : /* Interrupt the function smoothly */
187 : : /* Interrupt when Ctrl+C */
188 [ - + ]: 628 : if(global_interrupt_flag == true)
189 : : {
190 : 0 : provide(status);
191 : : }
192 : :
193 : : /* Skip in comparison mode */
194 [ + + ]: 628 : if(config->compare == true)
195 : : {
196 : 142 : slog(TRACE,"Comparison mode is enabled. The primary database does not require cleanup\n");
197 : 142 : provide(status);
198 : : }
199 : :
200 : : /* Update mode should be enabled */
201 [ + + ]: 486 : if(config->update == true)
202 : : {
203 : 163 : slog(EVERY,"Searching for files that no longer exist on the file system…\n");
204 : :
205 : : } else {
206 : : // Don't do anything
207 : 323 : provide(status);
208 : : }
209 : :
210 [ + + + - ]: 163 : if(config->dry_run == true && config->db_primary_file_exists == true)
211 : : {
212 : 15 : slog(TRACE,"Dry-run mode is enabled. The primary database will remain unchanged\n");
213 : : }
214 : :
215 : : // Print deletion banners only once per run
216 : 163 : bool first_iteration = true;
217 : :
218 : : // Tracks whether cleanup reported an unavailable checksum-locked path
219 : 163 : bool locked_unavailable_violation_detected = false;
220 : :
221 : : // Stores the root directory path retrieved from the database
222 : 163 : m_create(char,root_path,MEMORY_STRING);
223 : :
224 : : // Stores the relative path of the file record currently being processed
225 : 163 : m_create(char,relative_path,MEMORY_STRING);
226 : :
227 : : // Holds the prepared SQLite statement used to iterate over file records
228 : 163 : sqlite3_stmt *select_stmt = NULL;
229 : :
230 : : // Stores the result code returned by the most recent SQLite operation
231 : 163 : int rc = 0;
232 : :
233 : : // Identifies the open root directory used as the base for relative access checks
234 : 163 : int root_directory_fd = -1;
235 : :
236 : : // Stores whether the database root was opened for directory-relative checks
237 : 163 : FileAccessStatus root_access_status = FILE_ACCESS_ERROR;
238 : :
239 : : /*
240 : : * Load the shared root path and open it once before processing file rows.
241 : : * Each file record stores only a relative path, so access checks use this
242 : : * directory descriptor. If the root cannot be opened, the open helper has
243 : : * already reported and remembered the warning, and cleanup safely stops
244 : : * without treating that root-level access problem as a technical failure
245 : : */
246 : 163 : run(db_retrieve_root_path(root_path));
247 : :
248 [ + - ]: 163 : if(SUCCESS == status)
249 : : {
250 : 163 : root_access_status = directory_open_root(root_path,&root_directory_fd);
251 : : }
252 : :
253 : : /*
254 : : * Without an open root, file rows cannot be classified safely.
255 : : * Release local memory and keep the current status when the root was not
256 : : * opened or no descriptor was returned for directory-relative checks
257 : : */
258 [ + + - + ]: 163 : if(root_access_status != FILE_ACCESS_ALLOWED || root_directory_fd < 0)
259 : : {
260 : 6 : call(m_del(relative_path));
261 : 6 : call(m_del(root_path));
262 : :
263 : 6 : provide(status);
264 : : }
265 : :
266 : : /* Keep all cleanup deletions in one transaction, separate from the main
267 : : traversal. Dry-run only checks rows and must not start a write transaction */
268 [ + - + + ]: 157 : if(SUCCESS == status && config->dry_run == false)
269 : : {
270 : 142 : rc = sqlite3_exec(config->db,"BEGIN IMMEDIATE;",NULL,NULL,NULL);
271 : :
272 [ - + ]: 142 : if(SQLITE_OK != rc)
273 : : {
274 : 0 : log_sqlite_error(config->db,rc,NULL,"Failed to begin missing file cleanup transaction");
275 : 0 : status = FAILURE;
276 : : }
277 : : }
278 : :
279 [ + - ]: 157 : if(SUCCESS == status)
280 : : {
281 : : #if 0 // Disabled multi-root path index implementation
282 : : const char *select_sql = "SELECT files.ID,paths.prefix,files.relative_path FROM files LEFT JOIN paths ON files.root_path_index = paths.ID;";
283 : : #endif
284 : 157 : const char *select_sql = "SELECT ID,relative_path FROM files;";
285 : :
286 : 157 : rc = sqlite3_prepare_v2(config->db,select_sql,-1,&select_stmt,NULL);
287 : :
288 [ - + ]: 157 : if(SQLITE_OK != rc)
289 : : {
290 : 0 : log_sqlite_error(config->db,rc,NULL,"Can't prepare select statement");
291 : 0 : status = FAILURE;
292 : : }
293 : : }
294 : :
295 : : /*
296 : : * Iterate over every file record selected from the files table
297 : : */
298 [ + - + + ]: 1944 : while(SUCCESS == status && SQLITE_ROW == (rc = sqlite3_step(select_stmt)))
299 : : {
300 : : /* Interrupt the loop smoothly */
301 : : /* Interrupt when Ctrl+C */
302 [ - + ]: 1789 : if(global_interrupt_flag == true)
303 : : {
304 : 2 : break;
305 : : }
306 : :
307 : 1789 : sqlite_int64 ID = sqlite3_column_int64(select_stmt,0);
308 : :
309 : 1789 : const unsigned char *db_relative_path = sqlite3_column_text(select_stmt,1);
310 : :
311 : : // Marks paths excluded by the current --ignore/--include scope
312 : 1789 : bool ignored = false;
313 : :
314 : : // Marks deletions triggered by --db-drop-ignored
315 : 1789 : bool drop_ignored = false;
316 : :
317 : : // Marks deletions triggered by unavailable access when --db-drop-inaccessible is active
318 : 1789 : bool inaccessible = false;
319 : :
320 : : // Marks deletions triggered by a missing path on disk
321 : 1789 : bool file_not_found = false;
322 : :
323 : : // Aggregates whether the current record should be deleted for any reason
324 : 1789 : bool should_delete = false;
325 : :
326 : : /*
327 : : * files.relative_path is required by the database contract to be non-NULL.
328 : : * This is the single boundary check before the helper chain below relies on that invariant
329 : : */
330 [ - + ]: 1789 : if(db_relative_path == NULL)
331 : : {
332 : 0 : slog(ERROR,"The files table returned a NULL relative path\n");
333 : 0 : status = FAILURE;
334 : 0 : break;
335 : : }
336 : :
337 : : /*
338 : : * sqlite3_column_bytes() returns the relative path length without the
339 : : * terminating NUL byte, so add one byte to copy a complete C string
340 : : */
341 : 1789 : run(m_copy_fixed_string(relative_path,(size_t)sqlite3_column_bytes(select_stmt,1) + 1U,db_relative_path));
342 : :
343 [ - + ]: 1789 : if(SUCCESS != status)
344 : : {
345 : 0 : break;
346 : : }
347 : :
348 : 1789 : const char *runtime_relative_path = m_text(relative_path);
349 : :
350 : : /*
351 : : * Apply the current include and ignore scope to database rows before
352 : : * checking filesystem availability. Ignored rows stay outside normal
353 : : * missing-file cleanup unless --db-drop-ignored explicitly allows removing them
354 : : */
355 [ + + ]: 1789 : if(config->ignore != NULL)
356 : : {
357 : 594 : status = match_include_ignore(relative_path,NULL,&ignored);
358 : :
359 [ - + ]: 594 : if(SUCCESS != status)
360 : : {
361 : 0 : break;
362 : : }
363 : : }
364 : :
365 [ + + ]: 1789 : if(ignored == true)
366 : : {
367 [ + + ]: 112 : if(config->db_drop_ignored == true)
368 : : {
369 : 90 : drop_ignored = true;
370 : :
371 : : } else {
372 : :
373 : : /*
374 : : * YES means the ignored row is checksum-locked and still needs
375 : : * an availability check. NO means normal ignore protection keeps
376 : : * the row without touching the filesystem
377 : : */
378 : 22 : if(ask(path_check_locked_checksum(relative_path)))
379 : : {
380 : 0 : FileAccessStatus access_status = file_check_access(root_directory_fd,relative_path,R_OK);
381 : :
382 [ # # ]: 0 : if(access_status != FILE_ACCESS_ALLOWED)
383 : : {
384 : : /*
385 : : * YES means the unavailable ignored row was reported as a checksum-lock violation.
386 : : * NO is not expected after the positive lock-check above, but keeps status handling explicit
387 : : */
388 : 0 : if(ask(db_check_locked_unavailable_violation(relative_path,access_status)))
389 : : {
390 : 0 : locked_unavailable_violation_detected = true;
391 : : }
392 : :
393 [ # # ]: 0 : if(SUCCESS != status)
394 : : {
395 : 0 : break;
396 : : }
397 : : }
398 : : }
399 : :
400 [ - + ]: 22 : if(SUCCESS != status)
401 : : {
402 : 0 : break;
403 : : }
404 : :
405 : 1670 : continue;
406 : : }
407 : : }
408 : :
409 [ + + ]: 1767 : if(drop_ignored == true)
410 : : {
411 : 90 : bool locked_unavailable_violation = false;
412 : :
413 : : /*
414 : : * YES means the ignored DB row must be kept because it is checksum-locked.
415 : : * NO means checksum-lock protection does not apply here, so the ignored row may be deleted
416 : : */
417 : 90 : if(ask(db_preserve_locked_ignored_record(root_directory_fd,relative_path,&locked_unavailable_violation)))
418 : : {
419 [ + + ]: 16 : if(locked_unavailable_violation == true)
420 : : {
421 : 6 : locked_unavailable_violation_detected = true;
422 : : }
423 : :
424 : 16 : continue;
425 : : }
426 : :
427 [ - + ]: 74 : if(SUCCESS != status)
428 : : {
429 : 0 : break;
430 : : }
431 : :
432 : 74 : should_delete = true;
433 : :
434 : : } else {
435 : :
436 : : /*
437 : : * This changed access-check block requires a new line-by-line human
438 : : * review before it is considered trusted
439 : : *
440 : : * Check the path relative to the open root directory without
441 : : * constructing an absolute path
442 : : */
443 : 1677 : FileAccessStatus access_status = file_check_access(root_directory_fd,relative_path,R_OK);
444 : :
445 [ + + ]: 1677 : if(access_status == FILE_ACCESS_ALLOWED)
446 : : {
447 : 1620 : continue;
448 : :
449 [ + + + + ]: 57 : } else if(access_status == FILE_ACCESS_DENIED || access_status == FILE_ACCESS_ERROR){
450 : :
451 : : /*
452 : : * YES means the unavailable DB row is checksum-locked and was reported as a violation.
453 : : * NO means no checksum-lock violation was reported, so normal inaccessible handling continues
454 : : */
455 : 18 : if(ask(db_check_locked_unavailable_violation(relative_path,access_status)))
456 : : {
457 : 4 : locked_unavailable_violation_detected = true;
458 : 4 : continue;
459 : : }
460 : :
461 [ - + ]: 14 : if(SUCCESS != status)
462 : : {
463 : 0 : break;
464 : : }
465 : :
466 [ + + ]: 14 : if(config->db_drop_inaccessible == true)
467 : : {
468 : 8 : inaccessible = true;
469 : 8 : should_delete = true;
470 : :
471 : : } else {
472 : 6 : slog(EVERY|UNDECOR,"kept inaccessible %s\n",runtime_relative_path);
473 : 6 : continue;
474 : : }
475 : :
476 [ + - ]: 39 : } else if(access_status == FILE_NOT_FOUND){
477 : :
478 : : /*
479 : : * YES means the missing DB row is checksum-locked and was reported as a violation.
480 : : * NO means no checksum-lock violation was reported, so normal missing-file handling continues
481 : : */
482 : 39 : if(ask(db_check_locked_unavailable_violation(relative_path,access_status)))
483 : : {
484 : 2 : locked_unavailable_violation_detected = true;
485 : 2 : continue;
486 : : }
487 : :
488 [ - + ]: 37 : if(SUCCESS != status)
489 : : {
490 : 0 : break;
491 : : }
492 : :
493 : 37 : file_not_found = true;
494 : 37 : should_delete = true;
495 : :
496 : : }
497 : : }
498 : :
499 [ + - ]: 119 : if(should_delete == true)
500 : : {
501 [ + + ]: 119 : if(first_iteration == true)
502 : : {
503 : 51 : first_iteration = false;
504 : :
505 [ + + ]: 51 : if(config->ignore != NULL)
506 : : {
507 [ + + ]: 28 : if(config->db_drop_ignored == false)
508 : : {
509 : 8 : slog(EVERY,"If the information about ignored files should be removed from the database the @{bold}--db-drop-ignored@{reset} option must be specified. This is special protection against accidental deletion of information from the database\n");
510 : : } else {
511 : 20 : slog(TRACE,"The @{bold}--db-drop-ignored@{reset} option has been used, so the information about ignored files will be removed against the database %s\n",confstr(db_file_name));
512 : : }
513 : : }
514 : :
515 [ + + ]: 51 : if(config->db_drop_inaccessible == true)
516 : : {
517 : 4 : slog(EVERY,"@{bold}Dropping DB records for missing, inaccessible, or ignored paths in %s:@{reset}\n",confstr(db_file_name));
518 : : } else {
519 : 47 : slog(EVERY,"@{bold}Dropping DB records for missing or ignored paths in %s:@{reset}\n",confstr(db_file_name));
520 : : }
521 : : }
522 : :
523 : : /* Remembered messages also write through this connection. Detect an
524 : : automatic rollback before another DELETE could commit on its own */
525 [ + + - + ]: 119 : if(config->dry_run == false && sqlite3_get_autocommit(config->db) != 0)
526 : : {
527 : 0 : slog(ERROR,"Missing file cleanup transaction ended before commit\n");
528 : 0 : status = FAILURE;
529 : 0 : break;
530 : : }
531 : :
532 : 119 : status = db_delete_the_record_by_id(&ID);
533 : :
534 [ + + ]: 119 : if(SUCCESS != status)
535 : : {
536 : 2 : break;
537 : : }
538 : :
539 [ + + ]: 117 : if(drop_ignored == true)
540 : : {
541 : 74 : slog(EVERY|UNDECOR|REMEMBER,"dropped as ignored %s\n",runtime_relative_path);
542 : :
543 [ + + ]: 43 : } else if(inaccessible == true){
544 : 8 : slog(EVERY|UNDECOR|REMEMBER,"dropped as inaccessible %s\n",runtime_relative_path);
545 : :
546 [ + - ]: 35 : } else if(file_not_found == true){
547 : 35 : slog(EVERY|UNDECOR,"dropped as missing %s\n",runtime_relative_path);
548 : : }
549 : : }
550 : : }
551 : :
552 [ + + - + ]: 157 : if(SUCCESS == status && SQLITE_DONE != rc)
553 : : {
554 [ # # ]: 0 : if(global_interrupt_flag == false)
555 : : {
556 : 0 : log_sqlite_error(config->db,rc,NULL,"Select statement didn't finish with DONE");
557 : 0 : status = FAILURE;
558 : : }
559 : : }
560 : :
561 : 157 : rc = sqlite3_finalize(select_stmt);
562 : :
563 [ + + - + ]: 157 : if(SUCCESS == status && SQLITE_OK != rc)
564 : : {
565 : 0 : log_sqlite_error(config->db,rc,NULL,"Failed to finalize select statement");
566 : 0 : status = FAILURE;
567 : : }
568 : :
569 [ - + ]: 157 : if(close(root_directory_fd) != 0)
570 : : {
571 : 0 : slog(ERROR,"Failed to close root directory descriptor: %s\n",strerror(errno));
572 : 0 : status = FAILURE;
573 : : }
574 : :
575 [ + + ]: 157 : if(config->dry_run == false)
576 : : {
577 : : /* Commit after the SELECT is finalized, including a graceful Ctrl+C.
578 : : Warnings about protected paths do not invalidate other deletions */
579 [ + + ]: 142 : if((FAILURE & status) == 0)
580 : : {
581 : 141 : rc = sqlite3_exec(config->db,"COMMIT;",NULL,NULL,NULL);
582 : :
583 [ + + ]: 141 : if(SQLITE_OK != rc)
584 : : {
585 : 1 : log_sqlite_error(config->db,rc,NULL,"Failed to commit missing file cleanup transaction");
586 : 1 : status = FAILURE;
587 : : }
588 : : }
589 : :
590 : : /* Roll back after a cleanup or commit failure. SQLite may already have
591 : : ended the transaction automatically, in which case no rollback is needed */
592 [ + + ]: 142 : if(sqlite3_get_autocommit(config->db) == 0)
593 : : {
594 : 2 : rc = sqlite3_exec(config->db,"ROLLBACK;",NULL,NULL,NULL);
595 : :
596 [ - + ]: 2 : if(SQLITE_OK != rc)
597 : : {
598 : 0 : log_sqlite_error(config->db,rc,NULL,"Failed to roll back missing file cleanup transaction");
599 : 0 : status = FAILURE;
600 : : }
601 : : }
602 : : }
603 : :
604 [ + + + - ]: 157 : if(SUCCESS == status && global_interrupt_flag == false)
605 : : {
606 : 154 : slog(EVERY,"Missing file search finished\n");
607 : : }
608 : :
609 : 157 : call(m_del(relative_path));
610 : 157 : call(m_del(root_path));
611 : :
612 [ + + ]: 157 : if(locked_unavailable_violation_detected == true)
613 : : {
614 : 12 : slog(EVERY,"@{bold}Warning! Data corruption detected for checksum-locked file!@{reset}\n");
615 : :
616 [ + - ]: 12 : if(SUCCESS == status)
617 : : {
618 : 12 : status = WARNING;
619 : : }
620 : : }
621 : :
622 : 157 : provide(status);
623 : : }
|