Line data Source code
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 "replace.h"
21 : #include "dbwrap/dbwrap.h"
22 : #include "dbwrap/dbwrap_private.h"
23 : #include "dbwrap/dbwrap_tdb.h"
24 : #include "lib/tdb_wrap/tdb_wrap.h"
25 : #include "lib/util/util_tdb.h"
26 : #include "lib/util/debug.h"
27 : #include "lib/util/samba_util.h"
28 : #include "system/filesys.h"
29 : #include "lib/param/param.h"
30 : #include "libcli/util/error.h"
31 :
32 : struct db_tdb_ctx {
33 : struct tdb_wrap *wtdb;
34 :
35 : struct {
36 : dev_t dev;
37 : ino_t ino;
38 : } id;
39 : };
40 :
41 : static NTSTATUS db_tdb_storev(struct db_record *rec,
42 : const TDB_DATA *dbufs, int num_dbufs, int flag);
43 : static NTSTATUS db_tdb_delete(struct db_record *rec);
44 :
45 4972389 : static void db_tdb_log_key(const char *prefix, TDB_DATA key)
46 : {
47 4972389 : if (DEBUGLEVEL < 10) {
48 4947030 : return;
49 : }
50 0 : if (DEBUGLEVEL == 10) {
51 : /*
52 : * Only fully spam at debuglevel > 10
53 : */
54 0 : key.dsize = MIN(10, key.dsize);
55 : }
56 :
57 0 : if (key.dsize < 1024) {
58 0 : char keystr[key.dsize*2+1];
59 0 : hex_encode_buf(keystr, key.dptr, key.dsize);
60 0 : DBG_DEBUG("%s key %s\n", prefix, keystr);
61 0 : return;
62 : }
63 :
64 0 : dump_data(DEBUGLEVEL, key.dptr, key.dsize);
65 : }
66 :
67 2486194 : static int db_tdb_record_destr(struct db_record* data)
68 : {
69 12679 : struct db_tdb_ctx *ctx =
70 2486194 : talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
71 :
72 2486194 : db_tdb_log_key("Unlocking", data->key);
73 2486194 : tdb_chainunlock(ctx->wtdb->tdb, data->key);
74 2486194 : return 0;
75 : }
76 :
77 : struct tdb_fetch_locked_state {
78 : TALLOC_CTX *mem_ctx;
79 : struct db_record *result;
80 : };
81 :
82 2486195 : static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
83 : void *private_data)
84 : {
85 2486195 : struct tdb_fetch_locked_state *state =
86 : (struct tdb_fetch_locked_state *)private_data;
87 12680 : struct db_record *result;
88 :
89 2486195 : result = (struct db_record *)talloc_size(
90 : state->mem_ctx,
91 : sizeof(struct db_record) + key.dsize + data.dsize);
92 :
93 2486195 : if (result == NULL) {
94 0 : return 0;
95 : }
96 2486195 : state->result = result;
97 :
98 2486195 : result->key.dsize = key.dsize;
99 2486195 : result->key.dptr = ((uint8_t *)result) + sizeof(struct db_record);
100 2486195 : memcpy(result->key.dptr, key.dptr, key.dsize);
101 :
102 2486195 : result->value.dsize = data.dsize;
103 :
104 2486195 : if (data.dsize > 0) {
105 1398485 : result->value.dptr = result->key.dptr+key.dsize;
106 1398485 : memcpy(result->value.dptr, data.dptr, data.dsize);
107 : }
108 : else {
109 1087710 : result->value.dptr = NULL;
110 : }
111 2486195 : result->value_valid = true;
112 :
113 2486195 : return 0;
114 : }
115 :
116 2486195 : static struct db_record *db_tdb_fetch_locked_internal(
117 : struct db_context *db,
118 : struct db_tdb_ctx *ctx,
119 : TALLOC_CTX *mem_ctx,
120 : TDB_DATA key)
121 : {
122 12680 : struct tdb_fetch_locked_state state;
123 12680 : int ret;
124 :
125 2486195 : state = (struct tdb_fetch_locked_state) {
126 : .mem_ctx = mem_ctx,
127 : };
128 :
129 2486195 : ret = tdb_parse_record(ctx->wtdb->tdb,
130 : key,
131 : db_tdb_fetchlock_parse,
132 : &state);
133 2486195 : if ((ret < 0) && (tdb_error(ctx->wtdb->tdb) != TDB_ERR_NOEXIST)) {
134 0 : tdb_chainunlock(ctx->wtdb->tdb, key);
135 0 : return NULL;
136 : }
137 :
138 2486195 : if (state.result == NULL) {
139 1087710 : db_tdb_fetchlock_parse(key, tdb_null, &state);
140 : }
141 :
142 2486195 : if (state.result == NULL) {
143 0 : tdb_chainunlock(ctx->wtdb->tdb, key);
144 0 : return NULL;
145 : }
146 :
147 2486195 : talloc_set_destructor(state.result, db_tdb_record_destr);
148 :
149 2486195 : state.result->private_data = ctx;
150 2486195 : state.result->storev = db_tdb_storev;
151 2486195 : state.result->delete_rec = db_tdb_delete;
152 :
153 2486195 : DBG_DEBUG("Allocated locked data %p\n", state.result);
154 :
155 2486195 : return state.result;
156 : }
157 :
158 2486195 : static struct db_record *db_tdb_fetch_locked(
159 : struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
160 : {
161 2486195 : struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
162 : struct db_tdb_ctx);
163 :
164 2486195 : db_tdb_log_key("Locking", key);
165 2486195 : if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
166 0 : DEBUG(3, ("tdb_chainlock failed\n"));
167 0 : return NULL;
168 : }
169 2486195 : return db_tdb_fetch_locked_internal(db, ctx, mem_ctx, key);
170 : }
171 :
172 2874214 : static NTSTATUS db_tdb_do_locked(struct db_context *db, TDB_DATA key,
173 : void (*fn)(struct db_record *rec,
174 : TDB_DATA value,
175 : void *private_data),
176 : void *private_data)
177 : {
178 2874214 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
179 : db->private_data, struct db_tdb_ctx);
180 2874214 : uint8_t *buf = NULL;
181 13279 : struct db_record rec;
182 13279 : int ret;
183 :
184 2874214 : ret = tdb_chainlock(ctx->wtdb->tdb, key);
185 2874214 : if (ret == -1) {
186 0 : enum TDB_ERROR err = tdb_error(ctx->wtdb->tdb);
187 0 : DBG_DEBUG("tdb_chainlock failed: %s\n",
188 : tdb_errorstr(ctx->wtdb->tdb));
189 0 : return map_nt_error_from_tdb(err);
190 : }
191 :
192 2874214 : ret = tdb_fetch_talloc(ctx->wtdb->tdb, key, ctx, &buf);
193 :
194 2874214 : if ((ret != 0) && (ret != ENOENT)) {
195 0 : DBG_DEBUG("tdb_fetch_talloc failed: %s\n",
196 : strerror(errno));
197 0 : tdb_chainunlock(ctx->wtdb->tdb, key);
198 0 : return map_nt_error_from_unix_common(ret);
199 : }
200 :
201 2874214 : rec = (struct db_record) {
202 : .db = db, .key = key,
203 : .value_valid = false,
204 : .storev = db_tdb_storev, .delete_rec = db_tdb_delete,
205 : .private_data = ctx
206 : };
207 :
208 2887493 : fn(&rec,
209 2874214 : (TDB_DATA) { .dptr = buf, .dsize = talloc_get_size(buf) },
210 : private_data);
211 :
212 2874214 : tdb_chainunlock(ctx->wtdb->tdb, key);
213 :
214 2874214 : talloc_free(buf);
215 :
216 2874214 : return NT_STATUS_OK;
217 : }
218 :
219 54661 : static int db_tdb_exists(struct db_context *db, TDB_DATA key)
220 : {
221 54661 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
222 : db->private_data, struct db_tdb_ctx);
223 54661 : return tdb_exists(ctx->wtdb->tdb, key);
224 : }
225 :
226 45 : static int db_tdb_wipe(struct db_context *db)
227 : {
228 45 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
229 : db->private_data, struct db_tdb_ctx);
230 45 : return tdb_wipe_all(ctx->wtdb->tdb);
231 : }
232 :
233 0 : static int db_tdb_check(struct db_context *db)
234 : {
235 0 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
236 : db->private_data, struct db_tdb_ctx);
237 0 : return tdb_check(ctx->wtdb->tdb, NULL, NULL);
238 : }
239 :
240 : struct db_tdb_parse_state {
241 : void (*parser)(TDB_DATA key, TDB_DATA data,
242 : void *private_data);
243 : void *private_data;
244 : };
245 :
246 : /*
247 : * tdb_parse_record expects a parser returning int, mixing up tdb and
248 : * parser errors. Wrap around that by always returning 0 and have
249 : * dbwrap_parse_record expect a parser returning void.
250 : */
251 :
252 22412660 : static int db_tdb_parser(TDB_DATA key, TDB_DATA data, void *private_data)
253 : {
254 22412660 : struct db_tdb_parse_state *state =
255 : (struct db_tdb_parse_state *)private_data;
256 22412660 : state->parser(key, data, state->private_data);
257 22412660 : return 0;
258 : }
259 :
260 31612253 : static NTSTATUS db_tdb_parse(struct db_context *db, TDB_DATA key,
261 : void (*parser)(TDB_DATA key, TDB_DATA data,
262 : void *private_data),
263 : void *private_data)
264 : {
265 31612253 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
266 : db->private_data, struct db_tdb_ctx);
267 108842 : struct db_tdb_parse_state state;
268 108842 : int ret;
269 :
270 31612253 : state.parser = parser;
271 31612253 : state.private_data = private_data;
272 :
273 31612253 : ret = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_parser, &state);
274 :
275 31612253 : if (ret != 0) {
276 9199593 : return map_nt_error_from_tdb(tdb_error(ctx->wtdb->tdb));
277 : }
278 22412660 : return NT_STATUS_OK;
279 : }
280 :
281 3129384 : static NTSTATUS db_tdb_storev(struct db_record *rec,
282 : const TDB_DATA *dbufs, int num_dbufs, int flag)
283 : {
284 3129384 : struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
285 : struct db_tdb_ctx);
286 3129384 : struct tdb_context *tdb = ctx->wtdb->tdb;
287 3129384 : NTSTATUS status = NT_STATUS_OK;
288 15806 : int ret;
289 :
290 : /*
291 : * This has a bug: We need to replace rec->value for correct
292 : * operation, but right now brlock and locking don't use the value
293 : * anymore after it was stored.
294 : */
295 :
296 3129384 : ret = tdb_storev(tdb, rec->key, dbufs, num_dbufs, flag);
297 3129384 : if (ret == -1) {
298 0 : enum TDB_ERROR err = tdb_error(tdb);
299 0 : status = map_nt_error_from_tdb(err);
300 : }
301 3129384 : return status;
302 : }
303 :
304 1673633 : static NTSTATUS db_tdb_delete(struct db_record *rec)
305 : {
306 1673633 : struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
307 : struct db_tdb_ctx);
308 :
309 1673633 : if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
310 1456817 : return NT_STATUS_OK;
311 : }
312 :
313 216816 : if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
314 216816 : return NT_STATUS_NOT_FOUND;
315 : }
316 :
317 0 : return NT_STATUS_UNSUCCESSFUL;
318 : }
319 :
320 : struct db_tdb_traverse_ctx {
321 : struct db_context *db;
322 : int (*f)(struct db_record *rec, void *private_data);
323 : void *private_data;
324 : };
325 :
326 730 : static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
327 : void *private_data)
328 : {
329 730 : struct db_tdb_traverse_ctx *ctx =
330 : (struct db_tdb_traverse_ctx *)private_data;
331 35 : struct db_record rec;
332 :
333 730 : rec.key = kbuf;
334 730 : rec.value = dbuf;
335 730 : rec.value_valid = true;
336 730 : rec.storev = db_tdb_storev;
337 730 : rec.delete_rec = db_tdb_delete;
338 730 : rec.private_data = ctx->db->private_data;
339 730 : rec.db = ctx->db;
340 :
341 730 : return ctx->f(&rec, ctx->private_data);
342 : }
343 :
344 342 : static int db_tdb_traverse(struct db_context *db,
345 : int (*f)(struct db_record *rec, void *private_data),
346 : void *private_data)
347 : {
348 14 : struct db_tdb_ctx *db_ctx =
349 342 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
350 14 : struct db_tdb_traverse_ctx ctx;
351 :
352 342 : ctx.db = db;
353 342 : ctx.f = f;
354 342 : ctx.private_data = private_data;
355 342 : return tdb_traverse(db_ctx->wtdb->tdb, db_tdb_traverse_func, &ctx);
356 : }
357 :
358 0 : static NTSTATUS db_tdb_storev_deny(struct db_record *rec,
359 : const TDB_DATA *dbufs, int num_dbufs,
360 : int flag)
361 : {
362 0 : return NT_STATUS_MEDIA_WRITE_PROTECTED;
363 : }
364 :
365 0 : static NTSTATUS db_tdb_delete_deny(struct db_record *rec)
366 : {
367 0 : return NT_STATUS_MEDIA_WRITE_PROTECTED;
368 : }
369 :
370 3458951 : static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
371 : void *private_data)
372 : {
373 3458951 : struct db_tdb_traverse_ctx *ctx =
374 : (struct db_tdb_traverse_ctx *)private_data;
375 681 : struct db_record rec;
376 :
377 3458951 : rec.key = kbuf;
378 3458951 : rec.value = dbuf;
379 3458951 : rec.value_valid = true;
380 3458951 : rec.storev = db_tdb_storev_deny;
381 3458951 : rec.delete_rec = db_tdb_delete_deny;
382 3458951 : rec.private_data = ctx->db->private_data;
383 3458951 : rec.db = ctx->db;
384 :
385 3458951 : return ctx->f(&rec, ctx->private_data);
386 : }
387 :
388 232761 : static int db_tdb_traverse_read(struct db_context *db,
389 : int (*f)(struct db_record *rec, void *private_data),
390 : void *private_data)
391 : {
392 53 : struct db_tdb_ctx *db_ctx =
393 232761 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
394 53 : struct db_tdb_traverse_ctx ctx;
395 :
396 232761 : ctx.db = db;
397 232761 : ctx.f = f;
398 232761 : ctx.private_data = private_data;
399 232761 : return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
400 : }
401 :
402 2477610 : static int db_tdb_get_seqnum(struct db_context *db)
403 :
404 : {
405 1967 : struct db_tdb_ctx *db_ctx =
406 2477610 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
407 2477610 : return tdb_get_seqnum(db_ctx->wtdb->tdb);
408 : }
409 :
410 117045 : static int db_tdb_transaction_start(struct db_context *db)
411 : {
412 625 : struct db_tdb_ctx *db_ctx =
413 117045 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
414 117045 : return tdb_transaction_start(db_ctx->wtdb->tdb) ? -1 : 0;
415 : }
416 :
417 0 : static NTSTATUS db_tdb_transaction_start_nonblock(struct db_context *db)
418 : {
419 0 : struct db_tdb_ctx *db_ctx =
420 0 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
421 0 : int ret;
422 :
423 0 : ret = tdb_transaction_start_nonblock(db_ctx->wtdb->tdb);
424 0 : if (ret != 0) {
425 0 : return map_nt_error_from_tdb(tdb_error(db_ctx->wtdb->tdb));
426 : }
427 0 : return NT_STATUS_OK;
428 : }
429 :
430 116817 : static int db_tdb_transaction_commit(struct db_context *db)
431 : {
432 618 : struct db_tdb_ctx *db_ctx =
433 116817 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
434 116817 : return tdb_transaction_commit(db_ctx->wtdb->tdb) ? -1 : 0;
435 : }
436 :
437 227 : static int db_tdb_transaction_cancel(struct db_context *db)
438 : {
439 6 : struct db_tdb_ctx *db_ctx =
440 227 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
441 227 : tdb_transaction_cancel(db_ctx->wtdb->tdb);
442 227 : return 0;
443 : }
444 :
445 0 : static size_t db_tdb_id(struct db_context *db, uint8_t *id, size_t idlen)
446 : {
447 0 : struct db_tdb_ctx *db_ctx =
448 0 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
449 :
450 0 : if (idlen >= sizeof(db_ctx->id)) {
451 0 : memcpy(id, &db_ctx->id, sizeof(db_ctx->id));
452 : }
453 :
454 0 : return sizeof(db_ctx->id);
455 : }
456 :
457 309102 : struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
458 : const char *name,
459 : int hash_size, int tdb_flags,
460 : int open_flags, mode_t mode,
461 : enum dbwrap_lock_order lock_order,
462 : uint64_t dbwrap_flags)
463 : {
464 309102 : struct db_context *result = NULL;
465 11988 : struct db_tdb_ctx *db_tdb;
466 11988 : struct stat st;
467 :
468 309102 : result = talloc_zero(mem_ctx, struct db_context);
469 309102 : if (result == NULL) {
470 0 : DEBUG(0, ("talloc failed\n"));
471 0 : goto fail;
472 : }
473 :
474 309102 : result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
475 309102 : if (db_tdb == NULL) {
476 0 : DEBUG(0, ("talloc failed\n"));
477 0 : goto fail;
478 : }
479 309102 : result->lock_order = lock_order;
480 :
481 309102 : db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
482 : open_flags, mode);
483 309102 : if (db_tdb->wtdb == NULL) {
484 829 : DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
485 829 : goto fail;
486 : }
487 :
488 308273 : ZERO_STRUCT(db_tdb->id);
489 :
490 308273 : if (fstat(tdb_fd(db_tdb->wtdb->tdb), &st) == -1) {
491 0 : DEBUG(3, ("fstat failed: %s\n", strerror(errno)));
492 0 : goto fail;
493 : }
494 308273 : db_tdb->id.dev = st.st_dev;
495 308273 : db_tdb->id.ino = st.st_ino;
496 :
497 308273 : result->fetch_locked = db_tdb_fetch_locked;
498 308273 : result->do_locked = db_tdb_do_locked;
499 308273 : result->traverse = db_tdb_traverse;
500 308273 : result->traverse_read = db_tdb_traverse_read;
501 308273 : result->parse_record = db_tdb_parse;
502 308273 : result->get_seqnum = db_tdb_get_seqnum;
503 308273 : result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
504 308273 : result->transaction_start = db_tdb_transaction_start;
505 308273 : result->transaction_start_nonblock = db_tdb_transaction_start_nonblock;
506 308273 : result->transaction_commit = db_tdb_transaction_commit;
507 308273 : result->transaction_cancel = db_tdb_transaction_cancel;
508 308273 : result->exists = db_tdb_exists;
509 308273 : result->wipe = db_tdb_wipe;
510 308273 : result->id = db_tdb_id;
511 308273 : result->check = db_tdb_check;
512 308273 : result->name = tdb_name(db_tdb->wtdb->tdb);
513 308273 : return result;
514 :
515 829 : fail:
516 829 : TALLOC_FREE(result);
517 824 : return NULL;
518 : }
|