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