r15356: Remove unused 'flags' argument from socket_send() and friends.
[bbaumbach/samba-autobuild/.git] / source4 / lib / db_wrap.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    database wrap functions
5
6    Copyright (C) Andrew Tridgell 2004
7    
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 2 of the License, or
11    (at your option) any later version.
12    
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.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 /*
24   the stupidity of the unix fcntl locking design forces us to never
25   allow a database file to be opened twice in the same process. These
26   wrappers provide convenient access to a tdb or ldb, taking advantage
27   of talloc destructors to ensure that only a single open is done
28 */
29
30 #include "includes.h"
31 #include "dlinklist.h"
32 #include "lib/events/events.h"
33 #include "lib/tdb/include/tdb.h"
34 #include "lib/ldb/include/ldb.h"
35 #include "lib/ldb/samba/ldif_handlers.h"
36 #include "db_wrap.h"
37
38 static struct tdb_wrap *tdb_list;
39
40 /*
41   this is used to catch debug messages from ldb
42 */
43 static void ldb_wrap_debug(void *context, enum ldb_debug_level level, 
44                            const char *fmt, va_list ap)  PRINTF_ATTRIBUTE(3,0);
45
46 static void ldb_wrap_debug(void *context, enum ldb_debug_level level, 
47                            const char *fmt, va_list ap)
48 {
49         char *s = NULL;
50         if (DEBUGLEVEL < 4 && level > LDB_DEBUG_WARNING) {
51                 return;
52         }
53         if (DEBUGLEVEL < 2 && level > LDB_DEBUG_ERROR) {
54                 return;
55         }
56         vasprintf(&s, fmt, ap);
57         if (!s) return;
58         DEBUG(level, ("ldb: %s\n", s));
59         free(s);
60 }
61
62 char *wrap_casefold(void *context, void *mem_ctx, const char *s)
63 {
64         return strupper_talloc(mem_ctx, s);
65 }
66
67 /*
68   wrapped connection to a ldb database
69   to close just talloc_free() the returned ldb_context
70  */
71 struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
72                                      const char *url,
73                                      struct auth_session_info *session_info,
74                                      struct cli_credentials *credentials,
75                                      unsigned int flags,
76                                      const char *options[])
77 {
78         struct ldb_context *ldb;
79         int ret;
80         struct event_context *ev;
81         char *real_url = NULL;
82
83         ldb = ldb_init(mem_ctx);
84         if (ldb == NULL) {
85                 return NULL;
86         }
87
88         /* we want to use the existing event context if possible. This
89            relies on the fact that in smbd, everything is a child of
90            the main event_context */
91         ev = event_context_find(ldb);
92
93         if (ldb_set_opaque(ldb, "EventContext", ev)) {
94                 talloc_free(ldb);
95                 return NULL;
96         }
97
98         if (ldb_set_opaque(ldb, "sessionInfo", session_info)) {
99                 talloc_free(ldb);
100                 return NULL;
101         }
102
103         if (ldb_set_opaque(ldb, "credentials", credentials)) {
104                 talloc_free(ldb);
105                 return NULL;
106         }
107
108         ret = ldb_register_samba_handlers(ldb);
109         if (ret == -1) {
110                 talloc_free(ldb);
111                 return NULL;
112         }
113
114         real_url = private_path(ldb, url);
115         if (real_url == NULL) {
116                 talloc_free(ldb);
117                 return NULL;
118         }
119
120         /* allow admins to force non-sync ldb for all databases */
121         if (lp_parm_bool(-1, "ldb", "nosync", False)) {
122                 flags |= LDB_FLG_NOSYNC;
123         }
124         
125         ret = ldb_connect(ldb, real_url, flags, options);
126         if (ret == -1) {
127                 talloc_free(ldb);
128                 return NULL;
129         }
130
131         talloc_free(real_url);
132
133         ldb_set_debug(ldb, ldb_wrap_debug, NULL);
134
135         ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
136
137         return ldb;
138 }
139
140
141 /*
142  Log tdb messages via DEBUG().
143 */
144 static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, 
145                          const char *format, ...) PRINTF_ATTRIBUTE(3,4);
146
147 static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, 
148                          const char *format, ...)
149 {
150         va_list ap;
151         char *ptr = NULL;
152
153         va_start(ap, format);
154         vasprintf(&ptr, format, ap);
155         va_end(ap);
156         
157         if (ptr != NULL) {
158                 const char *name = tdb_name(tdb);
159                 DEBUG(level, ("tdb(%s): %s", name ? name : "unnamed", ptr));
160                 free(ptr);
161         }
162 }
163
164
165 /* destroy the last connection to a tdb */
166 static int tdb_wrap_destructor(void *ctx)
167 {
168         struct tdb_wrap *w = ctx;
169         tdb_close(w->tdb);
170         DLIST_REMOVE(tdb_list, w);
171         return 0;
172 }                                
173
174 /*
175   wrapped connection to a tdb database
176   to close just talloc_free() the tdb_wrap pointer
177  */
178 struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx,
179                                const char *name, int hash_size, int tdb_flags,
180                                int open_flags, mode_t mode)
181 {
182         struct tdb_wrap *w;
183
184         for (w=tdb_list;w;w=w->next) {
185                 if (strcmp(name, w->name) == 0) {
186                         return talloc_reference(mem_ctx, w);
187                 }
188         }
189
190         w = talloc(mem_ctx, struct tdb_wrap);
191         if (w == NULL) {
192                 return NULL;
193         }
194
195         w->name = talloc_strdup(w, name);
196
197         w->tdb = tdb_open_ex(name, hash_size, tdb_flags, 
198                              open_flags, mode, tdb_wrap_log, NULL);
199         if (w->tdb == NULL) {
200                 talloc_free(w);
201                 return NULL;
202         }
203
204         talloc_set_destructor(w, tdb_wrap_destructor);
205
206         DLIST_ADD(tdb_list, w);
207
208         return w;
209 }