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