fixed segfault when opening a SQLite database fails
[strongswan.git] / src / libstrongswan / plugins / sqlite / sqlite_database.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "sqlite_database.h"
19
20 #include <sqlite3.h>
21 #include <library.h>
22 #include <debug.h>
23 #include <utils/mutex.h>
24
25 typedef struct private_sqlite_database_t private_sqlite_database_t;
26
27 /**
28 * private data of sqlite_database
29 */
30 struct private_sqlite_database_t {
31
32 /**
33 * public functions
34 */
35 sqlite_database_t public;
36
37 /**
38 * sqlite database connection
39 */
40 sqlite3 *db;
41
42 /**
43 * mutex used to lock execute()
44 */
45 mutex_t *mutex;
46 };
47
48 /**
49 * Create and run a sqlite stmt using a sql string and args
50 */
51 static sqlite3_stmt* run(private_sqlite_database_t *this, char *sql,
52 va_list *args)
53 {
54 sqlite3_stmt *stmt;
55 int params, i, res = SQLITE_OK;
56
57 if (sqlite3_prepare_v2(this->db, sql, -1, &stmt, NULL) == SQLITE_OK)
58 {
59 params = sqlite3_bind_parameter_count(stmt);
60 for (i = 1; i <= params; i++)
61 {
62 switch (va_arg(*args, db_type_t))
63 {
64 case DB_INT:
65 {
66 res = sqlite3_bind_int(stmt, i, va_arg(*args, int));
67 break;
68 }
69 case DB_UINT:
70 {
71 res = sqlite3_bind_int64(stmt, i, va_arg(*args, u_int));
72 break;
73 }
74 case DB_TEXT:
75 {
76 const char *text = va_arg(*args, const char*);
77 res = sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC);
78 break;
79 }
80 case DB_BLOB:
81 {
82 chunk_t c = va_arg(*args, chunk_t);
83 res = sqlite3_bind_blob(stmt, i, c.ptr, c.len, SQLITE_STATIC);
84 break;
85 }
86 case DB_DOUBLE:
87 {
88 res = sqlite3_bind_double(stmt, i, va_arg(*args, double));
89 break;
90 }
91 case DB_NULL:
92 {
93 res = sqlite3_bind_null(stmt, i);
94 break;
95 }
96 default:
97 {
98 res = SQLITE_MISUSE;
99 break;
100 }
101 }
102 if (res != SQLITE_OK)
103 {
104 break;
105 }
106 }
107 }
108 if (res != SQLITE_OK)
109 {
110 sqlite3_finalize(stmt);
111 return NULL;
112 }
113 return stmt;
114 }
115
116 typedef struct {
117 /** implements enumerator_t */
118 enumerator_t public;
119 /** associated sqlite statement */
120 sqlite3_stmt *stmt;
121 /** number of result columns */
122 int count;
123 /** column types */
124 db_type_t *columns;
125 } sqlite_enumerator_t;
126
127 /**
128 * destroy a sqlite enumerator
129 */
130 static void sqlite_enumerator_destroy(sqlite_enumerator_t *this)
131 {
132 sqlite3_finalize(this->stmt);
133 free(this->columns);
134 free(this);
135 }
136
137 /**
138 * Implementation of database.query().enumerate
139 */
140 static bool sqlite_enumerator_enumerate(sqlite_enumerator_t *this, ...)
141 {
142 int i;
143 va_list args;
144
145 if (sqlite3_step(this->stmt) != SQLITE_ROW)
146 {
147 return FALSE;
148 }
149 va_start(args, this);
150 for (i = 0; i < this->count; i++)
151 {
152 switch (this->columns[i])
153 {
154 case DB_INT:
155 {
156 int *value = va_arg(args, int*);
157 *value = sqlite3_column_int(this->stmt, i);
158 break;
159 }
160 case DB_UINT:
161 {
162 u_int *value = va_arg(args, u_int*);
163 *value = (u_int)sqlite3_column_int64(this->stmt, i);
164 break;
165 }
166 case DB_TEXT:
167 {
168 const unsigned char **value = va_arg(args, const unsigned char**);
169 *value = sqlite3_column_text(this->stmt, i);
170 break;
171 }
172 case DB_BLOB:
173 {
174 chunk_t *chunk = va_arg(args, chunk_t*);
175 chunk->len = sqlite3_column_bytes(this->stmt, i);
176 chunk->ptr = (u_char*)sqlite3_column_blob(this->stmt, i);
177 break;
178 }
179 case DB_DOUBLE:
180 {
181 double *value = va_arg(args, double*);
182 *value = sqlite3_column_double(this->stmt, i);
183 break;
184 }
185 default:
186 return FALSE;
187 }
188 }
189 va_end(args);
190 return TRUE;
191 }
192
193 /**
194 * Implementation of database_t.query.
195 */
196 static enumerator_t* query(private_sqlite_database_t *this, char *sql, ...)
197 {
198 sqlite3_stmt *stmt;
199 va_list args;
200 sqlite_enumerator_t *enumerator = NULL;
201 int i;
202
203
204 va_start(args, sql);
205 stmt = run(this, sql, &args);
206 if (stmt)
207 {
208 enumerator = malloc_thing(sqlite_enumerator_t);
209 enumerator->public.enumerate = (void*)sqlite_enumerator_enumerate;
210 enumerator->public.destroy = (void*)sqlite_enumerator_destroy;
211 enumerator->stmt = stmt;
212 enumerator->count = sqlite3_column_count(stmt);
213 enumerator->columns = malloc(sizeof(db_type_t) * enumerator->count);
214 for (i = 0; i < enumerator->count; i++)
215 {
216 enumerator->columns[i] = va_arg(args, db_type_t);
217 }
218 }
219 va_end(args);
220 return (enumerator_t*)enumerator;
221 }
222
223 /**
224 * Implementation of database_t.execute.
225 */
226 static int execute(private_sqlite_database_t *this, int *rowid, char *sql, ...)
227 {
228 sqlite3_stmt *stmt;
229 int affected = -1;
230 va_list args;
231
232 /* we need a lock to get our rowid/changes correctly */
233 this->mutex->lock(this->mutex);
234 va_start(args, sql);
235 stmt = run(this, sql, &args);
236 va_end(args);
237 if (stmt)
238 {
239 if (sqlite3_step(stmt) == SQLITE_DONE)
240 {
241 if (rowid)
242 {
243 *rowid = sqlite3_last_insert_rowid(this->db);
244 }
245 affected = sqlite3_changes(this->db);
246 }
247 sqlite3_finalize(stmt);
248 }
249 this->mutex->unlock(this->mutex);
250 return affected;
251 }
252
253 /**
254 * Implementation of database_t.destroy
255 */
256 static void destroy(private_sqlite_database_t *this)
257 {
258 sqlite3_close(this->db);
259 this->mutex->destroy(this->mutex);
260 free(this);
261 }
262
263 /*
264 * see header file
265 */
266 sqlite_database_t *sqlite_database_create(char *uri)
267 {
268 char *file;
269 private_sqlite_database_t *this;
270
271 /**
272 * parse sqlite:///path/to/file.db uri
273 */
274 if (!strneq(uri, "sqlite://", 9))
275 {
276 return NULL;
277 }
278 file = uri + 9;
279
280 this = malloc_thing(private_sqlite_database_t);
281
282 this->public.db.query = (enumerator_t* (*)(database_t *this, char *sql, ...))query;
283 this->public.db.execute = (int (*)(database_t *this, int *rowid, char *sql, ...))execute;
284 this->public.db.destroy = (void(*)(database_t*))destroy;
285
286 this->mutex = mutex_create(MUTEX_DEFAULT);
287
288 if (sqlite3_open(file, &this->db) != SQLITE_OK)
289 {
290 DBG1("opening SQLite database '%s' failed", file);
291 destroy(this);
292 return NULL;
293 }
294
295 return &this->public;
296 }
297