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 4959665 : static void db_tdb_log_key(const char *prefix, TDB_DATA key)
46 : {
47 4959665 : if (DEBUGLEVEL < 10) {
48 4934766 : 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 2479832 : static int db_tdb_record_destr(struct db_record* data)
68 : {
69 12449 : struct db_tdb_ctx *ctx =
70 2479832 : talloc_get_type_abort(data->private_data, struct db_tdb_ctx);
71 :
72 2479832 : db_tdb_log_key("Unlocking", data->key);
73 2479832 : tdb_chainunlock(ctx->wtdb->tdb, data->key);
74 2479832 : return 0;
75 : }
76 :
77 : struct tdb_fetch_locked_state {
78 : TALLOC_CTX *mem_ctx;
79 : struct db_record *result;
80 : };
81 :
82 2479833 : static int db_tdb_fetchlock_parse(TDB_DATA key, TDB_DATA data,
83 : void *private_data)
84 : {
85 2479833 : struct tdb_fetch_locked_state *state =
86 : (struct tdb_fetch_locked_state *)private_data;
87 12450 : struct db_record *result;
88 :
89 2479833 : result = (struct db_record *)talloc_size(
90 : state->mem_ctx,
91 : sizeof(struct db_record) + key.dsize + data.dsize);
92 :
93 2479833 : if (result == NULL) {
94 0 : return 0;
95 : }
96 2479833 : state->result = result;
97 :
98 2479833 : result->key.dsize = key.dsize;
99 2479833 : result->key.dptr = ((uint8_t *)result) + sizeof(struct db_record);
100 2479833 : memcpy(result->key.dptr, key.dptr, key.dsize);
101 :
102 2479833 : result->value.dsize = data.dsize;
103 :
104 2479833 : if (data.dsize > 0) {
105 1394650 : result->value.dptr = result->key.dptr+key.dsize;
106 1394650 : memcpy(result->value.dptr, data.dptr, data.dsize);
107 : }
108 : else {
109 1085183 : result->value.dptr = NULL;
110 : }
111 2479833 : result->value_valid = true;
112 :
113 2479833 : return 0;
114 : }
115 :
116 2479833 : 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 12450 : struct tdb_fetch_locked_state state;
123 12450 : int ret;
124 :
125 2479833 : state = (struct tdb_fetch_locked_state) {
126 : .mem_ctx = mem_ctx,
127 : };
128 :
129 2479833 : ret = tdb_parse_record(ctx->wtdb->tdb,
130 : key,
131 : db_tdb_fetchlock_parse,
132 : &state);
133 2479833 : 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 2479833 : if (state.result == NULL) {
139 1085183 : db_tdb_fetchlock_parse(key, tdb_null, &state);
140 : }
141 :
142 2479833 : if (state.result == NULL) {
143 0 : tdb_chainunlock(ctx->wtdb->tdb, key);
144 0 : return NULL;
145 : }
146 :
147 2479833 : talloc_set_destructor(state.result, db_tdb_record_destr);
148 :
149 2479833 : state.result->private_data = ctx;
150 2479833 : state.result->storev = db_tdb_storev;
151 2479833 : state.result->delete_rec = db_tdb_delete;
152 :
153 2479833 : DBG_DEBUG("Allocated locked data %p\n", state.result);
154 :
155 2479833 : return state.result;
156 : }
157 :
158 2479833 : static struct db_record *db_tdb_fetch_locked(
159 : struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key)
160 : {
161 2479833 : struct db_tdb_ctx *ctx = talloc_get_type_abort(db->private_data,
162 : struct db_tdb_ctx);
163 :
164 2479833 : db_tdb_log_key("Locking", key);
165 2479833 : if (tdb_chainlock(ctx->wtdb->tdb, key) != 0) {
166 0 : DEBUG(3, ("tdb_chainlock failed\n"));
167 0 : return NULL;
168 : }
169 2479833 : return db_tdb_fetch_locked_internal(db, ctx, mem_ctx, key);
170 : }
171 :
172 2879452 : 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 2879452 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
179 : db->private_data, struct db_tdb_ctx);
180 2879452 : uint8_t *buf = NULL;
181 13134 : struct db_record rec;
182 13134 : int ret;
183 :
184 2879452 : ret = tdb_chainlock(ctx->wtdb->tdb, key);
185 2879452 : 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 2879452 : ret = tdb_fetch_talloc(ctx->wtdb->tdb, key, ctx, &buf);
193 :
194 2879452 : 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 2879452 : 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 2892586 : fn(&rec,
209 2879452 : (TDB_DATA) { .dptr = buf, .dsize = talloc_get_size(buf) },
210 : private_data);
211 :
212 2879452 : tdb_chainunlock(ctx->wtdb->tdb, key);
213 :
214 2879452 : talloc_free(buf);
215 :
216 2879452 : return NT_STATUS_OK;
217 : }
218 :
219 55244 : static int db_tdb_exists(struct db_context *db, TDB_DATA key)
220 : {
221 55244 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
222 : db->private_data, struct db_tdb_ctx);
223 55244 : 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 22383865 : static int db_tdb_parser(TDB_DATA key, TDB_DATA data, void *private_data)
253 : {
254 22383865 : struct db_tdb_parse_state *state =
255 : (struct db_tdb_parse_state *)private_data;
256 22383865 : state->parser(key, data, state->private_data);
257 22383865 : return 0;
258 : }
259 :
260 31490784 : 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 31490784 : struct db_tdb_ctx *ctx = talloc_get_type_abort(
266 : db->private_data, struct db_tdb_ctx);
267 108506 : struct db_tdb_parse_state state;
268 108506 : int ret;
269 :
270 31490784 : state.parser = parser;
271 31490784 : state.private_data = private_data;
272 :
273 31490784 : ret = tdb_parse_record(ctx->wtdb->tdb, key, db_tdb_parser, &state);
274 :
275 31490784 : if (ret != 0) {
276 9106919 : return map_nt_error_from_tdb(tdb_error(ctx->wtdb->tdb));
277 : }
278 22383865 : return NT_STATUS_OK;
279 : }
280 :
281 3129349 : static NTSTATUS db_tdb_storev(struct db_record *rec,
282 : const TDB_DATA *dbufs, int num_dbufs, int flag)
283 : {
284 3129349 : struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
285 : struct db_tdb_ctx);
286 3129349 : struct tdb_context *tdb = ctx->wtdb->tdb;
287 3129349 : NTSTATUS status = NT_STATUS_OK;
288 15516 : 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 3129349 : ret = tdb_storev(tdb, rec->key, dbufs, num_dbufs, flag);
297 3129349 : if (ret == -1) {
298 0 : enum TDB_ERROR err = tdb_error(tdb);
299 0 : status = map_nt_error_from_tdb(err);
300 : }
301 3129349 : return status;
302 : }
303 :
304 1671935 : static NTSTATUS db_tdb_delete(struct db_record *rec)
305 : {
306 1671935 : struct db_tdb_ctx *ctx = talloc_get_type_abort(rec->private_data,
307 : struct db_tdb_ctx);
308 :
309 1671935 : if (tdb_delete(ctx->wtdb->tdb, rec->key) == 0) {
310 1454618 : return NT_STATUS_OK;
311 : }
312 :
313 217317 : if (tdb_error(ctx->wtdb->tdb) == TDB_ERR_NOEXIST) {
314 217317 : 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 3449592 : static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
371 : void *private_data)
372 : {
373 3449592 : struct db_tdb_traverse_ctx *ctx =
374 : (struct db_tdb_traverse_ctx *)private_data;
375 681 : struct db_record rec;
376 :
377 3449592 : rec.key = kbuf;
378 3449592 : rec.value = dbuf;
379 3449592 : rec.value_valid = true;
380 3449592 : rec.storev = db_tdb_storev_deny;
381 3449592 : rec.delete_rec = db_tdb_delete_deny;
382 3449592 : rec.private_data = ctx->db->private_data;
383 3449592 : rec.db = ctx->db;
384 :
385 3449592 : return ctx->f(&rec, ctx->private_data);
386 : }
387 :
388 231734 : 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 231734 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
394 53 : struct db_tdb_traverse_ctx ctx;
395 :
396 231734 : ctx.db = db;
397 231734 : ctx.f = f;
398 231734 : ctx.private_data = private_data;
399 231734 : return tdb_traverse_read(db_ctx->wtdb->tdb, db_tdb_traverse_read_func, &ctx);
400 : }
401 :
402 2477033 : static int db_tdb_get_seqnum(struct db_context *db)
403 :
404 : {
405 1967 : struct db_tdb_ctx *db_ctx =
406 2477033 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
407 2477033 : return tdb_get_seqnum(db_ctx->wtdb->tdb);
408 : }
409 :
410 117485 : static int db_tdb_transaction_start(struct db_context *db)
411 : {
412 625 : struct db_tdb_ctx *db_ctx =
413 117485 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
414 117485 : 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 117257 : static int db_tdb_transaction_commit(struct db_context *db)
431 : {
432 618 : struct db_tdb_ctx *db_ctx =
433 117257 : talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
434 117257 : 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 310251 : 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 310251 : struct db_context *result = NULL;
465 11757 : struct db_tdb_ctx *db_tdb;
466 11757 : struct stat st;
467 :
468 310251 : result = talloc_zero(mem_ctx, struct db_context);
469 310251 : if (result == NULL) {
470 0 : DEBUG(0, ("talloc failed\n"));
471 0 : goto fail;
472 : }
473 :
474 310251 : result->private_data = db_tdb = talloc(result, struct db_tdb_ctx);
475 310251 : if (db_tdb == NULL) {
476 0 : DEBUG(0, ("talloc failed\n"));
477 0 : goto fail;
478 : }
479 310251 : result->lock_order = lock_order;
480 :
481 310251 : db_tdb->wtdb = tdb_wrap_open(db_tdb, name, hash_size, tdb_flags,
482 : open_flags, mode);
483 310251 : if (db_tdb->wtdb == NULL) {
484 829 : DEBUG(3, ("Could not open tdb: %s\n", strerror(errno)));
485 829 : goto fail;
486 : }
487 :
488 309422 : ZERO_STRUCT(db_tdb->id);
489 :
490 309422 : 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 309422 : db_tdb->id.dev = st.st_dev;
495 309422 : db_tdb->id.ino = st.st_ino;
496 :
497 309422 : result->fetch_locked = db_tdb_fetch_locked;
498 309422 : result->do_locked = db_tdb_do_locked;
499 309422 : result->traverse = db_tdb_traverse;
500 309422 : result->traverse_read = db_tdb_traverse_read;
501 309422 : result->parse_record = db_tdb_parse;
502 309422 : result->get_seqnum = db_tdb_get_seqnum;
503 309422 : result->persistent = ((tdb_flags & TDB_CLEAR_IF_FIRST) == 0);
504 309422 : result->transaction_start = db_tdb_transaction_start;
505 309422 : result->transaction_start_nonblock = db_tdb_transaction_start_nonblock;
506 309422 : result->transaction_commit = db_tdb_transaction_commit;
507 309422 : result->transaction_cancel = db_tdb_transaction_cancel;
508 309422 : result->exists = db_tdb_exists;
509 309422 : result->wipe = db_tdb_wipe;
510 309422 : result->id = db_tdb_id;
511 309422 : result->check = db_tdb_check;
512 309422 : result->name = tdb_name(db_tdb->wtdb->tdb);
513 309422 : return result;
514 :
515 829 : fail:
516 829 : TALLOC_FREE(result);
517 824 : return NULL;
518 : }
|