]> jfr.im git - irc/rqf/shadowircd.git/blame - bandb/rsdb_sqlite3.c
Fix bandb's interaction with --enable-fhs-paths by storing ban.db in the correct...
[irc/rqf/shadowircd.git] / bandb / rsdb_sqlite3.c
CommitLineData
7641ecd8
WP
1/* src/rsdb_sqlite.h
2 * Contains the code for the sqlite database backend.
3 *
4 * Copyright (C) 2003-2006 Lee Hardy <leeh@leeh.co.uk>
5 * Copyright (C) 2003-2006 ircd-ratbox development team
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * 1.Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2.Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3.The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
7641ecd8
WP
31 */
32#include "stdinc.h"
33#include "rsdb.h"
34
35#include <sqlite3.h>
36
37struct sqlite3 *rb_bandb;
38
39rsdb_error_cb *error_cb;
40
41static void
42mlog(const char *errstr, ...)
43{
44 if(error_cb != NULL)
45 {
46 char buf[256];
47 va_list ap;
48 va_start(ap, errstr);
49 rb_vsnprintf(buf, sizeof(buf), errstr, ap);
50 va_end(ap);
51 error_cb(buf);
52 }
53 else
54 exit(1);
55}
56
57int
58rsdb_init(rsdb_error_cb * ecb)
59{
6bdef3d5 60 const char *bandb_dbpath_env;
7641ecd8
WP
61 char dbpath[PATH_MAX];
62 char errbuf[128];
63 error_cb = ecb;
64
65 /* try a path from the environment first, useful for basedir overrides */
6bdef3d5 66 bandb_dbpath_env = getenv("BANDB_DBPATH");
7641ecd8 67
6bdef3d5
NPB
68 if(bandb_dbpath_env != NULL)
69 rb_strlcpy(dbpath, bandb_dbpath_env, sizeof(dbpath));
7641ecd8
WP
70 else
71 rb_strlcpy(dbpath, DBPATH, sizeof(dbpath));
6bdef3d5 72
7641ecd8
WP
73 if(sqlite3_open(dbpath, &rb_bandb) != SQLITE_OK)
74 {
75 rb_snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database: %s",
76 sqlite3_errmsg(rb_bandb));
77 mlog(errbuf);
78 return -1;
79 }
80 if(access(dbpath, W_OK))
81 {
82 rb_snprintf(errbuf, sizeof(errbuf), "Unable to open sqlite database for write: %s", strerror(errno));
83 mlog(errbuf);
84 return -1;
85 }
86 return 0;
87}
88
89void
90rsdb_shutdown(void)
91{
92 if(rb_bandb)
93 sqlite3_close(rb_bandb);
94}
95
96const char *
97rsdb_quote(const char *src)
98{
99 static char buf[BUFSIZE * 4];
100 char *p = buf;
101
102 /* cheap and dirty length check.. */
103 if(strlen(src) >= (sizeof(buf) / 2))
104 return NULL;
105
106 while(*src)
107 {
108 if(*src == '\'')
109 *p++ = '\'';
110
111 *p++ = *src++;
112 }
113
114 *p = '\0';
115 return buf;
116}
117
118static int
119rsdb_callback_func(void *cbfunc, int argc, char **argv, char **colnames)
120{
121 rsdb_callback cb = (rsdb_callback)((uintptr_t)cbfunc);
122 (cb) (argc, (const char **)argv);
123 return 0;
124}
125
126void
127rsdb_exec(rsdb_callback cb, const char *format, ...)
128{
129 static char buf[BUFSIZE * 4];
130 va_list args;
131 char *errmsg;
132 unsigned int i;
133 int j;
134
135 va_start(args, format);
136 i = rs_vsnprintf(buf, sizeof(buf), format, args);
137 va_end(args);
138
139 if(i >= sizeof(buf))
140 {
141 mlog("fatal error: length problem with compiling sql");
142 }
143
144 if((i = sqlite3_exec(rb_bandb, buf, (cb ? rsdb_callback_func : NULL), (void *)((uintptr_t)cb), &errmsg)))
145 {
146 switch (i)
147 {
148 case SQLITE_BUSY:
149 for(j = 0; j < 5; j++)
150 {
151 rb_sleep(0, 500000);
152 if(!sqlite3_exec
153 (rb_bandb, buf, (cb ? rsdb_callback_func : NULL), (void *)((uintptr_t)cb), &errmsg))
154 return;
155 }
156
157 /* failed, fall through to default */
158 mlog("fatal error: problem with db file: %s", errmsg);
159 break;
160
161 default:
162 mlog("fatal error: problem with db file: %s", errmsg);
163 break;
164 }
165 }
166}
167
168void
169rsdb_exec_fetch(struct rsdb_table *table, const char *format, ...)
170{
171 static char buf[BUFSIZE * 4];
172 va_list args;
173 char *errmsg;
174 char **data;
175 int pos;
176 unsigned int retval;
177 int i, j;
178
179 va_start(args, format);
180 retval = rs_vsnprintf(buf, sizeof(buf), format, args);
181 va_end(args);
182
183 if(retval >= sizeof(buf))
184 {
185 mlog("fatal error: length problem with compiling sql");
186 }
187
188 if((retval =
189 sqlite3_get_table(rb_bandb, buf, &data, &table->row_count, &table->col_count, &errmsg)))
190 {
191 int success = 0;
192
193 switch (retval)
194 {
195 case SQLITE_BUSY:
196 for(i = 0; i < 5; i++)
197 {
198 rb_sleep(0, 500000);
199 if(!sqlite3_get_table
200 (rb_bandb, buf, &data, &table->row_count, &table->col_count,
201 &errmsg))
202 {
203 success++;
204 break;
205 }
206 }
207
208 if(success)
209 break;
210
211 mlog("fatal error: problem with db file: %s", errmsg);
212 break;
213
214 default:
215 mlog("fatal error: problem with db file: %s", errmsg);
216 break;
217 }
218 }
219
220 /* we need to be able to free data afterward */
221 table->arg = data;
222
223 if(table->row_count == 0)
224 {
225 table->row = NULL;
226 return;
227 }
228
229 /* sqlite puts the column names as the first row */
230 pos = table->col_count;
231 table->row = rb_malloc(sizeof(char **) * table->row_count);
232 for(i = 0; i < table->row_count; i++)
233 {
234 table->row[i] = rb_malloc(sizeof(char *) * table->col_count);
235
236 for(j = 0; j < table->col_count; j++)
237 {
238 table->row[i][j] = data[pos++];
239 }
240 }
241}
242
243void
244rsdb_exec_fetch_end(struct rsdb_table *table)
245{
246 int i;
247
248 for(i = 0; i < table->row_count; i++)
249 {
250 rb_free(table->row[i]);
251 }
252 rb_free(table->row);
253
254 sqlite3_free_table((char **)table->arg);
255}
256
257void
258rsdb_transaction(rsdb_transtype type)
259{
260 if(type == RSDB_TRANS_START)
261 rsdb_exec(NULL, "BEGIN TRANSACTION");
262 else if(type == RSDB_TRANS_END)
263 rsdb_exec(NULL, "COMMIT TRANSACTION");
264}