Branch data Line data Source code
1 : : #include "precizer.h"
2 : :
3 : : /**
4 : : * @brief Validates the integrity of SQLite database file
5 : : * @details Performs integrity check on the specified database file using either
6 : : * quick or full check based on configuration. Also verifies database
7 : : * version and upgrades if necessary.
8 : : *
9 : : * @param[in] db_file_path Path to the SQLite database file to validate
10 : : * @return Return status code:
11 : : * - SUCCESS: Database validation passed successfully
12 : : * - FAILURE: Database validation failed or errors occurred
13 : : */
14 : 268 : Return db_test(const char *db_file_path)
15 : : {
16 : : /* Status returned by this function through provide()
17 : : Default value assumes successful completion */
18 : 268 : Return status = SUCCESS;
19 : :
20 : 268 : sqlite3_stmt *select_stmt = NULL;
21 : 268 : sqlite3 *db = NULL;
22 : :
23 : : // Default value
24 : 268 : bool database_is_ok = false;
25 : :
26 : 268 : const char *db_file_name = NULL;
27 : :
28 : : /* Extract file name from path */
29 : 268 : char *dirc = strdup(db_file_path);
30 : :
31 [ - + ]: 268 : if(dirc == NULL)
32 : : {
33 : 0 : serp("Memory allocation failed during strdup operation");
34 : 0 : provide(FAILURE);
35 : : }
36 : :
37 : 268 : db_file_name = basename(dirc);
38 : :
39 [ - + ]: 268 : if(db_file_name == NULL)
40 : : {
41 : 0 : report("basename() failed for path: %s",db_file_path);
42 : 0 : free(dirc);
43 : 0 : provide(FAILURE);
44 : : }
45 : :
46 : : /* Check if verification should be skipped */
47 [ + + - + ]: 268 : if(config->dry_run == true && config->db_primary_file_exists == false)
48 : : {
49 : 0 : slog(TRACE,"Dry Run mode is enabled. Database verification for %s is skipped\n",db_file_name);
50 : 0 : free(dirc);
51 : 0 : provide(SUCCESS);
52 : : }
53 : :
54 : : /* Open database in read-only mode */
55 : 268 : slog(EVERY,"Starting database file %s integrity checkā¦\n",db_file_name);
56 : 268 : int sqlite_open_flag = SQLITE_OPEN_READONLY;
57 : :
58 : : /* Open database */
59 : 268 : int rc = sqlite3_open_v2(db_file_path,&db,sqlite_open_flag,NULL);
60 : :
61 [ + + ]: 268 : if(rc != SQLITE_OK)
62 : : {
63 : 4 : log_sqlite_error(db,rc,NULL,"Can't open database");
64 : 4 : status = FAILURE;
65 : : }
66 : :
67 : : /* Prepare integrity check statement */
68 [ + + ]: 268 : if(SUCCESS == status)
69 : : {
70 : 264 : const char *sql = "PRAGMA integrity_check";
71 : :
72 [ + + ]: 264 : if(config->db_check_level == QUICK)
73 : : {
74 : 2 : sql = "PRAGMA quick_check";
75 : 2 : slog(TRACE,"The database verification level has been set to QUICK\n");
76 : : } else {
77 : 262 : slog(TRACE,"The database verification level has been set to FULL\n");
78 : : }
79 : :
80 : 264 : rc = sqlite3_prepare_v2(db,sql,-1,&select_stmt,NULL);
81 : :
82 [ - + ]: 264 : if(SQLITE_OK != rc)
83 : : {
84 : 0 : log_sqlite_error(db,rc,NULL,"Can't prepare select statement");
85 : 0 : status = FAILURE;
86 : : }
87 : : }
88 : :
89 : : /* Execute integrity check */
90 [ + + ]: 268 : if(SUCCESS == status)
91 : : {
92 [ + + ]: 528 : while(SQLITE_ROW == (rc = sqlite3_step(select_stmt)))
93 : : {
94 : 264 : const char *response = (const char *)sqlite3_column_text(select_stmt,0);
95 : :
96 [ + - ]: 264 : if(strcmp(response,"ok") == 0)
97 : : {
98 : 264 : database_is_ok = true;
99 : : }
100 : : }
101 : :
102 [ - + ]: 264 : if(SQLITE_DONE != rc)
103 : : {
104 : 0 : log_sqlite_error(db,rc,NULL,"Select statement didn't finish with DONE");
105 : 0 : status = FAILURE;
106 : : }
107 : : }
108 : :
109 [ + + ]: 268 : if(select_stmt != NULL)
110 : : {
111 : 264 : sqlite3_finalize(select_stmt);
112 : : }
113 : :
114 : : /* Report integrity check results */
115 [ + + ]: 268 : if(SUCCESS == status)
116 : : {
117 [ + - ]: 264 : if(database_is_ok == true)
118 : : {
119 : 264 : slog(EVERY,"Database %s has been verified and is in good condition\n",db_file_name);
120 : : } else {
121 : 0 : slog(ERROR,"The database %s is in poor condition!\n",db_file_name);
122 : 0 : status = FAILURE;
123 : : }
124 : : }
125 : :
126 : : /* Cleanup resources */
127 : :
128 : 268 : rc = sqlite3_close(db);
129 : :
130 [ - + ]: 268 : if(SQLITE_OK != rc)
131 : : {
132 : 0 : log_sqlite_error(db,rc,NULL,"Warning: failed to close database");
133 : 0 : status = FAILURE;
134 : : }
135 : :
136 : : /* Check database version if integrity check passed */
137 [ + + ]: 268 : if(SUCCESS == status)
138 : : {
139 : : /* Check the database version number and upgrade the database if necessary */
140 : 264 : status = db_check_version(db_file_path,db_file_name);
141 : : }
142 : :
143 [ + - ]: 268 : if(dirc != NULL)
144 : : {
145 : 268 : free(dirc);
146 : : }
147 : :
148 : 268 : provide(status);
149 : : }
|