r10753: don't require every ldb module to implement both a search_bytree() and
[jra/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 /*
118   start a transaction
119 */
120 int ldb_transaction_start(struct ldb_context *ldb)
121 {
122         ldb->transaction_active++;
123
124         ldb_reset_err_string(ldb);
125
126         return ldb->modules->ops->start_transaction(ldb->modules);
127 }
128
129 /*
130   commit a transaction
131 */
132 int ldb_transaction_commit(struct ldb_context *ldb)
133 {
134         if (ldb->transaction_active > 0) {
135                 ldb->transaction_active--;
136         } else {
137                 return LDB_ERR_OPERATIONS_ERROR;
138         }
139
140         ldb_reset_err_string(ldb);
141
142         return ldb->modules->ops->end_transaction(ldb->modules);
143 }
144
145 /*
146   cancel a transaction
147 */
148 int ldb_transaction_cancel(struct ldb_context *ldb)
149 {
150         if (ldb->transaction_active > 0) {
151                 ldb->transaction_active--;
152         } else {
153                 return LDB_ERR_OPERATIONS_ERROR;
154         }
155
156         ldb_reset_err_string(ldb);
157
158         return ldb->modules->ops->del_transaction(ldb->modules);
159 }
160
161 /*
162   search the database given a LDAP-like search expression
163
164   return the number of records found, or -1 on error
165
166   Use talloc_free to free the ldb_message returned in 'res'
167
168 */
169 int ldb_search(struct ldb_context *ldb, 
170                const struct ldb_dn *base,
171                enum ldb_scope scope,
172                const char *expression,
173                const char * const *attrs, struct ldb_message ***res)
174 {
175         struct ldb_parse_tree *tree;
176         int ret;
177
178         tree = ldb_parse_tree(ldb, expression);
179         if (tree == NULL) {
180                 ldb_set_errstring(ldb->modules, talloc_strdup(ldb, "Unable to parse search expression"));
181                 return -1;
182         }
183
184         ret = ldb_search_bytree(ldb, base, scope, tree, attrs, res);
185         talloc_free(tree);
186
187         return ret;
188 }
189
190 /*
191   search the database given a search tree
192
193   return the number of records found, or -1 on error
194
195   Use talloc_free to free the ldb_message returned in 'res'
196
197 */
198 int ldb_search_bytree(struct ldb_context *ldb, 
199                       const struct ldb_dn *base,
200                       enum ldb_scope scope,
201                       struct ldb_parse_tree *tree,
202                       const char * const *attrs, struct ldb_message ***res)
203 {
204         ldb_reset_err_string(ldb);
205
206         return ldb->modules->ops->search_bytree(ldb->modules, base, scope, tree, attrs, res);
207 }
208
209 /*
210   add a record to the database. Will fail if a record with the given class and key
211   already exists
212 */
213 int ldb_add(struct ldb_context *ldb, 
214             const struct ldb_message *message)
215 {
216         int status;
217
218         ldb_reset_err_string(ldb);
219
220         status = ldb_msg_sanity_check(message);
221         if (status != LDB_SUCCESS) return status;
222
223         if (! ldb->transaction_active) {
224                 status = ldb_transaction_start(ldb);
225                 if (status != LDB_SUCCESS) return status;
226
227                 status = ldb->modules->ops->add_record(ldb->modules, message);
228                 if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb);
229                 return ldb_transaction_commit(ldb);
230         }
231
232         return ldb->modules->ops->add_record(ldb->modules, message);
233 }
234
235 /*
236   modify the specified attributes of a record
237 */
238 int ldb_modify(struct ldb_context *ldb, 
239                const struct ldb_message *message)
240 {
241         int status;
242
243         ldb_reset_err_string(ldb);
244
245         status = ldb_msg_sanity_check(message);
246         if (status != LDB_SUCCESS) return status;
247
248         if (! ldb->transaction_active) {
249                 status = ldb_transaction_start(ldb);
250                 if (status != LDB_SUCCESS) return status;
251
252                 status = ldb->modules->ops->modify_record(ldb->modules, message);
253                 if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb);
254                 return ldb_transaction_commit(ldb);
255         }
256
257         return ldb->modules->ops->modify_record(ldb->modules, message);
258 }
259
260
261 /*
262   delete a record from the database
263 */
264 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
265 {
266         int status;
267
268         ldb_reset_err_string(ldb);
269
270         if (! ldb->transaction_active) {
271                 status = ldb_transaction_start(ldb);
272                 if (status != LDB_SUCCESS) return status;
273
274                 status = ldb->modules->ops->delete_record(ldb->modules, dn);
275                 if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb);
276                 return ldb_transaction_commit(ldb);
277         }
278
279         return ldb->modules->ops->delete_record(ldb->modules, dn);
280 }
281
282 /*
283   rename a record in the database
284 */
285 int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
286 {
287         int status;
288
289         ldb_reset_err_string(ldb);
290
291         if (! ldb->transaction_active) {
292                 status = ldb_transaction_start(ldb);
293                 if (status != LDB_SUCCESS) return status;
294
295                 status = ldb->modules->ops->rename_record(ldb->modules, olddn, newdn);
296                 if (status != LDB_SUCCESS) return ldb_transaction_cancel(ldb);
297                 return ldb_transaction_commit(ldb);
298         }
299
300         return ldb->modules->ops->rename_record(ldb->modules, olddn, newdn);
301 }
302
303
304
305 /*
306   return extended error information 
307 */
308 const char *ldb_errstring(struct ldb_context *ldb)
309 {
310         if (ldb->err_string) {
311                 return ldb->err_string;
312         }
313
314         return NULL;
315 }
316
317
318 /*
319   set backend specific opaque parameters
320 */
321 int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
322 {
323         struct ldb_opaque *o = talloc(ldb, struct ldb_opaque);
324         if (o == NULL) {
325                 ldb_oom(ldb);
326                 return LDB_ERR_OTHER;
327         }
328         o->next = ldb->opaque;
329         o->name = name;
330         o->value = value;
331         ldb->opaque = o;
332         return LDB_SUCCESS;
333 }
334
335 /*
336   get a previously set opaque value
337 */
338 void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
339 {
340         struct ldb_opaque *o;
341         for (o=ldb->opaque;o;o=o->next) {
342                 if (strcmp(o->name, name) == 0) {
343                         return o->value;
344                 }
345         }
346         return NULL;
347 }