r13992: change the way ldb_async_wait() works.
[ira/wip.git] / source4 / 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         return handle->module->ops->async_wait(handle, type);
237 }
238
239 /*
240   check for an error return from an op 
241   if an op fails, but has not setup an error string, then setup one now
242 */
243 static int ldb_op_finish(struct ldb_context *ldb, int status)
244 {
245         if (status == LDB_SUCCESS) {
246                 return ldb_transaction_commit(ldb);
247         }
248         if (ldb->err_string == NULL) {
249                 /* no error string was setup by the backend */
250                 ldb_set_errstring(ldb, 
251                                   talloc_asprintf(ldb, "ldb error %d", status));
252         }
253         ldb_transaction_cancel(ldb);
254         return status;
255 }
256
257 /*
258   start an ldb request
259   autostarts a transacion if none active and the operation is not a search
260   returns LDB_ERR_* on errors.
261 */
262 int ldb_request(struct ldb_context *ldb, struct ldb_request *request)
263 {
264         int status, started_transaction=0;
265         struct ldb_request *r;
266
267         ldb_reset_err_string(ldb);
268
269         /* to allow ldb modules to assume they can use the request ptr
270            as a talloc context for the request, we have to copy the 
271            structure here */
272         r = talloc(ldb, struct ldb_request);
273         if (r == NULL) {
274                 ldb_oom(ldb);
275                 return LDB_ERR_OPERATIONS_ERROR;
276         }
277
278         *r = *request;
279
280         if (r->operation == LDB_REQ_SEARCH) {
281                 r->op.search.res = NULL;
282         }
283
284         /* start a transaction if needed */
285         if ((!ldb->transaction_active) &&
286             (request->operation == LDB_REQ_ADD ||
287              request->operation == LDB_REQ_MODIFY ||
288              request->operation == LDB_REQ_DELETE ||
289              request->operation == LDB_REQ_RENAME)) {
290                 status = ldb_transaction_start(ldb);
291                 if (status != LDB_SUCCESS) {
292                         talloc_free(r);
293                         return status;
294                 }
295                 started_transaction = 1;
296         }
297
298         /* call the first module in the chain */
299         status = ldb->modules->ops->request(ldb->modules, r);
300
301         /* the search call is the only one that returns something
302            other than a status code. We steal the results into
303            the context of the ldb before freeing the request */
304         if (status == LDB_SUCCESS && request->operation == LDB_REQ_SEARCH) {
305                 request->op.search.res = talloc_steal(ldb, r->op.search.res);
306         }
307         if (status == LDB_SUCCESS && request->operation == LDB_ASYNC_SEARCH) {
308                 request->async.handle = r->async.handle;
309         }
310         talloc_free(r);
311
312         if (started_transaction) {
313                 return ldb_op_finish(ldb, status);
314         }
315
316         return status;
317 }
318
319 /*
320   search the database given a LDAP-like search expression
321
322   return the number of records found, or -1 on error
323
324   Use talloc_free to free the ldb_message returned in 'res'
325
326 */
327 int ldb_search(struct ldb_context *ldb, 
328                const struct ldb_dn *base,
329                enum ldb_scope scope,
330                const char *expression,
331                const char * const *attrs, 
332                struct ldb_result **res)
333 {
334         struct ldb_request request;
335         struct ldb_parse_tree *tree;
336         int ret;
337
338         (*res) = NULL;
339
340         tree = ldb_parse_tree(ldb, expression);
341         if (tree == NULL) {
342                 ldb_set_errstring(ldb, talloc_strdup(ldb, "Unable to parse search expression"));
343                 return -1;
344         }
345
346         request.operation = LDB_REQ_SEARCH;
347         request.op.search.base = base;
348         request.op.search.scope = scope;
349         request.op.search.tree = tree;
350         request.op.search.attrs = attrs;
351         request.controls = NULL;
352
353         ret = ldb_request(ldb, &request);
354
355         (*res) = request.op.search.res;
356
357         talloc_free(tree);
358
359         return ret;
360 }
361
362 /*
363   add a record to the database. Will fail if a record with the given class and key
364   already exists
365 */
366 int ldb_add(struct ldb_context *ldb, 
367             const struct ldb_message *message)
368 {
369         struct ldb_request request;
370         int status;
371
372         status = ldb_msg_sanity_check(message);
373         if (status != LDB_SUCCESS) return status;
374
375         request.operation = LDB_REQ_ADD;
376         request.op.add.message = message;
377         request.controls = NULL;
378
379         return ldb_request(ldb, &request);
380 }
381
382 /*
383   modify the specified attributes of a record
384 */
385 int ldb_modify(struct ldb_context *ldb, 
386                const struct ldb_message *message)
387 {
388         struct ldb_request request;
389         int status;
390
391         status = ldb_msg_sanity_check(message);
392         if (status != LDB_SUCCESS) return status;
393
394         request.operation = LDB_REQ_MODIFY;
395         request.op.mod.message = message;
396         request.controls = NULL;
397
398         return ldb_request(ldb, &request);
399 }
400
401
402 /*
403   delete a record from the database
404 */
405 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
406 {
407         struct ldb_request request;
408
409         request.operation = LDB_REQ_DELETE;
410         request.op.del.dn = dn;
411         request.controls = NULL;
412
413         return ldb_request(ldb, &request);
414 }
415
416 /*
417   rename a record in the database
418 */
419 int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
420 {
421         struct ldb_request request;
422
423         request.operation = LDB_REQ_RENAME;
424         request.op.rename.olddn = olddn;
425         request.op.rename.newdn = newdn;
426         request.controls = NULL;
427
428         return ldb_request(ldb, &request);
429 }
430
431
432
433 /*
434   return extended error information 
435 */
436 const char *ldb_errstring(struct ldb_context *ldb)
437 {
438         if (ldb->err_string) {
439                 return ldb->err_string;
440         }
441
442         return NULL;
443 }
444
445
446 /*
447   set backend specific opaque parameters
448 */
449 int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
450 {
451         struct ldb_opaque *o;
452
453         /* allow updating an existing value */
454         for (o=ldb->opaque;o;o=o->next) {
455                 if (strcmp(o->name, name) == 0) {
456                         o->value = value;
457                         return LDB_SUCCESS;
458                 }
459         }
460
461         o = talloc(ldb, struct ldb_opaque);
462         if (o == NULL) {
463                 ldb_oom(ldb);
464                 return LDB_ERR_OTHER;
465         }
466         o->next = ldb->opaque;
467         o->name = name;
468         o->value = value;
469         ldb->opaque = o;
470         return LDB_SUCCESS;
471 }
472
473 /*
474   get a previously set opaque value
475 */
476 void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
477 {
478         struct ldb_opaque *o;
479         for (o=ldb->opaque;o;o=o->next) {
480                 if (strcmp(o->name, name) == 0) {
481                         return o->value;
482                 }
483         }
484         return NULL;
485 }