1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
|
/*
* Copyright (C) 2010 Dennis Schafroth <dennis@schafroth.com>
* Copyright (C) 2010 Johannes Thoma <johannes.thoma@gmx.at>
* Copyright (C) 2010 - 2013 LINBIT Information Technologies GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "csync2.h"
#if defined(HAVE_SQLITE3)
#include <sqlite3.h>
#endif
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include "db_api.h"
#include "db_sqlite.h"
#include "dl.h"
#ifndef HAVE_SQLITE3
int db_sqlite_open(const char *file, db_conn_p * conn_p)
{
return DB_ERROR;
}
#else
static struct db_sqlite3_fns {
int (*sqlite3_open_fn) (const char *, sqlite3 **);
int (*sqlite3_close_fn) (sqlite3 *);
const char *(*sqlite3_errmsg_fn) (sqlite3 *);
int (*sqlite3_exec_fn) (sqlite3 *, const char *, int (*)(void *, int, char **, char **), void *, char **);
int (*sqlite3_prepare_v2_fn) (sqlite3 *, const char *, int, sqlite3_stmt **, const char **pzTail);
const unsigned char *(*sqlite3_column_text_fn) (sqlite3_stmt *, int);
const void *(*sqlite3_column_blob_fn) (sqlite3_stmt *, int);
int (*sqlite3_column_int_fn) (sqlite3_stmt *, int);
int (*sqlite3_step_fn) (sqlite3_stmt *);
int (*sqlite3_finalize_fn) (sqlite3_stmt *);
} f;
static void *dl_handle;
static void db_sqlite3_dlopen(void)
{
csync_debug(2, "Opening shared library libsqlite3.so.0\n");
dl_handle = dlopen("libsqlite3.so.0", RTLD_LAZY);
if (dl_handle == NULL) {
csync_fatal
("Could not open libsqlite3.so.0: %s\n"
"Please install sqlite3 client library (libsqlite3) or use other database (postgres, mysql)\n",
dlerror());
}
csync_debug(2, "Reading symbols from shared library libsqlite3.so.0\n");
LOOKUP_SYMBOL(dl_handle, sqlite3_open);
LOOKUP_SYMBOL(dl_handle, sqlite3_close);
LOOKUP_SYMBOL(dl_handle, sqlite3_errmsg);
LOOKUP_SYMBOL(dl_handle, sqlite3_exec);
LOOKUP_SYMBOL(dl_handle, sqlite3_prepare_v2);
LOOKUP_SYMBOL(dl_handle, sqlite3_column_text);
LOOKUP_SYMBOL(dl_handle, sqlite3_column_blob);
LOOKUP_SYMBOL(dl_handle, sqlite3_column_int);
LOOKUP_SYMBOL(dl_handle, sqlite3_step);
LOOKUP_SYMBOL(dl_handle, sqlite3_finalize);
}
static int sqlite_errors[] = { SQLITE_OK, SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, SQLITE_DONE, -1 };
static int db_errors[] = { DB_OK, DB_ERROR, DB_BUSY, DB_ROW, DB_DONE, -1 };
int db_sqlite_error_map(int sqlite_err)
{
int index;
for (index = 0;; index++) {
if (sqlite_errors[index] == -1)
return DB_ERROR;
if (sqlite_err == sqlite_errors[index])
return db_errors[index];
}
}
int db_sqlite_open(const char *file, db_conn_p * conn_p)
{
sqlite3 *db;
db_sqlite3_dlopen();
int rc = f.sqlite3_open_fn(file, &db);
if (rc != SQLITE_OK) {
return db_sqlite_error_map(rc);
};
db_conn_p conn = calloc(1, sizeof(*conn));
if (conn == NULL) {
return DB_ERROR;
}
*conn_p = conn;
conn->private = db;
conn->close = db_sqlite_close;
conn->exec = db_sqlite_exec;
conn->prepare = db_sqlite_prepare;
conn->errmsg = db_sqlite_errmsg;
conn->upgrade_to_schema = db_sqlite_upgrade_to_schema;
return db_sqlite_error_map(rc);
}
void db_sqlite_close(db_conn_p conn)
{
if (!conn)
return;
if (!conn->private)
return;
f.sqlite3_close_fn(conn->private);
conn->private = 0;
}
const char *db_sqlite_errmsg(db_conn_p conn)
{
if (!conn)
return "(no connection)";
if (!conn->private)
return "(no private data in conn)";
return f.sqlite3_errmsg_fn(conn->private);
}
int db_sqlite_exec(db_conn_p conn, const char *sql)
{
int rc;
if (!conn)
return DB_NO_CONNECTION;
if (!conn->private) {
/* added error element */
return DB_NO_CONNECTION_REAL;
}
rc = f.sqlite3_exec_fn(conn->private, sql, 0, 0, 0);
return db_sqlite_error_map(rc);
}
int db_sqlite_prepare(db_conn_p conn, const char *sql, db_stmt_p * stmt_p, char **pptail)
{
int rc;
*stmt_p = NULL;
if (!conn)
return DB_NO_CONNECTION;
if (!conn->private) {
/* added error element */
return DB_NO_CONNECTION_REAL;
}
db_stmt_p stmt = malloc(sizeof(*stmt));
sqlite3_stmt *sqlite_stmt = 0;
/* TODO avoid strlen, use configurable limit? */
rc = f.sqlite3_prepare_v2_fn(conn->private, sql, strlen(sql), &sqlite_stmt, (const char **)pptail);
if (rc != SQLITE_OK)
return db_sqlite_error_map(rc);
stmt->private = sqlite_stmt;
*stmt_p = stmt;
stmt->get_column_text = db_sqlite_stmt_get_column_text;
stmt->get_column_blob = db_sqlite_stmt_get_column_blob;
stmt->get_column_int = db_sqlite_stmt_get_column_int;
stmt->next = db_sqlite_stmt_next;
stmt->close = db_sqlite_stmt_close;
stmt->db = conn;
return db_sqlite_error_map(rc);
}
const char *db_sqlite_stmt_get_column_text(db_stmt_p stmt, int column)
{
if (!stmt || !stmt->private) {
return 0;
}
sqlite3_stmt *sqlite_stmt = stmt->private;
const unsigned char *result = f.sqlite3_column_text_fn(sqlite_stmt, column);
/* error handling */
return (const char *)result;
}
#if defined(HAVE_SQLITE3)
const void *db_sqlite_stmt_get_column_blob(db_stmt_p stmtx, int col)
{
sqlite3_stmt *stmt = stmtx->private;
return f.sqlite3_column_blob_fn(stmt, col);
}
#endif
int db_sqlite_stmt_get_column_int(db_stmt_p stmt, int column)
{
sqlite3_stmt *sqlite_stmt = stmt->private;
int rc = f.sqlite3_column_int_fn(sqlite_stmt, column);
return db_sqlite_error_map(rc);
}
int db_sqlite_stmt_next(db_stmt_p stmt)
{
sqlite3_stmt *sqlite_stmt = stmt->private;
int rc = f.sqlite3_step_fn(sqlite_stmt);
return db_sqlite_error_map(rc);
}
int db_sqlite_stmt_close(db_stmt_p stmt)
{
sqlite3_stmt *sqlite_stmt = stmt->private;
int rc = f.sqlite3_finalize_fn(sqlite_stmt);
free(stmt);
return db_sqlite_error_map(rc);
}
int db_sqlite_upgrade_to_schema(int version)
{
if (version < 0)
return DB_OK;
if (version > 0)
return DB_ERROR;
csync_debug(2, "Upgrading database schema to version %d.\n", version);
/* *INDENT-OFF* */
csync_db_sql("Creating file table",
"CREATE TABLE file ("
" filename, checktxt,"
" UNIQUE ( filename ) ON CONFLICT REPLACE"
")");
csync_db_sql("Creating dirty table",
"CREATE TABLE dirty ("
" filename, forced, myname, peername,"
" UNIQUE ( filename, peername ) ON CONFLICT IGNORE"
")");
csync_db_sql("Creating hint table",
"CREATE TABLE hint ("
" filename, recursive,"
" UNIQUE ( filename, recursive ) ON CONFLICT IGNORE"
")");
csync_db_sql("Creating action table",
"CREATE TABLE action ("
" filename, command, logfile,"
" UNIQUE ( filename, command ) ON CONFLICT IGNORE"
")");
csync_db_sql("Creating x509_cert table",
"CREATE TABLE x509_cert ("
" peername, certdata,"
" UNIQUE ( peername ) ON CONFLICT IGNORE"
")");
/* *INDENT-ON* */
return DB_OK;
}
#endif
|