2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* these are little tdb utility functions that are meant to make
24 dealing with a tdb database a little less cumbersome in Samba */
26 /****************************************************************************
27 Lock a chain by string.
28 ****************************************************************************/
30 int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval)
35 key.dsize = strlen(keyval)+1;
37 return tdb_chainlock(tdb, key);
40 /****************************************************************************
41 Unlock a chain by string.
42 ****************************************************************************/
44 void tdb_unlock_bystring(TDB_CONTEXT *tdb, char *keyval)
49 key.dsize = strlen(keyval)+1;
51 tdb_chainunlock(tdb, key);
54 /****************************************************************************
55 Fetch a int32 value by a arbitrary blob key, return -1 if not found.
56 Output is int32 in native byte order.
57 ****************************************************************************/
59 int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len)
66 data = tdb_fetch(tdb, key);
67 if (!data.dptr || data.dsize != sizeof(int32))
70 ret = IVAL(data.dptr,0);
75 /****************************************************************************
76 Fetch a int32 value by string key, return -1 if not found.
77 Output is int32 in native byte order.
78 ****************************************************************************/
80 int32 tdb_fetch_int32(TDB_CONTEXT *tdb, char *keystr)
82 return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1);
85 /****************************************************************************
86 Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
87 Input is int32 in native byte order. Output in tdb is in little-endian.
88 ****************************************************************************/
90 int tdb_store_int32_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, int32 v)
98 data.dptr = (void *)&v_store;
99 data.dsize = sizeof(int32);
101 return tdb_store(tdb, key, data, TDB_REPLACE);
104 /****************************************************************************
105 Store a int32 value by string key, return 0 on success, -1 on failure.
106 Input is int32 in native byte order. Output in tdb is in little-endian.
107 ****************************************************************************/
109 int tdb_store_int32(TDB_CONTEXT *tdb, char *keystr, int32 v)
111 return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v);
114 /****************************************************************************
115 Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
116 Output is uint32 in native byte order.
117 ****************************************************************************/
119 BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len, uint32 *value)
125 data = tdb_fetch(tdb, key);
126 if (!data.dptr || data.dsize != sizeof(uint32))
129 *value = IVAL(data.dptr,0);
130 SAFE_FREE(data.dptr);
134 /****************************************************************************
135 Fetch a uint32 value by string key, return -1 if not found.
136 Output is uint32 in native byte order.
137 ****************************************************************************/
139 BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, char *keystr, uint32 *value)
141 return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
144 /****************************************************************************
145 Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
146 Input is uint32 in native byte order. Output in tdb is in little-endian.
147 ****************************************************************************/
149 BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, uint32 value)
157 SIVAL(&v_store, 0, value);
158 data.dptr = (void *)&v_store;
159 data.dsize = sizeof(uint32);
161 if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
167 /****************************************************************************
168 Store a uint32 value by string key, return 0 on success, -1 on failure.
169 Input is uint32 in native byte order. Output in tdb is in little-endian.
170 ****************************************************************************/
172 BOOL tdb_store_uint32(TDB_CONTEXT *tdb, char *keystr, uint32 value)
174 return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
176 /****************************************************************************
177 Store a buffer by a null terminated string key. Return 0 on success, -1
179 ****************************************************************************/
181 int tdb_store_by_string(TDB_CONTEXT *tdb, char *keystr, void *buffer, int len)
186 key.dsize = strlen(keystr) + 1;
191 return tdb_store(tdb, key, data, TDB_REPLACE);
194 /****************************************************************************
195 Fetch a buffer using a null terminated string key. Don't forget to call
196 free() on the result dptr.
197 ****************************************************************************/
199 TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, char *keystr)
204 key.dsize = strlen(keystr) + 1;
206 return tdb_fetch(tdb, key);
209 /****************************************************************************
210 Atomic integer change. Returns old value. To create, set initial value in *oldval.
211 ****************************************************************************/
213 int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, char *keystr, int32 *oldval, int32 change_val)
218 if (tdb_lock_bystring(tdb, keystr) == -1)
221 if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
222 if (tdb_error(tdb) != TDB_ERR_NOEXIST)
232 if (tdb_store_int32(tdb, keystr, val) == -1)
239 tdb_unlock_bystring(tdb, keystr);
243 /****************************************************************************
244 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
245 ****************************************************************************/
247 BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, char *keystr, uint32 *oldval, uint32 change_val)
252 if (tdb_lock_bystring(tdb, keystr) == -1)
255 if (!tdb_fetch_uint32(tdb, keystr, &val)) {
256 if (tdb_error(tdb) != TDB_ERR_NOEXIST)
266 if (!tdb_store_uint32(tdb, keystr, val))
273 tdb_unlock_bystring(tdb, keystr);
277 /****************************************************************************
278 Useful pair of routines for packing/unpacking data consisting of
279 integers and strings.
280 ****************************************************************************/
282 size_t tdb_pack(char *buf, int bufsize, char *fmt, ...)
294 int bufsize0 = bufsize;
299 switch ((c = *fmt++)) {
302 w = (uint16)va_arg(ap, int);
308 d = va_arg(ap, uint32);
314 p = va_arg(ap, void *);
320 s = va_arg(ap,char *);
327 s = va_arg(ap,char *);
335 s = va_arg(ap, char *);
337 if (bufsize >= len) {
343 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
355 DEBUG(18,("tdb_pack(%s, %d) -> %d\n",
356 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
358 return PTR_DIFF(buf, buf0);
361 /****************************************************************************
362 Useful pair of routines for packing/unpacking data consisting of
363 integers and strings.
364 ****************************************************************************/
366 int tdb_unpack(char *buf, int bufsize, char *fmt, ...)
378 int bufsize0 = bufsize;
383 switch ((c=*fmt++)) {
386 w = va_arg(ap, uint16 *);
393 d = va_arg(ap, uint32 *);
400 p = va_arg(ap, void **);
403 *p = (void *)IVAL(buf, 0);
406 s = va_arg(ap,char *);
407 len = strlen(buf) + 1;
408 if (bufsize < len || len > sizeof(pstring))
413 s = va_arg(ap,char *);
414 len = strlen(buf) + 1;
415 if (bufsize < len || len > sizeof(fstring))
420 i = va_arg(ap, int *);
421 b = va_arg(ap, char **);
433 *b = (char *)malloc(*i);
436 memcpy(*b, buf+4, *i);
439 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
452 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
453 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
455 return PTR_DIFF(buf, buf0);
461 /****************************************************************************
462 Log tdb messages via DEBUG().
463 ****************************************************************************/
465 static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
470 va_start(ap, format);
471 vasprintf(&ptr, format, ap);
477 DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr));
481 /****************************************************************************
482 Like tdb_open() but also setup a logging function that redirects to
483 the samba DEBUG() system.
484 ****************************************************************************/
486 TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
487 int open_flags, mode_t mode)
492 tdb_flags |= TDB_NOMMAP;
494 tdb = tdb_open_ex(name, hash_size, tdb_flags,
495 open_flags, mode, tdb_log);
503 /****************************************************************************
504 Allow tdb_delete to be used as a tdb_traversal_fn.
505 ****************************************************************************/
507 int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
510 return tdb_delete(the_tdb, key);