r5585: LDB interfaces change:
[kai/samba.git] / source / lib / ldb / common / ldb_modules.c
1
2 /* 
3    ldb database library
4
5    Copyright (C) Simo Sorce  2004
6
7      ** NOTE! The following LGPL license applies to the ldb
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10    
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 2 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, write to the Free Software
23    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26 /*
27  *  Name: ldb
28  *
29  *  Component: ldb modules core
30  *
31  *  Description: core modules routines
32  *
33  *  Author: Simo Sorce
34  */
35
36 #include "includes.h"
37 #include "ldb/include/ldb.h"
38 #include "ldb/include/ldb_private.h"
39 #include "dlinklist.h"
40 #include <sys/types.h> 
41 #include <sys/stat.h> 
42 #include <unistd.h> 
43
44 #ifdef HAVE_DLOPEN_DISABLED
45 #include <dlfcn.h>
46 #endif
47
48 #define LDB_MODULE_PREFIX       "modules"
49 #define LDB_MODULE_PREFIX_LEN   7
50 #define LDB_MODULE_SEP          ':'
51
52 int ldb_load_modules(struct ldb_context *ldb, const char *options[])
53 {
54         struct ldb_module *current;
55         char **modules;
56         int mnum, i;
57
58         /* find out which modules we are requested to activate */
59         modules = NULL;
60         mnum = 0;
61
62         if (options) {
63                 char *q, *p;
64
65                 for (i = 0; options[i] != NULL; i++) {
66                         if (strncmp(options[i], LDB_MODULE_PREFIX, 
67                                     LDB_MODULE_PREFIX_LEN) == 0) {
68                                 p = q = talloc_strdup(ldb, &options[i][LDB_MODULE_PREFIX_LEN]);
69                                 if (*q != ':') {
70                                         talloc_free(q);
71                                         return -1;
72                                 }
73                                 do {
74                                         *p = '\0';
75                                         q = p + 1;
76                                         mnum++;
77                                         modules = talloc_realloc(ldb, modules, char *, mnum);
78                                         if (!modules) {
79                                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_load_modules()\n");
80                                                 return -1;
81                                         }
82                                         modules[mnum - 1] = q;
83                                 } while ((p = strchr(q, LDB_MODULE_SEP)));
84                         }
85                 }
86         }
87
88         if (!modules && strcmp("ldap", ldb->modules->ops->name)) { 
89                 /* no modules in the options, look for @MODULES in the
90                    db (not for ldap) */
91                 int ret;
92                 const char * const attrs[] = { "@LIST" , NULL};
93                 struct ldb_message **msg = NULL;
94                 char *modstr, *c, *p; 
95
96                 ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg);
97                 if (ret == 0) {
98                         ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n");
99                 } else {
100                         if (ret < 0) {
101                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out\n", ldb_errstring(ldb));
102                                 return -1;
103                         }
104                         if (ret > 1) {
105                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n");
106                                 return -1;
107                         }
108
109 /*
110                         for (j = 0; j < msg[0]->num_elements; j++) {
111                                 for (k = 0; k < msg[0]->elements[j].num_values; k++) {
112                                         pn++;
113                                         modules = talloc_realloc(ldb, modules, char *, pn);
114                                         if (!modules) {
115                                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n");
116                                                 return -1;
117                                         }
118                                         modules[pn - 1] = talloc_strndup(modules, msg[0]->elements[j].values[k].data, msg[0]->elements[j].values[k].length);
119                                         if (!modules[pn - 1]) {
120                                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n");
121                                                 return -1;
122                                         }
123                                 }
124                         }
125 */
126                         modstr = msg[0]->elements[0].values[0].data;
127                         for (c = modstr, mnum = 0; c != NULL; mnum++) {
128                                 c = strchr(c, ',');
129                                 if (c != NULL) {
130                                         c++;
131                                         if (*c == '\0') { /* avoid failing if the modules string lasts with ',' */
132                                                 break;
133                                         }
134                                 }
135                         }
136                         
137
138                         modules = talloc_array(ldb, char *, mnum);
139                         if ( ! modules ) {
140                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_load_modules()\n");
141                                 return -1;
142                         }
143
144                         for (p = c = modstr, i = 0; mnum > i; i++) {
145                                 c = strchr(p, ',');
146                                 if (c) {
147                                         *c = '\0';
148                                 }
149                                 /* modules are seeked in inverse order. Lets place them as an admin would think the right order is */
150                                 modules[mnum - i - 1] = talloc_strdup(modules, p);
151                                 p = c + 1;
152                         }
153                 }
154                 talloc_free(msg);
155         }
156
157         if (modules) {
158                 for (i = 0; i < mnum; i++) {
159 #ifdef HAVE_DLOPEN_DISABLED
160                         void *handle;
161                         ldb_module_init_function init;
162                         struct stat st;
163                         char *filename;
164                         const char *errstr;
165 #endif
166
167                         if (strcmp(modules[i], "schema") == 0) {
168                                 current = schema_module_init(ldb, options);
169                                 if (!current) {
170                                         ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
171                                         return -1;
172                                 }
173                                 DLIST_ADD(ldb->modules, current);
174                                 continue;
175                         }
176
177                         if (strcmp(modules[i], "timestamps") == 0) {
178                                 current = timestamps_module_init(ldb, options);
179                                 if (!current) {
180                                         ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
181                                         return -1;
182                                 }
183                                 DLIST_ADD(ldb->modules, current);
184                                 continue;
185                         }
186
187                         if (strcmp(modules[i], "samldb") == 0) {
188                                 current = samldb_module_init(ldb, options);
189                                 if (!current) {
190                                         ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
191                                         return -1;
192                                 }
193                                 DLIST_ADD(ldb->modules, current);
194                                 continue;
195                         }
196
197 #ifdef HAVE_DLOPEN_DISABLED
198                         filename = talloc_asprintf(ldb, "%s.so", modules[i]);
199                         if (!filename) {
200                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Talloc failed!\n");
201                                 return -1;
202                         }
203
204                         if (stat(filename, &st) < 0) {
205                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]);
206                                 return -1;
207                         }
208
209                         handle = dlopen(filename, RTLD_LAZY);
210
211                         if (!handle) {
212                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Error loading module %s [%s]\n", modules[i], dlerror());
213                                 return -1;
214                         }
215
216                         init = (ldb_module_init_function)dlsym(handle, "init_module");
217
218                         errstr = dlerror();
219                         if (errstr) {
220                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Error trying to resolve symbol 'init_module' in %s [%s]\n", modules[i], errstr);
221                                 return -1;
222                         }
223
224                         current = init(ldb, options);
225                         if (!current) {
226                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
227                                 return -1;
228                         }
229                         DLIST_ADD(ldb->modules, current);
230 #else
231                         ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]);
232                         return -1;
233 #endif
234                 }
235         }
236
237         return 0; 
238 }
239
240 /*
241    helper functions to call the next module in chain
242 */
243
244 int ldb_next_search(struct ldb_module *module, 
245                const char *base,
246                enum ldb_scope scope,
247                const char *expression,
248                const char * const *attrs, struct ldb_message ***res)
249 {
250         if (!module->next) {
251                 return -1;
252         }
253         return module->next->ops->search(module->next, base, scope, expression, attrs, res);
254 }
255
256 int ldb_next_search_free(struct ldb_module *module, struct ldb_message **msg)
257 {
258         if (!module->next) {
259                 return -1;
260         }
261         return module->next->ops->search_free(module->next, msg);
262 }
263
264 int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message)
265 {
266         if (!module->next) {
267                 return -1;
268         }
269         return module->next->ops->add_record(module->next, message);
270 }
271
272 int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message)
273 {
274         if (!module->next) {
275                 return -1;
276         }
277         return module->next->ops->modify_record(module->next, message);
278 }
279
280 int ldb_next_delete_record(struct ldb_module *module, const char *dn)
281 {
282         if (!module->next) {
283                 return -1;
284         }
285         return module->next->ops->delete_record(module->next, dn);
286 }
287
288 int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const char *newdn)
289 {
290         if (!module->next) {
291                 return -1;
292         }
293         return module->next->ops->rename_record(module->next, olddn, newdn);
294 }
295
296 int ldb_next_named_lock(struct ldb_module *module, const char *lockname)
297 {
298         if (!module->next) {
299                 return -1;
300         }
301         return module->next->ops->named_lock(module->next, lockname);
302 }
303
304 int ldb_next_named_unlock(struct ldb_module *module, const char *lockname)
305 {
306         if (!module->next) {
307                 return -1;
308         }
309         return module->next->ops->named_unlock(module->next, lockname);
310 }
311
312 const char *ldb_next_errstring(struct ldb_module *module)
313 {
314         if (!module->next) {
315                 return NULL;
316         }
317         return module->next->ops->errstring(module->next);
318 }
319