r13615: Make ldb_set_errstring get ldb instead of module as parameter.
[abartlet/samba.git/.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  second stage init all modules loaded
133 */
134 int ldb_second_stage_init(struct ldb_context *ldb)
135 {
136         struct ldb_module *module;
137
138         FIRST_OP(ldb, second_stage_init);
139
140         return module->ops->second_stage_init(module);
141 }
142
143
144 /*
145   start a transaction
146 */
147 int ldb_transaction_start(struct ldb_context *ldb)
148 {
149         struct ldb_module *module;
150         int status;
151         FIRST_OP(ldb, start_transaction);
152         
153         ldb->transaction_active++;
154
155         ldb_reset_err_string(ldb);
156
157         status = module->ops->start_transaction(module);
158         if (status != LDB_SUCCESS) {
159                 if (ldb->err_string == NULL) {
160                         /* no error string was setup by the backend */
161                         ldb_set_errstring(ldb, 
162                                           talloc_asprintf(ldb, "ldb transaction start error %d", status));
163                 }
164         }
165         return status;
166 }
167
168 /*
169   commit a transaction
170 */
171 int ldb_transaction_commit(struct ldb_context *ldb)
172 {
173         struct ldb_module *module;
174         int status;
175         FIRST_OP(ldb, end_transaction);
176
177         if (ldb->transaction_active > 0) {
178                 ldb->transaction_active--;
179         } else {
180                 return LDB_ERR_OPERATIONS_ERROR;
181         }
182
183         ldb_reset_err_string(ldb);
184
185         status = module->ops->end_transaction(module);
186         if (status != LDB_SUCCESS) {
187                 if (ldb->err_string == NULL) {
188                         /* no error string was setup by the backend */
189                         ldb_set_errstring(ldb, 
190                                           talloc_asprintf(ldb, "ldb transaction commit error %d", status));
191                 }
192         }
193         return status;
194 }
195
196 /*
197   cancel a transaction
198 */
199 int ldb_transaction_cancel(struct ldb_context *ldb)
200 {
201         struct ldb_module *module;
202         int status;
203         FIRST_OP(ldb, del_transaction);
204
205         if (ldb->transaction_active > 0) {
206                 ldb->transaction_active--;
207         } else {
208                 return LDB_ERR_OPERATIONS_ERROR;
209         }
210
211         status = module->ops->del_transaction(module);
212         if (status != LDB_SUCCESS) {
213                 if (ldb->err_string == NULL) {
214                         /* no error string was setup by the backend */
215                         ldb_set_errstring(ldb, 
216                                           talloc_asprintf(ldb, "ldb transaction cancel error %d", status));
217                 }
218         }
219         return status;
220 }
221
222 int ldb_async_wait(struct ldb_context *ldb, struct ldb_async_handle *handle, enum ldb_async_wait_type type)
223 {
224         if (ldb->async_wait != NULL)
225                 return ldb->async_wait(handle, type);
226
227         return LDB_ERR_OPERATIONS_ERROR;
228 }
229
230 /*
231   check for an error return from an op 
232   if an op fails, but has not setup an error string, then setup one now
233 */
234 static int ldb_op_finish(struct ldb_context *ldb, int status)
235 {
236         if (status == LDB_SUCCESS) {
237                 return ldb_transaction_commit(ldb);
238         }
239         if (ldb->err_string == NULL) {
240                 /* no error string was setup by the backend */
241                 ldb_set_errstring(ldb, 
242                                   talloc_asprintf(ldb, "ldb error %d", status));
243         }
244         ldb_transaction_cancel(ldb);
245         return status;
246 }
247
248 /*
249   start an ldb request
250   autostarts a transacion if none active and the operation is not a search
251   returns LDB_ERR_* on errors.
252 */
253 int ldb_request(struct ldb_context *ldb, struct ldb_request *request)
254 {
255         int status, started_transaction=0;
256         struct ldb_request *r;
257
258         ldb_reset_err_string(ldb);
259
260         /* to allow ldb modules to assume they can use the request ptr
261            as a talloc context for the request, we have to copy the 
262            structure here */
263         r = talloc(ldb, struct ldb_request);
264         if (r == NULL) {
265                 ldb_oom(ldb);
266                 return LDB_ERR_OPERATIONS_ERROR;
267         }
268
269         *r = *request;
270
271         if (r->operation == LDB_REQ_SEARCH) {
272                 r->op.search.res = NULL;
273         }
274
275         /* start a transaction if needed */
276         if ((!ldb->transaction_active) &&
277             (request->operation == LDB_REQ_ADD ||
278              request->operation == LDB_REQ_MODIFY ||
279              request->operation == LDB_REQ_DELETE ||
280              request->operation == LDB_REQ_RENAME)) {
281                 status = ldb_transaction_start(ldb);
282                 if (status != LDB_SUCCESS) {
283                         talloc_free(r);
284                         return status;
285                 }
286                 started_transaction = 1;
287         }
288
289         /* call the first module in the chain */
290         status = ldb->modules->ops->request(ldb->modules, r);
291
292         /* the search call is the only one that returns something
293            other than a status code. We steal the results into
294            the context of the ldb before freeing the request */
295         if (request->operation == LDB_REQ_SEARCH) {
296                 request->op.search.res = talloc_steal(ldb, r->op.search.res);
297         }
298         if (request->operation == LDB_ASYNC_SEARCH) {
299                 request->async.handle = r->async.handle;
300         }
301         talloc_free(r);
302
303         if (started_transaction) {
304                 return ldb_op_finish(ldb, status);
305         }
306
307         return status;
308 }
309
310 /*
311   search the database given a LDAP-like search expression
312
313   return the number of records found, or -1 on error
314
315   Use talloc_free to free the ldb_message returned in 'res'
316
317 */
318 int ldb_search(struct ldb_context *ldb, 
319                const struct ldb_dn *base,
320                enum ldb_scope scope,
321                const char *expression,
322                const char * const *attrs, 
323                struct ldb_result **res)
324 {
325         struct ldb_request request;
326         struct ldb_parse_tree *tree;
327         int ret;
328
329         (*res) = NULL;
330
331         tree = ldb_parse_tree(ldb, expression);
332         if (tree == NULL) {
333                 ldb_set_errstring(ldb, talloc_strdup(ldb, "Unable to parse search expression"));
334                 return -1;
335         }
336
337         request.operation = LDB_REQ_SEARCH;
338         request.op.search.base = base;
339         request.op.search.scope = scope;
340         request.op.search.tree = tree;
341         request.op.search.attrs = attrs;
342         request.controls = NULL;
343
344         ret = ldb_request(ldb, &request);
345
346         (*res) = request.op.search.res;
347
348         talloc_free(tree);
349
350         return ret;
351 }
352
353 /*
354   add a record to the database. Will fail if a record with the given class and key
355   already exists
356 */
357 int ldb_add(struct ldb_context *ldb, 
358             const struct ldb_message *message)
359 {
360         struct ldb_request request;
361         int status;
362
363         status = ldb_msg_sanity_check(message);
364         if (status != LDB_SUCCESS) return status;
365
366         request.operation = LDB_REQ_ADD;
367         request.op.add.message = message;
368         request.controls = NULL;
369
370         return ldb_request(ldb, &request);
371 }
372
373 /*
374   modify the specified attributes of a record
375 */
376 int ldb_modify(struct ldb_context *ldb, 
377                const struct ldb_message *message)
378 {
379         struct ldb_request request;
380         int status;
381
382         status = ldb_msg_sanity_check(message);
383         if (status != LDB_SUCCESS) return status;
384
385         request.operation = LDB_REQ_MODIFY;
386         request.op.mod.message = message;
387         request.controls = NULL;
388
389         return ldb_request(ldb, &request);
390 }
391
392
393 /*
394   delete a record from the database
395 */
396 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
397 {
398         struct ldb_request request;
399
400         request.operation = LDB_REQ_DELETE;
401         request.op.del.dn = dn;
402         request.controls = NULL;
403
404         return ldb_request(ldb, &request);
405 }
406
407 /*
408   rename a record in the database
409 */
410 int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
411 {
412         struct ldb_request request;
413
414         request.operation = LDB_REQ_RENAME;
415         request.op.rename.olddn = olddn;
416         request.op.rename.newdn = newdn;
417         request.controls = NULL;
418
419         return ldb_request(ldb, &request);
420 }
421
422
423
424 /*
425   return extended error information 
426 */
427 const char *ldb_errstring(struct ldb_context *ldb)
428 {
429         if (ldb->err_string) {
430                 return ldb->err_string;
431         }
432
433         return NULL;
434 }
435
436
437 /*
438   set backend specific opaque parameters
439 */
440 int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
441 {
442         struct ldb_opaque *o;
443
444         /* allow updating an existing value */
445         for (o=ldb->opaque;o;o=o->next) {
446                 if (strcmp(o->name, name) == 0) {
447                         o->value = value;
448                         return LDB_SUCCESS;
449                 }
450         }
451
452         o = talloc(ldb, struct ldb_opaque);
453         if (o == NULL) {
454                 ldb_oom(ldb);
455                 return LDB_ERR_OTHER;
456         }
457         o->next = ldb->opaque;
458         o->name = name;
459         o->value = value;
460         ldb->opaque = o;
461         return LDB_SUCCESS;
462 }
463
464 /*
465   get a previously set opaque value
466 */
467 void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
468 {
469         struct ldb_opaque *o;
470         for (o=ldb->opaque;o;o=o->next) {
471                 if (strcmp(o->name, name) == 0) {
472                         return o->value;
473                 }
474         }
475         return NULL;
476 }