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 /****************************************************************************
28 Lock a chain by string.
29 ****************************************************************************/
31 int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval)
36 key.dsize = strlen(keyval)+1;
38 return tdb_chainlock(tdb, key);
41 /****************************************************************************
42 Unlock a chain by string.
43 ****************************************************************************/
45 void tdb_unlock_bystring(TDB_CONTEXT *tdb, char *keyval)
50 key.dsize = strlen(keyval)+1;
52 tdb_chainunlock(tdb, key);
55 /****************************************************************************
56 Fetch a int32 value by a arbitrary blob key, return -1 if not found.
57 Output is int32 in native byte order.
58 ****************************************************************************/
60 int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len)
67 data = tdb_fetch(tdb, key);
68 if (!data.dptr || data.dsize != sizeof(int32))
71 ret = IVAL(data.dptr,0);
76 /****************************************************************************
77 Fetch a int32 value by string key, return -1 if not found.
78 Output is int32 in native byte order.
79 ****************************************************************************/
81 int32 tdb_fetch_int32(TDB_CONTEXT *tdb, char *keystr)
83 return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1);
86 /****************************************************************************
87 Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
88 Input is int32 in native byte order. Output in tdb is in little-endian.
89 ****************************************************************************/
91 int tdb_store_int32_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, int32 v)
99 data.dptr = (void *)&v_store;
100 data.dsize = sizeof(int32);
102 return tdb_store(tdb, key, data, TDB_REPLACE);
105 /****************************************************************************
106 Store a int32 value by string key, return 0 on success, -1 on failure.
107 Input is int32 in native byte order. Output in tdb is in little-endian.
108 ****************************************************************************/
110 int tdb_store_int32(TDB_CONTEXT *tdb, char *keystr, int32 v)
112 return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v);
115 /****************************************************************************
116 Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
117 Output is uint32 in native byte order.
118 ****************************************************************************/
120 BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, char *keyval, size_t len, uint32 *value)
126 data = tdb_fetch(tdb, key);
127 if (!data.dptr || data.dsize != sizeof(uint32))
130 *value = IVAL(data.dptr,0);
131 SAFE_FREE(data.dptr);
135 /****************************************************************************
136 Fetch a uint32 value by string key, return -1 if not found.
137 Output is uint32 in native byte order.
138 ****************************************************************************/
140 BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, char *keystr, uint32 *value)
142 return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
145 /****************************************************************************
146 Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
147 Input is uint32 in native byte order. Output in tdb is in little-endian.
148 ****************************************************************************/
150 BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, char *keystr, size_t len, uint32 value)
158 SIVAL(&v_store, 0, value);
159 data.dptr = (void *)&v_store;
160 data.dsize = sizeof(uint32);
162 if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
168 /****************************************************************************
169 Store a uint32 value by string key, return 0 on success, -1 on failure.
170 Input is uint32 in native byte order. Output in tdb is in little-endian.
171 ****************************************************************************/
173 BOOL tdb_store_uint32(TDB_CONTEXT *tdb, char *keystr, uint32 value)
175 return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
177 /****************************************************************************
178 Store a buffer by a null terminated string key. Return 0 on success, -1
180 ****************************************************************************/
182 int tdb_store_by_string(TDB_CONTEXT *tdb, char *keystr, void *buffer, int len)
187 key.dsize = strlen(keystr) + 1;
192 return tdb_store(tdb, key, data, TDB_REPLACE);
195 /****************************************************************************
196 Fetch a buffer using a null terminated string key. Don't forget to call
197 free() on the result dptr.
198 ****************************************************************************/
200 TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, char *keystr)
205 key.dsize = strlen(keystr) + 1;
207 return tdb_fetch(tdb, key);
210 /****************************************************************************
211 Delete a buffer using a null terminated string key.
212 ****************************************************************************/
214 int tdb_delete_by_string(TDB_CONTEXT *tdb, char *keystr)
219 key.dsize = strlen(keystr) + 1;
221 return tdb_delete(tdb, key);
224 /****************************************************************************
225 Atomic integer change. Returns old value. To create, set initial value in *oldval.
226 ****************************************************************************/
228 int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, char *keystr, int32 *oldval, int32 change_val)
233 if (tdb_lock_bystring(tdb, keystr) == -1)
236 if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
237 /* The lookup failed */
238 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
239 /* but not becouse it didn't exist */
243 /* Start with 'old' value */
247 /* It worked, set return value (oldval) to tdb data */
251 /* Increment value for storage and return next time */
254 if (tdb_store_int32(tdb, keystr, val) == -1)
261 tdb_unlock_bystring(tdb, keystr);
265 /****************************************************************************
266 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
267 ****************************************************************************/
269 BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, char *keystr, uint32 *oldval, uint32 change_val)
274 if (tdb_lock_bystring(tdb, keystr) == -1)
277 if (!tdb_fetch_uint32(tdb, keystr, &val)) {
279 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
280 /* and not becouse it didn't exist */
284 /* Start with 'old' value */
288 /* it worked, set return value (oldval) to tdb data */
293 /* get a new value to store */
296 if (!tdb_store_uint32(tdb, keystr, val))
303 tdb_unlock_bystring(tdb, keystr);
307 /****************************************************************************
308 Useful pair of routines for packing/unpacking data consisting of
309 integers and strings.
310 ****************************************************************************/
312 size_t tdb_pack(char *buf, int bufsize, char *fmt, ...)
324 int bufsize0 = bufsize;
329 switch ((c = *fmt++)) {
332 w = (uint16)va_arg(ap, int);
338 d = va_arg(ap, uint32);
344 p = va_arg(ap, void *);
350 s = va_arg(ap,char *);
357 s = va_arg(ap,char *);
365 s = va_arg(ap, char *);
367 if (bufsize >= len) {
373 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
385 DEBUG(18,("tdb_pack(%s, %d) -> %d\n",
386 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
388 return PTR_DIFF(buf, buf0);
391 /****************************************************************************
392 Useful pair of routines for packing/unpacking data consisting of
393 integers and strings.
394 ****************************************************************************/
396 int tdb_unpack(char *buf, int bufsize, char *fmt, ...)
408 int bufsize0 = bufsize;
413 switch ((c=*fmt++)) {
416 w = va_arg(ap, uint16 *);
423 d = va_arg(ap, uint32 *);
430 p = va_arg(ap, void **);
433 *p = (void *)IVAL(buf, 0);
436 s = va_arg(ap,char *);
437 len = strlen(buf) + 1;
438 if (bufsize < len || len > sizeof(pstring))
443 s = va_arg(ap,char *);
444 len = strlen(buf) + 1;
445 if (bufsize < len || len > sizeof(fstring))
450 i = va_arg(ap, int *);
451 b = va_arg(ap, char **);
463 *b = (char *)malloc(*i);
466 memcpy(*b, buf+4, *i);
469 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
482 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
483 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
485 return PTR_DIFF(buf, buf0);
491 /****************************************************************************
492 Log tdb messages via DEBUG().
493 ****************************************************************************/
495 static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
500 va_start(ap, format);
501 vasprintf(&ptr, format, ap);
507 DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr));
511 /****************************************************************************
512 Like tdb_open() but also setup a logging function that redirects to
513 the samba DEBUG() system.
514 ****************************************************************************/
516 TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
517 int open_flags, mode_t mode)
522 tdb_flags |= TDB_NOMMAP;
524 tdb = tdb_open_ex(name, hash_size, tdb_flags,
525 open_flags, mode, tdb_log);
533 /****************************************************************************
534 Allow tdb_delete to be used as a tdb_traversal_fn.
535 ****************************************************************************/
537 int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
540 return tdb_delete(the_tdb, key);
546 * Search across the whole tdb for keys that match the given pattern
547 * return the result as a list of keys
549 * @param tdb pointer to opened tdb file context
550 * @param pattern searching pattern used by fnmatch(3) functions
552 * @return list of keys found by looking up with given pattern
554 TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
557 TDB_LIST_NODE *list = NULL;
558 TDB_LIST_NODE *rec = NULL;
559 TDB_LIST_NODE *tmp = NULL;
561 for (key = tdb_firstkey(tdb); key.dptr; key = next) {
562 /* duplicate key string to ensure null-termination */
563 char *key_str = (char*) strndup(key.dptr, key.dsize);
565 DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
566 smb_panic("strndup failed!\n");
569 DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern));
571 next = tdb_nextkey(tdb, key);
573 /* do the pattern checking */
574 if (fnmatch(pattern, key_str, 0) == 0) {
575 rec = (TDB_LIST_NODE*) malloc(sizeof(*rec));
580 DLIST_ADD_END(list, rec, tmp);
582 DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
587 /* free duplicated key string */
597 * Free the list returned by tdb_search_keys
599 * @param node list of results found by tdb_search_keys
601 void tdb_search_list_free(TDB_LIST_NODE* node)
603 TDB_LIST_NODE *next_node;
606 next_node = node->next;