source: branches/samba-3.5.x/lib/util/util_tdb.c

Last change on this file was 429, checked in by Silvan Scherrer, 15 years ago

Samba 3.5.x: trunk update to 3.5.2

File size: 10.9 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3
4 tdb utility functions
5
6 Copyright (C) Andrew Tridgell 1992-2006
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "tdb.h"
24#include "../lib/util/util_tdb.h"
25
26/* these are little tdb utility functions that are meant to make
27 dealing with a tdb database a little less cumbersome in Samba */
28
29/***************************************************************
30 Make a TDB_DATA and keep the const warning in one place
31****************************************************************/
32
33TDB_DATA make_tdb_data(const uint8_t *dptr, size_t dsize)
34{
35 TDB_DATA ret;
36 ret.dptr = discard_const_p(uint8_t, dptr);
37 ret.dsize = dsize;
38 return ret;
39}
40
41bool tdb_data_equal(TDB_DATA t1, TDB_DATA t2)
42{
43 if (t1.dsize != t2.dsize) {
44 return false;
45 }
46 return (memcmp(t1.dptr, t2.dptr, t1.dsize) == 0);
47}
48
49TDB_DATA string_tdb_data(const char *string)
50{
51 return make_tdb_data((const uint8_t *)string, string ? strlen(string) : 0 );
52}
53
54TDB_DATA string_term_tdb_data(const char *string)
55{
56 return make_tdb_data((const uint8_t *)string, string ? strlen(string) + 1 : 0);
57}
58
59/****************************************************************************
60 Lock a chain by string. Return -1 if lock failed.
61****************************************************************************/
62
63int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval)
64{
65 TDB_DATA key = string_term_tdb_data(keyval);
66
67 return tdb_chainlock(tdb, key);
68}
69
70/****************************************************************************
71 Unlock a chain by string.
72****************************************************************************/
73
74void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval)
75{
76 TDB_DATA key = string_term_tdb_data(keyval);
77
78 tdb_chainunlock(tdb, key);
79}
80
81/****************************************************************************
82 Read lock a chain by string. Return -1 if lock failed.
83****************************************************************************/
84
85int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval)
86{
87 TDB_DATA key = string_term_tdb_data(keyval);
88
89 return tdb_chainlock_read(tdb, key);
90}
91
92/****************************************************************************
93 Read unlock a chain by string.
94****************************************************************************/
95
96void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval)
97{
98 TDB_DATA key = string_term_tdb_data(keyval);
99
100 tdb_chainunlock_read(tdb, key);
101}
102
103
104/****************************************************************************
105 Fetch a int32_t value by a arbitrary blob key, return -1 if not found.
106 Output is int32_t in native byte order.
107****************************************************************************/
108
109int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, TDB_DATA key)
110{
111 TDB_DATA data;
112 int32_t ret;
113
114 data = tdb_fetch(tdb, key);
115 if (!data.dptr || data.dsize != sizeof(int32_t)) {
116 SAFE_FREE(data.dptr);
117 return -1;
118 }
119
120 ret = IVAL(data.dptr,0);
121 SAFE_FREE(data.dptr);
122 return ret;
123}
124
125/****************************************************************************
126 Fetch a int32_t value by string key, return -1 if not found.
127 Output is int32_t in native byte order.
128****************************************************************************/
129
130int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr)
131{
132 return tdb_fetch_int32_byblob(tdb, string_term_tdb_data(keystr));
133}
134
135/****************************************************************************
136 Store a int32_t value by an arbitary blob key, return 0 on success, -1 on failure.
137 Input is int32_t in native byte order. Output in tdb is in little-endian.
138****************************************************************************/
139
140int tdb_store_int32_byblob(struct tdb_context *tdb, TDB_DATA key, int32_t v)
141{
142 TDB_DATA data;
143 int32_t v_store;
144
145 SIVAL(&v_store,0,v);
146 data.dptr = (unsigned char *)&v_store;
147 data.dsize = sizeof(int32_t);
148
149 return tdb_store(tdb, key, data, TDB_REPLACE);
150}
151
152/****************************************************************************
153 Store a int32_t value by string key, return 0 on success, -1 on failure.
154 Input is int32_t in native byte order. Output in tdb is in little-endian.
155****************************************************************************/
156
157int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v)
158{
159 return tdb_store_int32_byblob(tdb, string_term_tdb_data(keystr), v);
160}
161
162/****************************************************************************
163 Fetch a uint32_t value by a arbitrary blob key, return false if not found.
164 Output is uint32_t in native byte order.
165****************************************************************************/
166
167bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t *value)
168{
169 TDB_DATA data;
170
171 data = tdb_fetch(tdb, key);
172 if (!data.dptr || data.dsize != sizeof(uint32_t)) {
173 SAFE_FREE(data.dptr);
174 return false;
175 }
176
177 *value = IVAL(data.dptr,0);
178 SAFE_FREE(data.dptr);
179 return true;
180}
181
182/****************************************************************************
183 Fetch a uint32_t value by string key, return false if not found.
184 Output is uint32_t in native byte order.
185****************************************************************************/
186
187bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value)
188{
189 return tdb_fetch_uint32_byblob(tdb, string_term_tdb_data(keystr), value);
190}
191
192/****************************************************************************
193 Store a uint32_t value by an arbitary blob key, return 0 on success, -1 on failure.
194 Input is uint32_t in native byte order. Output in tdb is in little-endian.
195****************************************************************************/
196
197bool tdb_store_uint32_byblob(struct tdb_context *tdb, TDB_DATA key, uint32_t value)
198{
199 TDB_DATA data;
200 uint32_t v_store;
201 bool ret = true;
202
203 SIVAL(&v_store, 0, value);
204 data.dptr = (unsigned char *)&v_store;
205 data.dsize = sizeof(uint32_t);
206
207 if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
208 ret = false;
209
210 return ret;
211}
212
213/****************************************************************************
214 Store a uint32_t value by string key, return 0 on success, -1 on failure.
215 Input is uint32_t in native byte order. Output in tdb is in little-endian.
216****************************************************************************/
217
218bool tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value)
219{
220 return tdb_store_uint32_byblob(tdb, string_term_tdb_data(keystr), value);
221}
222/****************************************************************************
223 Store a buffer by a null terminated string key. Return 0 on success, -1
224 on failure.
225****************************************************************************/
226
227int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags)
228{
229 TDB_DATA key = string_term_tdb_data(keystr);
230
231 return tdb_store(tdb, key, data, flags);
232}
233
234/****************************************************************************
235 Fetch a buffer using a null terminated string key. Don't forget to call
236 free() on the result dptr.
237****************************************************************************/
238
239TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr)
240{
241 TDB_DATA key = string_term_tdb_data(keystr);
242
243 return tdb_fetch(tdb, key);
244}
245
246/****************************************************************************
247 Delete an entry using a null terminated string key.
248****************************************************************************/
249
250int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr)
251{
252 TDB_DATA key = string_term_tdb_data(keystr);
253
254 return tdb_delete(tdb, key);
255}
256
257/****************************************************************************
258 Atomic integer change. Returns old value. To create, set initial value in *oldval.
259****************************************************************************/
260
261int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val)
262{
263 int32_t val;
264 int32_t ret = -1;
265
266 if (tdb_lock_bystring(tdb, keystr) == -1)
267 return -1;
268
269 if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
270 /* The lookup failed */
271 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
272 /* but not because it didn't exist */
273 goto err_out;
274 }
275
276 /* Start with 'old' value */
277 val = *oldval;
278
279 } else {
280 /* It worked, set return value (oldval) to tdb data */
281 *oldval = val;
282 }
283
284 /* Increment value for storage and return next time */
285 val += change_val;
286
287 if (tdb_store_int32(tdb, keystr, val) == -1)
288 goto err_out;
289
290 ret = 0;
291
292 err_out:
293
294 tdb_unlock_bystring(tdb, keystr);
295 return ret;
296}
297
298/****************************************************************************
299 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
300****************************************************************************/
301
302bool tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val)
303{
304 uint32_t val;
305 bool ret = false;
306
307 if (tdb_lock_bystring(tdb, keystr) == -1)
308 return false;
309
310 if (!tdb_fetch_uint32(tdb, keystr, &val)) {
311 /* It failed */
312 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
313 /* and not because it didn't exist */
314 goto err_out;
315 }
316
317 /* Start with 'old' value */
318 val = *oldval;
319
320 } else {
321 /* it worked, set return value (oldval) to tdb data */
322 *oldval = val;
323
324 }
325
326 /* get a new value to store */
327 val += change_val;
328
329 if (!tdb_store_uint32(tdb, keystr, val))
330 goto err_out;
331
332 ret = true;
333
334 err_out:
335
336 tdb_unlock_bystring(tdb, keystr);
337 return ret;
338}
339
340/****************************************************************************
341 Allow tdb_delete to be used as a tdb_traversal_fn.
342****************************************************************************/
343
344int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf,
345 void *state)
346{
347 return tdb_delete(the_tdb, key);
348}
Note: See TracBrowser for help on using the repository browser.