s3-pdb_ipa: Add ipasam_create_dom_group()
[Samba/vl.git] / source3 / lib / dbwrap_util.c
blob35f8a14d0d487e7429271b025a987a5040029b3b
1 /*
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.
22 #include "includes.h"
23 #include "dbwrap.h"
25 int32_t dbwrap_fetch_int32(struct db_context *db, const char *keystr)
27 TDB_DATA dbuf;
28 int32 ret;
30 if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) {
31 return -1;
34 if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(int32_t))) {
35 TALLOC_FREE(dbuf.dptr);
36 return -1;
39 ret = IVAL(dbuf.dptr, 0);
40 TALLOC_FREE(dbuf.dptr);
41 return ret;
44 int dbwrap_store_int32(struct db_context *db, const char *keystr, int32_t v)
46 struct db_record *rec;
47 int32 v_store;
48 NTSTATUS status;
50 rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr));
51 if (rec == NULL) {
52 return -1;
55 SIVAL(&v_store, 0, v);
57 status = rec->store(rec, make_tdb_data((const uint8 *)&v_store,
58 sizeof(v_store)),
59 TDB_REPLACE);
60 TALLOC_FREE(rec);
61 return NT_STATUS_IS_OK(status) ? 0 : -1;
64 bool dbwrap_fetch_uint32(struct db_context *db, const char *keystr,
65 uint32_t *val)
67 TDB_DATA dbuf;
69 if (db->fetch(db, NULL, string_term_tdb_data(keystr), &dbuf) != 0) {
70 return false;
73 if ((dbuf.dptr == NULL) || (dbuf.dsize != sizeof(uint32_t))) {
74 TALLOC_FREE(dbuf.dptr);
75 return false;
78 *val = IVAL(dbuf.dptr, 0);
79 TALLOC_FREE(dbuf.dptr);
80 return true;
83 int dbwrap_store_uint32(struct db_context *db, const char *keystr, uint32_t v)
85 struct db_record *rec;
86 uint32 v_store;
87 NTSTATUS status;
89 rec = db->fetch_locked(db, NULL, string_term_tdb_data(keystr));
90 if (rec == NULL) {
91 return -1;
94 SIVAL(&v_store, 0, v);
96 status = rec->store(rec, make_tdb_data((const uint8 *)&v_store,
97 sizeof(v_store)),
98 TDB_REPLACE);
99 TALLOC_FREE(rec);
100 return NT_STATUS_IS_OK(status) ? 0 : -1;
104 * Atomic unsigned integer change (addition):
106 * if value does not exist yet in the db, use *oldval as initial old value.
107 * return old value in *oldval.
108 * store *oldval + change_val to db.
111 struct dbwrap_change_uint32_atomic_context {
112 const char *keystr;
113 uint32_t *oldval;
114 uint32_t change_val;
117 static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
118 void *private_data)
120 struct db_record *rec;
121 uint32_t val = (uint32_t)-1;
122 uint32_t v_store;
123 NTSTATUS ret;
124 struct dbwrap_change_uint32_atomic_context *state;
126 state = (struct dbwrap_change_uint32_atomic_context *)private_data;
128 rec = db->fetch_locked(db, NULL, string_term_tdb_data(state->keystr));
129 if (!rec) {
130 return NT_STATUS_UNSUCCESSFUL;
133 if (rec->value.dptr == NULL) {
134 val = *(state->oldval);
135 } else if (rec->value.dsize == sizeof(val)) {
136 val = IVAL(rec->value.dptr, 0);
137 *(state->oldval) = val;
138 } else {
139 ret = NT_STATUS_UNSUCCESSFUL;
140 goto done;
143 val += state->change_val;
145 SIVAL(&v_store, 0, val);
147 ret = rec->store(rec,
148 make_tdb_data((const uint8 *)&v_store,
149 sizeof(v_store)),
150 TDB_REPLACE);
152 done:
153 TALLOC_FREE(rec);
154 return ret;
157 NTSTATUS dbwrap_change_uint32_atomic(struct db_context *db, const char *keystr,
158 uint32_t *oldval, uint32_t change_val)
160 NTSTATUS ret;
161 struct dbwrap_change_uint32_atomic_context state;
163 state.keystr = keystr;
164 state.oldval = oldval;
165 state.change_val = change_val;
167 ret = dbwrap_change_uint32_atomic_action(db, &state);
169 return ret;
172 NTSTATUS dbwrap_trans_change_uint32_atomic(struct db_context *db,
173 const char *keystr,
174 uint32_t *oldval,
175 uint32_t change_val)
177 NTSTATUS ret;
178 struct dbwrap_change_uint32_atomic_context state;
180 state.keystr = keystr;
181 state.oldval = oldval;
182 state.change_val = change_val;
184 ret = dbwrap_trans_do(db, dbwrap_change_uint32_atomic_action, &state);
186 return ret;
190 * Atomic integer change (addition):
192 * if value does not exist yet in the db, use *oldval as initial old value.
193 * return old value in *oldval.
194 * store *oldval + change_val to db.
197 struct dbwrap_change_int32_atomic_context {
198 const char *keystr;
199 int32_t *oldval;
200 int32_t change_val;
203 static NTSTATUS dbwrap_change_int32_atomic_action(struct db_context *db,
204 void *private_data)
206 struct db_record *rec;
207 int32_t val = -1;
208 int32_t v_store;
209 NTSTATUS ret;
210 struct dbwrap_change_int32_atomic_context *state;
212 state = (struct dbwrap_change_int32_atomic_context *)private_data;
214 rec = db->fetch_locked(db, NULL, string_term_tdb_data(state->keystr));
215 if (!rec) {
216 return NT_STATUS_UNSUCCESSFUL;
219 if (rec->value.dptr == NULL) {
220 val = *(state->oldval);
221 } else if (rec->value.dsize == sizeof(val)) {
222 val = IVAL(rec->value.dptr, 0);
223 *(state->oldval) = val;
224 } else {
225 ret = NT_STATUS_UNSUCCESSFUL;
226 goto done;
229 val += state->change_val;
231 SIVAL(&v_store, 0, val);
233 ret = rec->store(rec,
234 make_tdb_data((const uint8_t *)&v_store,
235 sizeof(v_store)),
236 TDB_REPLACE);
238 done:
239 TALLOC_FREE(rec);
240 return ret;
243 NTSTATUS dbwrap_change_int32_atomic(struct db_context *db, const char *keystr,
244 int32_t *oldval, int32_t change_val)
246 NTSTATUS ret;
247 struct dbwrap_change_int32_atomic_context state;
249 state.keystr = keystr;
250 state.oldval = oldval;
251 state.change_val = change_val;
253 ret = dbwrap_change_int32_atomic_action(db, &state);
255 return ret;
258 NTSTATUS dbwrap_trans_change_int32_atomic(struct db_context *db,
259 const char *keystr,
260 int32_t *oldval,
261 int32_t change_val)
263 NTSTATUS ret;
264 struct dbwrap_change_int32_atomic_context state;
266 state.keystr = keystr;
267 state.oldval = oldval;
268 state.change_val = change_val;
270 ret = dbwrap_trans_do(db, dbwrap_change_int32_atomic_action, &state);
272 return ret;
275 struct dbwrap_store_context {
276 TDB_DATA *key;
277 TDB_DATA *dbuf;
278 int flag;
281 static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
283 struct db_record *rec = NULL;
284 NTSTATUS status;
285 struct dbwrap_store_context *store_ctx;
287 store_ctx = (struct dbwrap_store_context *)private_data;
289 rec = db->fetch_locked(db, talloc_tos(), *(store_ctx->key));
290 if (rec == NULL) {
291 DEBUG(5, ("fetch_locked failed\n"));
292 return NT_STATUS_NO_MEMORY;
295 status = rec->store(rec, *(store_ctx->dbuf), store_ctx->flag);
296 if (!NT_STATUS_IS_OK(status)) {
297 DEBUG(5, ("store returned %s\n", nt_errstr(status)));
300 TALLOC_FREE(rec);
301 return status;
304 NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
305 int flag)
307 NTSTATUS status;
308 struct dbwrap_store_context store_ctx;
310 store_ctx.key = &key;
311 store_ctx.dbuf = &dbuf;
312 store_ctx.flag = flag;
314 status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
316 return status;
319 static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
321 NTSTATUS status;
322 struct db_record *rec;
323 TDB_DATA *key = (TDB_DATA *)private_data;
325 rec = db->fetch_locked(db, talloc_tos(), *key);
326 if (rec == NULL) {
327 DEBUG(5, ("fetch_locked failed\n"));
328 return NT_STATUS_NO_MEMORY;
331 status = rec->delete_rec(rec);
332 if (!NT_STATUS_IS_OK(status)) {
333 DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status)));
336 talloc_free(rec);
337 return status;
340 NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
342 NTSTATUS status;
344 status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
346 return status;
349 NTSTATUS dbwrap_trans_store_int32(struct db_context *db, const char *keystr,
350 int32_t v)
352 int32 v_store;
354 SIVAL(&v_store, 0, v);
356 return dbwrap_trans_store(db, string_term_tdb_data(keystr),
357 make_tdb_data((const uint8 *)&v_store,
358 sizeof(v_store)),
359 TDB_REPLACE);
362 NTSTATUS dbwrap_trans_store_uint32(struct db_context *db, const char *keystr,
363 uint32_t v)
365 uint32 v_store;
367 SIVAL(&v_store, 0, v);
369 return dbwrap_trans_store(db, string_term_tdb_data(keystr),
370 make_tdb_data((const uint8 *)&v_store,
371 sizeof(v_store)),
372 TDB_REPLACE);
375 NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
376 TDB_DATA data, int flags)
378 return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
381 NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
383 return dbwrap_trans_delete(db, string_term_tdb_data(key));
387 * Wrap db action(s) into a transaction.
389 NTSTATUS dbwrap_trans_do(struct db_context *db,
390 NTSTATUS (*action)(struct db_context *, void *),
391 void *private_data)
393 int res;
394 NTSTATUS status;
396 res = db->transaction_start(db);
397 if (res != 0) {
398 DEBUG(5, ("transaction_start failed\n"));
399 return NT_STATUS_INTERNAL_DB_CORRUPTION;
402 status = action(db, private_data);
403 if (!NT_STATUS_IS_OK(status)) {
404 if (db->transaction_cancel(db) != 0) {
405 smb_panic("Cancelling transaction failed");
407 return status;
410 res = db->transaction_commit(db);
411 if (res == 0) {
412 return NT_STATUS_OK;
415 DEBUG(2, ("transaction_commit failed\n"));
416 return NT_STATUS_INTERNAL_DB_CORRUPTION;
419 struct dbwrap_trans_traverse_action_ctx {
420 int (*f)(struct db_record* rec, void* private_data);
421 void* private_data;
425 static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
427 struct dbwrap_trans_traverse_action_ctx* ctx =
428 (struct dbwrap_trans_traverse_action_ctx*)private_data;
430 int ret = db->traverse(db, ctx->f, ctx->private_data);
432 return (ret == -1) ? NT_STATUS_INTERNAL_DB_CORRUPTION : NT_STATUS_OK;
435 NTSTATUS dbwrap_trans_traverse(struct db_context *db,
436 int (*f)(struct db_record*, void*),
437 void *private_data)
439 struct dbwrap_trans_traverse_action_ctx ctx = {
440 .f = f,
441 .private_data = private_data,
443 return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
446 NTSTATUS dbwrap_traverse(struct db_context *db,
447 int (*f)(struct db_record*, void*),
448 void *private_data)
450 int ret = db->traverse(db, f, private_data);
451 return (ret == -1) ? NT_STATUS_INTERNAL_DB_CORRUPTION : NT_STATUS_OK;
457 NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
459 char *key_upper;
460 NTSTATUS status;
462 key_upper = talloc_strdup_upper(talloc_tos(), key);
463 if (key_upper == NULL) {
464 return NT_STATUS_NO_MEMORY;
467 status = dbwrap_delete_bystring(db, key_upper);
469 talloc_free(key_upper);
470 return status;
473 NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
474 TDB_DATA data, int flags)
476 char *key_upper;
477 NTSTATUS status;
479 key_upper = talloc_strdup_upper(talloc_tos(), key);
480 if (key_upper == NULL) {
481 return NT_STATUS_NO_MEMORY;
484 status = dbwrap_store_bystring(db, key_upper, data, flags);
486 talloc_free(key_upper);
487 return status;
490 TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
491 const char *key)
493 char *key_upper;
494 TDB_DATA result;
496 key_upper = talloc_strdup_upper(talloc_tos(), key);
497 if (key_upper == NULL) {
498 return make_tdb_data(NULL, 0);
501 result = dbwrap_fetch_bystring(db, mem_ctx, key_upper);
503 talloc_free(key_upper);
504 return result;