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.
24 /* these are little tdb utility functions that are meant to make
25 dealing with a tdb database a little less cumbersome in Samba */
27 static SIG_ATOMIC_T gotalarm;
29 /***************************************************************
30 Signal function to tell us we timed out.
31 ****************************************************************/
33 static void gotalarm_sig(void)
38 /****************************************************************************
39 Lock a chain with timeout (in seconds).
40 ****************************************************************************/
42 int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout)
44 /* Allow tdb_chainlock to be interrupted by an alarm. */
47 tdb_set_lock_alarm(&gotalarm);
50 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
54 ret = tdb_chainlock(tdb, key);
58 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
66 /****************************************************************************
67 Lock a chain by string. Return -1 if timeout or lock failed.
68 ****************************************************************************/
70 int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval, unsigned int timeout)
75 key.dsize = strlen(keyval)+1;
77 return tdb_chainlock_with_timeout(tdb, key, timeout);
80 /****************************************************************************
81 Unlock a chain by string.
82 ****************************************************************************/
84 void tdb_unlock_bystring(TDB_CONTEXT *tdb, char *keyval)
89 key.dsize = strlen(keyval)+1;
91 tdb_chainunlock(tdb, key);
94 /****************************************************************************
95 Fetch a int32 value by a arbitrary blob key, return -1 if not found.
96 Output is int32 in native byte order.
97 ****************************************************************************/
99 int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len)
106 data = tdb_fetch(tdb, key);
107 if (!data.dptr || data.dsize != sizeof(int32))
110 ret = IVAL(data.dptr,0);
111 SAFE_FREE(data.dptr);
115 /****************************************************************************
116 Fetch a int32 value by string key, return -1 if not found.
117 Output is int32 in native byte order.
118 ****************************************************************************/
120 int32 tdb_fetch_int32(TDB_CONTEXT *tdb, char *keystr)
122 return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1);
125 /****************************************************************************
126 Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
127 Input is int32 in native byte order. Output in tdb is in little-endian.
128 ****************************************************************************/
130 int tdb_store_int32_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, int32 v)
138 data.dptr = (void *)&v_store;
139 data.dsize = sizeof(int32);
141 return tdb_store(tdb, key, data, TDB_REPLACE);
144 /****************************************************************************
145 Store a int32 value by string key, return 0 on success, -1 on failure.
146 Input is int32 in native byte order. Output in tdb is in little-endian.
147 ****************************************************************************/
149 int tdb_store_int32(TDB_CONTEXT *tdb, char *keystr, int32 v)
151 return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v);
154 /****************************************************************************
155 Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
156 Output is uint32 in native byte order.
157 ****************************************************************************/
159 BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len, uint32 *value)
165 data = tdb_fetch(tdb, key);
166 if (!data.dptr || data.dsize != sizeof(uint32))
169 *value = IVAL(data.dptr,0);
170 SAFE_FREE(data.dptr);
174 /****************************************************************************
175 Fetch a uint32 value by string key, return -1 if not found.
176 Output is uint32 in native byte order.
177 ****************************************************************************/
179 BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, char *keystr, uint32 *value)
181 return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
184 /****************************************************************************
185 Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
186 Input is uint32 in native byte order. Output in tdb is in little-endian.
187 ****************************************************************************/
189 BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, uint32 value)
197 SIVAL(&v_store, 0, value);
198 data.dptr = (void *)&v_store;
199 data.dsize = sizeof(uint32);
201 if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
207 /****************************************************************************
208 Store a uint32 value by string key, return 0 on success, -1 on failure.
209 Input is uint32 in native byte order. Output in tdb is in little-endian.
210 ****************************************************************************/
212 BOOL tdb_store_uint32(TDB_CONTEXT *tdb, char *keystr, uint32 value)
214 return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
216 /****************************************************************************
217 Store a buffer by a null terminated string key. Return 0 on success, -1
219 ****************************************************************************/
221 int tdb_store_by_string(TDB_CONTEXT *tdb, char *keystr, TDB_DATA data, int flags)
226 key.dsize = strlen(keystr) + 1;
228 return tdb_store(tdb, key, data, flags);
231 /****************************************************************************
232 Fetch a buffer using a null terminated string key. Don't forget to call
233 free() on the result dptr.
234 ****************************************************************************/
236 TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, char *keystr)
241 key.dsize = strlen(keystr) + 1;
243 return tdb_fetch(tdb, key);
246 /****************************************************************************
247 Delete an entry using a null terminated string key.
248 ****************************************************************************/
250 int tdb_delete_by_string(TDB_CONTEXT *tdb, char *keystr)
255 key.dsize = strlen(keystr) + 1;
257 return tdb_delete(tdb, key);
260 /****************************************************************************
261 Atomic integer change. Returns old value. To create, set initial value in *oldval.
262 ****************************************************************************/
264 int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, char *keystr, int32 *oldval, int32 change_val)
269 if (tdb_lock_bystring(tdb, keystr,0) == -1)
272 if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
273 /* The lookup failed */
274 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
275 /* but not becouse it didn't exist */
279 /* Start with 'old' value */
283 /* It worked, set return value (oldval) to tdb data */
287 /* Increment value for storage and return next time */
290 if (tdb_store_int32(tdb, keystr, val) == -1)
297 tdb_unlock_bystring(tdb, keystr);
301 /****************************************************************************
302 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
303 ****************************************************************************/
305 BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, char *keystr, uint32 *oldval, uint32 change_val)
310 if (tdb_lock_bystring(tdb, keystr,0) == -1)
313 if (!tdb_fetch_uint32(tdb, keystr, &val)) {
315 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
316 /* and not becouse it didn't exist */
320 /* Start with 'old' value */
324 /* it worked, set return value (oldval) to tdb data */
329 /* get a new value to store */
332 if (!tdb_store_uint32(tdb, keystr, val))
339 tdb_unlock_bystring(tdb, keystr);
343 /****************************************************************************
344 Useful pair of routines for packing/unpacking data consisting of
345 integers and strings.
346 ****************************************************************************/
348 size_t tdb_pack(char *buf, int bufsize, char *fmt, ...)
360 int bufsize0 = bufsize;
365 switch ((c = *fmt++)) {
368 w = (uint16)va_arg(ap, int);
374 d = va_arg(ap, uint32);
380 p = va_arg(ap, void *);
386 s = va_arg(ap,char *);
393 s = va_arg(ap,char *);
401 s = va_arg(ap, char *);
403 if (bufsize >= len) {
409 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
421 DEBUG(18,("tdb_pack(%s, %d) -> %d\n",
422 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
424 return PTR_DIFF(buf, buf0);
427 /****************************************************************************
428 Useful pair of routines for packing/unpacking data consisting of
429 integers and strings.
430 ****************************************************************************/
432 int tdb_unpack(char *buf, int bufsize, char *fmt, ...)
444 int bufsize0 = bufsize;
449 switch ((c=*fmt++)) {
452 w = va_arg(ap, uint16 *);
459 d = va_arg(ap, uint32 *);
466 p = va_arg(ap, void **);
469 *p = (void *)IVAL(buf, 0);
472 s = va_arg(ap,char *);
473 len = strlen(buf) + 1;
474 if (bufsize < len || len > sizeof(pstring))
479 s = va_arg(ap,char *);
480 len = strlen(buf) + 1;
481 if (bufsize < len || len > sizeof(fstring))
486 i = va_arg(ap, int *);
487 b = va_arg(ap, char **);
499 *b = (char *)malloc(*i);
502 memcpy(*b, buf+4, *i);
505 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
518 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
519 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
521 return PTR_DIFF(buf, buf0);
527 /****************************************************************************
528 Log tdb messages via DEBUG().
529 ****************************************************************************/
531 static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
536 va_start(ap, format);
537 vasprintf(&ptr, format, ap);
543 DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr));
547 /****************************************************************************
548 Like tdb_open() but also setup a logging function that redirects to
549 the samba DEBUG() system.
550 ****************************************************************************/
552 TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
553 int open_flags, mode_t mode)
558 tdb_flags |= TDB_NOMMAP;
560 tdb = tdb_open_ex(name, hash_size, tdb_flags,
561 open_flags, mode, tdb_log);
569 /****************************************************************************
570 Allow tdb_delete to be used as a tdb_traversal_fn.
571 ****************************************************************************/
573 int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
576 return tdb_delete(the_tdb, key);
582 * Search across the whole tdb for keys that match the given pattern
583 * return the result as a list of keys
585 * @param tdb pointer to opened tdb file context
586 * @param pattern searching pattern used by fnmatch(3) functions
588 * @return list of keys found by looking up with given pattern
590 TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
593 TDB_LIST_NODE *list = NULL;
594 TDB_LIST_NODE *rec = NULL;
595 TDB_LIST_NODE *tmp = NULL;
597 for (key = tdb_firstkey(tdb); key.dptr; key = next) {
598 /* duplicate key string to ensure null-termination */
599 char *key_str = (char*) strndup(key.dptr, key.dsize);
601 DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
602 smb_panic("strndup failed!\n");
605 DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern));
607 next = tdb_nextkey(tdb, key);
609 /* do the pattern checking */
610 if (fnmatch(pattern, key_str, 0) == 0) {
611 rec = (TDB_LIST_NODE*) malloc(sizeof(*rec));
616 DLIST_ADD_END(list, rec, tmp);
618 DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
623 /* free duplicated key string */
633 * Free the list returned by tdb_search_keys
635 * @param node list of results found by tdb_search_keys
637 void tdb_search_list_free(TDB_LIST_NODE* node)
639 TDB_LIST_NODE *next_node;
642 next_node = node->next;