</manager>
***/
-#define MAX_DB_FIELD 256
AST_MUTEX_DEFINE_STATIC(dblock);
static ast_cond_t dbcond;
static sqlite3 *astdb;
DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
-DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
+DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key TEXT, value TEXT, PRIMARY KEY(key))")
/* This query begs an explanation:
*
int ast_db_put(const char *family, const char *key, const char *value)
{
- char fullkey[MAX_DB_FIELD];
- size_t fullkey_len;
+ char *fullkey;
+ int fullkey_len;
int res = 0;
- if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
+ fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
+ if (fullkey_len < 0) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
+ family, key);
return -1;
}
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
-
ast_mutex_lock(&dblock);
if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
ast_log(LOG_WARNING, "Couldn't execute statement: %s\n", sqlite3_errmsg(astdb));
res = -1;
}
-
sqlite3_reset(put_stmt);
db_sync();
ast_mutex_unlock(&dblock);
+ ast_free(fullkey);
return res;
}
static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
{
const unsigned char *result;
- char fullkey[MAX_DB_FIELD];
- size_t fullkey_len;
+ char *fullkey;
+ int fullkey_len;
int res = 0;
- if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
+ fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
+ if (fullkey_len < 0) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
+ family, key);
return -1;
}
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
-
ast_mutex_lock(&dblock);
if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
}
sqlite3_reset(get_stmt);
ast_mutex_unlock(&dblock);
+ ast_free(fullkey);
return res;
}
int ast_db_exists(const char *family, const char *key)
{
int result;
- char fullkey[MAX_DB_FIELD];
- size_t fullkey_len;
+ char *fullkey;
+ int fullkey_len;
int res = 0;
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
- if (fullkey_len >= sizeof(fullkey)) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
+ fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
+ if (fullkey_len < 0) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
+ family, key);
return -1;
}
}
sqlite3_reset(exists_stmt);
ast_mutex_unlock(&dblock);
+ ast_free(fullkey);
return res;
}
int ast_db_del(const char *family, const char *key)
{
- char fullkey[MAX_DB_FIELD];
- size_t fullkey_len;
+ char *fullkey;
+ int fullkey_len;
int res = 0;
- if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
+ fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
+ if (fullkey_len < 0) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
+ family, key);
return -1;
}
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
-
ast_mutex_lock(&dblock);
if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
sqlite3_reset(del_stmt);
db_sync();
ast_mutex_unlock(&dblock);
+ ast_free(fullkey);
return res;
}
int ast_db_del2(const char *family, const char *key)
{
- char fullkey[MAX_DB_FIELD];
+ char *fullkey;
char tmp[1];
- size_t fullkey_len;
+ int fullkey_len;
int mres, res = 0;
- if (strlen(family) + strlen(key) + 2 > sizeof(fullkey) - 1) {
- ast_log(LOG_WARNING, "Family and key length must be less than %zu bytes\n", sizeof(fullkey) - 3);
+ fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
+ if (fullkey_len < 0) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
+ family, key);
return -1;
}
- fullkey_len = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, key);
-
ast_mutex_lock(&dblock);
if (ast_db_get(family, key, tmp, sizeof(tmp))) {
ast_log(LOG_WARNING, "AstDB key %s does not exist\n", fullkey);
sqlite3_reset(del_stmt);
db_sync();
ast_mutex_unlock(&dblock);
+ ast_free(fullkey);
return res;
}
-int ast_db_deltree(const char *family, const char *keytree)
+static char *create_prefix(const char *family, const char *keytree,
+ int *prefix_len)
{
- sqlite3_stmt *stmt = deltree_stmt;
- char prefix[MAX_DB_FIELD];
- int res = 0;
+ char *prefix = NULL;
+ *prefix_len = 0;
if (!ast_strlen_zero(family)) {
if (!ast_strlen_zero(keytree)) {
/* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
+ *prefix_len = ast_asprintf(&prefix, "/%s/%s", family, keytree);
} else {
/* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", family);
+ *prefix_len = ast_asprintf(&prefix, "/%s", family);
+ }
+ if (*prefix_len < 0) {
+ ast_log(LOG_WARNING, "Unable to allocate memory for family/keytree '/%s%s%s'\n",
+ S_OR(family, ""), S_COR(keytree, "/", ""), S_OR(keytree, ""));
+ return NULL;
}
} else {
- prefix[0] = '\0';
+ prefix = ast_strdup("");
+ }
+ return prefix;
+}
+
+int ast_db_deltree(const char *family, const char *keytree)
+{
+ sqlite3_stmt *stmt = deltree_stmt;
+ char *prefix = NULL;
+ int prefix_len = 0;
+ int res = 0;
+
+ if (ast_strlen_zero(family) && !ast_strlen_zero(keytree)) {
+ ast_log(LOG_WARNING, "Key tree '%s' specified without family\n", keytree);
+ return -1;
+ }
+
+ prefix = create_prefix(family, keytree, &prefix_len);
+ if (!prefix) {
+ return -1;
+ }
+ if (prefix_len == 0) {
stmt = deltree_all_stmt;
}
ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
+ if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
res = -1;
} else if (sqlite3_step(stmt) != SQLITE_DONE) {
sqlite3_reset(stmt);
db_sync();
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
return res;
}
struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
{
- char prefix[MAX_DB_FIELD];
+ char *prefix = NULL;
+ int prefix_len = 0;
sqlite3_stmt *stmt = gettree_stmt;
- size_t res = 0;
struct ast_db_entry *ret;
- if (!ast_strlen_zero(family)) {
- if (!ast_strlen_zero(keytree)) {
- /* Family and key tree */
- res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
- } else {
- /* Family only */
- res = snprintf(prefix, sizeof(prefix), "/%s", family);
- }
-
- if (res >= sizeof(prefix)) {
- ast_log(LOG_WARNING, "Requested prefix is too long: %s\n", keytree);
- return NULL;
- }
- } else {
- prefix[0] = '\0';
+ prefix = create_prefix(family, keytree, &prefix_len);
+ if (!prefix) {
+ return NULL;
+ }
+ if (prefix_len == 0) {
stmt = gettree_all_stmt;
}
ast_mutex_lock(&dblock);
- if (res && (sqlite3_bind_text(stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK)) {
+ if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
return NULL;
}
ret = db_gettree_common(stmt);
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
return ret;
}
struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
{
- char prefix[MAX_DB_FIELD];
- size_t res;
+ char *prefix = NULL;
+ int prefix_len = 0;
struct ast_db_entry *ret;
- res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, key_prefix);
- if (res >= sizeof(prefix)) {
- ast_log(LOG_WARNING, "Requested key prefix is too long: %s\n", key_prefix);
+ prefix = create_prefix(family, key_prefix, &prefix_len);
+ if (!prefix) {
return NULL;
}
ast_mutex_lock(&dblock);
- if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK) {
+ if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK) {
ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
sqlite3_reset(gettree_prefix_stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
return NULL;
}
ret = db_gettree_common(gettree_prefix_stmt);
sqlite3_reset(gettree_prefix_stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
return ret;
}
static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int res;
- char tmp[MAX_DB_FIELD];
+ char *tmp = NULL;
switch (cmd) {
case CLI_INIT:
if (a->argc != 4)
return CLI_SHOWUSAGE;
- res = ast_db_get(a->argv[2], a->argv[3], tmp, sizeof(tmp));
+ res = ast_db_get_allocated(a->argv[2], a->argv[3], &tmp);
if (res) {
ast_cli(a->fd, "Database entry not found.\n");
} else {
ast_cli(a->fd, "Value: %s\n", tmp);
+ ast_free(tmp);
}
+
return CLI_SUCCESS;
}
static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char prefix[MAX_DB_FIELD];
+ char *prefix = NULL;
+ int prefix_len = 0;
+ const char *family = a->argc > 2 ? a->argv[2] : "";
+ const char *keytree = a->argc > 3 ? a->argv[3] : "";
int counter = 0;
sqlite3_stmt *stmt = gettree_stmt;
return NULL;
}
- if (a->argc == 4) {
- /* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", a->argv[2], a->argv[3]);
- } else if (a->argc == 3) {
- /* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", a->argv[2]);
- } else if (a->argc == 2) {
- /* Neither */
- prefix[0] = '\0';
- stmt = gettree_all_stmt;
-
- } else {
+ if (a->argc > 4) {
return CLI_SHOWUSAGE;
}
+ prefix = create_prefix(family, keytree, &prefix_len);
+ if (!prefix) {
+ return NULL;
+ }
+ if (prefix_len == 0) {
+ stmt = gettree_all_stmt;
+ }
+
ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
+ if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
return NULL;
}
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
ast_cli(a->fd, "%d results found.\n", counter);
return CLI_SUCCESS;
char idText[256];
const char *family = astman_get_header(m, "Family");
const char *key = astman_get_header(m, "Key");
- char tmp[MAX_DB_FIELD];
+ char *tmp = NULL;
int res;
if (ast_strlen_zero(family)) {
if (!ast_strlen_zero(id))
snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
- res = ast_db_get(family, key, tmp, sizeof(tmp));
+ res = ast_db_get_allocated(family, key, &tmp);
if (res) {
astman_send_error(s, m, "Database entry not found");
} else {
"%s"
"\r\n",
family, key, tmp, idText);
-
+ ast_free(tmp);
astman_send_list_complete_start(s, m, "DBGetComplete", 1);
astman_send_list_complete_end(s);
}
static int manager_db_tree_get(struct mansession *s, const struct message *m)
{
- char prefix[MAX_DB_FIELD];
+ char *prefix;
+ int prefix_len = 0;
char idText[256];
const char *id = astman_get_header(m,"ActionID");
const char *family = astman_get_header(m, "Family");
sqlite3_stmt *stmt = gettree_stmt;
int count = 0;
- if (!ast_strlen_zero(family) && !ast_strlen_zero(key)) {
- /* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", family, key);
- } else if (!ast_strlen_zero(family)) {
- /* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", family);
- } else {
- /* Neither */
- prefix[0] = '\0';
+ prefix = create_prefix(family, key, &prefix_len);
+ if (!prefix) {
+ astman_send_error(s, m, "Unable to allocate memory for Family/Key");
+ return 0;
+ }
+ if (prefix_len == 0) {
stmt = gettree_all_stmt;
}
}
ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
+ if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
astman_send_error(s, m, "Unable to search database");
return 0;
}
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
+ ast_free(prefix);
astman_send_list_complete_start(s, m, "DBGetTreeComplete", count);
astman_send_list_complete_end(s);