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.
25 int32_t dbwrap_fetch_int32(struct db_context
*db
, const char *keystr
)
30 if (db
->fetch(db
, NULL
, string_term_tdb_data(keystr
), &dbuf
) != 0) {
34 if ((dbuf
.dptr
== NULL
) || (dbuf
.dsize
!= sizeof(int32_t))) {
35 TALLOC_FREE(dbuf
.dptr
);
39 ret
= IVAL(dbuf
.dptr
, 0);
40 TALLOC_FREE(dbuf
.dptr
);
44 int dbwrap_store_int32(struct db_context
*db
, const char *keystr
, int32_t v
)
46 struct db_record
*rec
;
50 rec
= db
->fetch_locked(db
, NULL
, string_term_tdb_data(keystr
));
55 SIVAL(&v_store
, 0, v
);
57 status
= rec
->store(rec
, make_tdb_data((const uint8
*)&v_store
,
61 return NT_STATUS_IS_OK(status
) ? 0 : -1;
64 bool dbwrap_fetch_uint32(struct db_context
*db
, const char *keystr
,
69 if (db
->fetch(db
, NULL
, string_term_tdb_data(keystr
), &dbuf
) != 0) {
73 if ((dbuf
.dptr
== NULL
) || (dbuf
.dsize
!= sizeof(uint32_t))) {
74 TALLOC_FREE(dbuf
.dptr
);
78 *val
= IVAL(dbuf
.dptr
, 0);
79 TALLOC_FREE(dbuf
.dptr
);
83 int dbwrap_store_uint32(struct db_context
*db
, const char *keystr
, uint32_t v
)
85 struct db_record
*rec
;
89 rec
= db
->fetch_locked(db
, NULL
, string_term_tdb_data(keystr
));
94 SIVAL(&v_store
, 0, v
);
96 status
= rec
->store(rec
, make_tdb_data((const uint8
*)&v_store
,
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
{
117 static NTSTATUS
dbwrap_change_uint32_atomic_action(struct db_context
*db
,
120 struct db_record
*rec
;
121 uint32_t val
= (uint32_t)-1;
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
));
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
;
139 ret
= NT_STATUS_UNSUCCESSFUL
;
143 val
+= state
->change_val
;
145 SIVAL(&v_store
, 0, val
);
147 ret
= rec
->store(rec
,
148 make_tdb_data((const uint8
*)&v_store
,
157 NTSTATUS
dbwrap_change_uint32_atomic(struct db_context
*db
, const char *keystr
,
158 uint32_t *oldval
, uint32_t change_val
)
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
);
172 NTSTATUS
dbwrap_trans_change_uint32_atomic(struct db_context
*db
,
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
);
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
{
203 static NTSTATUS
dbwrap_change_int32_atomic_action(struct db_context
*db
,
206 struct db_record
*rec
;
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
));
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
;
225 ret
= NT_STATUS_UNSUCCESSFUL
;
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
,
243 NTSTATUS
dbwrap_change_int32_atomic(struct db_context
*db
, const char *keystr
,
244 int32_t *oldval
, int32_t change_val
)
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
);
258 NTSTATUS
dbwrap_trans_change_int32_atomic(struct db_context
*db
,
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
);
275 struct dbwrap_store_context
{
281 static NTSTATUS
dbwrap_store_action(struct db_context
*db
, void *private_data
)
283 struct db_record
*rec
= NULL
;
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
));
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
)));
304 NTSTATUS
dbwrap_trans_store(struct db_context
*db
, TDB_DATA key
, TDB_DATA dbuf
,
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
);
319 static NTSTATUS
dbwrap_delete_action(struct db_context
* db
, void *private_data
)
322 struct db_record
*rec
;
323 TDB_DATA
*key
= (TDB_DATA
*)private_data
;
325 rec
= db
->fetch_locked(db
, talloc_tos(), *key
);
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
)));
340 NTSTATUS
dbwrap_trans_delete(struct db_context
*db
, TDB_DATA key
)
344 status
= dbwrap_trans_do(db
, dbwrap_delete_action
, &key
);
349 NTSTATUS
dbwrap_trans_store_int32(struct db_context
*db
, const char *keystr
,
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
,
362 NTSTATUS
dbwrap_trans_store_uint32(struct db_context
*db
, const char *keystr
,
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
,
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 *),
396 res
= db
->transaction_start(db
);
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");
410 res
= db
->transaction_commit(db
);
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
)
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
);
435 NTSTATUS
dbwrap_store_bystring_upper(struct db_context
*db
, const char *key
,
436 TDB_DATA data
, int flags
)
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
);
452 TDB_DATA
dbwrap_fetch_bystring_upper(struct db_context
*db
, TALLOC_CTX
*mem_ctx
,
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
);