aed4104f3e4ea197fd4adc39e9cc0ef8bfa62fd7
[platform/core/api/notification.git] / src / notification_db.c
1 /*
2  * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <errno.h>
18 #include <unistd.h>
19 #include <stdio.h>
20 #include <string.h>
21
22 #include <sqlite3.h>
23 #include <tizen.h>
24
25 #include <notification_error.h>
26 #include <notification_debug.h>
27 #include <notification_db.h>
28 #include "notification_db_query.h"
29
30 static bool is_db_corrupted = false;
31
32 static int __check_integrity_cb(void *pid, int argc, char **argv, char **notUsed)
33 {
34         char *check_str = "ok";
35
36         if (strncmp(argv[0], check_str, strlen(check_str))) {
37                 ERR("db integrity result : %s" , argv[0]);
38                 is_db_corrupted = true;
39                 return -1;
40         }
41
42         INFO("db integrity result : %s" , argv[0]);
43         return 0;
44 }
45
46 static int __recover_corrupted_db(sqlite3 *db)
47 {
48         int ret = NOTIFICATION_ERROR_NONE;
49         int sql_ret;
50         char *errmsg = NULL;
51
52         INFO("DB is corrupted, start to recover corrupted db");
53         if (db)
54                 sqlite3_close(db);
55         unlink(DBPATH);
56
57         sql_ret = sqlite3_open_v2(DBPATH, &db,
58                                 SQLITE_OPEN_CREATE |SQLITE_OPEN_READWRITE,
59                                 NULL);
60         if (sql_ret != SQLITE_OK) {
61                 ERR("Failed to open db[%d]", sql_ret);
62                 unlink(DBPATH);
63                 ret = NOTIFICATION_ERROR_FROM_DB;
64                 goto out;
65         }
66
67         sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
68         if (sql_ret != SQLITE_OK) {
69                 ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
70                 ret = NOTIFICATION_ERROR_FROM_DB;
71         }
72
73 out:
74         if (errmsg)
75                 sqlite3_free(errmsg);
76
77         return ret;
78 }
79
80 EXPORT_API int notification_db_init()
81 {
82         int ret = NOTIFICATION_ERROR_NONE;
83         int sql_ret;
84         sqlite3 *db = NULL;
85         char *errmsg = NULL;
86
87         sql_ret = sqlite3_open_v2(DBPATH, &db,
88                         SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
89         if (sql_ret != SQLITE_OK) {
90                 /* LCOV_EXCL_START */
91                 ERR("Failed to open db[%d]", ret);
92                 ret = NOTIFICATION_ERROR_FROM_DB;
93                 goto out;
94                 /* LCOV_EXCL_STOP */
95         }
96
97         sql_ret = sqlite3_exec(db, CREATE_NOTIFICATION_TABLE, NULL, NULL, &errmsg);
98         if (sql_ret != SQLITE_OK) {
99                 /* LCOV_EXCL_START */
100                 ERR("Failed to exec sqlite[%d][%s]", ret, errmsg);
101                 ret = NOTIFICATION_ERROR_FROM_DB;
102                 goto out;
103                 /* LCOV_EXCL_STOP */
104         }
105
106         sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
107                                __check_integrity_cb, NULL, &errmsg);
108         if (sql_ret != SQLITE_OK || is_db_corrupted) {
109                 ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
110                 ret = NOTIFICATION_ERROR_FROM_DB;
111         }
112
113 out:
114         if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
115                 ret = __recover_corrupted_db(db);
116         if (errmsg)
117                 sqlite3_free(errmsg);
118         if (db)
119                 sqlite3_close(db);
120
121         return ret;
122 }
123
124 sqlite3 *notification_db_open()
125 {
126         int ret = 0;
127         sqlite3 *db = 0;
128
129         ret = access(DBPATH, R_OK | W_OK);
130         if (ret != 0) {
131                 /* LCOV_EXCL_START */
132                 set_last_result(NOTIFICATION_ERROR_FROM_DB);
133                 return NULL;
134                 /* LCOV_EXCL_STOP */
135         }
136
137         ret = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, NULL);
138         if (ret != SQLITE_OK) {
139                 /* LCOV_EXCL_START */
140                 if (ret == SQLITE_PERM)
141                         set_last_result(NOTIFICATION_ERROR_PERMISSION_DENIED);
142                 else
143                         set_last_result(NOTIFICATION_ERROR_FROM_DB);
144
145                 return NULL;
146                 /* LCOV_EXCL_STOP */
147         }
148
149         return db;
150 }
151
152 int notification_db_close(sqlite3 **db)
153 {
154         int ret = 0;
155
156         if (db == NULL || *db == NULL)
157                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
158
159         ret = sqlite3_close(*db);
160         if (ret != SQLITE_OK) {
161                 /* LCOV_EXCL_START */
162                 ERR("Failed to close db[%d]", ret);
163                 return NOTIFICATION_ERROR_FROM_DB;
164                 /* LCOV_EXCL_STOP */
165         }
166
167         *db = NULL;
168
169         return NOTIFICATION_ERROR_NONE;
170 }
171
172 int notification_db_exec(sqlite3 *db, const char *query, int *num_changes)
173 {
174         int ret = NOTIFICATION_ERROR_NONE;
175         sqlite3_stmt *stmt = NULL;
176
177         if (db == NULL || query == NULL)
178                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
179
180         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
181         if (ret != SQLITE_OK) {
182                 /* LCOV_EXCL_START */
183                 ERR("Sqlite3 err[%d][%s]", ret, sqlite3_errmsg(db));
184                 return NOTIFICATION_ERROR_FROM_DB;
185                 /* LCOV_EXCL_STOP */
186         }
187
188         ret = sqlite3_step(stmt);
189         if (ret == SQLITE_OK || ret == SQLITE_DONE) {
190                 if (num_changes != NULL)
191                         *num_changes = sqlite3_changes(db);
192
193                 ret = NOTIFICATION_ERROR_NONE;
194         } else {
195                 /* LCOV_EXCL_START */
196                 ERR("Sqlite err[%d][%s]", ret, sqlite3_errmsg(db));
197                 ret = NOTIFICATION_ERROR_FROM_DB;
198                 /* LCOV_EXCL_STOP */
199         }
200
201         if (stmt)
202                 sqlite3_finalize(stmt);
203
204         return ret;
205 }
206
207 char *notification_db_column_text(sqlite3_stmt * stmt, int col)
208 {
209         const unsigned char *col_text = NULL;
210
211         col_text = sqlite3_column_text(stmt, col);
212         if (col_text == NULL || col_text[0] == '\0')
213                 return NULL;
214
215         return strdup((char *)col_text);
216 }
217
218 bundle *notification_db_column_bundle(sqlite3_stmt * stmt, int col)
219 {
220         const unsigned char *col_bundle = NULL;
221
222         col_bundle = sqlite3_column_text(stmt, col);
223         if (col_bundle == NULL || col_bundle[0] == '\0')
224                 return NULL;
225
226         return bundle_decode(col_bundle, strlen((char *)col_bundle));
227 }
228