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

Last change on this file was 133, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0pre3

File size: 9.3 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 NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag)
180{
181 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
182 struct db_tdb_ctx);
183
184 /*
185 * This has a bug: We need to replace rec->value for correct
186 * operation, but right now brlock and locking don't use the value
187 * anymore after it was stored.
188 */
189
190 return (tdb_store(ctx->wtdb->tdb, rec->key, data, flag) == 0) ?
191 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
192}
193
194static NTSTATUS db_tdb_delete(struct db_record *rec)
195{
196 struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
197 struct db_tdb_ctx);
198
199 if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
200 return NT_STATUS_OK;
201 }
202
203 if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
204 return NT_STATUS_NOT_FOUND;
205 }
206
207 return NT_STATUS_UNSUCCESSFUL;
208}
209
210struct db_tdb_traverse_ctx {
211 struct db_context *db;
212 int (*f)(struct db_record *rec, void *private_data);
213 void *private_data;
214};
215
216static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
217 void *private_data)
218{
219 struct db_tdb_traverse_ctx *ctx =
220 (struct db_tdb_traverse_ctx *)private_data;
221 struct db_record rec;
222
223 rec.key = kbuf;
224 rec.value = dbuf;
225 rec.store = db_tdb_store;
226 rec.delete_rec = db_tdb_delete;
227 rec.private_data = ctx->db->private_data;
228
229 return ctx->f(&rec, ctx->private_data);
230}
231
232static int db_tdb_traverse(struct db_context *db,
233 int (*f)(struct db_record *rec, void *private_data),
234 void *private_data)
235{
236 struct db_tdb_ctx *db_ctx =
237 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
238 struct db_tdb_traverse_ctx ctx;
239
240 ctx.db = db;
241 ctx.f = f;
242 ctx.private_data = private_data;
243 return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
244}
245
246static NTSTATUS db_tdb_store_deny(struct db_record *rec, TDB_DATA data, int flag)
247{
248 return NT_STATUS_MEDIA_WRITE_PROTECTED;
249}
250
251static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
252{
253 return NT_STATUS_MEDIA_WRITE_PROTECTED;
254}
255
256static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
257 void *private_data)
258{
259 struct db_tdb_traverse_ctx *ctx =
260 (struct db_tdb_traverse_ctx *)private_data;
261 struct db_record rec;
262
263 rec.key = kbuf;
264 rec.value = dbuf;
265 rec.store = db_tdb_store_deny;
266 rec.delete_rec = db_tdb_delete_deny;
267 rec.private_data = ctx->db->private_data;
268
269 return ctx->f(&rec, ctx->private_data);
270}
271
272static int db_tdb_traverse_read(struct db_context *db,
273 int (*f)(struct db_record *rec, void *private_data),
274 void *private_data)
275{
276 struct db_tdb_ctx *db_ctx =
277 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
278 struct db_tdb_traverse_ctx ctx;
279
280 ctx.db = db;
281 ctx.f = f;
282 ctx.private_data = private_data;
283 return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
284}
285
286static int db_tdb_get_seqnum(struct db_context *db)
287
288{
289 struct db_tdb_ctx *db_ctx =
290 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
291 return tdb_get_seqnum(db_ctx->wtdb->tdb);
292}
293
294static int db_tdb_transaction_start(struct db_context *db)
295{
296 struct db_tdb_ctx *db_ctx =
297 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
298 return tdb_transaction_start(db_ctx->wtdb->tdb);
299}
300
301static int db_tdb_transaction_commit(struct db_context *db)
302{
303 struct db_tdb_ctx *db_ctx =
304 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
305 return tdb_transaction_commit(db_ctx->wtdb->tdb);
306}
307
308static int db_tdb_transaction_cancel(struct db_context *db)
309{
310 struct db_tdb_ctx *db_ctx =
311 talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
312 return tdb_transaction_cancel(db_ctx->wtdb->tdb);
313}
314
315struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
316 const char *name,
317 int hash_size, int tdb_flags,
318 int open_flags, mode_t mode)
319{
320 struct db_context *result = NULL;
321 struct db_tdb_ctx *db_tdb;
322
323 result = TALLOC_ZERO_P(mem_ctx, struct db_context);
324 if (result == NULL) {
325 DEBUG(0, ("talloc failed\n"));
326 goto fail;
327 }
328
329 result->private_data = db_tdb = TALLOC_P(result, struct db_tdb_ctx);
330 if (db_tdb == NULL) {
331 DEBUG(0, ("talloc failed\n"));
332 goto fail;
333 }
334
335 db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
336 open_flags, mode);
337 if (db_tdb->wtdb == NULL) {
338 DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
339 goto fail;
340 }
341
342 result->fetch_locked = db_tdb_fetch_locked;
343 result->fetch = db_tdb_fetch;
344 result->traverse = db_tdb_traverse;
345 result->traverse_read = db_tdb_traverse_read;
346 result->get_seqnum = db_tdb_get_seqnum;
347 result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
348 result->transaction_start = db_tdb_transaction_start;
349 result->transaction_commit = db_tdb_transaction_commit;
350 result->transaction_cancel = db_tdb_transaction_cancel;
351 return result;
352
353 fail:
354 if (result != NULL) {
355 TALLOC_FREE(result);
356 }
357 return NULL;
358}
Note: See TracBrowser for help on using the repository browser.