2 Unix SMB/CIFS implementation.
3 Utility functions for the dbwrap API
4 Copyright (C) Volker Lendecke 2007
5 Copyright (C) Michael Adam 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 int32_t dbwrap_fetch_int32(struct db_context *db, const char *keystr)
31 if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) {
35 if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(int32_t))) {
36 TALLOC_FREE(dbuf.dptr);
40 ret = IVAL(dbuf.dptr, 0);
41 TALLOC_FREE(dbuf.dptr);
45 int dbwrap_store_int32(struct db_context *db, const char *keystr, int32_t v)
47 struct db_record *rec;
51 rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr));
56 SIVAL(&v_store, 0, v);
58 status = rec->store(rec, make_tdb_data((const uint8 *)&v_store,
62 return NT_STATUS_IS_OK(status) ? 0 : -1;
65 bool dbwrap_fetch_uint32(struct db_context *db, const char *keystr,
70 if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) {
74 if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(uint32_t))) {
75 TALLOC_FREE(dbuf.dptr);
79 *val = IVAL(dbuf.dptr, 0);
80 TALLOC_FREE(dbuf.dptr);
84 int dbwrap_store_uint32(struct db_context *db, const char *keystr, uint32_t v)
86 struct db_record *rec;
90 rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr));
95 SIVAL(&v_store, 0, v);
97 status = rec->store(rec, make_tdb_data((const uint8 *)&v_store,
101 return NT_STATUS_IS_OK(status) ? 0 : -1;
105 * Atomic unsigned integer change (addition):
107 * if value does not exist yet in the db, use *oldval as initial old value.
108 * return old value in *oldval.
109 * store *oldval + change_val to db.
112 struct dbwrap_change_uint32_atomic_context {
118 static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
121 struct db_record *rec;
122 uint32_t val = (uint32_t)-1;
125 struct dbwrap_change_uint32_atomic_context *state;
127 state = (struct dbwrap_change_uint32_atomic_context *)private_data;
129 rec = db->fetch_locked(db, NULL, string_term_tdb_data(state->keystr));
131 return NT_STATUS_UNSUCCESSFUL;
134 if (rec->value.dptr == NULL) {
135 val = *(state->oldval);
136 } else if (rec->value.dsize == sizeof(val)) {
137 val = IVAL(rec->value.dptr, 0);
138 *(state->oldval) = val;
140 ret = NT_STATUS_UNSUCCESSFUL;
144 val += state->change_val;
146 SIVAL(&v_store, 0, val);
148 ret = rec->store(rec,
149 make_tdb_data((const uint8 *)&v_store,
158 NTSTATUS dbwrap_change_uint32_atomic(struct db_context *db, const char *keystr,
159 uint32_t *oldval, uint32_t change_val)
162 struct dbwrap_change_uint32_atomic_context state;
164 state.keystr = keystr;
165 state.oldval = oldval;
166 state.change_val = change_val;
168 ret = dbwrap_change_uint32_atomic_action(db, &state);
173 NTSTATUS dbwrap_trans_change_uint32_atomic(struct db_context *db,
179 struct dbwrap_change_uint32_atomic_context state;
181 state.keystr = keystr;
182 state.oldval = oldval;
183 state.change_val = change_val;
185 ret = dbwrap_trans_do(db, dbwrap_change_uint32_atomic_action, &state);
191 * Atomic integer change (addition):
193 * if value does not exist yet in the db, use *oldval as initial old value.
194 * return old value in *oldval.
195 * store *oldval + change_val to db.
198 struct dbwrap_change_int32_atomic_context {
204 static NTSTATUS dbwrap_change_int32_atomic_action(struct db_context *db,
207 struct db_record *rec;
211 struct dbwrap_change_int32_atomic_context *state;
213 state = (struct dbwrap_change_int32_atomic_context *)private_data;
215 rec = db->fetch_locked(db, NULL, string_term_tdb_data(state->keystr));
217 return NT_STATUS_UNSUCCESSFUL;
220 if (rec->value.dptr == NULL) {
221 val = *(state->oldval);
222 } else if (rec->value.dsize == sizeof(val)) {
223 val = IVAL(rec->value.dptr, 0);
224 *(state->oldval) = val;
226 ret = NT_STATUS_UNSUCCESSFUL;
230 val += state->change_val;
232 SIVAL(&v_store, 0, val);
234 ret = rec->store(rec,
235 make_tdb_data((const uint8_t *)&v_store,
244 NTSTATUS dbwrap_change_int32_atomic(struct db_context *db, const char *keystr,
245 int32_t *oldval, int32_t change_val)
248 struct dbwrap_change_int32_atomic_context state;
250 state.keystr = keystr;
251 state.oldval = oldval;
252 state.change_val = change_val;
254 ret = dbwrap_change_int32_atomic_action(db, &state);
259 NTSTATUS dbwrap_trans_change_int32_atomic(struct db_context *db,
265 struct dbwrap_change_int32_atomic_context state;
267 state.keystr = keystr;
268 state.oldval = oldval;
269 state.change_val = change_val;
271 ret = dbwrap_trans_do(db, dbwrap_change_int32_atomic_action, &state);
276 struct dbwrap_store_context {
282 static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
284 struct db_record *rec = NULL;
286 struct dbwrap_store_context *store_ctx;
288 store_ctx = (struct dbwrap_store_context *)private_data;
290 rec = db->fetch_locked(db, talloc_tos(), *(store_ctx->key));
292 DEBUG(5, ("fetch_locked failed\n"));
293 return NT_STATUS_NO_MEMORY;
296 status = rec->store(rec, *(store_ctx->dbuf), store_ctx->flag);
297 if (!NT_STATUS_IS_OK(status)) {
298 DEBUG(5, ("store returned %s\n", nt_errstr(status)));
305 NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
309 struct dbwrap_store_context store_ctx;
311 store_ctx.key = &key;
312 store_ctx.dbuf = &dbuf;
313 store_ctx.flag = flag;
315 status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
320 static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
323 struct db_record *rec;
324 TDB_DATA *key = (TDB_DATA *)private_data;
326 rec = db->fetch_locked(db, talloc_tos(), *key);
328 DEBUG(5, ("fetch_locked failed\n"));
329 return NT_STATUS_NO_MEMORY;
332 status = rec->delete_rec(rec);
333 if (!NT_STATUS_IS_OK(status)) {
334 DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status)));
341 NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
345 status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
350 NTSTATUS dbwrap_trans_store_int32(struct db_context *db, const char *keystr,
355 SIVAL(&v_store, 0, v);
357 return dbwrap_trans_store(db, string_term_tdb_data(keystr),
358 make_tdb_data((const uint8 *)&v_store,
363 NTSTATUS dbwrap_trans_store_uint32(struct db_context *db, const char *keystr,
368 SIVAL(&v_store, 0, v);
370 return dbwrap_trans_store(db, string_term_tdb_data(keystr),
371 make_tdb_data((const uint8 *)&v_store,
376 NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
377 TDB_DATA data, int flags)
379 return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
382 NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
384 return dbwrap_trans_delete(db, string_term_tdb_data(key));
388 * Wrap db action(s) into a transaction.
390 NTSTATUS dbwrap_trans_do(struct db_context *db,
391 NTSTATUS (*action)(struct db_context *, void *),
397 res = db->transaction_start(db);
399 DEBUG(5, ("transaction_start failed\n"));
400 return NT_STATUS_INTERNAL_DB_CORRUPTION;
403 status = action(db, private_data);
404 if (!NT_STATUS_IS_OK(status)) {
405 if (db->transaction_cancel(db) != 0) {
406 smb_panic("Cancelling transaction failed");
411 res = db->transaction_commit(db);
416 DEBUG(2, ("transaction_commit failed\n"));
417 return NT_STATUS_INTERNAL_DB_CORRUPTION;
420 struct dbwrap_trans_traverse_action_ctx {
421 int (*f)(struct db_record* rec, void* private_data);
426 static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
428 struct dbwrap_trans_traverse_action_ctx* ctx =
429 (struct dbwrap_trans_traverse_action_ctx*)private_data;
431 int ret = db->traverse(db, ctx->f, ctx->private_data);
433 return (ret == -1) ? NT_STATUS_INTERNAL_DB_CORRUPTION : NT_STATUS_OK;
436 NTSTATUS dbwrap_trans_traverse(struct db_context *db,
437 int (*f)(struct db_record*, void*),
440 struct dbwrap_trans_traverse_action_ctx ctx = {
442 .private_data = private_data,
444 return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
447 NTSTATUS dbwrap_traverse(struct db_context *db,
448 int (*f)(struct db_record*, void*),
451 int ret = db->traverse(db, f, private_data);
452 return (ret == -1) ? NT_STATUS_INTERNAL_DB_CORRUPTION : NT_STATUS_OK;
458 NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
463 key_upper = talloc_strdup_upper(talloc_tos(), key);
464 if (key_upper == NULL) {
465 return NT_STATUS_NO_MEMORY;
468 status = dbwrap_delete_bystring(db, key_upper);
470 talloc_free(key_upper);
474 NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
475 TDB_DATA data, int flags)
480 key_upper = talloc_strdup_upper(talloc_tos(), key);
481 if (key_upper == NULL) {
482 return NT_STATUS_NO_MEMORY;
485 status = dbwrap_store_bystring(db, key_upper, data, flags);
487 talloc_free(key_upper);
491 TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
497 key_upper = talloc_strdup_upper(talloc_tos(), key);
498 if (key_upper == NULL) {
499 return make_tdb_data(NULL, 0);
502 result = dbwrap_fetch_bystring(db, mem_ctx, key_upper);
504 talloc_free(key_upper);