s3-waf: replace the dbwrap_util library by a dbwrap library that contains the dbwrap...
[kai/samba.git] / source3 / lib / dbwrap_tdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Database interface wrapper around tdb
4    Copyright (C) Volker Lendecke 2005-2007
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "dbwrap.h"
22 #include "lib/util/tdb_wrap.h"
23
24 struct db_tdb_ctx {
25         struct tdb_wrap *wtdb;
26 };
27
28 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
29 static NTSTATUS db_tdb_delete(struct db_record *rec);
30
31 static int db_tdb_record_destr(struct db_record* data)
32 {
33         struct db_tdb_ctx *ctx =
34                 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
35
36         /* This hex_encode_talloc() call allocates memory on data context. By way how current 
37            __talloc_free() code works, it is OK to allocate in the destructor as 
38            the children of data will be freed after call to the destructor and this 
39            new 'child' will be caught and freed correctly.
40          */
41         DEBUG(10, (DEBUGLEVEL > 10
42                    ? "Unlocking key %s\n" : "Unlocking key %.20s\n",
43                    hex_encode_talloc(data, (unsigned char *)data->key.dptr,
44                               data->key.dsize)));
45
46         tdb_chainunlock(ctx->wtdb->tdb, data->key);
47         return 0;
48 }
49
50 struct tdb_fetch_locked_state {
51         TALLOC_CTX *mem_ctx;
52         struct db_record *result;
53 };
54
55 static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
56                                   void *private_data)
57 {
58         struct tdb_fetch_locked_state *state =
59                 (struct tdb_fetch_locked_state *)private_data;
60
61         state->result = (struct db_record *)talloc_size(
62                 state->mem_ctx,
63                 sizeof(struct db_record) + key.dsize + data.dsize);
64
65         if (state->result == NULL) {
66                 return 0;
67         }
68
69         state->result->key.dsize = key.dsize;
70         state->result->key.dptr = ((uint8 *)state->result)
71                 + sizeof(struct db_record);
72         memcpy(state->result->key.dptr, key.dptr, key.dsize);
73
74         state->result->value.dsize = data.dsize;
75
76         if (data.dsize > 0) {
77                 state->result->value.dptr = state->result->key.dptr+key.dsize;
78                 memcpy(state->result->value.dptr, data.dptr, data.dsize);
79         }
80         else {
81                 state->result->value.dptr = NULL;
82         }
83
84         return 0;
85 }
86
87 static struct db_record *db_tdb_fetch_locked(struct db_context *db,
88                                      TALLOC_CTX *mem_ctx, TDB_DATA key)
89 {
90         struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
91                                                        struct db_tdb_ctx);
92         struct tdb_fetch_locked_state state;
93
94         /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
95         if(DEBUGLEVEL >= 10) {
96                 char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize);
97                 DEBUG(10, (DEBUGLEVEL > 10
98                            ? "Locking key %s\n" : "Locking key %.20s\n",
99                            keystr));
100                 TALLOC_FREE(keystr);
101         }
102
103         if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
104                 DEBUG(3, ("tdb_chainlock failed\n"));
105                 return NULL;
106         }
107
108         state.mem_ctx = mem_ctx;
109         state.result = NULL;
110
111         tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
112
113         if (state.result == NULL) {
114                 db_tdb_fetchlock_parse(key, tdb_null, &state);
115         }
116
117         if (state.result == NULL) {
118                 tdb_chainunlock(ctx->wtdb->tdb, key);
119                 return NULL;
120         }
121
122         talloc_set_destructor(state.result, db_tdb_record_destr);
123
124         state.result->private_data = talloc_reference(state.result, ctx);
125         state.result->store = db_tdb_store;
126         state.result->delete_rec = db_tdb_delete;
127
128         DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
129
130         return state.result;
131 }
132
133 struct tdb_fetch_state {
134         TALLOC_CTX *mem_ctx;
135         int result;
136         TDB_DATA data;
137 };
138
139 static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA data,
140                               void *private_data)
141 {
142         struct tdb_fetch_state *state =
143                 (struct tdb_fetch_state *)private_data;
144
145         state->data.dptr = (uint8 *)talloc_memdup(state->mem_ctx, data.dptr,
146                                                   data.dsize);
147         if (state->data.dptr == NULL) {
148                 state->result = -1;
149                 return 0;
150         }
151
152         state->data.dsize = data.dsize;
153         return 0;
154 }
155
156 static int db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
157                         TDB_DATA key, TDB_DATA *pdata)
158 {
159         struct db_tdb_ctx *ctx = talloc_get_type_abort(
160                 db->private_data, struct db_tdb_ctx);
161
162         struct tdb_fetch_state state;
163
164         state.mem_ctx = mem_ctx;
165         state.result = 0;
166         state.data = tdb_null;
167
168         tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
169
170         if (state.result == -1) {
171                 return -1;
172         }
173
174         *pdata = state.data;
175         return 0;
176 }
177
178 static int db_tdb_parse(struct db_context *db, TDB_DATA key,
179                         int (*parser)(TDB_DATA key, TDB_DATA data,
180                                       void *private_data),
181                         void *private_data)
182 {
183         struct db_tdb_ctx *ctx = talloc_get_type_abort(
184                 db->private_data, struct db_tdb_ctx);
185
186         return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data);
187 }
188
189 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
190 {
191         struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
192                                                        struct db_tdb_ctx);
193
194         /*
195          * This has a bug: We need to replace rec->value for correct
196          * operation, but right now brlock and locking don't use the value
197          * anymore after it was stored.
198          */
199
200         return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
201                 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
202 }
203
204 static NTSTATUS db_tdb_delete(struct db_record *rec)
205 {
206         struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
207                                                        struct db_tdb_ctx);
208
209         if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
210                 return NT_STATUS_OK;
211         }
212
213         if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
214                 return NT_STATUS_NOT_FOUND;
215         }
216
217         return NT_STATUS_UNSUCCESSFUL;
218 }
219
220 struct db_tdb_traverse_ctx {
221         struct db_context *db;
222         int (*f)(struct db_record *rec, void *private_data);
223         void *private_data;
224 };
225
226 static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
227                                 void *private_data)
228 {
229         struct db_tdb_traverse_ctx *ctx =
230                 (struct db_tdb_traverse_ctx *)private_data;
231         struct db_record rec;
232
233         rec.key = kbuf;
234         rec.value = dbuf;
235         rec.store = db_tdb_store;
236         rec.delete_rec = db_tdb_delete;
237         rec.private_data = ctx->db->private_data;
238
239         return ctx->f(&rec, ctx->private_data);
240 }
241
242 static int db_tdb_traverse(struct db_context *db,
243                            int (*f)(struct db_record *rec, void *private_data),
244                            void *private_data)
245 {
246         struct db_tdb_ctx *db_ctx =
247                 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
248         struct db_tdb_traverse_ctx ctx;
249
250         ctx.db = db;
251         ctx.f = f;
252         ctx.private_data = private_data;
253         return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
254 }
255
256 static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
257 {
258         return NT_STATUS_MEDIA_WRITE_PROTECTED;
259 }
260
261 static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
262 {
263         return NT_STATUS_MEDIA_WRITE_PROTECTED;
264 }
265
266 static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
267                                 void *private_data)
268 {
269         struct db_tdb_traverse_ctx *ctx =
270                 (struct db_tdb_traverse_ctx *)private_data;
271         struct db_record rec;
272
273         rec.key = kbuf;
274         rec.value = dbuf;
275         rec.store = db_tdb_store_deny;
276         rec.delete_rec = db_tdb_delete_deny;
277         rec.private_data = ctx->db->private_data;
278
279         return ctx->f(&rec, ctx->private_data);
280 }
281
282 static int db_tdb_traverse_read(struct db_context *db,
283                            int (*f)(struct db_record *rec, void *private_data),
284                            void *private_data)
285 {
286         struct db_tdb_ctx *db_ctx =
287                 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
288         struct db_tdb_traverse_ctx ctx;
289
290         ctx.db = db;
291         ctx.f = f;
292         ctx.private_data = private_data;
293         return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
294 }
295
296 static int db_tdb_get_seqnum(struct db_context *db)
297
298 {
299         struct db_tdb_ctx *db_ctx =
300                 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
301         return tdb_get_seqnum(db_ctx->wtdb->tdb);
302 }
303
304 static int db_tdb_get_flags(struct db_context *db)
305
306 {
307         struct db_tdb_ctx *db_ctx =
308                 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
309         return tdb_get_flags(db_ctx->wtdb->tdb);
310 }
311
312 static int db_tdb_transaction_start(struct db_context *db)
313 {
314         struct db_tdb_ctx *db_ctx =
315                 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
316         return tdb_transaction_start(db_ctx->wtdb->tdb);
317 }
318
319 static int db_tdb_transaction_commit(struct db_context *db)
320 {
321         struct db_tdb_ctx *db_ctx =
322                 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
323         return tdb_transaction_commit(db_ctx->wtdb->tdb);
324 }
325
326 static int db_tdb_transaction_cancel(struct db_context *db)
327 {
328         struct db_tdb_ctx *db_ctx =
329                 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
330         tdb_transaction_cancel(db_ctx->wtdb->tdb);
331         return 0;
332 }
333
334 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
335                                const char *name,
336                                int hash_size, int tdb_flags,
337                                int open_flags, mode_t mode)
338 {
339         struct db_context *result = NULL;
340         struct db_tdb_ctx *db_tdb;
341
342         result = talloc_zero(mem_ctx, struct db_context);
343         if (result == NULL) {
344                 DEBUG(0, ("talloc failed\n"));
345                 goto fail;
346         }
347
348         result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
349         if (db_tdb == NULL) {
350                 DEBUG(0, ("talloc failed\n"));
351                 goto fail;
352         }
353
354         db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
355                                      open_flags, mode);
356         if (db_tdb->wtdb == NULL) {
357                 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
358                 goto fail;
359         }
360
361         result->fetch_locked = db_tdb_fetch_locked;
362         result->fetch = db_tdb_fetch;
363         result->traverse = db_tdb_traverse;
364         result->traverse_read = db_tdb_traverse_read;
365         result->parse_record = db_tdb_parse;
366         result->get_seqnum = db_tdb_get_seqnum;
367         result->get_flags = db_tdb_get_flags;
368         result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
369         result->transaction_start = db_tdb_transaction_start;
370         result->transaction_commit = db_tdb_transaction_commit;
371         result->transaction_cancel = db_tdb_transaction_cancel;
372         return result;
373
374  fail:
375         if (result != NULL) {
376                 TALLOC_FREE(result);
377         }
378         return NULL;
379 }