r19429: moved tdb/common/tdbutil.c into lib/util_tdb.c
[ddiss/samba.git] / source3 / 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 /****************************************************************************
306  Fetch a buffer using a null terminated string key.  Don't forget to call
307  free() on the result dptr.
308 ****************************************************************************/
309
310 TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr)
311 {
312         TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
313
314         return tdb_fetch(tdb, key);
315 }
316
317 /****************************************************************************
318  Delete an entry using a null terminated string key. 
319 ****************************************************************************/
320
321 int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr)
322 {
323         TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
324
325         return tdb_delete(tdb, key);
326 }
327
328 /****************************************************************************
329  Atomic integer change. Returns old value. To create, set initial value in *oldval. 
330 ****************************************************************************/
331
332 int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val)
333 {
334         int32 val;
335         int32 ret = -1;
336
337         if (tdb_lock_bystring(tdb, keystr) == -1)
338                 return -1;
339
340         if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
341                 /* The lookup failed */
342                 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
343                         /* but not because it didn't exist */
344                         goto err_out;
345                 }
346                 
347                 /* Start with 'old' value */
348                 val = *oldval;
349
350         } else {
351                 /* It worked, set return value (oldval) to tdb data */
352                 *oldval = val;
353         }
354
355         /* Increment value for storage and return next time */
356         val += change_val;
357                 
358         if (tdb_store_int32(tdb, keystr, val) == -1)
359                 goto err_out;
360
361         ret = 0;
362
363   err_out:
364
365         tdb_unlock_bystring(tdb, keystr);
366         return ret;
367 }
368
369 /****************************************************************************
370  Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. 
371 ****************************************************************************/
372
373 BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val)
374 {
375         uint32 val;
376         BOOL ret = False;
377
378         if (tdb_lock_bystring(tdb, keystr) == -1)
379                 return False;
380
381         if (!tdb_fetch_uint32(tdb, keystr, &val)) {
382                 /* It failed */
383                 if (tdb_error(tdb) != TDB_ERR_NOEXIST) { 
384                         /* and not because it didn't exist */
385                         goto err_out;
386                 }
387
388                 /* Start with 'old' value */
389                 val = *oldval;
390
391         } else {
392                 /* it worked, set return value (oldval) to tdb data */
393                 *oldval = val;
394
395         }
396
397         /* get a new value to store */
398         val += change_val;
399                 
400         if (!tdb_store_uint32(tdb, keystr, val))
401                 goto err_out;
402
403         ret = True;
404
405   err_out:
406
407         tdb_unlock_bystring(tdb, keystr);
408         return ret;
409 }
410
411 /****************************************************************************
412  Useful pair of routines for packing/unpacking data consisting of
413  integers and strings.
414 ****************************************************************************/
415
416 size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap)
417 {
418         uint8 bt;
419         uint16 w;
420         uint32 d;
421         int i;
422         void *p;
423         int len;
424         char *s;
425         char c;
426         char *buf0 = buf;
427         const char *fmt0 = fmt;
428         int bufsize0 = bufsize;
429
430         while (*fmt) {
431                 switch ((c = *fmt++)) {
432                 case 'b': /* unsigned 8-bit integer */
433                         len = 1;
434                         bt = (uint8)va_arg(ap, int);
435                         if (bufsize && bufsize >= len)
436                                 SSVAL(buf, 0, bt);
437                         break;
438                 case 'w': /* unsigned 16-bit integer */
439                         len = 2;
440                         w = (uint16)va_arg(ap, int);
441                         if (bufsize && bufsize >= len)
442                                 SSVAL(buf, 0, w);
443                         break;
444                 case 'd': /* signed 32-bit integer (standard int in most systems) */
445                         len = 4;
446                         d = va_arg(ap, uint32);
447                         if (bufsize && bufsize >= len)
448                                 SIVAL(buf, 0, d);
449                         break;
450                 case 'p': /* pointer */
451                         len = 4;
452                         p = va_arg(ap, void *);
453                         d = p?1:0;
454                         if (bufsize && bufsize >= len)
455                                 SIVAL(buf, 0, d);
456                         break;
457                 case 'P': /* null-terminated string */
458                         s = va_arg(ap,char *);
459                         w = strlen(s);
460                         len = w + 1;
461                         if (bufsize && bufsize >= len)
462                                 memcpy(buf, s, len);
463                         break;
464                 case 'f': /* null-terminated string */
465                         s = va_arg(ap,char *);
466                         w = strlen(s);
467                         len = w + 1;
468                         if (bufsize && bufsize >= len)
469                                 memcpy(buf, s, len);
470                         break;
471                 case 'B': /* fixed-length string */
472                         i = va_arg(ap, int);
473                         s = va_arg(ap, char *);
474                         len = 4+i;
475                         if (bufsize && bufsize >= len) {
476                                 SIVAL(buf, 0, i);
477                                 memcpy(buf+4, s, i);
478                         }
479                         break;
480                 default:
481                         DEBUG(0,("Unknown tdb_pack format %c in %s\n", 
482                                  c, fmt));
483                         len = 0;
484                         break;
485                 }
486
487                 buf += len;
488                 if (bufsize)
489                         bufsize -= len;
490                 if (bufsize < 0)
491                         bufsize = 0;
492         }
493
494         DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n", 
495                  fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
496         
497         return PTR_DIFF(buf, buf0);
498 }
499
500 size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
501 {
502         va_list ap;
503         size_t result;
504
505         va_start(ap, fmt);
506         result = tdb_pack_va(buf, bufsize, fmt, ap);
507         va_end(ap);
508         return result;
509 }
510
511 BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len,
512                      const char *fmt, ...)
513 {
514         va_list ap;
515         size_t len1, len2;
516
517         va_start(ap, fmt);
518         len1 = tdb_pack_va(NULL, 0, fmt, ap);
519         va_end(ap);
520
521         if (mem_ctx != NULL) {
522                 *buf = TALLOC_REALLOC_ARRAY(mem_ctx, *buf, uint8,
523                                             (*len) + len1);
524         } else {
525                 *buf = SMB_REALLOC_ARRAY(*buf, uint8, (*len) + len1);
526         }
527
528         if (*buf == NULL) {
529                 return False;
530         }
531
532         va_start(ap, fmt);
533         len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap);
534         va_end(ap);
535
536         if (len1 != len2) {
537                 return False;
538         }
539
540         *len += len2;
541
542         return True;
543 }
544
545 /****************************************************************************
546  Useful pair of routines for packing/unpacking data consisting of
547  integers and strings.
548 ****************************************************************************/
549
550 int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
551 {
552         va_list ap;
553         uint8 *bt;
554         uint16 *w;
555         uint32 *d;
556         int len;
557         int *i;
558         void **p;
559         char *s, **b;
560         char c;
561         char *buf0 = buf;
562         const char *fmt0 = fmt;
563         int bufsize0 = bufsize;
564
565         va_start(ap, fmt);
566         
567         while (*fmt) {
568                 switch ((c=*fmt++)) {
569                 case 'b':
570                         len = 1;
571                         bt = va_arg(ap, uint8 *);
572                         if (bufsize < len)
573                                 goto no_space;
574                         *bt = SVAL(buf, 0);
575                         break;
576                 case 'w':
577                         len = 2;
578                         w = va_arg(ap, uint16 *);
579                         if (bufsize < len)
580                                 goto no_space;
581                         *w = SVAL(buf, 0);
582                         break;
583                 case 'd':
584                         len = 4;
585                         d = va_arg(ap, uint32 *);
586                         if (bufsize < len)
587                                 goto no_space;
588                         *d = IVAL(buf, 0);
589                         break;
590                 case 'p':
591                         len = 4;
592                         p = va_arg(ap, void **);
593                         if (bufsize < len)
594                                 goto no_space;
595                         /* 
596                          * This isn't a real pointer - only a token (1 or 0)
597                          * to mark the fact a pointer is present.
598                          */
599
600                         *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL);
601                         break;
602                 case 'P':
603                         s = va_arg(ap,char *);
604                         len = strlen(buf) + 1;
605                         if (bufsize < len || len > sizeof(pstring))
606                                 goto no_space;
607                         memcpy(s, buf, len);
608                         break;
609                 case 'f':
610                         s = va_arg(ap,char *);
611                         len = strlen(buf) + 1;
612                         if (bufsize < len || len > sizeof(fstring))
613                                 goto no_space;
614                         memcpy(s, buf, len);
615                         break;
616                 case 'B':
617                         i = va_arg(ap, int *);
618                         b = va_arg(ap, char **);
619                         len = 4;
620                         if (bufsize < len)
621                                 goto no_space;
622                         *i = IVAL(buf, 0);
623                         if (! *i) {
624                                 *b = NULL;
625                                 break;
626                         }
627                         len += *i;
628                         if (bufsize < len)
629                                 goto no_space;
630                         *b = (char *)SMB_MALLOC(*i);
631                         if (! *b)
632                                 goto no_space;
633                         memcpy(*b, buf+4, *i);
634                         break;
635                 default:
636                         DEBUG(0,("Unknown tdb_unpack format %c in %s\n", 
637                                  c, fmt));
638
639                         len = 0;
640                         break;
641                 }
642
643                 buf += len;
644                 bufsize -= len;
645         }
646
647         va_end(ap);
648
649         DEBUG(18,("tdb_unpack(%s, %d) -> %d\n", 
650                  fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
651
652         return PTR_DIFF(buf, buf0);
653
654  no_space:
655         return -1;
656 }
657
658
659 /****************************************************************************
660  Log tdb messages via DEBUG().
661 ****************************************************************************/
662
663 static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...)
664 {
665         va_list ap;
666         char *ptr = NULL;
667
668         va_start(ap, format);
669         vasprintf(&ptr, format, ap);
670         va_end(ap);
671         
672         if (!ptr || !*ptr)
673                 return;
674
675         DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr));
676         SAFE_FREE(ptr);
677 }
678
679 /****************************************************************************
680  Like tdb_open() but also setup a logging function that redirects to
681  the samba DEBUG() system.
682 ****************************************************************************/
683
684 TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
685                           int open_flags, mode_t mode)
686 {
687         TDB_CONTEXT *tdb;
688         struct tdb_logging_context log_ctx;
689
690         if (!lp_use_mmap())
691                 tdb_flags |= TDB_NOMMAP;
692
693         log_ctx.log_fn = tdb_log;
694         log_ctx.log_private = NULL;
695
696         tdb = tdb_open_ex(name, hash_size, tdb_flags, 
697                           open_flags, mode, &log_ctx, NULL);
698         if (!tdb)
699                 return NULL;
700
701         return tdb;
702 }
703
704 /****************************************************************************
705  Allow tdb_delete to be used as a tdb_traversal_fn.
706 ****************************************************************************/
707
708 int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
709                      void *state)
710 {
711     return tdb_delete(the_tdb, key);
712 }
713
714
715
716 /**
717  * Search across the whole tdb for keys that match the given pattern
718  * return the result as a list of keys
719  *
720  * @param tdb pointer to opened tdb file context
721  * @param pattern searching pattern used by fnmatch(3) functions
722  *
723  * @return list of keys found by looking up with given pattern
724  **/
725 TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
726 {
727         TDB_DATA key, next;
728         TDB_LIST_NODE *list = NULL;
729         TDB_LIST_NODE *rec = NULL;
730         
731         for (key = tdb_firstkey(tdb); key.dptr; key = next) {
732                 /* duplicate key string to ensure null-termination */
733                 char *key_str = (char*) SMB_STRNDUP(key.dptr, key.dsize);
734                 if (!key_str) {
735                         DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
736                         smb_panic("strndup failed!\n");
737                 }
738                 
739                 DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern));
740                 
741                 next = tdb_nextkey(tdb, key);
742
743                 /* do the pattern checking */
744                 if (fnmatch(pattern, key_str, 0) == 0) {
745                         rec = SMB_MALLOC_P(TDB_LIST_NODE);
746                         ZERO_STRUCTP(rec);
747
748                         rec->node_key = key;
749         
750                         DLIST_ADD_END(list, rec, TDB_LIST_NODE *);
751                 
752                         DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
753                 } else {
754                         free(key.dptr);
755                 }
756                 
757                 /* free duplicated key string */
758                 free(key_str);
759         }
760         
761         return list;
762
763 }
764
765
766 /**
767  * Free the list returned by tdb_search_keys
768  *
769  * @param node list of results found by tdb_search_keys
770  **/
771 void tdb_search_list_free(TDB_LIST_NODE* node)
772 {
773         TDB_LIST_NODE *next_node;
774         
775         while (node) {
776                 next_node = node->next;
777                 SAFE_FREE(node->node_key.dptr);
778                 SAFE_FREE(node);
779                 node = next_node;
780         };
781 }
782
783 /****************************************************************************
784  tdb_store, wrapped in a transaction. This way we make sure that a process
785  that dies within writing does not leave a corrupt tdb behind.
786 ****************************************************************************/
787
788 int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
789                     int flag)
790 {
791         int res;
792
793         if ((res = tdb_transaction_start(tdb)) != 0) {
794                 DEBUG(5, ("tdb_transaction_start failed\n"));
795                 return res;
796         }
797
798         if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) {
799                 DEBUG(10, ("tdb_store failed\n"));
800                 if (tdb_transaction_cancel(tdb) != 0) {
801                         smb_panic("Cancelling transaction failed\n");
802                 }
803                 return res;
804         }
805
806         if ((res = tdb_transaction_commit(tdb)) != 0) {
807                 DEBUG(5, ("tdb_transaction_commit failed\n"));
808         }
809
810         return res;
811 }