s4/tests: Move command line processing into separate method to be reused
[Samba.git] / source3 / lib / dbwrap_util.c
blob8ebc4f474f618db67d684cda8445a060458b5e0a
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 val = -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 NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
421 char *key_upper;
422 NTSTATUS status;
424 key_upper = talloc_strdup_upper(talloc_tos(), key);
425 if (key_upper == NULL) {
426 return NT_STATUS_NO_MEMORY;
429 status = dbwrap_delete_bystring(db, key_upper);
431 talloc_free(key_upper);
432 return status;
435 NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
436 TDB_DATA data, int flags)
438 char *key_upper;
439 NTSTATUS status;
441 key_upper = talloc_strdup_upper(talloc_tos(), key);
442 if (key_upper == NULL) {
443 return NT_STATUS_NO_MEMORY;
446 status = dbwrap_store_bystring(db, key_upper, data, flags);
448 talloc_free(key_upper);
449 return status;
452 TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
453 const char *key)
455 char *key_upper;
456 TDB_DATA result;
458 key_upper = talloc_strdup_upper(talloc_tos(), key);
459 if (key_upper == NULL) {
460 return make_tdb_data(NULL, 0);
463 result = dbwrap_fetch_bystring(db, mem_ctx, key_upper);
465 talloc_free(key_upper);
466 return result;