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