ctdb-tests: Extend ctdb stub to support "ptrans", "pdelete", "catdb"
[Samba.git] / lib / ldb-samba / ldb_wrap.c
blob05d0451beed9f2f227edb6028408840fb20e8f74
1 /*
2 Unix SMB/CIFS implementation.
4 LDB wrap functions
6 Copyright (C) Andrew Tridgell 2004-2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 the stupidity of the unix fcntl locking design forces us to never
24 allow a database file to be opened twice in the same process. These
25 wrappers provide convenient access to a tdb or ldb, taking advantage
26 of talloc destructors to ensure that only a single open is done
29 #include "includes.h"
30 #include "lib/events/events.h"
31 #include <ldb.h>
32 #include <ldb_errors.h>
33 #include "lib/ldb-samba/ldif_handlers.h"
34 #include "ldb_wrap.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "param/param.h"
37 #include "../lib/util/dlinklist.h"
38 #include <tdb.h>
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_LDB
44 this is used to catch debug messages from ldb
46 static void ldb_wrap_debug(void *context, enum ldb_debug_level level,
47 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
49 static void ldb_wrap_debug(void *context, enum ldb_debug_level level,
50 const char *fmt, va_list ap)
52 int samba_level = -1;
53 switch (level) {
54 case LDB_DEBUG_FATAL:
55 samba_level = 0;
56 break;
57 case LDB_DEBUG_ERROR:
58 samba_level = 1;
59 break;
60 case LDB_DEBUG_WARNING:
61 samba_level = 2;
62 break;
63 case LDB_DEBUG_TRACE:
64 samba_level = 10;
65 break;
68 if (CHECK_DEBUGLVL(samba_level)) {
69 char *s = NULL;
70 vasprintf(&s, fmt, ap);
71 if (!s) return;
72 DEBUG(samba_level, ("ldb: %s\n", s));
73 free(s);
79 connecting to a ldb can be a relatively expensive operation because
80 of the schema and partition loads. We keep a list of open ldb
81 contexts here, and try to re-use when possible.
83 This means callers of ldb_wrap_connect() must use talloc_unlink() or
84 the free of a parent to destroy the context
86 static struct ldb_wrap {
87 struct ldb_wrap *next, *prev;
88 struct ldb_wrap_context {
89 /* the context is what we use to tell if two ldb
90 * connections are exactly equivalent
92 const char *url;
93 struct tevent_context *ev;
94 struct loadparm_context *lp_ctx;
95 struct auth_session_info *session_info;
96 struct cli_credentials *credentials;
97 unsigned int flags;
98 } context;
99 struct ldb_context *ldb;
100 } *ldb_wrap_list;
103 free a ldb_wrap structure
105 static int ldb_wrap_destructor(struct ldb_wrap *w)
107 DLIST_REMOVE(ldb_wrap_list, w);
108 return 0;
112 * The casefolder for s4's LDB databases - Unicode-safe
114 char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)
116 return strupper_talloc_n(mem_ctx, s, n);
120 struct ldb_context *samba_ldb_init(TALLOC_CTX *mem_ctx,
121 struct tevent_context *ev,
122 struct loadparm_context *lp_ctx,
123 struct auth_session_info *session_info,
124 struct cli_credentials *credentials)
126 struct ldb_context *ldb;
127 int ret;
129 ldb = ldb_init(mem_ctx, ev);
130 if (ldb == NULL) {
131 return NULL;
134 ldb_set_modules_dir(ldb, modules_path(ldb, "ldb"));
136 ldb_set_debug(ldb, ldb_wrap_debug, NULL);
138 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
140 if (session_info) {
141 if (ldb_set_opaque(ldb, "sessionInfo", session_info)) {
142 talloc_free(ldb);
143 return NULL;
147 if (credentials) {
148 if (ldb_set_opaque(ldb, "credentials", credentials)) {
149 talloc_free(ldb);
150 return NULL;
154 if (ldb_set_opaque(ldb, "loadparm", lp_ctx)) {
155 talloc_free(ldb);
156 return NULL;
159 /* This must be done before we load the schema, as these
160 * handlers for objectSid and objectGUID etc must take
161 * precedence over the 'binary attribute' declaration in the
162 * schema */
163 ret = ldb_register_samba_handlers(ldb);
164 if (ret != LDB_SUCCESS) {
165 talloc_free(ldb);
166 return NULL;
169 /* we usually want Samba databases to be private. If we later
170 find we need one public, we will need to add a parameter to
171 ldb_wrap_connect() */
172 ldb_set_create_perms(ldb, 0600);
174 return ldb;
177 struct ldb_context *ldb_wrap_find(const char *url,
178 struct tevent_context *ev,
179 struct loadparm_context *lp_ctx,
180 struct auth_session_info *session_info,
181 struct cli_credentials *credentials,
182 unsigned int flags)
184 struct ldb_wrap *w;
185 /* see if we can re-use an existing ldb */
186 for (w=ldb_wrap_list; w; w=w->next) {
187 if (w->context.ev == ev &&
188 w->context.lp_ctx == lp_ctx &&
189 w->context.session_info == session_info &&
190 w->context.credentials == credentials &&
191 w->context.flags == flags &&
192 (w->context.url == url || strcmp(w->context.url, url) == 0))
193 return w->ldb;
196 return NULL;
199 int samba_ldb_connect(struct ldb_context *ldb, struct loadparm_context *lp_ctx,
200 const char *url, unsigned int flags)
202 int ret;
203 char *real_url = NULL;
205 /* allow admins to force non-sync ldb for all databases */
206 if (lpcfg_parm_bool(lp_ctx, NULL, "ldb", "nosync", false)) {
207 flags |= LDB_FLG_NOSYNC;
210 if (DEBUGLVL(10)) {
211 flags |= LDB_FLG_ENABLE_TRACING;
214 real_url = lpcfg_private_path(ldb, lp_ctx, url);
215 if (real_url == NULL) {
216 return LDB_ERR_OPERATIONS_ERROR;
219 ret = ldb_connect(ldb, real_url, flags, NULL);
221 if (ret != LDB_SUCCESS) {
222 return ret;
225 /* setup for leak detection */
226 ldb_set_opaque(ldb, "wrap_url", real_url);
228 return LDB_SUCCESS;
231 bool ldb_wrap_add(const char *url, struct tevent_context *ev,
232 struct loadparm_context *lp_ctx,
233 struct auth_session_info *session_info,
234 struct cli_credentials *credentials,
235 unsigned int flags,
236 struct ldb_context *ldb)
238 struct ldb_wrap *w;
239 struct ldb_wrap_context c;
241 /* add to the list of open ldb contexts */
242 w = talloc(ldb, struct ldb_wrap);
243 if (w == NULL) {
244 return false;
247 c.url = url;
248 c.ev = ev;
249 c.lp_ctx = lp_ctx;
250 c.session_info = session_info;
251 c.credentials = credentials;
252 c.flags = flags;
254 w->context = c;
255 w->context.url = talloc_strdup(w, url);
256 if (w->context.url == NULL) {
257 return false;
260 if (session_info) {
261 /* take a reference to the session_info, as it is
262 * possible for the ldb to live longer than the
263 * session_info. This happens when a DRS DsBind call
264 * reuses a handle, but the original connection is
265 * shutdown. The token for the new connection is still
266 * valid, so we need the session_info to remain valid for
267 * ldb modules to use
269 if (talloc_reference(w, session_info) == NULL) {
270 return false;
274 w->ldb = ldb;
276 DLIST_ADD(ldb_wrap_list, w);
278 talloc_set_destructor(w, ldb_wrap_destructor);
280 return true;
285 wrapped connection to a ldb database
286 to close just talloc_free() the returned ldb_context
288 TODO: We need an error_string parameter
290 struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
291 struct tevent_context *ev,
292 struct loadparm_context *lp_ctx,
293 const char *url,
294 struct auth_session_info *session_info,
295 struct cli_credentials *credentials,
296 unsigned int flags)
298 struct ldb_context *ldb;
299 int ret;
301 ldb = ldb_wrap_find(url, ev, lp_ctx, session_info, credentials, flags);
302 if (ldb != NULL)
303 return talloc_reference(mem_ctx, ldb);
305 ldb = samba_ldb_init(mem_ctx, ev, lp_ctx, session_info, credentials);
307 if (ldb == NULL)
308 return NULL;
310 ret = samba_ldb_connect(ldb, lp_ctx, url, flags);
311 if (ret != LDB_SUCCESS) {
312 talloc_free(ldb);
313 return NULL;
316 if (!ldb_wrap_add(url, ev, lp_ctx, session_info, credentials, flags, ldb)) {
317 talloc_free(ldb);
318 return NULL;
321 DEBUG(3,("ldb_wrap open of %s\n", url));
323 return ldb;
327 when we fork() we need to make sure that any open ldb contexts have
328 any open transactions cancelled (ntdb databases doesn't need reopening,
329 as we don't use clear_if_first).
331 void ldb_wrap_fork_hook(void)
333 struct ldb_wrap *w;
335 for (w=ldb_wrap_list; w; w=w->next) {
336 if (ldb_transaction_cancel_noerr(w->ldb) != LDB_SUCCESS) {
337 smb_panic("Failed to cancel child transactions\n");
341 if (tdb_reopen_all(1) != 0) {
342 smb_panic("tdb_reopen_all failed\n");
346 char *ldb_relative_path(struct ldb_context *ldb,
347 TALLOC_CTX *mem_ctx,
348 const char *name)
350 const char *base_url =
351 (const char *)ldb_get_opaque(ldb, "ldb_url");
352 char *path, *p, *full_name;
353 if (name == NULL) {
354 return NULL;
356 if (strncmp("tdb://", base_url, 6) == 0) {
357 base_url = base_url+6;
359 path = talloc_strdup(mem_ctx, base_url);
360 if (path == NULL) {
361 return NULL;
363 if ( (p = strrchr(path, '/')) != NULL) {
364 p[0] = '\0';
365 full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
366 } else {
367 full_name = talloc_asprintf(mem_ctx, "./%s", name);
369 talloc_free(path);
370 return full_name;