ldb: allow ldb modules to specify LDB_MODULE(name) or LDB_BACKEND(name)
authorStefan Metzmacher <metze@samba.org>
Sat, 28 Jun 2008 08:49:49 +0000 (10:49 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 30 Jun 2008 07:14:07 +0000 (09:14 +0200)
metze

source/lib/ldb/common/ldb.c
source/lib/ldb/common/ldb_modules.c
source/lib/ldb/config.mk
source/lib/ldb/ldb_ildap/config.mk

index cac0a383d8d6e2c0112c93e8ad69691d5a907c5c..ce4796dee2b02d8659ee3fe61aad175b93eb2152 100644 (file)
@@ -68,153 +68,6 @@ struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct event_context *ev_ctx)
        return ldb;
 }
 
-static struct backends_list_entry {
-       struct ldb_backend_ops *ops;
-       struct backends_list_entry *prev, *next;
-} *ldb_backends = NULL;
-
-#ifndef STATIC_LIBLDB_BACKENDS
-
-#ifdef HAVE_LDB_LDAP
-#define LDAP_INIT &ldb_ldap_backend_ops, \
-                                 &ldb_ldapi_backend_ops, \
-                                 &ldb_ldaps_backend_ops,
-#else
-#define LDAP_INIT
-#endif
-
-#ifdef HAVE_LDB_SQLITE3
-#define SQLITE3_INIT &ldb_sqlite3_backend_ops,
-#else
-#define SQLITE3_INIT
-#endif
-
-#define STATIC_LIBLDB_BACKENDS \
-       LDAP_INIT \
-       SQLITE3_INIT \
-       &ldb_tdb_backend_ops,   \
-       NULL
-#endif
-
-const static struct ldb_backend_ops *builtin_backends[] = {
-       STATIC_LIBLDB_BACKENDS
-};
-
-static ldb_connect_fn ldb_find_backend(const char *url)
-{
-       struct backends_list_entry *backend;
-       int i;
-
-       for (i = 0; builtin_backends[i]; i++) {
-               if (strncmp(builtin_backends[i]->name, url,
-                           strlen(builtin_backends[i]->name)) == 0)
-                       return builtin_backends[i]->connect_fn;
-       }
-
-       for (backend = ldb_backends; backend; backend = backend->next) {
-               if (strncmp(backend->ops->name, url,
-                           strlen(backend->ops->name)) == 0) {
-                       return backend->ops->connect_fn;
-               }
-       }
-
-       return NULL;
-}
-
-/*
- register a new ldb backend
-*/
-int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn)
-{
-       struct ldb_backend_ops *backend;
-       struct backends_list_entry *entry;
-
-       backend = talloc(talloc_autofree_context(), struct ldb_backend_ops);
-       if (!backend) return LDB_ERR_OPERATIONS_ERROR;
-
-       entry = talloc(talloc_autofree_context(), struct backends_list_entry);
-       if (!entry) {
-               talloc_free(backend);
-               return LDB_ERR_OPERATIONS_ERROR;
-       }
-
-       if (ldb_find_backend(url_prefix)) {
-               return LDB_SUCCESS;
-       }
-
-       /* Maybe check for duplicity here later on? */
-
-       backend->name = talloc_strdup(backend, url_prefix);
-       backend->connect_fn = connectfn;
-       entry->ops = backend;
-       DLIST_ADD(ldb_backends, entry);
-
-       return LDB_SUCCESS;
-}
-
-/*
-   Return the ldb module form of a database.
-   The URL can either be one of the following forms
-   ldb://path
-   ldapi://path
-
-   flags is made up of LDB_FLG_*
-
-   the options are passed uninterpreted to the backend, and are
-   backend specific.
-
-   This allows modules to get at only the backend module, for example where a
-   module may wish to direct certain requests at a particular backend.
-*/
-int ldb_connect_backend(struct ldb_context *ldb,
-                       const char *url,
-                       const char *options[],
-                       struct ldb_module **backend_module)
-{
-       int ret;
-       char *backend;
-       ldb_connect_fn fn;
-
-       if (strchr(url, ':') != NULL) {
-               backend = talloc_strndup(ldb, url, strchr(url, ':')-url);
-       } else {
-               /* Default to tdb */
-               backend = talloc_strdup(ldb, "tdb");
-       }
-
-       fn = ldb_find_backend(backend);
-
-       if (fn == NULL) {
-               struct ldb_backend_ops *ops;
-               char *symbol_name = talloc_asprintf(ldb, "ldb_%s_backend_ops", backend);
-               if (symbol_name == NULL) {
-                       return LDB_ERR_OPERATIONS_ERROR;
-               }
-               ops = ldb_dso_load_symbol(ldb, backend, symbol_name);
-               if (ops != NULL) {
-                       fn = ops->connect_fn;
-               }
-               talloc_free(symbol_name);
-       }
-
-       talloc_free(backend);
-
-       if (fn == NULL) {
-               ldb_debug(ldb, LDB_DEBUG_FATAL,
-                         "Unable to find backend for '%s'\n", url);
-               return LDB_ERR_OTHER;
-       }
-
-       ret = fn(ldb, url, ldb->flags, options, backend_module);
-
-       if (ret != LDB_SUCCESS) {
-               ldb_debug(ldb, LDB_DEBUG_ERROR,
-                         "Failed to connect to '%s'\n", url);
-               return ret;
-       }
-       return ret;
-}
-
 /*
   try to autodetect a basedn if none specified. This fixes one of my
   pet hates about ldapsearch, which is that you have to get a long,
index fbfb5e5322fdca4f05e71e2066908e6e049c37ca..4d69dc662ee10ee9c3c724496465e3aa03edb6a4 100644 (file)
@@ -120,36 +120,149 @@ const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *m
        return m;
 }
 
+static struct backends_list_entry {
+       struct ldb_backend_ops *ops;
+       struct backends_list_entry *prev, *next;
+} *ldb_backends = NULL;
+
 static struct ops_list_entry {
        const struct ldb_module_ops *ops;
        struct ops_list_entry *next;    
 } *registered_modules = NULL;
 
-#define LDB_MODULE(name) (&ldb_ ## name ## _module_ops)
+static const struct ldb_builtins {
+       const struct ldb_backend_ops *backend_ops;
+       const struct ldb_module_ops *module_ops;
+} builtins[];
 
-#ifndef STATIC_LIBLDB_MODULES
+static ldb_connect_fn ldb_find_backend(const char *url)
+{
+       struct backends_list_entry *backend;
+       int i;
 
-#define STATIC_LIBLDB_MODULES \
-       LDB_MODULE(operational),        \
-       LDB_MODULE(rdn_name),   \
-       LDB_MODULE(paged_results),      \
-       LDB_MODULE(server_sort),                \
-       LDB_MODULE(asq), \
-       NULL
-#endif
+       for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
+               if (builtins[i].backend_ops == NULL) continue;
 
-const static struct ldb_module_ops *builtin_modules[] = {
-       STATIC_LIBLDB_MODULES
-};
+               if (strncmp(builtins[i].backend_ops->name, url,
+                           strlen(builtins[i].backend_ops->name)) == 0) {
+                       return builtins[i].backend_ops->connect_fn;
+               }
+       }
+
+       for (backend = ldb_backends; backend; backend = backend->next) {
+               if (strncmp(backend->ops->name, url,
+                           strlen(backend->ops->name)) == 0) {
+                       return backend->ops->connect_fn;
+               }
+       }
+
+       return NULL;
+}
+
+/*
+ register a new ldb backend
+*/
+int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn)
+{
+       struct ldb_backend_ops *backend;
+       struct backends_list_entry *entry;
+
+       backend = talloc(talloc_autofree_context(), struct ldb_backend_ops);
+       if (!backend) return LDB_ERR_OPERATIONS_ERROR;
+
+       entry = talloc(talloc_autofree_context(), struct backends_list_entry);
+       if (!entry) {
+               talloc_free(backend);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       if (ldb_find_backend(url_prefix)) {
+               return LDB_SUCCESS;
+       }
+
+       /* Maybe check for duplicity here later on? */
+
+       backend->name = talloc_strdup(backend, url_prefix);
+       backend->connect_fn = connectfn;
+       entry->ops = backend;
+       DLIST_ADD(ldb_backends, entry);
+
+       return LDB_SUCCESS;
+}
+
+/*
+   Return the ldb module form of a database.
+   The URL can either be one of the following forms
+   ldb://path
+   ldapi://path
+
+   flags is made up of LDB_FLG_*
+
+   the options are passed uninterpreted to the backend, and are
+   backend specific.
+
+   This allows modules to get at only the backend module, for example where a
+   module may wish to direct certain requests at a particular backend.
+*/
+int ldb_connect_backend(struct ldb_context *ldb,
+                       const char *url,
+                       const char *options[],
+                       struct ldb_module **backend_module)
+{
+       int ret;
+       char *backend;
+       ldb_connect_fn fn;
+
+       if (strchr(url, ':') != NULL) {
+               backend = talloc_strndup(ldb, url, strchr(url, ':')-url);
+       } else {
+               /* Default to tdb */
+               backend = talloc_strdup(ldb, "tdb");
+       }
+
+       fn = ldb_find_backend(backend);
+
+       if (fn == NULL) {
+               struct ldb_backend_ops *ops;
+               char *symbol_name = talloc_asprintf(ldb, "ldb_%s_backend_ops", backend);
+               if (symbol_name == NULL) {
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+               ops = ldb_dso_load_symbol(ldb, backend, symbol_name);
+               if (ops != NULL) {
+                       fn = ops->connect_fn;
+               }
+               talloc_free(symbol_name);
+       }
+
+       talloc_free(backend);
+
+       if (fn == NULL) {
+               ldb_debug(ldb, LDB_DEBUG_FATAL,
+                         "Unable to find backend for '%s'\n", url);
+               return LDB_ERR_OTHER;
+       }
+
+       ret = fn(ldb, url, ldb->flags, options, backend_module);
+
+       if (ret != LDB_SUCCESS) {
+               ldb_debug(ldb, LDB_DEBUG_ERROR,
+                         "Failed to connect to '%s'\n", url);
+               return ret;
+       }
+       return ret;
+}
 
 static const struct ldb_module_ops *ldb_find_module_ops(const char *name)
 {
        struct ops_list_entry *e;
        int i;
 
-       for (i = 0; builtin_modules[i]; i++) {
-               if (strcmp(builtin_modules[i]->name, name) == 0)
-                       return builtin_modules[i];
+       for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
+               if (builtins[i].module_ops == NULL) continue;
+
+               if (strcmp(builtins[i].module_ops->name, name) == 0)
+                       return builtins[i].module_ops;
        }
  
        for (e = registered_modules; e; e = e->next) {
@@ -441,3 +554,72 @@ int ldb_next_del_trans(struct ldb_module *module)
        FIND_OP(module, del_transaction);
        return module->ops->del_transaction(module);
 }
+
+#ifndef STATIC_LIBLDB_MODULES
+
+#ifdef HAVE_LDB_LDAP
+#define LDAP_BACKEND LDB_BACKEND(ldap), LDB_BACKEND(ldapi), LDB_BACKEND(ldaps),
+#else
+#define LDAP_BACKEND
+#endif
+
+#ifdef HAVE_LDB_SQLITE3
+#define SQLITE3_BACKEND LDB_BACKEND(sqlite3),
+#else
+#define SQLITE3_BACKEND
+#endif
+
+#define STATIC_LIBLDB_MODULES \
+       LDB_BACKEND(tdb),       \
+       LDAP_BACKEND    \
+       SQLITE3_BACKEND \
+       LDB_MODULE(operational),        \
+       LDB_MODULE(rdn_name),   \
+       LDB_MODULE(paged_results),      \
+       LDB_MODULE(server_sort),                \
+       LDB_MODULE(asq), \
+       NULL
+#endif
+
+/*
+ * this is a bit hacked, as STATIC_LIBLDB_MODULES contains ','
+ * between the elements and we want to autogenerate the
+ * extern struct declarations, so we do some hacks and let the
+ * ',' appear in an unused function prototype.
+ */
+#undef NULL
+#define NULL LDB_MODULE(NULL),
+
+#define LDB_BACKEND(name) \
+       int); \
+       extern const struct ldb_backend_ops ldb_ ## name ## _backend_ops;\
+       extern void ldb_noop ## name (int
+#define LDB_MODULE(name) \
+       int); \
+       extern const struct ldb_module_ops ldb_ ## name ## _module_ops;\
+       extern void ldb_noop ## name (int
+
+extern void ldb_start_noop(int,
+STATIC_LIBLDB_MODULES
+int);
+
+#undef NULL
+#define NULL { \
+       .backend_ops = (void *)0, \
+       .module_ops = (void *)0 \
+}
+
+#undef LDB_BACKEND
+#define LDB_BACKEND(name) { \
+       .backend_ops = &ldb_ ## name ## _backend_ops, \
+       .module_ops = (void *)0 \
+}
+#undef LDB_MODULE
+#define LDB_MODULE(name) { \
+       .backend_ops = (void *)0, \
+       .module_ops = &ldb_ ## name ## _module_ops \
+}
+
+static const struct ldb_builtins builtins[] = {
+       STATIC_LIBLDB_MODULES
+};
index 36a5870a3e8995eb49b5821c529f33bbd8035153..6821c058f2f41a8acd0fc79671e356761c0878cc 100644 (file)
@@ -92,6 +92,7 @@ ldb_skel_OBJ_FILES = $(ldbsrcdir)/modules/skel.o
 SUBSYSTEM = LIBLDB
 CFLAGS = -I$(ldbsrcdir)/include
 PRIVATE_DEPENDENCIES = LIBTALLOC SQLITE3 LIBEVENTS
