source: branches/samba-3.3.x/source/lib/dbwrap_tdb.c

Last change on this file was 223, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 branch to 3.3.3

File size: 10.0 KB
Line 
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
22struct db_tdb_ctx {
23 struct tdb_wrap *wtdb;
24};
25
26static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
27static NTSTATUS db_tdb_delete(struct db_record *rec);
28
29static int db_tdb_record_destr(struct db_record* data)
30{
31 struct db_tdb_ctx *ctx =
32 talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
33
34 /* This hex_encode() call allocates memory on data context. By way how current
35 __talloc_free() code works, it is OK to allocate in the destructor as
36 the children of data will be freed after call to the destructor and this
37 new 'child' will be caught and freed correctly.
38 */
39 DEBUG(10, (DEBUGLEVEL > 10
40 ? "Unlocking key %s\n" : "Unlocking key %.20s\n",
41 hex_encode(data, (unsigned char *)data->key.dptr,
42 data->key.dsize)));
43
44 if (tdb_chainunlock(ctx->wtdb->tdb, data->key) != 0) {
45 DEBUG(0, ("tdb_chainunlock failed\n"));
46 return -1;
47 }
48 return 0;
49}
50
51struct tdb_fetch_locked_state {
52 TALLOC_CTX *mem_ctx;
53 struct db_record *result;
54};
55
56static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
57 void *private_data)
58{
59 struct tdb_fetch_locked_state *state =
60 (struct tdb_fetch_locked_state *)private_data;
61
62 state->result = (struct db_record *)talloc_size(
63 state->mem_ctx,
64 sizeof(struct db_record) + key.dsize + data.dsize);
65
66 if (state->result == NULL) {
67 return 0;
68 }
69
70 state->result->key.dsize = key.dsize;
71 state->result->key.dptr = ((uint8 *)state->result)
72 + sizeof(struct db_record);
73 memcpy(state->result->key.dptr, key.dptr, key.dsize);
74
75 state->result->value.dsize = data.dsize;
76
77 if (data.dsize > 0) {
78 state->result->value.dptr = state->result->key.dptr+key.dsize;
79 memcpy(state->result->value.dptr, data.dptr, data.dsize);
80 }
81 else {
82 state->result->value.dptr = NULL;
83 }
84
85 return 0;
86}
87
88static struct db_record *db_tdb_fetch_locked(struct db_context *db,
89 TALLOC_CTX *mem_ctx, TDB_DATA key)
90{
91 struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
92 struct db_tdb_ctx);
93 struct tdb_fetch_locked_state state;
94
95 /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */
96 if(DEBUGLEVEL >= 10) {
97 char *keystr = hex_encode(NULL, (unsigned char*)key.dptr, key.dsize);
98 DEBUG(10, (DEBUGLEVEL > 10
99 ? "Locking key %s\n" : "Locking key %.20s\n",
100 keystr));
101 TALLOC_FREE(keystr);
102 }
103
104 if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
105 DEBUG(3, ("tdb_chainlock failed\n"));
106 return NULL;
107 }
108
109 state.mem_ctx = mem_ctx;
110 state.result = NULL;
111
112 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetchlock_parse, &state);
113
114 if (state.result == NULL) {
115 db_tdb_fetchlock_parse(key, tdb_null, &state);
116 }
117
118 if (state.result == NULL) {
119 tdb_chainunlock(ctx->wtdb->tdb, key);
120 return NULL;
121 }
122
123 talloc_set_destructor(state.result, db_tdb_record_destr);
124
125 state.result->private_data = talloc_reference(state.result, ctx);
126 state.result->store = db_tdb_store;
127 state.result->delete_rec = db_tdb_delete;
128
129 DEBUG(10, ("Allocated locked data 0x%p\n", state.result));
130
131 return state.result;
132}
133
134struct tdb_fetch_state {
135 TALLOC_CTX *mem_ctx;
136 int result;
137 TDB_DATA data;
138};
139
140static int db_tdb_fetch_parse(TDB_DATA key, TDB_DATA data,
141 void *private_data)
142{
143 struct tdb_fetch_state *state =
144 (struct tdb_fetch_state *)private_data;
145
146 state->data.dptr = (uint8 *)talloc_memdup(state->mem_ctx, data.dptr,
147 data.dsize);
148 if (state->data.dptr == NULL) {
149 state->result = -1;
150 return 0;
151 }
152
153 state->data.dsize = data.dsize;
154 return 0;
155}
156
157static int db_tdb_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
158 TDB_DATA key, TDB_DATA *pdata)
159{
160 struct db_tdb_ctx *ctx = talloc_get_type_abort(
161 db->private_data, struct db_tdb_ctx);
162
163 struct tdb_fetch_state state;
164
165 state.mem_ctx = mem_ctx;
166 state.result = 0;
167 state.data = tdb_null;
168
169 tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_fetch_parse, &state);
170
171 if (state.result == -1) {
172 return -1;
173 }
174
175 *pdata = state.data;
176 return 0;
177}
178
179static int db_tdb_parse(struct db_context *db, TDB_DATA key,
180 int (*parser)(TDB_DATA key, TDB_DATA data,
181 void *private_data),
182 void *private_data)
183{
184 struct db_tdb_ctx *ctx = talloc_get_type_abort(
185 db->private_data, struct db_tdb_ctx);
186
187 return tdb_parse_record(ctx->wtdb->tdb, key, parser, private_data);
188}
189
190static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
191{
192 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
193 struct db_tdb_ctx);
194
195 /*
196 * This has a bug: We need to replace rec->value for correct
197 * operation, but right now brlock and locking don't use the value
198 * anymore after it was stored.
199 */
200
201 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
202 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
203}
204
205static NTSTATUS db_tdb_delete(struct db_record *rec)
206{
207 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
208 struct db_tdb_ctx);
209
210 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
211 return NT_STATUS_OK;
212 }
213
214 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
215 return NT_STATUS_NOT_FOUND;
216 }
217
218 return NT_STATUS_UNSUCCESSFUL;
219}
220
221struct db_tdb_traverse_ctx {
222 struct db_context *db;
223 int (*f)(struct db_record *rec, void *private_data);
224 void *private_data;
225};
226
227static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
228 void *private_data)
229{
230 struct db_tdb_traverse_ctx *ctx =
231 (struct db_tdb_traverse_ctx *)private_data;
232 struct db_record rec;
233
234 rec.key = kbuf;
235 rec.value = dbuf;
236 rec.store = db_tdb_store;
237 rec.delete_rec = db_tdb_delete;
238 rec.private_data = ctx->db->private_data;
239
240 return ctx->f(&rec, ctx->private_data);
241}
242
243static int db_tdb_traverse(struct db_context *db,
244 int (*f)(struct db_record *rec, void *private_data),
245 void *private_data)
246{
247 struct db_tdb_ctx *db_ctx =
248 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
249 struct db_tdb_traverse_ctx ctx;
250
251 ctx.db = db;
252 ctx.f = f;
253 ctx.private_data = private_data;
254 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
255}
256
257static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
258{
259 return NT_STATUS_MEDIA_WRITE_PROTECTED;
260}
261
262static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
263{
264 return NT_STATUS_MEDIA_WRITE_PROTECTED;
265}
266
267static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
268 void *private_data)
269{
270 struct db_tdb_traverse_ctx *ctx =
271 (struct db_tdb_traverse_ctx *)private_data;
272 struct db_record rec;
273
274 rec.key = kbuf;
275 rec.value = dbuf;
276 rec.store = db_tdb_store_deny;
277 rec.delete_rec = db_tdb_delete_deny;
278 rec.private_data = ctx->db->private_data;
279
280 return ctx->f(&rec, ctx->private_data);
281}
282
283static int db_tdb_traverse_read(struct db_context *db,
284 int (*f)(struct db_record *rec, void *private_data),
285 void *private_data)
286{
287 struct db_tdb_ctx *db_ctx =
288 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
289 struct db_tdb_traverse_ctx ctx;
290
291 ctx.db = db;
292 ctx.f = f;
293 ctx.private_data = private_data;
294 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
295}
296
297static int db_tdb_get_seqnum(struct db_context *db)
298
299{
300 struct db_tdb_ctx *db_ctx =
301 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
302 return tdb_get_seqnum(db_ctx->wtdb->tdb);
303}
304
305static int db_tdb_transaction_start(struct db_context *db)
306{
307 struct db_tdb_ctx *db_ctx =
308 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
309 return tdb_transaction_start(db_ctx->wtdb->tdb);
310}
311
312static int db_tdb_transaction_commit(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_commit(db_ctx->wtdb->tdb);
317}
318
319static int db_tdb_transaction_cancel(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_cancel(db_ctx->wtdb->tdb);
324}
325
326struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
327 const char *name,
328 int hash_size, int tdb_flags,
329 int open_flags, mode_t mode)
330{
331 struct db_context *result = NULL;
332 struct db_tdb_ctx *db_tdb;
333
334 result = TALLOC_ZERO_P(mem_ctx, struct db_context);
335 if (result == NULL) {
336 DEBUG(0, ("talloc failed\n"));
337 goto fail;
338 }
339
340 result->private_data = db_tdb = TALLOC_P(result, struct db_tdb_ctx);
341 if (db_tdb == NULL) {
342 DEBUG(0, ("talloc failed\n"));
343 goto fail;
344 }
345
346 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
347 open_flags, mode);
348 if (db_tdb->wtdb == NULL) {
349 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
350 goto fail;
351 }
352
353 result->fetch_locked = db_tdb_fetch_locked;
354 result->fetch = db_tdb_fetch;
355 result->traverse = db_tdb_traverse;
356 result->traverse_read = db_tdb_traverse_read;
357 result->parse_record = db_tdb_parse;
358 result->get_seqnum = db_tdb_get_seqnum;
359 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
360 result->transaction_start = db_tdb_transaction_start;
361 result->transaction_commit = db_tdb_transaction_commit;
362 result->transaction_cancel = db_tdb_transaction_cancel;
363 return result;
364
365 fail:
366 if (result != NULL) {
367 TALLOC_FREE(result);
368 }
369 return NULL;
370}
Note: See TracBrowser for help on using the repository browser.