r13786: [merge] Add registration functions for LDB modules
[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 /* 
59  connect to a database. The URL can either be one of the following forms
60    ldb://path
61    ldapi://path
62
63    flags is made up of LDB_FLG_*
64
65    the options are passed uninterpreted to the backend, and are
66    backend specific
67 */
68 int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[])
69 {
70         int ret;
71
72         if (strncmp(url, "tdb:", 4) == 0 ||
73             strchr(url, ':') == NULL) {
74                 ret = ltdb_connect(ldb, url, flags, options);
75         }
76
77 #if HAVE_ILDAP
78         else if (strncmp(url, "ldap", 4) == 0) {
79                 ret = ildb_connect(ldb, url, flags, options);
80         }
81 #elif HAVE_LDAP
82         else if (strncmp(url, "ldap", 4) == 0) {
83                 ret = lldb_connect(ldb, url, flags, options);
84         }
85 #endif
86 #if HAVE_SQLITE3
87         else if (strncmp(url, "sqlite:", 7) == 0) {
88                 ret = lsqlite3_connect(ldb, url, flags, options);
89         }
90 #endif
91         else {
92                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to find backend for '%s'\n", url);
93                 return LDB_ERR_OTHER;
94         }
95
96         if (ret != LDB_SUCCESS) {
97                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'\n", url);
98                 return ret;
99         }
100
101         if (ldb_load_modules(ldb, options) != LDB_SUCCESS) {
102                 ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'\n", url);
103                 return LDB_ERR_OTHER;
104         }
105
106         return LDB_SUCCESS;
107 }
108
109 void ldb_set_errstring(struct ldb_context *ldb, char *err_string)
110 {
111         if (ldb->err_string) {
112                 talloc_free(ldb->err_string);
113         }
114         ldb->err_string = talloc_steal(ldb, err_string);
115 }
116
117 void ldb_reset_err_string(struct ldb_context *ldb)
118 {
119         if (ldb->err_string) {
120                 talloc_free(ldb->err_string);
121                 ldb->err_string = NULL;
122         }
123 }
124
125 #define FIRST_OP(ldb, op) do { \
126         module = ldb->modules; \
127         while (module && module->ops->op == NULL) module = module->next; \
128         if (module == NULL) return -1; \
129 } while (0)
130
131 /*
132   start a transaction
133 */
134 int ldb_transaction_start(struct ldb_context *ldb)
135 {
136         struct ldb_module *module;
137         int status;
138         FIRST_OP(ldb, start_transaction);
139         
140         ldb->transaction_active++;
141
142         ldb_reset_err_string(ldb);
143
144         status = module->ops->start_transaction(module);
145         if (status != LDB_SUCCESS) {
146                 if (ldb->err_string == NULL) {
147                         /* no error string was setup by the backend */
148                         ldb_set_errstring(ldb, 
149                                           talloc_asprintf(ldb, "ldb transaction start error %d", status));
150                 }
151         }
152         return status;
153 }
154
155 /*
156   commit a transaction
157 */
158 int ldb_transaction_commit(struct ldb_context *ldb)
159 {
160         struct ldb_module *module;
161         int status;
162         FIRST_OP(ldb, end_transaction);
163
164         if (ldb->transaction_active > 0) {
165                 ldb->transaction_active--;
166         } else {
167                 return LDB_ERR_OPERATIONS_ERROR;
168         }
169
170         ldb_reset_err_string(ldb);
171
172         status = module->ops->end_transaction(module);
173         if (status != LDB_SUCCESS) {
174                 if (ldb->err_string == NULL) {
175                         /* no error string was setup by the backend */
176                         ldb_set_errstring(ldb, 
177                                           talloc_asprintf(ldb, "ldb transaction commit error %d", status));
178                 }
179         }
180         return status;
181 }
182
183 /*
184   cancel a transaction
185 */
186 int ldb_transaction_cancel(struct ldb_context *ldb)
187 {
188         struct ldb_module *module;
189         int status;
190         FIRST_OP(ldb, del_transaction);
191
192         if (ldb->transaction_active > 0) {
193                 ldb->transaction_active--;
194         } else {
195                 return LDB_ERR_OPERATIONS_ERROR;
196         }
197
198         status = module->ops->del_transaction(module);
199         if (status != LDB_SUCCESS) {
200                 if (ldb->err_string == NULL) {
201                         /* no error string was setup by the backend */
202                         ldb_set_errstring(ldb, 
203                                           talloc_asprintf(ldb, "ldb transaction cancel error %d", status));
204                 }
205         }
206         return status;
207 }
208
209 int ldb_async_wait(struct ldb_context *ldb, struct ldb_async_handle *handle, enum ldb_async_wait_type type)
210 {
211         if (ldb->async_wait != NULL)
212                 return ldb->async_wait(handle, type);
213
214         return LDB_ERR_OPERATIONS_ERROR;
215 }
216
217 /*
218   check for an error return from an op 
219   if an op fails, but has not setup an error string, then setup one now
220 */
221 static int ldb_op_finish(struct ldb_context *ldb, int status)
222 {
223         if (status == LDB_SUCCESS) {
224                 return ldb_transaction_commit(ldb);
225         }
226         if (ldb->err_string == NULL) {
227                 /* no error string was setup by the backend */
228                 ldb_set_errstring(ldb, 
229                                   talloc_asprintf(ldb, "ldb error %d", status));
230         }
231         ldb_transaction_cancel(ldb);
232         return status;
233 }
234
235 /*
236   start an ldb request
237   autostarts a transacion if none active and the operation is not a search
238   returns LDB_ERR_* on errors.
239 */
240 int ldb_request(struct ldb_context *ldb, struct ldb_request *request)
241 {
242         int status, started_transaction=0;
243         struct ldb_request *r;
244
245         ldb_reset_err_string(ldb);
246
247         /* to allow ldb modules to assume they can use the request ptr
248            as a talloc context for the request, we have to copy the 
249            structure here */
250         r = talloc(ldb, struct ldb_request);
251         if (r == NULL) {
252                 ldb_oom(ldb);
253                 return LDB_ERR_OPERATIONS_ERROR;
254         }
255
256         *r = *request;
257
258         if (r->operation == LDB_REQ_SEARCH) {
259                 r->op.search.res = NULL;
260         }
261
262         /* start a transaction if needed */
263         if ((!ldb->transaction_active) &&
264             (request->operation == LDB_REQ_ADD ||
265              request->operation == LDB_REQ_MODIFY ||
266              request->operation == LDB_REQ_DELETE ||
267              request->operation == LDB_REQ_RENAME)) {
268                 status = ldb_transaction_start(ldb);
269                 if (status != LDB_SUCCESS) {
270                         talloc_free(r);
271                         return status;
272                 }
273                 started_transaction = 1;
274         }
275
276         /* call the first module in the chain */
277         status = ldb->modules->ops->request(ldb->modules, r);
278
279         /* the search call is the only one that returns something
280            other than a status code. We steal the results into
281            the context of the ldb before freeing the request */
282         if (request->operation == LDB_REQ_SEARCH) {
283                 request->op.search.res = talloc_steal(ldb, r->op.search.res);
284         }
285         if (request->operation == LDB_ASYNC_SEARCH) {
286                 request->async.handle = r->async.handle;
287         }
288         talloc_free(r);
289
290         if (started_transaction) {
291                 return ldb_op_finish(ldb, status);
292         }
293
294         return status;
295 }
296
297 /*
298   search the database given a LDAP-like search expression
299
300   return the number of records found, or -1 on error
301
302   Use talloc_free to free the ldb_message returned in 'res'
303
304 */
305 int ldb_search(struct ldb_context *ldb, 
306                const struct ldb_dn *base,
307                enum ldb_scope scope,
308                const char *expression,
309                const char * const *attrs, 
310                struct ldb_result **res)
311 {
312         struct ldb_request request;
313         struct ldb_parse_tree *tree;
314         int ret;
315
316         (*res) = NULL;
317
318         tree = ldb_parse_tree(ldb, expression);
319         if (tree == NULL) {
320                 ldb_set_errstring(ldb, talloc_strdup(ldb, "Unable to parse search expression"));
321                 return -1;
322         }
323
324         request.operation = LDB_REQ_SEARCH;
325         request.op.search.base = base;
326         request.op.search.scope = scope;
327         request.op.search.tree = tree;
328         request.op.search.attrs = attrs;
329         request.controls = NULL;
330
331         ret = ldb_request(ldb, &request);
332
333         (*res) = request.op.search.res;
334
335         talloc_free(tree);
336
337         return ret;
338 }
339
340 /*
341   add a record to the database. Will fail if a record with the given class and key
342   already exists
343 */
344 int ldb_add(struct ldb_context *ldb, 
345             const struct ldb_message *message)
346 {
347         struct ldb_request request;
348         int status;
349
350         status = ldb_msg_sanity_check(message);
351         if (status != LDB_SUCCESS) return status;
352
353         request.operation = LDB_REQ_ADD;
354         request.op.add.message = message;
355         request.controls = NULL;
356
357         return ldb_request(ldb, &request);
358 }
359
360 /*
361   modify the specified attributes of a record
362 */
363 int ldb_modify(struct ldb_context *ldb, 
364                const struct ldb_message *message)
365 {
366         struct ldb_request request;
367         int status;
368
369         status = ldb_msg_sanity_check(message);
370         if (status != LDB_SUCCESS) return status;
371
372         request.operation = LDB_REQ_MODIFY;
373         request.op.mod.message = message;
374         request.controls = NULL;
375
376         return ldb_request(ldb, &request);
377 }
378
379
380 /*
381   delete a record from the database
382 */
383 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
384 {
385         struct ldb_request request;
386
387         request.operation = LDB_REQ_DELETE;
388         request.op.del.dn = dn;
389         request.controls = NULL;
390
391         return ldb_request(ldb, &request);
392 }
393
394 /*
395   rename a record in the database
396 */
397 int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
398 {
399         struct ldb_request request;
400
401         request.operation = LDB_REQ_RENAME;
402         request.op.rename.olddn = olddn;
403         request.op.rename.newdn = newdn;
404         request.controls = NULL;
405
406         return ldb_request(ldb, &request);
407 }
408
409
410
411 /*
412   return extended error information 
413 */
414 const char *ldb_errstring(struct ldb_context *ldb)
415 {
416         if (ldb->err_string) {
417                 return ldb->err_string;
418         }
419
420         return NULL;
421 }
422
423
424 /*
425   set backend specific opaque parameters
426 */
427 int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
428 {
429         struct ldb_opaque *o;
430
431         /* allow updating an existing value */
432         for (o=ldb->opaque;o;o=o->next) {
433                 if (strcmp(o->name, name) == 0) {
434                         o->value = value;
435                         return LDB_SUCCESS;
436                 }
437         }
438
439         o = talloc(ldb, struct ldb_opaque);
440         if (o == NULL) {
441                 ldb_oom(ldb);
442                 return LDB_ERR_OTHER;
443         }
444         o->next = ldb->opaque;
445         o->name = name;
446         o->value = value;
447         ldb->opaque = o;
448         return LDB_SUCCESS;
449 }
450
451 /*
452   get a previously set opaque value
453 */
454 void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
455 {
456         struct ldb_opaque *o;
457         for (o=ldb->opaque;o;o=o->next) {
458                 if (strcmp(o->name, name) == 0) {
459                         return o->value;
460                 }
461         }
462         return NULL;
463 }