+INIT_FUNCTION = LDB_BACKEND(sqlite3)
 # End MODULE ldb_sqlite3
 ################################################
 
@@ -104,6 +105,7 @@ SUBSYSTEM = LIBLDB
 CFLAGS = -I$(ldbsrcdir)/include -I$(ldbsrcdir)/ldb_tdb
 PRIVATE_DEPENDENCIES = \
                LIBTDB LIBTALLOC LIBEVENTS
+INIT_FUNCTION = LDB_BACKEND(tdb)
 # End MODULE ldb_tdb
 ################################################
 
@@ -114,7 +116,6 @@ ldb_tdb_OBJ_FILES = $(addprefix $(ldbsrcdir)/ldb_tdb/, ldb_tdb.o ldb_search.o ld
 # Start SUBSYSTEM ldb
 [LIBRARY::LIBLDB]
 CFLAGS = -I$(ldbsrcdir)/include
-INIT_FUNCTION_TYPE = extern const struct ldb_module_ops
 PUBLIC_DEPENDENCIES = \
                LIBTALLOC LIBEVENTS
 PRIVATE_DEPENDENCIES = \
index 4247bd96b7e68103d8efac1e8dcee853448f4b04..82d8267cfa93d0c4bcd5aa358a2b8392a81e8f05 100644 (file)
@@ -5,6 +5,7 @@ SUBSYSTEM = LIBLDB
 CFLAGS = -I$(ldbsrcdir)/include
 OUTPUT_TYPE = SHARED_LIBRARY
 PRIVATE_DEPENDENCIES = LIBTALLOC LIBCLI_LDAP CREDENTIALS
+INIT_FUNCTION = LDB_BACKEND(ldapi),LDB_BACKEND(ldaps),LDB_BACKEND(ldap)
 ALIASES = ldapi ldaps ldap
 # End MODULE ldb_ildap
 ################################################