diff options
author | Derrell Lipman <derrell@samba.org> | 2005-06-09 14:50:32 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:17:53 -0500 |
commit | ee3f4b12d22459405372e1c72efe3079a052601d (patch) | |
tree | 7a86b841d35426fa047ee0e9397e243696bacd38 /source4/lib/ldb | |
parent | c63c28f5bd46e4a03e1cdd12b78934c0b88635a8 (diff) | |
download | samba-ee3f4b12d22459405372e1c72efe3079a052601d.tar.gz samba-ee3f4b12d22459405372e1c72efe3079a052601d.tar.bz2 samba-ee3f4b12d22459405372e1c72efe3079a052601d.zip |
r7438: work in progress
(This used to be commit 2fc5343f0637ef3109b079dbc33d6cf4e58c8d5e)
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r-- | source4/lib/ldb/common/ldb_explode_dn.c | 66 | ||||
-rw-r--r-- | source4/lib/ldb/config.mk | 5 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 323 | ||||
-rw-r--r-- | source4/lib/ldb/tools/ldbsearch.c | 13 |
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; |