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 152 : Return db_test(const char *db_file_path)
15 : {
16 : /// The status that will be passed to return() before exiting.
17 : /// By default, the function worked without errors.
18 152 : Return status = SUCCESS;
19 :
20 152 : sqlite3_stmt *select_stmt = NULL;
21 152 : sqlite3 *db = NULL;
22 :
23 : // Default value
24 152 : bool database_is_ok = false;
25 :
26 152 : const char *db_file_name = NULL;
27 :
28 : /* Extract file name from path */
29 152 : char *dirc = strdup(db_file_path);
30 :
31 152 : if(dirc == NULL)
32 : {
33 0 : serp("Memory allocation failed during strdup operation");
34 0 : provide(FAILURE);
35 : }
36 :
37 152 : db_file_name = basename(dirc);
38 :
39 152 : 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 152 : 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 152 : slog(EVERY,"Starting database file %s integrity checkā¦\n",db_file_name);
56 152 : int sqlite_open_flag = SQLITE_OPEN_READONLY;
57 :
58 : /* Open database */
59 152 : int rc = sqlite3_open_v2(db_file_path,&db,sqlite_open_flag,NULL);
60 :
61 152 : 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 152 : if(SUCCESS == status)
69 : {
70 148 : const char *sql = "PRAGMA integrity_check";
71 :
72 148 : 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 146 : slog(TRACE,"The database verification level has been set to FULL\n");
78 : }
79 :
80 148 : rc = sqlite3_prepare_v2(db,sql,-1,&select_stmt,NULL);
81 :
82 148 : 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 152 : if(SUCCESS == status)
91 : {
92 296 : while(SQLITE_ROW == (rc = sqlite3_step(select_stmt)))
93 : {
94 148 : const char *response = (const char *)sqlite3_column_text(select_stmt,0);
95 :
96 148 : if(strcmp(response,"ok") == 0)
97 : {
98 148 : database_is_ok = true;
99 : }
100 : }
101 :
102 148 : 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 152 : if(select_stmt != NULL)
110 : {
111 148 : sqlite3_finalize(select_stmt);
112 : }
113 :
114 : /* Report integrity check results */
115 152 : if(SUCCESS == status)
116 : {
117 148 : if(database_is_ok == true)
118 : {
119 148 : 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 152 : rc = sqlite3_close(db);
129 :
130 152 : 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 152 : if(SUCCESS == status)
138 : {
139 : /* Check the database version number and upgrade the database if necessary */
140 148 : status = db_check_version(db_file_path,db_file_name);
141 : }
142 :
143 152 : if(dirc != NULL)
144 : {
145 152 : free(dirc);
146 : }
147 :
148 152 : provide(status);
149 : }
|