summaryrefslogtreecommitdiff
path: root/source4/lib/ldb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r--source4/lib/ldb/common/ldb_explode_dn.c66
-rw-r--r--source4/lib/ldb/config.mk5
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c323
-rw-r--r--source4/lib/ldb/tools/ldbsearch.c13
4 files changed, 177 insertions, 230 deletions
diff --git a/source4/lib/ldb/common/ldb_explode_dn.c b/source4/lib/ldb/common/ldb_explode_dn.c
index d3f278c776..e3cd53d047 100644
--- a/source4/lib/ldb/common/ldb_explode_dn.c
+++ b/source4/lib/ldb/common/ldb_explode_dn.c
@@ -21,6 +21,7 @@
#include "includes.h"
#include "ldb/include/ldb.h"
+#include "ldb/include/ldb_private.h"
#include "ldb/include/ldb_explode_dn.h"
#define LDB_PARSE_DN_INVALID(x) do { \
@@ -34,10 +35,6 @@
* Forward declarations
*/
-static char
-octet_from_hex(char * p,
- char * ret);
-
static char *
parse_slash(char *p,
char *end);
@@ -388,13 +385,14 @@ ldb_explode_dn(void * mem_ctx,
/* copy each of the attributes to the normalized component */
for (i = 0; i < component->attr_num; i++) {
if (i != 0) {
- *dest = '+';
- dest++;
+ *dest++ = '+';
}
src = component->attributes[i]->rdn;
/* we are guaranteed to have enough space in dest */
- strcpy(dest, src);
+ size = strlen(src);
+ strncpy(dest, src, size + 1);
+ dest += size;
}
ldb_debug(mem_ctx,
@@ -449,7 +447,9 @@ ldb_explode_dn(void * mem_ctx,
src = dn->components[i]->component;
/* we are guaranteed to have enough space in dest */
- strcpy(dest, src);
+ size = strlen(src);
+ strncpy(dest, src, size + 1);
+ dest += size;
}
ldb_debug(mem_ctx, LDB_DEBUG_TRACE, "dn: [%s]\n", dn->dn);
@@ -468,47 +468,6 @@ failed:
}
-static char
-octet_from_hex(char * p,
- char * ret)
-{
- unsigned char low_char;
- unsigned char high_char;
-
- unsigned char low_binary;
- unsigned char high_binary;
-
- if (p[0] == '\0' || p[1] == '\0') {
- return -1;
- }
-
- high_char = p[0];
- low_char = p[1];
-
- if (high_char >= '0' && high_char <= '9') {
- high_binary = high_char - '0';
- } else if (high_char >= 'A' && high_char <= 'F') {
- high_binary = 10 + (high_char - 'A');
- } else if (high_char >= 'a' && high_char <= 'f') {
- high_binary = 10 + (high_char - 'a');
- } else {
- return -1;
- }
-
- if (low_char >= '0' && low_char <= '9') {
- low_binary = low_char - '0';
- } else if (low_char >= 'A' && low_char <= 'F') {
- low_binary = 10 + (low_char - 'A');
- } else if (low_char >= 'a' && low_char <= 'f') {
- low_binary = 10 + (low_char - 'a');
- } else {
- return -1;
- }
-
- *ret = (char) ((high_binary << 4) | low_binary);
- return 0;
-}
-
static char *
parse_slash(char *p,
char *end)
@@ -528,10 +487,11 @@ parse_slash(char *p,
return (end - 1);
default:
- if (*(p + 1) != '\0' && *(p + 2) != '\0') {
- if (octet_from_hex(p + 1, p) < 0) {
- return NULL;
- }
+ if (isxdigit(p[1]) && isxdigit(p[2])) {
+ int x;
+
+ sscanf(p + 1, "%02x", &x);
+ *p = (char) x;
memmove(p + 1, p + 3, end - (p + 3));
return (end - 2);
} else {
diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk
index 03a3a401fb..03855017ba 100644
--- a/source4/lib/ldb/config.mk
+++ b/source4/lib/ldb/config.mk
@@ -25,7 +25,7 @@ INIT_OBJ_FILES = \
REQUIRED_SUBSYSTEMS = \
EXT_LIB_LDAP
NOPROTO = YES
-# End MODULE libldb_tdb
+# End MODULE libldb_ldap
################################################
################################################
@@ -70,7 +70,8 @@ ADD_OBJ_FILES = \
lib/ldb/common/util.o \
lib/ldb/common/ldb_utf8.o \
lib/ldb/common/ldb_debug.o \
- lib/ldb/common/ldb_modules.o
+ lib/ldb/common/ldb_modules.o \
+ lib/ldb/common/ldb_explode_dn.o
REQUIRED_SUBSYSTEMS = \
LIBREPLACE LIBTALLOC
NOPROTO = YES
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
index 54f8903231..c0e3963743 100644
--- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
+++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
@@ -56,6 +56,16 @@
} \
} while (0)
+#define QUERY_INT(lsqlite3, result_var, bRollbackOnError, sql...) \
+ do { \
+ if (lsqlite3_query_int(lsqlite3, &result_var, sql) != 0) { \
+ if (bRollbackOnError) { \
+ lsqlite3_query_norows(lsqlite3, \
+ "ROLLBACK;"); \
+ } \
+ return -1; \
+ } \
+ } while (0)
/*
* lsqlite3_query_norows()
@@ -140,6 +150,94 @@ lsqlite3_query_norows(const struct lsqlite3_private *lsqlite3,
}
+/*
+ * lsqlite3_query_int()
+ *
+ * This function is used for the common case of queries that return a single
+ * integer value.
+ *
+ * NOTE: If more than one value is returned by the query, all but the first
+ * one will be ignored.
+ */
+static int
+lsqlite3_query_int(const struct lsqlite3_private * lsqlite3,
+ long long * pRet,
+ const char * pSql,
+ ...)
+{
+ int ret;
+ int bLoop;
+ char * p;
+ const char * pTail;
+ sqlite3_stmt * pStmt;
+ va_list args;
+
+ /* Begin access to variable argument list */
+ va_start(args, pSql);
+
+ /* Format the query */
+ if ((p = sqlite3_vmprintf(pSql, args)) == NULL) {
+ return -1;
+ }
+
+ /*
+ * Prepare and execute the SQL statement. Loop allows retrying on
+ * certain errors, e.g. SQLITE_SCHEMA occurs if the schema changes,
+ * requiring retrying the operation.
+ */
+ for (bLoop = TRUE; bLoop; ) {
+
+ /* Compile the SQL statement into sqlite virtual machine */
+ if ((ret = sqlite3_prepare(lsqlite3->sqlite,
+ pTail,
+ -1,
+ &pStmt,
+ &pTail)) != SQLITE_OK) {
+ ret = -1;
+ break;
+ }
+
+ /* No rows expected, so just step through machine code once */
+ if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) {
+ (void) sqlite3_finalize(pStmt);
+ continue;
+ } else if (ret != SQLITE_ROW) {
+ (void) sqlite3_finalize(pStmt);
+ ret = -1;
+ break;
+ }
+
+ /* Get the value to be returned */
+ *pRet = sqlite3_column_int64(pStmt, 0);
+
+ /* Free the virtual machine */
+ if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) {
+ (void) sqlite3_finalize(pStmt);
+ continue;
+ } else if (ret != SQLITE_OK) {
+ (void) sqlite3_finalize(pStmt);
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Normal condition is only one time through loop. Loop is
+ * rerun in error conditions, via "continue", above.
+ */
+ ret = 0;
+ bLoop = FALSE;
+ }
+
+ /* All done with variable argument list */
+ va_end(args);
+
+ /* Free the memory we allocated for our query string */
+ sqlite3_free(p);
+
+ return ret;
+}
+
+
#if 0
/*
* we don't need this right now, but will once we add some backend options
@@ -479,15 +577,11 @@ lsqlite3_search(struct ldb_module * module,
const char * const attrs[],
struct ldb_message *** res)
{
- int ret;
- int bLoop;
long long eid = 0;
char * sql;
char * sql_constraints;
char * table_list;
char * hTalloc;
- const char * pTail;
- sqlite3_stmt * pStmt;
struct ldb_parse_tree * pTree;
struct lsqlite3_private * lsqlite3 = module->private_data;
@@ -495,68 +589,22 @@ lsqlite3_search(struct ldb_module * module,
pBaseDN = "";
}
+ /* Begin a transaction */
+ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN IMMEDIATE;");
+
/*
* Obtain the eid of the base DN
*/
- if ((pTail = sqlite3_mprintf("SELECT eid "
- " FROM ldb_attr_dn "
- " WHERE attr_value = %Q;",
- pBaseDN)) == NULL) {
- return -1;
- }
-
- for (bLoop = TRUE; bLoop; ) {
-
- /* Compile the SQL statement into sqlite virtual machine */
- if ((ret = sqlite3_prepare(lsqlite3->sqlite,
- pTail,
- -1,
- &pStmt,
- NULL)) != SQLITE_OK) {
- ret = -1;
- break;
- }
-
- /* One row expected */
- if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) {
- (void) sqlite3_finalize(pStmt);
- continue;
- } else if (ret != SQLITE_ROW) {
- (void) sqlite3_finalize(pStmt);
- ret = -1;
- break;
- }
-
- /* Retrieve the EID */
- eid = sqlite3_column_int64(pStmt, 0);
-
- /* Free the virtual machine */
- if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) {
- (void) sqlite3_finalize(pStmt);
- continue;
- } else if (ret != SQLITE_OK) {
- (void) sqlite3_finalize(pStmt);
- ret = -1;
- break;
- }
-
- /*
- * Normal condition is only one time through loop. Loop is
- * rerun in error conditions, via "continue", above.
- */
- sqlite3_free(discard_const_p(char, pTail));
- ret = 0;
- bLoop = FALSE;
- }
-
- if (ret != 0) {
- sqlite3_free(discard_const_p(char, pTail));
- return -1;
- }
+ QUERY_INT(lsqlite3,
+ eid,
+ TRUE,
+ "SELECT eid "
+ " FROM ldb_attr_dn "
+ " WHERE attr_value = %Q;",
+ pBaseDN);
/* Parse the filter expression into a tree we can work with */
if ((pTree = ldb_parse_tree(module->ldb, pExpression)) == NULL) {
- sqlite3_free(discard_const_p(char, pTail));
return -1;
}
@@ -628,7 +676,12 @@ lsqlite3_search(struct ldb_module * module,
break;
}
- return ret;
+#warning "retrieve and return the result set of the search here"
+
+ /* End the transaction */
+ QUERY_NOROWS(lsqlite3, FALSE, "END TRANSACTION;");
+
+ return 0;
}
@@ -830,12 +883,6 @@ static int
lsqlite3_modify(struct ldb_module *module,
const struct ldb_message *msg)
{
- int ret;
- int bLoop;
- char * p;
- const char * pTail;
- long long eid;
- sqlite3_stmt * pStmt;
struct lsqlite3_private * lsqlite3 = module->private_data;
/* ignore ltdb specials */
@@ -846,72 +893,6 @@ lsqlite3_modify(struct ldb_module *module,
/* Begin a transaction */
QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;");
- /* Format the query */
- if ((p = sqlite3_mprintf(
- "SELECT eid "
- " FROM ldb_entry "
- " WHERE dn = %Q;",
- ldb_dn_fold(module,
- msg->dn,
- lsqlite3_case_fold_attr_required))) == NULL) {
- return -1;
- }
-
- /* Get the id of this DN. */
- for (bLoop = TRUE; bLoop; ) {
-
- /* Compile the SQL statement into sqlite virtual machine */
- if ((ret = sqlite3_prepare(lsqlite3->sqlite,
- pTail,
- -1,
- &pStmt,
- &pTail)) != SQLITE_OK) {
- ret = -1;
- break;
- }
-
- /* One row expected */
- if ((ret = sqlite3_step(pStmt)) == SQLITE_SCHEMA) {
- (void) sqlite3_finalize(pStmt);
- continue;
- } else if (ret != SQLITE_ROW) {
- (void) sqlite3_finalize(pStmt);
- ret = -1;
- break;
- }
-
- /* Retrieve the EID */
- eid = sqlite3_column_int64(pStmt, 0);
-
- /* Free the virtual machine */
- if ((ret = sqlite3_finalize(pStmt)) == SQLITE_SCHEMA) {
- (void) sqlite3_finalize(pStmt);
- continue;
- } else if (ret != SQLITE_OK) {
- (void) sqlite3_finalize(pStmt);
- ret = -1;
- break;
- }
-
- /* Modify attributes as specified */
- if (lsqlite3_msg_to_sql(module, msg, eid, FALSE) != 0) {
- QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;");
- return -1;
- }
-
- /*
- * Normal condition is only one time through loop. Loop is
- * rerun in error conditions, via "continue", above.
- */
- ret = 0;
- bLoop = FALSE;
- }
-
- if (ret != 0) {
- QUERY_NOROWS(lsqlite3, FALSE, "ROLLBACK;");
- return -1;
- }
-
/* Everything worked. Commit it! */
QUERY_NOROWS(lsqlite3, TRUE, "COMMIT;");
return 0 ;
@@ -982,10 +963,9 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3,
const char *url)
{
int ret;
- int bNewDatabase = FALSE;
- char * p;
+ const char * p;
+ long long queryInt;
const char * pTail;
- struct stat statbuf;
sqlite3_stmt * stmt;
const char * schema =
"-- ------------------------------------------------------"
@@ -1133,25 +1113,29 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3,
if (strncmp(url, "sqlite://", 9) != 0) {
return SQLITE_MISUSE;
} else {
- ++p;
+ p = url + 9;
}
/*
* See if we'll be creating a new database, or opening an existing one
*/
-#warning "eliminate stat() here; concurrent processes could conflict"
- if ((stat(p, &statbuf) < 0 && errno == ENOENT) ||
- statbuf.st_size == 0) {
-
- bNewDatabase = TRUE;
- }
-
/* Try to open the (possibly empty/non-existent) database */
if ((ret = sqlite3_open(p, &lsqlite3->sqlite)) != SQLITE_OK) {
return ret;
}
- if (bNewDatabase) {
+ /* Begin a transaction */
+ QUERY_NOROWS(lsqlite3, FALSE, "BEGIN EXCLUSIVE;");
+
+ /* Determine if this is a new database */
+ QUERY_INT(lsqlite3,
+ queryInt,
+ TRUE,
+ "SELECT COUNT(*) "
+ " FROM sqlite_master "
+ " WHERE type = 'table';");
+
+ if (queryInt == 0) {
/*
* Create the database schema
*/
@@ -1174,35 +1158,26 @@ lsqlite3_initialize(struct lsqlite3_private *lsqlite3,
/*
* Ensure that the database we opened is one of ours
*/
- if ((ret = sqlite3_prepare(
- lsqlite3->sqlite,
- "SELECT COUNT(*) "
- " FROM sqlite_master "
- " WHERE type = 'table' "
- " AND name IN "
- " ("
- " 'ldb_entry', "
- " 'ldb_descendants', "
- " 'ldb_object_classes' "
- " );",
- -1,
- &stmt,
- &pTail)) != SQLITE_OK ||
- (ret = sqlite3_step(stmt)) != SQLITE_ROW ||
- sqlite3_column_int(stmt, 0) != 3 ||
- (ret = sqlite3_finalize(stmt)) != SQLITE_OK ||
-
- (ret = sqlite3_prepare(
- lsqlite3->sqlite,
- "SELECT 1 "
- " FROM ldb_info "
- " WHERE database_type = 'LDB' "
- " AND version = '1.0';",
- -1,
- &stmt,
- &pTail)) != SQLITE_OK ||
- (ret = sqlite3_step(stmt)) != SQLITE_ROW ||
- (ret = sqlite3_finalize(stmt)) != SQLITE_OK) {
+ if (lsqlite3_query_int(lsqlite3,
+ &queryInt,
+ "SELECT "
+ " (SELECT COUNT(*) = 3"
+ " FROM sqlite_master "
+ " WHERE type = 'table' "
+ " AND name IN "
+ " ("
+ " 'ldb_entry', "
+ " 'ldb_descendants', "
+ " 'ldb_object_classes' "
+ " ) "
+ " ) "
+ " AND "
+ " (SELECT 1 "
+ " FROM ldb_info "
+ " WHERE database_type = 'LDB' "
+ " AND version = '1.0'"
+ " );") != 0 ||
+ queryInt != 1) {
/* It's not one that we created. See ya! */
(void) sqlite3_close(lsqlite3->sqlite);
diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c
index 26bd198d1d..4bf9db8d90 100644
--- a/source4/lib/ldb/tools/ldbsearch.c
+++ b/source4/lib/ldb/tools/ldbsearch.c
@@ -54,6 +54,12 @@ static void usage(void)
exit(1);
}
+static int do_compare_msg(struct ldb_message **el1,
+ struct ldb_message **el2)
+{
+ return ldb_dn_cmp((*el1)->dn, (*el2)->dn);
+}
+
static int do_search(struct ldb_context *ldb,
const char *basedn,
int scope,
@@ -72,6 +78,11 @@ static int do_search(struct ldb_context *ldb,
printf("# returned %d records\n", ret);
+ if (sort_attribs) {
+ qsort(msgs, ret, sizeof(struct ldb_message *),
+ (comparison_fn_t)do_compare_msg);
+ }
+
for (i=0;i<ret;i++) {
struct ldb_ldif ldif;
printf("# record %d\n", i+1);
@@ -116,7 +127,7 @@ static int do_search(struct ldb_context *ldb,
ldb_url = getenv("LDB_URL");
ldbopts = 0;
- while ((opt = getopt(argc, argv, "b:H:s:o:hi")) != EOF) {
+ while ((opt = getopt(argc, argv, "b:H:s:o:hiS")) != EOF) {
switch (opt) {
case 'b':
basedn = optarg;