4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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
28 * Component: ldb core API
30 * Description: core API routines interfacing to ldb backends
32 * Author: Andrew Tridgell
36 #include "ldb/include/includes.h"
39 initialise a ldb context
40 The mem_ctx is optional
42 struct ldb_context *ldb_init(void *mem_ctx)
44 struct ldb_context *ldb = talloc_zero(mem_ctx, struct ldb_context);
47 ret = ldb_setup_wellknown_attributes(ldb);
53 ldb_set_utf8_default(ldb);
59 connect to a database. The URL can either be one of the following forms
63 flags is made up of LDB_FLG_*
65 the options are passed uninterpreted to the backend, and are
68 int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[])
72 if (strncmp(url, "tdb:", 4) == 0 ||
73 strchr(url, ':') == NULL) {
74 ret = ltdb_connect(ldb, url, flags, options);
78 else if (strncmp(url, "ldap", 4) == 0) {
79 ret = ildb_connect(ldb, url, flags, options);
82 else if (strncmp(url, "ldap", 4) == 0) {
83 ret = lldb_connect(ldb, url, flags, options);
87 else if (strncmp(url, "sqlite:", 7) == 0) {
88 ret = lsqlite3_connect(ldb, url, flags, options);
92 ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to find backend for '%s'\n", url);
96 if (ret != LDB_SUCCESS) {
97 ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to '%s'\n", url);
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;
109 void ldb_set_errstring(struct ldb_context *ldb, char *err_string)
111 if (ldb->err_string) {
112 talloc_free(ldb->err_string);
114 ldb->err_string = talloc_steal(ldb, err_string);
117 void ldb_reset_err_string(struct ldb_context *ldb)
119 if (ldb->err_string) {
120 talloc_free(ldb->err_string);
121 ldb->err_string = NULL;
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; \
134 int ldb_transaction_start(struct ldb_context *ldb)
136 struct ldb_module *module;
138 FIRST_OP(ldb, start_transaction);
140 ldb->transaction_active++;
142 ldb_reset_err_string(ldb);
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));
158 int ldb_transaction_commit(struct ldb_context *ldb)
160 struct ldb_module *module;
162 FIRST_OP(ldb, end_transaction);
164 if (ldb->transaction_active > 0) {
165 ldb->transaction_active--;
167 return LDB_ERR_OPERATIONS_ERROR;
170 ldb_reset_err_string(ldb);
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));
186 int ldb_transaction_cancel(struct ldb_context *ldb)
188 struct ldb_module *module;
190 FIRST_OP(ldb, del_transaction);
192 if (ldb->transaction_active > 0) {
193 ldb->transaction_active--;
195 return LDB_ERR_OPERATIONS_ERROR;
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));
209 int ldb_async_wait(struct ldb_context *ldb, struct ldb_async_handle *handle, enum ldb_async_wait_type type)
211 if (ldb->async_wait != NULL)
212 return ldb->async_wait(handle, type);
214 return LDB_ERR_OPERATIONS_ERROR;
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
221 static int ldb_op_finish(struct ldb_context *ldb, int status)
223 if (status == LDB_SUCCESS) {
224 return ldb_transaction_commit(ldb);
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));
231 ldb_transaction_cancel(ldb);
237 autostarts a transacion if none active and the operation is not a search
238 returns LDB_ERR_* on errors.
240 int ldb_request(struct ldb_context *ldb, struct ldb_request *request)
242 int status, started_transaction=0;
243 struct ldb_request *r;
245 ldb_reset_err_string(ldb);
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
250 r = talloc(ldb, struct ldb_request);
253 return LDB_ERR_OPERATIONS_ERROR;
258 if (r->operation == LDB_REQ_SEARCH) {
259 r->op.search.res = NULL;
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) {
273 started_transaction = 1;
276 /* call the first module in the chain */
277 status = ldb->modules->ops->request(ldb->modules, r);
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);
285 if (request->operation == LDB_ASYNC_SEARCH) {
286 request->async.handle = r->async.handle;
290 if (started_transaction) {
291 return ldb_op_finish(ldb, status);
298 search the database given a LDAP-like search expression
300 return the number of records found, or -1 on error
302 Use talloc_free to free the ldb_message returned in 'res'
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)
312 struct ldb_request request;
313 struct ldb_parse_tree *tree;
318 tree = ldb_parse_tree(ldb, expression);
320 ldb_set_errstring(ldb, talloc_strdup(ldb, "Unable to parse search expression"));
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;
331 ret = ldb_request(ldb, &request);
333 (*res) = request.op.search.res;
341 add a record to the database. Will fail if a record with the given class and key
344 int ldb_add(struct ldb_context *ldb,
345 const struct ldb_message *message)
347 struct ldb_request request;
350 status = ldb_msg_sanity_check(message);
351 if (status != LDB_SUCCESS) return status;
353 request.operation = LDB_REQ_ADD;
354 request.op.add.message = message;
355 request.controls = NULL;
357 return ldb_request(ldb, &request);
361 modify the specified attributes of a record
363 int ldb_modify(struct ldb_context *ldb,
364 const struct ldb_message *message)
366 struct ldb_request request;
369 status = ldb_msg_sanity_check(message);
370 if (status != LDB_SUCCESS) return status;
372 request.operation = LDB_REQ_MODIFY;
373 request.op.mod.message = message;
374 request.controls = NULL;
376 return ldb_request(ldb, &request);
381 delete a record from the database
383 int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn)
385 struct ldb_request request;
387 request.operation = LDB_REQ_DELETE;
388 request.op.del.dn = dn;
389 request.controls = NULL;
391 return ldb_request(ldb, &request);
395 rename a record in the database
397 int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
399 struct ldb_request request;
401 request.operation = LDB_REQ_RENAME;
402 request.op.rename.olddn = olddn;
403 request.op.rename.newdn = newdn;
404 request.controls = NULL;
406 return ldb_request(ldb, &request);
412 return extended error information
414 const char *ldb_errstring(struct ldb_context *ldb)
416 if (ldb->err_string) {
417 return ldb->err_string;
425 set backend specific opaque parameters
427 int ldb_set_opaque(struct ldb_context *ldb, const char *name, void *value)
429 struct ldb_opaque *o;
431 /* allow updating an existing value */
432 for (o=ldb->opaque;o;o=o->next) {
433 if (strcmp(o->name, name) == 0) {
439 o = talloc(ldb, struct ldb_opaque);
442 return LDB_ERR_OTHER;
444 o->next = ldb->opaque;
452 get a previously set opaque value
454 void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
456 struct ldb_opaque *o;
457 for (o=ldb->opaque;o;o=o->next) {
458 if (strcmp(o->name, name) == 0) {