r4505: Add a first very basic schema module
[samba.git] / source4 / 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 #define LDB_MODULE_PREFIX       "modules"
45 #define LDB_MODULE_PREFIX_LEN   7
46 #define LDB_MODULE_SEP          ':'
47
48 int ldb_load_modules(struct ldb_context *ldb, const char *options[])
49 {
50         struct ldb_module *current;
51         char **modules;
52         char *p, *q;
53         int pn, i;
54
55         /* find out which modules we are requested to activate */
56         modules = NULL;
57         pn = 0;
58
59         if (options) {
60                 for (i = 0; options[i] != NULL; i++) {
61                         if (strncmp(options[i], LDB_MODULE_PREFIX, 
62                                     LDB_MODULE_PREFIX_LEN) == 0) {
63                                 p = q = talloc_strdup(ldb, &options[i][LDB_MODULE_PREFIX_LEN]);
64                                 if (*q != ':') {
65                                         talloc_free(q);
66                                         return -1;
67                                 }
68                                 do {
69                                         *p = '\0';
70                                         q = p + 1;
71                                         pn++;
72                                         modules = talloc_realloc_p(ldb, modules, char *, pn);
73                                         if (!modules) {
74                                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n");
75                                                 return -1;
76                                         }
77                                         modules[pn - 1] = q;
78                                 } while ((p = strchr(q, LDB_MODULE_SEP)));
79                         }
80                 }
81         }
82
83         if (!modules && strcmp("ldap", ldb->modules->ops->name)) { 
84                 /* no modules in the options, look for @MODULES in the
85                    db (not for ldap) */
86                 int ret, j, k;
87                 const char * const attrs[] = { "@MODULE" , NULL};
88                 struct ldb_message **msg = NULL;
89
90                 ret = ldb_search(ldb, "", LDB_SCOPE_BASE, "dn=@MODULES", attrs, &msg);
91                 if (ret == 0) {
92                         ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n");
93                 } else {
94                         if (ret < 0) {
95                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out\n", ldb_errstring(ldb));
96                                 return -1;
97                         }
98                         if (ret > 1) {
99                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found, bailing out\n");
100                                 return -1;
101                         }
102
103                         for (j = 0; j < msg[0]->num_elements; j++) {
104                                 for (k = 0; k < msg[0]->elements[j].num_values; k++) {
105                                         pn++;
106                                         modules = talloc_realloc_p(ldb, modules, char *, pn);
107                                         if (!modules) {
108                                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n");
109                                                 return -1;
110                                         }
111                                         modules[pn - 1] = talloc_strndup(modules, msg[0]->elements[j].values[k].data, msg[0]->elements[j].values[k].length);
112                                         if (!modules[pn - 1]) {
113                                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in register_modules()\n");
114                                                 return -1;
115                                         }
116                                 }
117                         }
118                 }
119                 talloc_free(msg);
120         }
121
122         if (modules) {
123                 for (i = 0; i < pn; i++) {
124                         if (strcmp(modules[i], "timestamps") == 0) {
125                                 current = timestamps_module_init(ldb, options);
126                                 if (!current) {
127                                         ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
128                                         return -1;
129                                 }
130                                 DLIST_ADD(ldb->modules, current);
131                                 continue;
132                         }
133
134                         if (strcmp(modules[i], "schema") == 0) {
135                                 current = schema_module_init(ldb, options);
136                                 if (!current) {
137                                         ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
138                                         return -1;
139                                 }
140                                 DLIST_ADD(ldb->modules, current);
141                                 continue;
142                         }
143
144 #ifdef HAVE_DLOPEN_DISABLED
145                 {
146                         void *handle;
147                         ldb_module_init_function init;
148                         struct stat st;
149                         const char *errstr;
150
151                         if (stat(modules[i], &st) < 0) {
152                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]);
153                                 return -1;
154                         }
155
156                         handle = dlopen(modules[i], RTLD_LAZY);
157
158                         if (!handle) {
159                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Error loading module %s [%s]\n", modules[i], dlerror());
160                                 return -1;
161                         }
162
163                         init = (ldb_module_init_function)dlsym(handle, "init_module");
164
165                         errstr = dlerror();
166                         if (errstr) {
167                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Error trying to resolve symbol 'init_module' in %s [%s]\n", modules[i], errstr);
168                                 return -1;
169                         }
170
171                         current = init(ldb, options);
172                         if (!current) {
173                                 ldb_debug(ldb, LDB_DEBUG_FATAL, "function 'init_module' in %s fails\n", modules[i]);
174                                 return -1;
175                         }
176                         DLIST_ADD(ldb->modules, current);
177                 }
178 #else
179                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Required module [%s] not found, bailing out!\n", modules[i]);
180                 return -1;
181 #endif
182                 }
183         }
184
185         return 0; 
186 }
187
188 /*
189    helper functions to call the next module in chain
190 */
191 int ldb_next_close(struct ldb_module *module)
192 {
193         if (!module->next) {
194                 return -1;
195         }
196         return module->next->ops->close(module->next);
197 }
198
199 int ldb_next_search(struct ldb_module *module, 
200                const char *base,
201                enum ldb_scope scope,
202                const char *expression,
203                const char * const *attrs, struct ldb_message ***res)
204 {
205         if (!module->next) {
206                 return -1;
207         }
208         return module->next->ops->search(module->next, base, scope, expression, attrs, res);
209 }
210
211 int ldb_next_search_free(struct ldb_module *module, struct ldb_message **msg)
212 {
213         if (!module->next) {
214                 return -1;
215         }
216         return module->next->ops->search_free(module->next, msg);
217 }
218
219 int ldb_next_add_record(struct ldb_module *module, const struct ldb_message *message)
220 {
221         if (!module->next) {
222                 return -1;
223         }
224         return module->next->ops->add_record(module->next, message);
225 }
226
227 int ldb_next_modify_record(struct ldb_module *module, const struct ldb_message *message)
228 {
229         if (!module->next) {
230                 return -1;
231         }
232         return module->next->ops->modify_record(module->next, message);
233 }
234
235 int ldb_next_delete_record(struct ldb_module *module, const char *dn)
236 {
237         if (!module->next) {
238                 return -1;
239         }
240         return module->next->ops->delete_record(module->next, dn);
241 }
242
243 int ldb_next_rename_record(struct ldb_module *module, const char *olddn, const char *newdn)
244 {
245         if (!module->next) {
246                 return -1;
247         }
248         return module->next->ops->rename_record(module->next, olddn, newdn);
249 }
250
251 int ldb_next_named_lock(struct ldb_module *module, const char *lockname)
252 {
253         if (!module->next) {
254                 return -1;
255         }
256         return module->next->ops->named_lock(module->next, lockname);
257 }
258
259 int ldb_next_named_unlock(struct ldb_module *module, const char *lockname)
260 {
261         if (!module->next) {
262                 return -1;
263         }
264         return module->next->ops->named_unlock(module->next, lockname);
265 }
266
267 const char *ldb_next_errstring(struct ldb_module *module)
268 {
269         if (!module->next) {
270                 return NULL;
271         }
272         return module->next->ops->errstring(module->next);
273 }
274