2 Unix SMB/CIFS implementation.
3 Utility functions for the dbwrap API
4 Copyright (C) Volker Lendecke 2007
5 Copyright (C) Michael Adam 2009
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
8 Major code contributions from Aleksey Fedoseev (fedoseev@ru.ibm.com)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "lib/util/util_tdb.h"
29 struct dbwrap_fetch_int32_state {
34 static void dbwrap_fetch_int32_parser(TDB_DATA key, TDB_DATA data,
37 struct dbwrap_fetch_int32_state *state =
38 (struct dbwrap_fetch_int32_state *)private_data;
40 if (data.dsize != sizeof(state->result)) {
41 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
44 state->result = IVAL(data.dptr, 0);
45 state->status = NT_STATUS_OK;
48 NTSTATUS dbwrap_fetch_int32(struct db_context *db, TDB_DATA key,
51 struct dbwrap_fetch_int32_state state;
54 return NT_STATUS_INVALID_PARAMETER;
57 dbwrap_parse_record(db, key, dbwrap_fetch_int32_parser, &state);
59 if (NT_STATUS_IS_OK(state.status)) {
60 *result = state.result;
65 NTSTATUS dbwrap_fetch_int32_bystring(struct db_context *db, const char *keystr,
68 return dbwrap_fetch_int32(db, string_term_tdb_data(keystr), result);
71 NTSTATUS dbwrap_store_int32_bystring(struct db_context *db, const char *keystr,
74 struct db_record *rec;
78 rec = dbwrap_fetch_locked(db, talloc_tos(),
79 string_term_tdb_data(keystr));
81 return NT_STATUS_UNSUCCESSFUL;
84 SIVAL(&v_store, 0, v);
86 status = dbwrap_record_store(rec,
87 make_tdb_data((const uint8_t *)&v_store,
94 NTSTATUS dbwrap_fetch_uint32_bystring(struct db_context *db,
95 const char *keystr, uint32_t *val)
101 return NT_STATUS_INVALID_PARAMETER;
104 status = dbwrap_fetch_bystring(db, talloc_tos(), keystr, &dbuf);
105 if (!NT_STATUS_IS_OK(status)) {
109 if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(uint32_t))) {
110 TALLOC_FREE(dbuf.dptr);
111 return NT_STATUS_NOT_FOUND;
114 *val = IVAL(dbuf.dptr, 0);
115 TALLOC_FREE(dbuf.dptr);
119 NTSTATUS dbwrap_store_uint32_bystring(struct db_context *db,
120 const char *keystr, uint32_t v)
122 struct db_record *rec;
126 rec = dbwrap_fetch_locked(db, talloc_tos(),
127 string_term_tdb_data(keystr));
129 return NT_STATUS_INVALID_PARAMETER;
132 SIVAL(&v_store, 0, v);
134 status = dbwrap_record_store(rec,
135 make_tdb_data((const uint8_t *)&v_store,
143 * Atomic unsigned integer change (addition):
145 * if value does not exist yet in the db, use *oldval as initial old value.
146 * return old value in *oldval.
147 * store *oldval + change_val to db.
150 struct dbwrap_change_uint32_atomic_context {
156 static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
159 struct db_record *rec;
160 uint32_t val = (uint32_t)-1;
163 struct dbwrap_change_uint32_atomic_context *state;
166 state = (struct dbwrap_change_uint32_atomic_context *)private_data;
168 rec = dbwrap_fetch_locked(db, talloc_tos(),
169 string_term_tdb_data(state->keystr));
171 return NT_STATUS_UNSUCCESSFUL;
174 value = dbwrap_record_get_value(rec);
176 if (value.dptr == NULL) {
177 val = *(state->oldval);
178 } else if (value.dsize == sizeof(val)) {
179 val = IVAL(value.dptr, 0);
180 *(state->oldval) = val;
182 ret = NT_STATUS_UNSUCCESSFUL;
186 val += state->change_val;
188 SIVAL(&v_store, 0, val);
190 ret = dbwrap_record_store(rec,
191 make_tdb_data((const uint8_t *)&v_store,
200 NTSTATUS dbwrap_change_uint32_atomic_bystring(struct db_context *db,
206 struct dbwrap_change_uint32_atomic_context state;
208 state.keystr = keystr;
209 state.oldval = oldval;
210 state.change_val = change_val;
212 ret = dbwrap_change_uint32_atomic_action(db, &state);
217 NTSTATUS dbwrap_trans_change_uint32_atomic_bystring(struct db_context *db,
223 struct dbwrap_change_uint32_atomic_context state;
225 state.keystr = keystr;
226 state.oldval = oldval;
227 state.change_val = change_val;
229 ret = dbwrap_trans_do(db, dbwrap_change_uint32_atomic_action, &state);
235 * Atomic integer change (addition):
237 * if value does not exist yet in the db, use *oldval as initial old value.
238 * return old value in *oldval.
239 * store *oldval + change_val to db.
242 struct dbwrap_change_int32_atomic_context {
248 static NTSTATUS dbwrap_change_int32_atomic_action(struct db_context *db,
251 struct db_record *rec;
255 struct dbwrap_change_int32_atomic_context *state;
258 state = (struct dbwrap_change_int32_atomic_context *)private_data;
260 rec = dbwrap_fetch_locked(db, talloc_tos(), state->key);
262 return NT_STATUS_UNSUCCESSFUL;
265 value = dbwrap_record_get_value(rec);
267 if (value.dptr == NULL) {
268 val = *(state->oldval);
269 } else if (value.dsize == sizeof(val)) {
270 val = IVAL(value.dptr, 0);
271 *(state->oldval) = val;
273 ret = NT_STATUS_UNSUCCESSFUL;
277 val += state->change_val;
279 SIVAL(&v_store, 0, val);
281 ret = dbwrap_record_store(rec,
282 make_tdb_data((const uint8_t *)&v_store,
291 NTSTATUS dbwrap_change_int32_atomic(struct db_context *db,
297 struct dbwrap_change_int32_atomic_context state;
300 state.oldval = oldval;
301 state.change_val = change_val;
303 ret = dbwrap_change_int32_atomic_action(db, &state);
308 NTSTATUS dbwrap_change_int32_atomic_bystring(struct db_context *db,
313 return dbwrap_change_int32_atomic(db, string_term_tdb_data(keystr),
317 NTSTATUS dbwrap_trans_change_int32_atomic_bystring(struct db_context *db,
323 struct dbwrap_change_int32_atomic_context state;
325 state.key = string_term_tdb_data(keystr);
326 state.oldval = oldval;
327 state.change_val = change_val;
329 ret = dbwrap_trans_do(db, dbwrap_change_int32_atomic_action, &state);
334 struct dbwrap_store_context {
340 static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
342 struct db_record *rec = NULL;
344 struct dbwrap_store_context *store_ctx;
346 store_ctx = (struct dbwrap_store_context *)private_data;
348 rec = dbwrap_fetch_locked(db, talloc_tos(), *(store_ctx->key));
350 DEBUG(5, ("fetch_locked failed\n"));
351 return NT_STATUS_NO_MEMORY;
354 status = dbwrap_record_store(rec, *(store_ctx->dbuf), store_ctx->flag);
355 if (!NT_STATUS_IS_OK(status)) {
356 DEBUG(5, ("store returned %s\n", nt_errstr(status)));
363 NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
367 struct dbwrap_store_context store_ctx;
369 store_ctx.key = &key;
370 store_ctx.dbuf = &dbuf;
371 store_ctx.flag = flag;
373 status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
378 static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
381 struct db_record *rec;
382 TDB_DATA *key = (TDB_DATA *)private_data;
384 rec = dbwrap_fetch_locked(db, talloc_tos(), *key);
386 DEBUG(5, ("fetch_locked failed\n"));
387 return NT_STATUS_NO_MEMORY;
390 status = dbwrap_record_delete(rec);
391 if (!NT_STATUS_IS_OK(status)) {
392 DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status)));
399 NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
403 status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
408 NTSTATUS dbwrap_trans_store_int32_bystring(struct db_context *db,
414 SIVAL(&v_store, 0, v);
416 return dbwrap_trans_store(db, string_term_tdb_data(keystr),
417 make_tdb_data((const uint8_t *)&v_store,
422 NTSTATUS dbwrap_trans_store_uint32_bystring(struct db_context *db,
428 SIVAL(&v_store, 0, v);
430 return dbwrap_trans_store(db, string_term_tdb_data(keystr),
431 make_tdb_data((const uint8_t *)&v_store,
436 NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
437 TDB_DATA data, int flags)
439 return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
442 NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
444 return dbwrap_trans_delete(db, string_term_tdb_data(key));
448 * Wrap db action(s) into a transaction.
450 NTSTATUS dbwrap_trans_do(struct db_context *db,
451 NTSTATUS (*action)(struct db_context *, void *),
457 res = dbwrap_transaction_start(db);
459 DEBUG(5, ("transaction_start failed\n"));
460 return NT_STATUS_INTERNAL_DB_CORRUPTION;
463 status = action(db, private_data);
464 if (!NT_STATUS_IS_OK(status)) {
465 if (dbwrap_transaction_cancel(db) != 0) {
466 smb_panic("Cancelling transaction failed");
471 res = dbwrap_transaction_commit(db);
476 DEBUG(2, ("transaction_commit failed\n"));
477 return NT_STATUS_INTERNAL_DB_CORRUPTION;
480 struct dbwrap_trans_traverse_action_ctx {
481 int (*f)(struct db_record* rec, void* private_data);
486 static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
488 struct dbwrap_trans_traverse_action_ctx* ctx =
489 (struct dbwrap_trans_traverse_action_ctx*)private_data;
491 NTSTATUS status = dbwrap_traverse(db, ctx->f, ctx->private_data, NULL);
496 NTSTATUS dbwrap_trans_traverse(struct db_context *db,
497 int (*f)(struct db_record*, void*),
500 struct dbwrap_trans_traverse_action_ctx ctx = {
502 .private_data = private_data,
504 return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
507 NTSTATUS dbwrap_delete_bystring(struct db_context *db, const char *key)
509 return dbwrap_delete(db, string_term_tdb_data(key));
512 NTSTATUS dbwrap_store_bystring(struct db_context *db, const char *key,
513 TDB_DATA data, int flags)
515 return dbwrap_store(db, string_term_tdb_data(key), data, flags);
518 NTSTATUS dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx,
519 const char *key, TDB_DATA *value)
521 return dbwrap_fetch(db, mem_ctx, string_term_tdb_data(key), value);
526 NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
531 key_upper = talloc_strdup_upper(talloc_tos(), key);
532 if (key_upper == NULL) {
533 return NT_STATUS_NO_MEMORY;
536 status = dbwrap_delete_bystring(db, key_upper);
538 talloc_free(key_upper);
542 NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
543 TDB_DATA data, int flags)
548 key_upper = talloc_strdup_upper(talloc_tos(), key);
549 if (key_upper == NULL) {
550 return NT_STATUS_NO_MEMORY;
553 status = dbwrap_store_bystring(db, key_upper, data, flags);
555 talloc_free(key_upper);
559 NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
560 const char *key, TDB_DATA *value)
565 key_upper = talloc_strdup_upper(talloc_tos(), key);
566 if (key_upper == NULL) {
567 return NT_STATUS_NO_MEMORY;
570 status = dbwrap_fetch_bystring(db, mem_ctx, key_upper, value);
572 talloc_free(key_upper);