2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 1992-2006
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.
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.
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/>.
23 #include "../tdb/include/tdb.h"
25 #include "lib/util/util_tdb.h"
27 /* these are little tdb utility functions that are meant to make
28 dealing with a tdb database a little less cumbersome in Samba */
30 /***************************************************************
31 Make a TDB_DATA and keep the const warning in one place
32 ****************************************************************/
34 static TDB_DATA make_tdb_data(const char *dptr, size_t dsize)
37 ret.dptr = discard_const_p(unsigned char, dptr);
42 /****************************************************************************
43 Lock a chain by string. Return -1 if lock failed.
44 ****************************************************************************/
46 int tdb_lock_bystring(struct tdb_context *tdb, const char *keyval)
48 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
50 return tdb_chainlock(tdb, key);
53 /****************************************************************************
54 Unlock a chain by string.
55 ****************************************************************************/
57 void tdb_unlock_bystring(struct tdb_context *tdb, const char *keyval)
59 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
61 tdb_chainunlock(tdb, key);
64 /****************************************************************************
65 Read lock a chain by string. Return -1 if lock failed.
66 ****************************************************************************/
68 int tdb_read_lock_bystring(struct tdb_context *tdb, const char *keyval)
70 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
72 return tdb_chainlock_read(tdb, key);
75 /****************************************************************************
76 Read unlock a chain by string.
77 ****************************************************************************/
79 void tdb_read_unlock_bystring(struct tdb_context *tdb, const char *keyval)
81 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
83 tdb_chainunlock_read(tdb, key);
87 /****************************************************************************
88 Fetch a int32_t value by a arbitrary blob key, return -1 if not found.
89 Output is int32_t in native byte order.
90 ****************************************************************************/
92 int32_t tdb_fetch_int32_byblob(struct tdb_context *tdb, const char *keyval, size_t len)
94 TDB_DATA key = make_tdb_data(keyval, len);
98 data = tdb_fetch(tdb, key);
99 if (!data.dptr || data.dsize != sizeof(int32_t)) {
100 SAFE_FREE(data.dptr);
104 ret = IVAL(data.dptr,0);
105 SAFE_FREE(data.dptr);
109 /****************************************************************************
110 Fetch a int32_t value by string key, return -1 if not found.
111 Output is int32_t in native byte order.
112 ****************************************************************************/
114 int32_t tdb_fetch_int32(struct tdb_context *tdb, const char *keystr)
116 return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1);
119 /****************************************************************************
120 Store a int32_t value by an arbitary blob key, return 0 on success, -1 on failure.
121 Input is int32_t in native byte order. Output in tdb is in little-endian.
122 ****************************************************************************/
124 int tdb_store_int32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, int32_t v)
126 TDB_DATA key = make_tdb_data(keystr, len);
131 data.dptr = (unsigned char *)&v_store;
132 data.dsize = sizeof(int32_t);
134 return tdb_store(tdb, key, data, TDB_REPLACE);
137 /****************************************************************************
138 Store a int32_t value by string key, return 0 on success, -1 on failure.
139 Input is int32_t in native byte order. Output in tdb is in little-endian.
140 ****************************************************************************/
142 int tdb_store_int32(struct tdb_context *tdb, const char *keystr, int32_t v)
144 return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v);
147 /****************************************************************************
148 Fetch a uint32_t value by a arbitrary blob key, return -1 if not found.
149 Output is uint32_t in native byte order.
150 ****************************************************************************/
152 bool tdb_fetch_uint32_byblob(struct tdb_context *tdb, const char *keyval, size_t len, uint32_t *value)
154 TDB_DATA key = make_tdb_data(keyval, len);
157 data = tdb_fetch(tdb, key);
158 if (!data.dptr || data.dsize != sizeof(uint32_t)) {
159 SAFE_FREE(data.dptr);
163 *value = IVAL(data.dptr,0);
164 SAFE_FREE(data.dptr);
168 /****************************************************************************
169 Fetch a uint32_t value by string key, return -1 if not found.
170 Output is uint32_t in native byte order.
171 ****************************************************************************/
173 bool tdb_fetch_uint32(struct tdb_context *tdb, const char *keystr, uint32_t *value)
175 return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
178 /****************************************************************************
179 Store a uint32_t value by an arbitary blob key, return 0 on success, -1 on failure.
180 Input is uint32_t in native byte order. Output in tdb is in little-endian.
181 ****************************************************************************/
183 bool tdb_store_uint32_byblob(struct tdb_context *tdb, const char *keystr, size_t len, uint32_t value)
185 TDB_DATA key = make_tdb_data(keystr, len);
190 SIVAL(&v_store, 0, value);
191 data.dptr = (unsigned char *)&v_store;
192 data.dsize = sizeof(uint32_t);
194 if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
200 /****************************************************************************
201 Store a uint32_t value by string key, return 0 on success, -1 on failure.
202 Input is uint32_t in native byte order. Output in tdb is in little-endian.
203 ****************************************************************************/
205 bool tdb_store_uint32(struct tdb_context *tdb, const char *keystr, uint32_t value)
207 return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
209 /****************************************************************************
210 Store a buffer by a null terminated string key. Return 0 on success, -1
212 ****************************************************************************/
214 int tdb_store_bystring(struct tdb_context *tdb, const char *keystr, TDB_DATA data, int flags)
216 TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
218 return tdb_store(tdb, key, data, flags);
221 /****************************************************************************
222 Fetch a buffer using a null terminated string key. Don't forget to call
223 free() on the result dptr.
224 ****************************************************************************/
226 TDB_DATA tdb_fetch_bystring(struct tdb_context *tdb, const char *keystr)
228 TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
230 return tdb_fetch(tdb, key);
233 /****************************************************************************
234 Delete an entry using a null terminated string key.
235 ****************************************************************************/
237 int tdb_delete_bystring(struct tdb_context *tdb, const char *keystr)
239 TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
241 return tdb_delete(tdb, key);
244 /****************************************************************************
245 Atomic integer change. Returns old value. To create, set initial value in *oldval.
246 ****************************************************************************/
248 int32_t tdb_change_int32_atomic(struct tdb_context *tdb, const char *keystr, int32_t *oldval, int32_t change_val)
253 if (tdb_lock_bystring(tdb, keystr) == -1)
256 if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
257 /* The lookup failed */
258 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
259 /* but not because it didn't exist */
263 /* Start with 'old' value */
267 /* It worked, set return value (oldval) to tdb data */
271 /* Increment value for storage and return next time */
274 if (tdb_store_int32(tdb, keystr, val) == -1)
281 tdb_unlock_bystring(tdb, keystr);
285 /****************************************************************************
286 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
287 ****************************************************************************/
289 bool tdb_change_uint32_atomic(struct tdb_context *tdb, const char *keystr, uint32_t *oldval, uint32_t change_val)
294 if (tdb_lock_bystring(tdb, keystr) == -1)
297 if (!tdb_fetch_uint32(tdb, keystr, &val)) {
299 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
300 /* and not because it didn't exist */
304 /* Start with 'old' value */
308 /* it worked, set return value (oldval) to tdb data */
313 /* get a new value to store */
316 if (!tdb_store_uint32(tdb, keystr, val))
323 tdb_unlock_bystring(tdb, keystr);
327 /****************************************************************************
328 Allow tdb_delete to be used as a tdb_traversal_fn.
329 ****************************************************************************/
331 int tdb_traverse_delete_fn(struct tdb_context *the_tdb, TDB_DATA key, TDB_DATA dbuf,
334 return tdb_delete(the_tdb, key);
339 /****************************************************************************
340 Useful pair of routines for packing/unpacking data consisting of
341 integers and strings.
342 ****************************************************************************/
344 size_t tdb_pack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...)
356 const char *fmt0 = fmt;
357 int bufsize0 = bufsize;
358 tdb_log_func log_fn = tdb_log_fn(tdb);
363 switch ((c = *fmt++)) {
364 case 'b': /* unsigned 8-bit integer */
366 bt = (uint8_t)va_arg(ap, int);
367 if (bufsize && bufsize >= len)
370 case 'w': /* unsigned 16-bit integer */
372 w = (uint16_t)va_arg(ap, int);
373 if (bufsize && bufsize >= len)
376 case 'd': /* signed 32-bit integer (standard int in most systems) */
378 d = va_arg(ap, uint32_t);
379 if (bufsize && bufsize >= len)
382 case 'p': /* pointer */
384 p = va_arg(ap, void *);
386 if (bufsize && bufsize >= len)
389 case 'P': /* null-terminated string */
390 s = va_arg(ap,char *);
393 if (bufsize && bufsize >= len)
396 case 'f': /* null-terminated string */
397 s = va_arg(ap,char *);
400 if (bufsize && bufsize >= len)
403 case 'B': /* fixed-length string */
405 s = va_arg(ap, char *);
407 if (bufsize && bufsize >= len) {
413 log_fn(tdb, 0,"Unknown tdb_pack format %c in %s\n",
428 log_fn(tdb, 18,"tdb_pack(%s, %d) -> %d\n",
429 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0));
431 return PTR_DIFF(buf, buf0);
434 /****************************************************************************
435 Useful pair of routines for packing/unpacking data consisting of
436 integers and strings.
437 ****************************************************************************/
439 int tdb_unpack(TDB_CONTEXT *tdb, char *buf, int bufsize, const char *fmt, ...)
451 const char *fmt0 = fmt;
452 int bufsize0 = bufsize;
453 tdb_log_func log_fn = tdb_log_fn(tdb);
458 switch ((c=*fmt++)) {
461 bt = va_arg(ap, uint8_t *);
468 w = va_arg(ap, uint16_t *);
475 d = va_arg(ap, uint32_t *);
482 p = va_arg(ap, void **);
487 * This isn't a real pointer - only a token (1 or 0)
488 * to mark the fact a pointer is present.
491 *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL);
494 /* Return a malloc'ed string. */
495 ps = va_arg(ap,char ** );
496 len = strlen((const char *)buf) + 1;
497 *ps = strdup((const char *)buf);
500 s = va_arg(ap,char *);
501 len = strlen(buf) + 1;
502 if (bufsize < len || len > sizeof(fstring))
507 i = va_arg(ap, int *);
508 b = va_arg(ap, char **);
520 *b = (char *)malloc(*i);
523 memcpy(*b, buf+4, *i);
526 log_fn(tdb, 0, "Unknown tdb_unpack format %c in %s\n",
539 log_fn(tdb, 18, "tdb_unpack(%s, %d) -> %d\n",
540 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0));
542 return PTR_DIFF(buf, buf0);