r11353: a bit of an improvement to the ldb_tdb error handling
[gd/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         FIRST_OP(ldb, start_transaction);
130         
131         ldb->transaction_active++;
132
133         ldb_reset_err_string(ldb);
134
135         return module->ops->start_transaction(module);
136 }
137
138 /*
139   commit a transaction
140 */
141 int ldb_transaction_commit(struct ldb_context *ldb)
142 {
143         struct ldb_module *module;
144         FIRST_OP(ldb, end_transaction);
145
146         if (ldb->transaction_active > 0) {
147                 ldb->transaction_active--;
148         } else {
149                 return LDB_ERR_OPERATIONS_ERROR;
150         }
151
152         ldb_reset_err_string(ldb);
153
154         return module->ops->end_transaction(module);
155 }
156
157 /*
158   cancel a transaction
159 */
160 int ldb_transaction_cancel(struct ldb_context *ldb)
161 {
162         struct ldb_module *module;
163         FIRST_OP(ldb, del_transaction);
164
165         if (ldb->transaction_active > 0) {
166                 ldb->transaction_active--;
167         } else {
168                 return LDB_ERR_OPERATIONS_ERROR;
169         }
170
171         return module->ops->del_transaction(module);
172 }
173
174 /*
175   search the database given a LDAP-like search expression
176
177   return the number of records found, or -1 on error
178
179   Use talloc_free to free the ldb_message returned in 'res'
180
181 */
182 int ldb_search(struct ldb_context *ldb, 
183                const struct ldb_dn *base,
184                enum ldb_scope scope,
185                const char *expression,
186                const char * const *attrs, struct ldb_message ***res)
187 {
188         struct ldb_parse_tree *tree;
189         int ret;
190
191         tree = ldb_parse_tree(ldb, expression);
192         if (tree == NULL) {
193                 ldb_set_errstring(ldb->modules, talloc_strdup(ldb, "Unable to parse search expression"));
194                 return -1;
195         }
196
197         ret = ldb_search_bytree(ldb, base, scope, tree, attrs, res);
198         talloc_free(tree);
199
200         return ret;
201 }
202
203 /*
204   search the database given a search tree
205
206   return the number of records found, or -1 on error
207
208   Use talloc_free to free the ldb_message returned in 'res'
209
210 */
211 int ldb_search_bytree(struct ldb_context *ldb, 
212                       const struct ldb_dn *base,
213                       enum ldb_scope scope,
214                       struct ldb_parse_tree *tree,
215                       const char * const *attrs, struct ldb_message ***res)
216 {
217         struct ldb_module *module;
218         FIRST_OP(ldb, search_bytree);
219
220         ldb_reset_err_string(ldb);
221
222         return module->ops->search_bytree(module, base, scope, tree, attrs, res);
223 }
224
225 /*
226   check for an error return from an op 
227   if an op fails, but has not setup an error string, then setup one now
228 */
229 static int ldb_op_finish(struct ldb_context *ldb, int status)
230 {
231         if (status == LDB_SUCCESS) {
232                 return ldb_transaction_commit(ldb);
233         }
234         if (ldb->err_string == NULL) {
235                 /* no error string was setup by the backend */
236                 ldb_set_errstring(ldb->modules, 
237                                   talloc_asprintf(ldb, "ldb error %d", status));
238         }
239         ldb_transaction_cancel(ldb);
240         return status;
241 }
242
243 /*
244   add a record to the database. Will fail if a record with the given class and key
245   already exists
246 */
247 int ldb_add(struct ldb_context *ldb, 
248             const struct ldb_message *message)
249 {
250         struct ldb_module *module;
251         int status;
252
253         FIRST_OP(ldb, add_record);
254
255         ldb_reset_err_string(ldb);
256
257         status = ldb_msg_sanity_check(message);
258         if (status != LDB_SUCCESS) return status;
259
260         if (! ldb->transaction_active) {
261                 status = ldb_transaction_start(ldb);
262                 if (status != LDB_SUCCESS) return status;
263
264                 status = module->ops->add_record(module, message);
265                 return ldb_op_finish(ldb, status);
266         }
267
268         return module->ops->add_record(module, message);
269 }
270
271 /*
272   modify the specified attributes of a record
273 */
274 int ldb_modify(struct ldb_context *ldb, 
275                const struct ldb_message *message)
276 {
277         struct ldb_module *module;
278         int status;
279
280         FIRST_OP(ldb, modify_record);
281
282         ldb_reset_err_string(ldb);
283
284         status = ldb_msg_sanity_check(message);
285         if (status != LDB_SUCCESS) return status;
286
287         if (! ldb->transaction_active) {
288                 status = ldb_transaction_start(ldb);
289                 if (status != LDB_SUCCESS) return status;
290
291                 status = module->ops->modify_record(module, message);
292                 return ldb_op_finish(ldb, status);
293         }
294
295         return module->ops->modify_record(module, message);
296 }
297
298
299 /*
300   delete a record from the database
301 */
302 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
303 {
304         struct ldb_module *module;
305         int status;
306
307         FIRST_OP(ldb, delete_record);
308
309         ldb_reset_err_string(ldb);
310
311         if (! ldb->transaction_active) {
312                 status = ldb_transaction_start(ldb);
313                 if (status != LDB_SUCCESS) return status;
314
315                 status = module->ops->delete_record(module, dn);
316                 return ldb_op_finish(ldb, status);
317         }
318
319         return module->ops->delete_record(module, dn);
320 }
321
322 /*
323   rename a record in the database
324 */
325 int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
326 {
327         struct ldb_module *module;
328         int status;
329
330         FIRST_OP(ldb, rename_record);
331
332         ldb_reset_err_string(ldb);
333
334         if (! ldb->transaction_active) {
335                 status = ldb_transaction_start(ldb);
336                 if (status != LDB_SUCCESS) return status;
337
338                 status = module->ops->rename_record(module, olddn, newdn);
339                 return ldb_op_finish(ldb, status);
340         }
341
342         return module->ops->rename_record(module, olddn, newdn);
343 }
344
345
346
347 /*
348   return extended error information 
349 */
350 const char *ldb_errstring(struct ldb_context *ldb)
351 {
352         if (ldb->err_string) {
353                 return ldb->err_string;
354         }
355
356         return NULL;
357 }
358
359
360 /*
361   set backend specific opaque parameters
362 */
363 int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
364 {
365         struct ldb_opaque *o;
366
367         /* allow updating an existing value */
368         for (o=ldb->opaque;o;o=o->next) {
369                 if (strcmp(o->name, name) == 0) {
370                         o->value = value;
371                         return LDB_SUCCESS;
372                 }
373         }
374
375         o = talloc(ldb, struct ldb_opaque);
376         if (o == NULL) {
377                 ldb_oom(ldb);
378                 return LDB_ERR_OTHER;
379         }
380         o->next = ldb->opaque;
381         o->name = name;
382         o->value = value;
383         ldb->opaque = o;
384         return LDB_SUCCESS;
385 }
386
387 /*
388   get a previously set opaque value
389 */
390 void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
391 {
392         struct ldb_opaque *o;
393         for (o=ldb->opaque;o;o=o->next) {
394                 if (strcmp(o->name, name) == 0) {
395                         return o->value;
396                 }
397         }
398         return NULL;
399 }