r21076: Two pieces of infrastructure from Samba4: An API-compatible messaging wrapper
[sfrench/samba-autobuild/.git] / source / lib / util_tdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    tdb utility functions
4    Copyright (C) Andrew Tridgell   1992-1998
5    Copyright (C) Rafal Szczesniak  2002
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #undef malloc
24 #undef realloc
25 #undef calloc
26 #undef strdup
27
28 /***************************************************************
29  Allow a caller to set a "alarm" flag that tdb can check to abort
30  a blocking lock on SIGALRM.
31 ***************************************************************/
32
33 static sig_atomic_t *palarm_fired;
34
35 static void tdb_set_lock_alarm(sig_atomic_t *palarm)
36 {
37         palarm_fired = palarm;
38 }
39
40 /* these are little tdb utility functions that are meant to make
41    dealing with a tdb database a little less cumbersome in Samba */
42
43 static SIG_ATOMIC_T gotalarm;
44
45 /***************************************************************
46  Signal function to tell us we timed out.
47 ****************************************************************/
48
49 static void gotalarm_sig(void)
50 {
51         gotalarm = 1;
52 }
53
54 /***************************************************************
55  Make a TDB_DATA and keep the const warning in one place
56 ****************************************************************/
57
58 TDB_DATA make_tdb_data(const char *dptr, size_t dsize)
59 {
60         TDB_DATA ret;
61         ret.dptr = CONST_DISCARD(char *, dptr);
62         ret.dsize = dsize;
63         return ret;
64 }
65
66 TDB_DATA string_tdb_data(const char *string)
67 {
68         return make_tdb_data(string, strlen(string));
69 }
70
71 /****************************************************************************
72  Lock a chain with timeout (in seconds).
73 ****************************************************************************/
74
75 static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type)
76 {
77         /* Allow tdb_chainlock to be interrupted by an alarm. */
78         int ret;
79         gotalarm = 0;
80         tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm));
81
82         if (timeout) {
83                 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
84                 alarm(timeout);
85         }
86
87         if (rw_type == F_RDLCK)
88                 ret = tdb_chainlock_read(tdb, key);
89         else
90                 ret = tdb_chainlock(tdb, key);
91
92         if (timeout) {
93                 alarm(0);
94                 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
95                 if (gotalarm) {
96                         DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",
97                                 timeout, key.dptr, tdb_name(tdb)));
98                         /* TODO: If we time out waiting for a lock, it might
99                          * be nice to use F_GETLK to get the pid of the
100                          * process currently holding the lock and print that
101                          * as part of the debugging message. -- mbp */
102                         return -1;
103                 }
104         }
105
106         return ret;
107 }
108
109 /****************************************************************************
110  Write lock a chain. Return -1 if timeout or lock failed.
111 ****************************************************************************/
112
113 int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout)
114 {
115         return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK);
116 }
117
118 /****************************************************************************
119  Lock a chain by string. Return -1 if timeout or lock failed.
120 ****************************************************************************/
121
122 int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval)
123 {
124         TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
125         
126         return tdb_chainlock(tdb, key);
127 }
128
129 int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
130                                    int timeout)
131 {
132         TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
133         
134         return tdb_chainlock_with_timeout(tdb, key, timeout);
135 }
136
137 /****************************************************************************
138  Unlock a chain by string.
139 ****************************************************************************/
140
141 void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval)
142 {
143         TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
144
145         tdb_chainunlock(tdb, key);
146 }
147
148 /****************************************************************************
149  Read lock a chain by string. Return -1 if timeout or lock failed.
150 ****************************************************************************/
151
152 int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout)
153 {
154         TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
155         
156         return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK);
157 }
158
159 /****************************************************************************
160  Read unlock a chain by string.
161 ****************************************************************************/
162
163 void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval)
164 {
165         TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
166         
167         tdb_chainunlock_read(tdb, key);
168 }
169
170
171 /****************************************************************************
172  Fetch a int32 value by a arbitrary blob key, return -1 if not found.
173  Output is int32 in native byte order.
174 ****************************************************************************/
175
176 int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len)
177 {
178         TDB_DATA key = make_tdb_data(keyval, len);
179         TDB_DATA data;
180         int32 ret;
181
182         data = tdb_fetch(tdb, key);
183         if (!data.dptr || data.dsize != sizeof(int32)) {
184                 SAFE_FREE(data.dptr);
185                 return -1;
186         }
187
188         ret = IVAL(data.dptr,0);
189         SAFE_FREE(data.dptr);
190         return ret;
191 }
192
193 /****************************************************************************
194  Fetch a int32 value by string key, return -1 if not found.
195  Output is int32 in native byte order.
196 ****************************************************************************/
197
198 int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr)
199 {
200         return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1);
201 }
202
203 /****************************************************************************
204  Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
205  Input is int32 in native byte order. Output in tdb is in little-endian.
206 ****************************************************************************/
207
208 int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v)
209 {
210         TDB_DATA key = make_tdb_data(keystr, len);
211         TDB_DATA data;
212         int32 v_store;
213
214         SIVAL(&v_store,0,v);
215         data.dptr = (char *)&v_store;
216         data.dsize = sizeof(int32);
217
218         return tdb_store(tdb, key, data, TDB_REPLACE);
219 }
220
221 /****************************************************************************
222  Store a int32 value by string key, return 0 on success, -1 on failure.
223  Input is int32 in native byte order. Output in tdb is in little-endian.
224 ****************************************************************************/
225
226 int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v)
227 {
228         return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v);
229 }
230
231 /****************************************************************************
232  Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
233  Output is uint32 in native byte order.
234 ****************************************************************************/
235
236 BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value)
237 {
238         TDB_DATA key = make_tdb_data(keyval, len);
239         TDB_DATA data;
240
241         data = tdb_fetch(tdb, key);
242         if (!data.dptr || data.dsize != sizeof(uint32)) {
243                 SAFE_FREE(data.dptr);
244                 return False;
245         }
246
247         *value = IVAL(data.dptr,0);
248         SAFE_FREE(data.dptr);
249         return True;
250 }
251
252 /****************************************************************************
253  Fetch a uint32 value by string key, return -1 if not found.
254  Output is uint32 in native byte order.
255 ****************************************************************************/
256
257 BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value)
258 {
259         return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
260 }
261
262 /****************************************************************************
263  Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
264  Input is uint32 in native byte order. Output in tdb is in little-endian.
265 ****************************************************************************/
266
267 BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value)
268 {
269         TDB_DATA key = make_tdb_data(keystr, len);
270         TDB_DATA data;
271         uint32 v_store;
272         BOOL ret = True;
273
274         SIVAL(&v_store, 0, value);
275         data.dptr = (char *)&v_store;
276         data.dsize = sizeof(uint32);
277
278         if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
279                 ret = False;
280
281         return ret;
282 }
283
284 /****************************************************************************
285  Store a uint32 value by string key, return 0 on success, -1 on failure.
286  Input is uint32 in native byte order. Output in tdb is in little-endian.
287 ****************************************************************************/
288
289 BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value)
290 {
291         return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
292 }
293 /****************************************************************************
294  Store a buffer by a null terminated string key.  Return 0 on success, -1
295  on failure.
296 ****************************************************************************/
297
298 int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags)
299 {
300         TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
301         
302         return tdb_store(tdb, key, data, flags);
303 }
304
305 int tdb_trans_store_bystring(TDB_CONTEXT *tdb, const char *keystr,
306                              TDB_DATA data, int flags)
307 {
308         TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
309         
310         return tdb_trans_store(tdb, key, data, flags);
311 }
312
313 /****************************************************************************
314  Fetch a buffer using a null terminated string key.  Don't forget to call
315  free() on the result dptr.
316 ****************************************************************************/
317
318 TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr)
319 {
320         TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
321
322         return tdb_fetch(tdb, key);
323 }
324
325 /****************************************************************************
326  Delete an entry using a null terminated string key. 
327 ****************************************************************************/
328
329 int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr)
330 {
331         TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
332
333         return tdb_delete(tdb, key);
334 }
335
336 /****************************************************************************
337  Atomic integer change. Returns old value. To create, set initial value in *oldval. 
338 ****************************************************************************/
339
340 int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val)
341 {
342         int32 val;
343         int32 ret = -1;
344
345         if (tdb_lock_bystring(tdb, keystr) == -1)
346                 return -1;
347
348         if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
349                 /* The lookup failed */
350                 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
351                         /* but not because it didn't exist */
352                         goto err_out;
353                 }
354                 
355                 /* Start with 'old' value */
356                 val = *oldval;
357
358         } else {
359                 /* It worked, set return value (oldval) to tdb data */
360                 *oldval = val;
361         }
362
363         /* Increment value for storage and return next time */
364         val += change_val;
365                 
366         if (tdb_store_int32(tdb, keystr, val) == -1)
367                 goto err_out;
368
369         ret = 0;
370
371   err_out:
372
373         tdb_unlock_bystring(tdb, keystr);
374         return ret;
375 }
376
377 /****************************************************************************
378  Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. 
379 ****************************************************************************/
380
381 BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val)
382 {
383         uint32 val;
384         BOOL ret = False;
385
386         if (tdb_lock_bystring(tdb, keystr) == -1)
387                 return False;
388
389         if (!tdb_fetch_uint32(tdb, keystr, &val)) {
390                 /* It failed */
391                 if (tdb_error(tdb) != TDB_ERR_NOEXIST) { 
392                         /* and not because it didn't exist */
393                         goto err_out;
394                 }
395
396                 /* Start with 'old' value */
397                 val = *oldval;
398
399         } else {
400                 /* it worked, set return value (oldval) to tdb data */
401                 *oldval = val;
402
403         }
404
405         /* get a new value to store */
406         val += change_val;
407                 
408         if (!tdb_store_uint32(tdb, keystr, val))
409                 goto err_out;
410
411         ret = True;
412
413   err_out:
414
415         tdb_unlock_bystring(tdb, keystr);
416         return ret;
417 }
418
419 /****************************************************************************
420  Useful pair of routines for packing/unpacking data consisting of
421  integers and strings.
422 ****************************************************************************/
423
424 size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap)
425 {
426         uint8 bt;
427         uint16 w;
428         uint32 d;
429         int i;
430         void *p;
431         int len;
432         char *s;
433         char c;
434         char *buf0 = buf;
435         const char *fmt0 = fmt;
436         int bufsize0 = bufsize;
437
438         while (*fmt) {
439                 switch ((c = *fmt++)) {
440                 case 'b': /* unsigned 8-bit integer */
441                         len = 1;
442                         bt = (uint8)va_arg(ap, int);
443                         if (bufsize && bufsize >= len)
444                                 SSVAL(buf, 0, bt);
445                         break;
446                 case 'w': /* unsigned 16-bit integer */
447                         len = 2;
448                         w = (uint16)va_arg(ap, int);
449                         if (bufsize && bufsize >= len)
450                                 SSVAL(buf, 0, w);
451                         break;
452                 case 'd': /* signed 32-bit integer (standard int in most systems) */
453                         len = 4;
454                         d = va_arg(ap, uint32);
455                         if (bufsize && bufsize >= len)
456                                 SIVAL(buf, 0, d);
457                         break;
458                 case 'p': /* pointer */
459                         len = 4;
460                         p = va_arg(ap, void *);
461                         d = p?1:0;
462                         if (bufsize && bufsize >= len)
463                                 SIVAL(buf, 0, d);
464                         break;
465                 case 'P': /* null-terminated string */
466                         s = va_arg(ap,char *);
467                         w = strlen(s);
468                         len = w + 1;
469                         if (bufsize && bufsize >= len)
470                                 memcpy(buf, s, len);
471                         break;
472                 case 'f': /* null-terminated string */
473                         s = va_arg(ap,char *);
474                         w = strlen(s);
475                         len = w + 1;
476                         if (bufsize && bufsize >= len)
477                                 memcpy(buf, s, len);
478                         break;
479                 case 'B': /* fixed-length string */
480                         i = va_arg(ap, int);
481                         s = va_arg(ap, char *);
482                         len = 4+i;
483                         if (bufsize && bufsize >= len) {
484                                 SIVAL(buf, 0, i);
485                                 memcpy(buf+4, s, i);
486                         }
487                         break;
488                 default:
489                         DEBUG(0,("Unknown tdb_pack format %c in %s\n", 
490                                  c, fmt));
491                         len = 0;
492                         break;
493                 }
494
495                 buf += len;
496                 if (bufsize)
497                         bufsize -= len;
498                 if (bufsize < 0)
499                         bufsize = 0;
500         }
501
502         DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n", 
503                  fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
504         
505         return PTR_DIFF(buf, buf0);
506 }
507
508 size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
509 {
510         va_list ap;
511         size_t result;
512
513         va_start(ap, fmt);
514         result = tdb_pack_va(buf, bufsize, fmt, ap);
515         va_end(ap);
516         return result;
517 }
518
519 BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len,
520                      const char *fmt, ...)
521 {
522         va_list ap;
523         size_t len1, len2;
524
525         va_start(ap, fmt);
526         len1 = tdb_pack_va(NULL, 0, fmt, ap);
527         va_end(ap);
528
529         if (mem_ctx != NULL) {
530                 *buf = TALLOC_REALLOC_ARRAY(mem_ctx, *buf, uint8,
531                                             (*len) + len1);
532         } else {
533                 *buf = SMB_REALLOC_ARRAY(*buf, uint8, (*len) + len1);
534         }
535
536         if (*buf == NULL) {
537                 return False;
538         }
539
540         va_start(ap, fmt);
541         len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap);
542         va_end(ap);
543
544         if (len1 != len2) {
545                 return False;
546         }
547
548         *len += len2;
549
550         return True;
551 }
552
553 /****************************************************************************
554  Useful pair of routines for packing/unpacking data consisting of
555  integers and strings.
556 ****************************************************************************/
557
558 int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
559 {
560         va_list ap;
561         uint8 *bt;
562         uint16 *w;
563         uint32 *d;
564         int len;
565         int *i;
566         void **p;
567         char *s, **b;
568         char c;
569         char *buf0 = buf;
570         const char *fmt0 = fmt;
571         int bufsize0 = bufsize;
572
573         va_start(ap, fmt);
574         
575         while (*fmt) {
576                 switch ((c=*fmt++)) {
577                 case 'b':
578                         len = 1;
579                         bt = va_arg(ap, uint8 *);
580                         if (bufsize < len)
581                                 goto no_space;
582                         *bt = SVAL(buf, 0);
583                         break;
584                 case 'w':
585                         len = 2;
586                         w = va_arg(ap, uint16 *);
587                         if (bufsize < len)
588                                 goto no_space;
589                         *w = SVAL(buf, 0);
590                         break;
591                 case 'd':
592                         len = 4;
593                         d = va_arg(ap, uint32 *);
594                         if (bufsize < len)
595                                 goto no_space;
596                         *d = IVAL(buf, 0);
597                         break;
598                 case 'p':
599                         len = 4;
600                         p = va_arg(ap, void **);
601                         if (bufsize < len)
602                                 goto no_space;
603                         /* 
604                          * This isn't a real pointer - only a token (1 or 0)
605                          * to mark the fact a pointer is present.
606                          */
607
608                         *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL);
609                         break;
610                 case 'P':
611                         s = va_arg(ap,char *);
612                         len = strlen(buf) + 1;
613                         if (bufsize < len || len > sizeof(pstring))
614                                 goto no_space;
615                         memcpy(s, buf, len);
616                         break;
617                 case 'f':
618                         s = va_arg(ap,char *);
619                         len = strlen(buf) + 1;
620                         if (bufsize < len || len > sizeof(fstring))
621                                 goto no_space;
622                         memcpy(s, buf, len);
623                         break;
624                 case 'B':
625                         i = va_arg(ap, int *);
626                         b = va_arg(ap, char **);
627                         len = 4;
628                         if (bufsize < len)
629                                 goto no_space;
630                         *i = IVAL(buf, 0);
631                         if (! *i) {
632                                 *b = NULL;
633                                 break;
634                         }
635                         len += *i;
636                         if (bufsize < len)
637                                 goto no_space;
638                         *b = (char *)SMB_MALLOC(*i);
639                         if (! *b)
640                                 goto no_space;
641                         memcpy(*b, buf+4, *i);
642                         break;
643                 default:
644                         DEBUG(0,("Unknown tdb_unpack format %c in %s\n", 
645                                  c, fmt));
646
647                         len = 0;
648                         break;
649                 }
650
651                 buf += len;
652                 bufsize -= len;
653         }
654
655         va_end(ap);
656
657         DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", 
658                  fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
659
660         return PTR_DIFF(buf, buf0);
661
662  no_space:
663         return -1;
664 }
665
666
667 /****************************************************************************
668  Log tdb messages via DEBUG().
669 ****************************************************************************/
670
671 static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...)
672 {
673         va_list ap;
674         char *ptr = NULL;
675
676         va_start(ap, format);
677         vasprintf(&ptr, format, ap);
678         va_end(ap);
679         
680         if (!ptr || !*ptr)
681                 return;
682
683         DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr));
684         SAFE_FREE(ptr);
685 }
686
687 /****************************************************************************
688  Like tdb_open() but also setup a logging function that redirects to
689  the samba DEBUG() system.
690 ****************************************************************************/
691
692 TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
693                           int open_flags, mode_t mode)
694 {
695         TDB_CONTEXT *tdb;
696         struct tdb_logging_context log_ctx;
697
698         if (!lp_use_mmap())
699                 tdb_flags |= TDB_NOMMAP;
700
701         log_ctx.log_fn = tdb_log;
702         log_ctx.log_private = NULL;
703
704         tdb = tdb_open_ex(name, hash_size, tdb_flags, 
705                           open_flags, mode, &log_ctx, NULL);
706         if (!tdb)
707                 return NULL;
708
709         return tdb;
710 }
711
712 /****************************************************************************
713  Allow tdb_delete to be used as a tdb_traversal_fn.
714 ****************************************************************************/
715
716 int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
717                      void *state)
718 {
719     return tdb_delete(the_tdb, key);
720 }
721
722
723
724 /**
725  * Search across the whole tdb for keys that match the given pattern
726  * return the result as a list of keys
727  *
728  * @param tdb pointer to opened tdb file context
729  * @param pattern searching pattern used by fnmatch(3) functions
730  *
731  * @return list of keys found by looking up with given pattern
732  **/
733 TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
734 {
735         TDB_DATA key, next;
736         TDB_LIST_NODE *list = NULL;
737         TDB_LIST_NODE *rec = NULL;
738         
739         for (key = tdb_firstkey(tdb); key.dptr; key = next) {
740                 /* duplicate key string to ensure null-termination */
741                 char *key_str = (char*) SMB_STRNDUP(key.dptr, key.dsize);
742                 if (!key_str) {
743                         DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
744                         smb_panic("strndup failed!\n");
745                 }
746                 
747                 DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern));
748                 
749                 next = tdb_nextkey(tdb, key);
750
751                 /* do the pattern checking */
752                 if (fnmatch(pattern, key_str, 0) == 0) {
753                         rec = SMB_MALLOC_P(TDB_LIST_NODE);
754                         ZERO_STRUCTP(rec);
755
756                         rec->node_key = key;
757         
758                         DLIST_ADD_END(list, rec, TDB_LIST_NODE *);
759                 
760                         DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
761                 } else {
762                         free(key.dptr);
763                 }
764                 
765                 /* free duplicated key string */
766                 free(key_str);
767         }
768         
769         return list;
770
771 }
772
773
774 /**
775  * Free the list returned by tdb_search_keys
776  *
777  * @param node list of results found by tdb_search_keys
778  **/
779 void tdb_search_list_free(TDB_LIST_NODE* node)
780 {
781         TDB_LIST_NODE *next_node;
782         
783         while (node) {
784                 next_node = node->next;
785                 SAFE_FREE(node->node_key.dptr);
786                 SAFE_FREE(node);
787                 node = next_node;
788         };
789 }
790
791 /****************************************************************************
792  tdb_store, wrapped in a transaction. This way we make sure that a process
793  that dies within writing does not leave a corrupt tdb behind.
794 ****************************************************************************/
795
796 int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
797                     int flag)
798 {
799         int res;
800
801         if ((res = tdb_transaction_start(tdb)) != 0) {
802                 DEBUG(5, ("tdb_transaction_start failed\n"));
803                 return res;
804         }
805
806         if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) {
807                 DEBUG(10, ("tdb_store failed\n"));
808                 if (tdb_transaction_cancel(tdb) != 0) {
809                         smb_panic("Cancelling transaction failed\n");
810                 }
811                 return res;
812         }
813
814         if ((res = tdb_transaction_commit(tdb)) != 0) {
815                 DEBUG(5, ("tdb_transaction_commit failed\n"));
816         }
817
818         return res;
819 }
820
821 /****************************************************************************
822  tdb_delete, wrapped in a transaction. This way we make sure that a process
823  that dies within deleting does not leave a corrupt tdb behind.
824 ****************************************************************************/
825
826 int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key)
827 {
828         int res;
829
830         if ((res = tdb_transaction_start(tdb)) != 0) {
831                 DEBUG(5, ("tdb_transaction_start failed\n"));
832                 return res;
833         }
834
835         if ((res = tdb_delete(tdb, key)) != 0) {
836                 DEBUG(10, ("tdb_delete failed\n"));
837                 if (tdb_transaction_cancel(tdb) != 0) {
838                         smb_panic("Cancelling transaction failed\n");
839                 }
840                 return res;
841         }
842
843         if ((res = tdb_transaction_commit(tdb)) != 0) {
844                 DEBUG(5, ("tdb_transaction_commit failed\n"));
845         }
846
847         return res;
848 }
849
850 /*
851  Log tdb messages via DEBUG().
852 */
853 static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, 
854                          const char *format, ...) PRINTF_ATTRIBUTE(3,4);
855
856 static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, 
857                          const char *format, ...)
858 {
859         va_list ap;
860         char *ptr = NULL;
861         int debuglevel = 0;
862
863         va_start(ap, format);
864         vasprintf(&ptr, format, ap);
865         va_end(ap);
866         
867         switch (level) {
868         case TDB_DEBUG_FATAL:
869                 debug_level = 0;
870                 break;
871         case TDB_DEBUG_ERROR:
872                 debuglevel = 1;
873                 break;
874         case TDB_DEBUG_WARNING:
875                 debuglevel = 2;
876                 break;
877         case TDB_DEBUG_TRACE:
878                 debuglevel = 5;
879                 break;
880         default:
881                 debuglevel = 0;
882         }               
883
884         if (ptr != NULL) {
885                 const char *name = tdb_name(tdb);
886                 DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr));
887                 free(ptr);
888         }
889 }
890
891 static struct tdb_wrap *tdb_list;
892
893 /* destroy the last connection to a tdb */
894 static int tdb_wrap_destructor(struct tdb_wrap *w)
895 {
896         tdb_close(w->tdb);
897         DLIST_REMOVE(tdb_list, w);
898         return 0;
899 }                                
900
901 /*
902   wrapped connection to a tdb database
903   to close just talloc_free() the tdb_wrap pointer
904  */
905 struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx,
906                                const char *name, int hash_size, int tdb_flags,
907                                int open_flags, mode_t mode)
908 {
909         struct tdb_wrap *w;
910         struct tdb_logging_context log_ctx;
911         log_ctx.log_fn = tdb_wrap_log;
912
913         for (w=tdb_list;w;w=w->next) {
914                 if (strcmp(name, w->name) == 0) {
915                         /*
916                          * Yes, talloc_reference is exactly what we want
917                          * here. Otherwise we would have to implement our own
918                          * reference counting.
919                          */
920                         return talloc_reference(mem_ctx, w);
921                 }
922         }
923
924         w = talloc(mem_ctx, struct tdb_wrap);
925         if (w == NULL) {
926                 return NULL;
927         }
928
929         if (!(w->name = talloc_strdup(w, name))) {
930                 talloc_free(w);
931                 return NULL;
932         }
933
934         w->tdb = tdb_open_ex(name, hash_size, tdb_flags, 
935                              open_flags, mode, &log_ctx, NULL);
936         if (w->tdb == NULL) {
937                 talloc_free(w);
938                 return NULL;
939         }
940
941         talloc_set_destructor(w, tdb_wrap_destructor);
942
943         DLIST_ADD(tdb_list, w);
944
945         return w;
946 }