Support large files on 32bit systems
[nagios-reports-module.git] / sql.c
bloba03ef9139f35ae472a0ee4269cf34bb0dbb03471
1 #include "ndbneb.h"
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include "sql.h"
5 #include "logging.h"
7 static struct {
8 char *host;
9 char *name;
10 char *user;
11 char *pass;
12 char *table;
13 unsigned int port;
14 MYSQL *link;
15 } db;
17 #undef ESC_BUFS
18 #define ESC_BUFS 8 /* must be a power of 2 */
19 #define MAX_ESC_STRING 65536
21 typedef unsigned int uint;
23 #define esc(s) sql_escape(s)
24 char *sql_escape(const char *str)
26 static int idx = 0;
27 static char *buf_ary[ESC_BUFS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
28 static uint bufsize[ESC_BUFS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
29 char *buf;
30 int len;
32 if (!str || !*str)
33 return "";
35 if (!db.link && sql_init() < 0)
36 return NULL;
38 len = strlen(str);
39 if (len > MAX_ESC_STRING) {
40 lwarn("Unescaped string too large (%d bytes, %d is allowed)",
41 len, MAX_ESC_STRING);
42 return "";
45 if (bufsize[idx] < len * 2) {
46 uint size = len * 2;
47 if (size < 16384)
48 size = 16384;
50 buf_ary[idx] = realloc(buf_ary[idx], size);
51 if (!buf_ary[idx]) {
52 bufsize[idx] = 0;
53 lwarn("Failed to allocate %d bytes for sql escape buffer", size);
54 return "";
56 bufsize[idx] = size;
58 buf = buf_ary[idx];
59 idx = (idx + 1) & (ESC_BUFS - 1);
60 mysql_real_escape_string(db.link, buf, str, len);
62 return buf;
66 * these two functions are only here to allow callers
67 * access to error reporting without having to expose
68 * the db-link to theh callers. It's also nifty as we
69 * want to remain database layer agnostic
71 const char *sql_error()
73 if (db.link)
74 return mysql_error(db.link);
76 return "unknown error (no link)";
79 int sql_errno(void)
81 if (db.link)
82 return mysql_errno(db.link);
84 return -1;
87 SQL_RESULT *sql_get_result(void)
89 if (db.link)
90 return mysql_use_result(db.link);
92 return NULL;
95 SQL_ROW sql_fetch_row(MYSQL_RES *result)
97 if (result)
98 return mysql_fetch_row(result);
100 return NULL;
103 void sql_free_result(SQL_RESULT *result)
105 if (result)
106 mysql_free_result(result);
109 static int sql_reinit(void)
111 sql_close();
112 return sql_init();
115 int sql_query(const char *fmt, ...)
117 char *query;
118 int len, result = 0;
119 va_list ap;
121 if (!db.link && sql_reinit() < 0)
122 return -1;
124 va_start(ap, fmt);
125 len = vasprintf(&query, fmt, ap);
126 va_end(ap);
128 if (len == -1 || !query) {
129 lerr("sql_query: Failed to build query from format-string '%s'", fmt);
130 return -1;
132 if ((result = mysql_real_query(db.link, query, len))) {
133 lerr("mysql_query(): Retrying failed query [%s]: %s",
134 query, sql_error());
136 sql_close();
137 if (sql_init() < 0 || (result = mysql_real_query(db.link, query, len)))
138 lerr("mysql_query(): Dropping failed query [%s]: %s",
139 query, sql_error());
142 free(query);
144 return result;
147 int sql_init(void)
149 if (!(db.link = mysql_init(NULL)))
150 return -1;
152 if (!db.host) {
153 db.host = "";
154 db.port = 0;
157 if (!(mysql_real_connect(db.link, db.host, db.user, db.pass,
158 db.name, db.port, NULL, 0)))
160 lerr("Failed to connect to '%s' at '%s':'%d' using %s:%s as credentials: %s",
161 db.name, db.host, db.port, db.user, db.pass, sql_error());
163 sql_close();
164 return -1;
167 return 0;
170 int sql_close(void)
172 if (db.link)
173 mysql_close(db.link);
175 db.link = NULL;
177 return 0;
180 const char *sql_db_name(void)
182 if (!db.name)
183 return "monitor_reports";
185 return db.name;
188 const char *sql_table_name(void)
190 if (!db.table)
191 return "report_data";
193 return db.table;
196 int sql_config(const char *key, const char *value)
198 if (!prefixcmp(key, "db_database"))
199 db.name = strdup(value);
200 else if (!prefixcmp(key, "db_user"))
201 db.user = strdup(value);
202 else if (!prefixcmp(key, "db_pass"))
203 db.pass = strdup(value);
204 else if (!prefixcmp(key, "db_host"))
205 db.host = strdup(value);
206 else if (!prefixcmp(key, "db_table")) {
207 db.table = strdup(value);
209 else if (!prefixcmp(key, "db_port")) {
210 char *endp;
212 db.port = (unsigned int)strtoul(value, &endp, 0);
214 if (endp == value || *endp != 0)
215 return -1;
217 else
218 return -1; /* config error */
220 return 0;