r13900: don't segfault on error
[metze/samba/wip.git] / source / lib / ldb / common / ldb.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb core API
29  *
30  *  Description: core API routines interfacing to ldb backends
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/include/includes.h"
37
38 /* 
39    initialise a ldb context
40    The mem_ctx is optional
41 */
42 struct ldb_context *ldb_init(void *mem_ctx)
43 {
44         struct ldb_context *ldb = talloc_zero(mem_ctx, struct ldb_context);
45         int ret;
46
47         ret = ldb_setup_wellknown_attributes(ldb);
48         if (ret != 0) {
49                 talloc_free(ldb);
50                 return NULL;
51         }
52
53         ldb_set_utf8_default(ldb);
54
55         return ldb;
56 }
57
58 static struct ldb_backend {
59         const char *name;
60         ldb_connect_fn connect_fn;
61         struct ldb_backend *prev, *next;
62 } *ldb_backends = NULL;
63 /*
64  register a new ldb backend
65 */
66 int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn)
67 {
68         struct ldb_backend *backend = talloc(talloc_autofree_context(), struct ldb_backend);
69
70         /* Maybe check for duplicity here later on? */
71
72         backend->name = talloc_strdup(backend, url_prefix);
73         backend->connect_fn = connectfn;
74         DLIST_ADD(ldb_backends, backend);
75
76         return LDB_SUCCESS;
77 }
78
79 static ldb_connect_fn ldb_find_backend(const char *url)
80 {
81         struct ldb_backend *backend;
82
83         for (backend = ldb_backends; backend; backend = backend->next) {
84                 if (strncmp(backend->name, url, strlen(backend->name)) == 0) {
85                         return backend->connect_fn;
86                 }
87         }
88
89         return NULL;
90 }
91
92 /* 
93  connect to a database. The URL can either be one of the following forms
94    ldb://path
95    ldapi://path
96
97    flags is made up of LDB_FLG_*
98
99    the options are passed uninterpreted to the backend, and are
100    backend specific
101 */
102 int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[])
103 {
104         int ret;
105         ldb_connect_fn fn;
106
107         if (strchr(url, ':') != NULL) {
108                 fn = ldb_find_backend(url);
109         } else {
110                 /* Default to tdb */
111                 fn = ldb_find_backend("tdb:");
112         }
113
114         if (fn == NULL) {
115                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to find backend for '%s'\n", url);
116                 return LDB_ERR_OTHER;
117         }
118
119         ret = fn(ldb, url, flags, options);
120
121         if (ret != LDB_SUCCESS) {
122                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'\n", url);
123                 return ret;
124         }
125
126         if (ldb_load_modules(ldb, options) != LDB_SUCCESS) {
127                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'\n", url);
128                 return LDB_ERR_OTHER;
129         }
130
131         return LDB_SUCCESS;
132 }
133
134 void ldb_set_errstring(struct ldb_context *ldb, char *err_string)
135 {
136         if (ldb->err_string) {
137                 talloc_free(ldb->err_string);
138         }
139         ldb->err_string = talloc_steal(ldb, err_string);
140 }
141
142 void ldb_reset_err_string(struct ldb_context *ldb)
143 {
144         if (ldb->err_string) {
145                 talloc_free(ldb->err_string);
146                 ldb->err_string = NULL;
147         }
148 }
149
150 #define FIRST_OP(ldb, op) do { \
151         module = ldb->modules; \
152         while (module && module->ops->op == NULL) module = module->next; \
153         if (module == NULL) return LDB_ERR_OPERATIONS_ERROR; \
154 } while (0)
155
156 /*
157   start a transaction
158 */
159 int ldb_transaction_start(struct ldb_context *ldb)
160 {
161         struct ldb_module *module;
162         int status;
163         FIRST_OP(ldb, start_transaction);
164         
165         ldb->transaction_active++;
166
167         ldb_reset_err_string(ldb);
168
169         status = module->ops->start_transaction(module);
170         if (status != LDB_SUCCESS) {
171                 if (ldb->err_string == NULL) {
172                         /* no error string was setup by the backend */
173                         ldb_set_errstring(ldb, 
174                                           talloc_asprintf(ldb, "ldb transaction start error %d", status));
175                 }
176         }
177         return status;
178 }
179
180 /*
181   commit a transaction
182 */
183 int ldb_transaction_commit(struct ldb_context *ldb)
184 {
185         struct ldb_module *module;
186         int status;
187         FIRST_OP(ldb, end_transaction);
188
189         if (ldb->transaction_active > 0) {
190                 ldb->transaction_active--;
191         } else {
192                 return LDB_ERR_OPERATIONS_ERROR;
193         }
194
195         ldb_reset_err_string(ldb);
196
197         status = module->ops->end_transaction(module);
198         if (status != LDB_SUCCESS) {
199                 if (ldb->err_string == NULL) {
200                         /* no error string was setup by the backend */
201                         ldb_set_errstring(ldb, 
202                                           talloc_asprintf(ldb, "ldb transaction commit error %d", status));
203                 }
204         }
205         return status;
206 }
207
208 /*
209   cancel a transaction
210 */
211 int ldb_transaction_cancel(struct ldb_context *ldb)
212 {
213         struct ldb_module *module;
214         int status;
215         FIRST_OP(ldb, del_transaction);
216
217         if (ldb->transaction_active > 0) {
218                 ldb->transaction_active--;
219         } else {
220                 return LDB_ERR_OPERATIONS_ERROR;
221         }
222
223         status = module->ops->del_transaction(module);
224         if (status != LDB_SUCCESS) {
225                 if (ldb->err_string == NULL) {
226                         /* no error string was setup by the backend */
227                         ldb_set_errstring(ldb, 
228                                           talloc_asprintf(ldb, "ldb transaction cancel error %d", status));
229                 }
230         }
231         return status;
232 }
233
234 int ldb_async_wait(struct ldb_context *ldb, struct ldb_async_handle *handle, enum ldb_async_wait_type type)
235 {
236         struct ldb_module *module;
237
238         FIRST_OP(ldb, async_wait);
239
240         return module->ops->async_wait(module, handle, type);
241 }
242
243 /*
244   check for an error return from an op 
245   if an op fails, but has not setup an error string, then setup one now
246 */
247 static int ldb_op_finish(struct ldb_context *ldb, int status)
248 {
249         if (status == LDB_SUCCESS) {
250                 return ldb_transaction_commit(ldb);
251         }
252         if (ldb->err_string == NULL) {
253                 /* no error string was setup by the backend */
254                 ldb_set_errstring(ldb, 
255                                   talloc_asprintf(ldb, "ldb error %d", status));
256         }
257         ldb_transaction_cancel(ldb);
258         return status;
259 }
260
261 /*
262   start an ldb request
263   autostarts a transacion if none active and the operation is not a search
264   returns LDB_ERR_* on errors.
265 */
266 int ldb_request(struct ldb_context *ldb, struct ldb_request *request)
267 {
268         int status, started_transaction=0;
269         struct ldb_request *r;
270
271         ldb_reset_err_string(ldb);
272
273         /* to allow ldb modules to assume they can use the request ptr
274            as a talloc context for the request, we have to copy the 
275            structure here */
276         r = talloc(ldb, struct ldb_request);
277         if (r == NULL) {
278                 ldb_oom(ldb);
279                 return LDB_ERR_OPERATIONS_ERROR;
280         }
281
282         *r = *request;
283
284         if (r->operation == LDB_REQ_SEARCH) {
285                 r->op.search.res = NULL;
286         }
287
288         /* start a transaction if needed */
289         if ((!ldb->transaction_active) &&
290             (request->operation == LDB_REQ_ADD ||
291              request->operation == LDB_REQ_MODIFY ||
292              request->operation == LDB_REQ_DELETE ||
293              request->operation == LDB_REQ_RENAME)) {
294                 status = ldb_transaction_start(ldb);
295                 if (status != LDB_SUCCESS) {
296                         talloc_free(r);
297                         return status;
298                 }
299                 started_transaction = 1;
300         }
301
302         /* call the first module in the chain */
303         status = ldb->modules->ops->request(ldb->modules, r);
304
305         /* the search call is the only one that returns something
306            other than a status code. We steal the results into
307            the context of the ldb before freeing the request */
308         if (status == LDB_SUCCESS && request->operation == LDB_REQ_SEARCH) {
309                 request->op.search.res = talloc_steal(ldb, r->op.search.res);
310         }
311         if (status == LDB_SUCCESS && request->operation == LDB_ASYNC_SEARCH) {
312                 request->async.handle = r->async.handle;
313         }
314         talloc_free(r);
315
316         if (started_transaction) {
317                 return ldb_op_finish(ldb, status);
318         }
319
320         return status;
321 }
322
323 /*
324   search the database given a LDAP-like search expression
325
326   return the number of records found, or -1 on error
327
328   Use talloc_free to free the ldb_message returned in 'res'
329
330 */
331 int ldb_search(struct ldb_context *ldb, 
332                const struct ldb_dn *base,
333                enum ldb_scope scope,
334                const char *expression,
335                const char * const *attrs, 
336                struct ldb_result **res)
337 {
338         struct ldb_request request;
339         struct ldb_parse_tree *tree;
340         int ret;
341
342         (*res) = NULL;
343
344         tree = ldb_parse_tree(ldb, expression);
345         if (tree == NULL) {
346                 ldb_set_errstring(ldb, talloc_strdup(ldb, "Unable to parse search expression"));
347                 return -1;
348         }
349
350         request.operation = LDB_REQ_SEARCH;
351         request.op.search.base = base;
352         request.op.search.scope = scope;
353         request.op.search.tree = tree;
354         request.op.search.attrs = attrs;
355         request.controls = NULL;
356
357         ret = ldb_request(ldb, &request);
358
359         (*res) = request.op.search.res;
360
361         talloc_free(tree);
362
363         return ret;
364 }
365
366 /*
367   add a record to the database. Will fail if a record with the given class and key
368   already exists
369 */
370 int ldb_add(struct ldb_context *ldb, 
371             const struct ldb_message *message)
372 {
373         struct ldb_request request;
374         int status;
375
376         status = ldb_msg_sanity_check(message);
377         if (status != LDB_SUCCESS) return status;
378
379         request.operation = LDB_REQ_ADD;
380         request.op.add.message = message;
381         request.controls = NULL;
382
383         return ldb_request(ldb, &request);
384 }
385
386 /*
387   modify the specified attributes of a record
388 */
389 int ldb_modify(struct ldb_context *ldb, 
390                const struct ldb_message *message)
391 {
392         struct ldb_request request;
393         int status;
394
395         status = ldb_msg_sanity_check(message);
396         if (status != LDB_SUCCESS) return status;
397
398         request.operation = LDB_REQ_MODIFY;
399         request.op.mod.message = message;
400         request.controls = NULL;
401
402         return ldb_request(ldb, &request);
403 }
404
405
406 /*
407   delete a record from the database
408 */
409 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
410 {
411         struct ldb_request request;
412
413         request.operation = LDB_REQ_DELETE;
414         request.op.del.dn = dn;
415         request.controls = NULL;
416
417         return ldb_request(ldb, &request);
418 }
419
420 /*
421   rename a record in the database
422 */
423 int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
424 {
425         struct ldb_request request;
426
427         request.operation = LDB_REQ_RENAME;
428         request.op.rename.olddn = olddn;
429         request.op.rename.newdn = newdn;
430         request.controls = NULL;
431
432         return ldb_request(ldb, &request);
433 }
434
435
436
437 /*
438   return extended error information 
439 */
440 const char *ldb_errstring(struct ldb_context *ldb)
441 {
442         if (ldb->err_string) {
443                 return ldb->err_string;
444         }
445
446         return NULL;
447 }
448
449
450 /*
451   set backend specific opaque parameters
452 */
453 int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
454 {
455         struct ldb_opaque *o;
456
457         /* allow updating an existing value */
458         for (o=ldb->opaque;o;o=o->next) {
459                 if (strcmp(o->name, name) == 0) {
460                         o->value = value;
461                         return LDB_SUCCESS;
462                 }
463         }
464
465         o = talloc(ldb, struct ldb_opaque);
466         if (o == NULL) {
467                 ldb_oom(ldb);
468                 return LDB_ERR_OTHER;
469         }
470         o->next = ldb->opaque;
471         o->name = name;
472         o->value = value;
473         ldb->opaque = o;
474         return LDB_SUCCESS;
475 }
476
477 /*
478   get a previously set opaque value
479 */
480 void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
481 {
482         struct ldb_opaque *o;
483         for (o=ldb->opaque;o;o=o->next) {
484                 if (strcmp(o->name, name) == 0) {
485                         return o->value;
486                 }
487         }
488         return NULL;
489 }