2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Rafal Szczesniak 2002
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.
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.
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.
28 /* these are little tdb utility functions that are meant to make
29 dealing with a tdb database a little less cumbersome in Samba */
31 static SIG_ATOMIC_T gotalarm
;
33 /***************************************************************
34 Signal function to tell us we timed out.
35 ****************************************************************/
37 static void gotalarm_sig(void)
42 /***************************************************************
43 Make a TDB_DATA and keep the const warning in one place
44 ****************************************************************/
46 TDB_DATA
make_tdb_data(const char *dptr
, size_t dsize
)
49 ret
.dptr
= CONST_DISCARD(char *, dptr
);
54 TDB_DATA
string_tdb_data(const char *string
)
56 return make_tdb_data(string
, strlen(string
));
59 /****************************************************************************
60 Lock a chain with timeout (in seconds).
61 ****************************************************************************/
63 static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
, int rw_type
)
65 /* Allow tdb_chainlock to be interrupted by an alarm. */
70 CatchSignal(SIGALRM
, SIGNAL_CAST gotalarm_sig
);
74 if (rw_type
== F_RDLCK
)
75 ret
= tdb_chainlock_read(tdb
, key
);
77 ret
= tdb_chainlock(tdb
, key
);
81 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_IGN
);
83 DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",
84 timeout
, key
.dptr
, tdb_name(tdb
)));
85 /* TODO: If we time out waiting for a lock, it might
86 * be nice to use F_GETLK to get the pid of the
87 * process currently holding the lock and print that
88 * as part of the debugging message. -- mbp */
96 /****************************************************************************
97 Write lock a chain. Return -1 if timeout or lock failed.
98 ****************************************************************************/
100 int tdb_chainlock_with_timeout( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
)
102 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_WRLCK
);
105 /****************************************************************************
106 Lock a chain by string. Return -1 if timeout or lock failed.
107 ****************************************************************************/
109 int tdb_lock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
111 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
113 return tdb_chainlock(tdb
, key
);
116 int tdb_lock_bystring_with_timeout(TDB_CONTEXT
*tdb
, const char *keyval
,
119 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
121 return tdb_chainlock_with_timeout(tdb
, key
, timeout
);
124 /****************************************************************************
125 Unlock a chain by string.
126 ****************************************************************************/
128 void tdb_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
130 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
132 tdb_chainunlock(tdb
, key
);
135 /****************************************************************************
136 Read lock a chain by string. Return -1 if timeout or lock failed.
137 ****************************************************************************/
139 int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT
*tdb
, const char *keyval
, unsigned int timeout
)
141 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
143 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_RDLCK
);
146 /****************************************************************************
147 Read unlock a chain by string.
148 ****************************************************************************/
150 void tdb_read_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
152 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
154 tdb_chainunlock_read(tdb
, key
);
158 /****************************************************************************
159 Fetch a int32 value by a arbitrary blob key, return -1 if not found.
160 Output is int32 in native byte order.
161 ****************************************************************************/
163 int32
tdb_fetch_int32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
)
165 TDB_DATA key
= make_tdb_data(keyval
, len
);
169 data
= tdb_fetch(tdb
, key
);
170 if (!data
.dptr
|| data
.dsize
!= sizeof(int32
)) {
171 SAFE_FREE(data
.dptr
);
175 ret
= IVAL(data
.dptr
,0);
176 SAFE_FREE(data
.dptr
);
180 /****************************************************************************
181 Fetch a int32 value by string key, return -1 if not found.
182 Output is int32 in native byte order.
183 ****************************************************************************/
185 int32
tdb_fetch_int32(TDB_CONTEXT
*tdb
, const char *keystr
)
187 return tdb_fetch_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1);
190 /****************************************************************************
191 Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
192 Input is int32 in native byte order. Output in tdb is in little-endian.
193 ****************************************************************************/
195 int tdb_store_int32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, int32 v
)
197 TDB_DATA key
= make_tdb_data(keystr
, len
);
202 data
.dptr
= (char *)&v_store
;
203 data
.dsize
= sizeof(int32
);
205 return tdb_store(tdb
, key
, data
, TDB_REPLACE
);
208 /****************************************************************************
209 Store a int32 value by string key, return 0 on success, -1 on failure.
210 Input is int32 in native byte order. Output in tdb is in little-endian.
211 ****************************************************************************/
213 int tdb_store_int32(TDB_CONTEXT
*tdb
, const char *keystr
, int32 v
)
215 return tdb_store_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1, v
);
218 /****************************************************************************
219 Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
220 Output is uint32 in native byte order.
221 ****************************************************************************/
223 BOOL
tdb_fetch_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
, uint32
*value
)
225 TDB_DATA key
= make_tdb_data(keyval
, len
);
228 data
= tdb_fetch(tdb
, key
);
229 if (!data
.dptr
|| data
.dsize
!= sizeof(uint32
)) {
230 SAFE_FREE(data
.dptr
);
234 *value
= IVAL(data
.dptr
,0);
235 SAFE_FREE(data
.dptr
);
239 /****************************************************************************
240 Fetch a uint32 value by string key, return -1 if not found.
241 Output is uint32 in native byte order.
242 ****************************************************************************/
244 BOOL
tdb_fetch_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*value
)
246 return tdb_fetch_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
249 /****************************************************************************
250 Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
251 Input is uint32 in native byte order. Output in tdb is in little-endian.
252 ****************************************************************************/
254 BOOL
tdb_store_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, uint32 value
)
256 TDB_DATA key
= make_tdb_data(keystr
, len
);
261 SIVAL(&v_store
, 0, value
);
262 data
.dptr
= (char *)&v_store
;
263 data
.dsize
= sizeof(uint32
);
265 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) == -1)
271 /****************************************************************************
272 Store a uint32 value by string key, return 0 on success, -1 on failure.
273 Input is uint32 in native byte order. Output in tdb is in little-endian.
274 ****************************************************************************/
276 BOOL
tdb_store_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32 value
)
278 return tdb_store_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
280 /****************************************************************************
281 Store a buffer by a null terminated string key. Return 0 on success, -1
283 ****************************************************************************/
285 int tdb_store_bystring(TDB_CONTEXT
*tdb
, const char *keystr
, TDB_DATA data
, int flags
)
287 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
289 return tdb_store(tdb
, key
, data
, flags
);
292 /****************************************************************************
293 Fetch a buffer using a null terminated string key. Don't forget to call
294 free() on the result dptr.
295 ****************************************************************************/
297 TDB_DATA
tdb_fetch_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
299 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
301 return tdb_fetch(tdb
, key
);
304 /****************************************************************************
305 Delete an entry using a null terminated string key.
306 ****************************************************************************/
308 int tdb_delete_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
310 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
312 return tdb_delete(tdb
, key
);
315 /****************************************************************************
316 Atomic integer change. Returns old value. To create, set initial value in *oldval.
317 ****************************************************************************/
319 int32
tdb_change_int32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, int32
*oldval
, int32 change_val
)
324 if (tdb_lock_bystring(tdb
, keystr
) == -1)
327 if ((val
= tdb_fetch_int32(tdb
, keystr
)) == -1) {
328 /* The lookup failed */
329 if (tdb_error(tdb
) != TDB_ERR_NOEXIST
) {
330 /* but not because it didn't exist */
334 /* Start with 'old' value */
338 /* It worked, set return value (oldval) to tdb data */
342 /* Increment value for storage and return next time */
345 if (tdb_store_int32(tdb
, keystr
, val
) == -1)
352 tdb_unlock_bystring(tdb
, keystr
);
356 /****************************************************************************
357 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
358 ****************************************************************************/
360 BOOL
tdb_change_uint32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*oldval
, uint32 change_val
)
365 if (tdb_lock_bystring(tdb
, keystr
) == -1)
368 if (!tdb_fetch_uint32(tdb
, keystr
, &val
)) {
370 if (tdb_error(tdb
) != TDB_ERR_NOEXIST
) {
371 /* and not because it didn't exist */
375 /* Start with 'old' value */
379 /* it worked, set return value (oldval) to tdb data */
384 /* get a new value to store */
387 if (!tdb_store_uint32(tdb
, keystr
, val
))
394 tdb_unlock_bystring(tdb
, keystr
);
398 /****************************************************************************
399 Useful pair of routines for packing/unpacking data consisting of
400 integers and strings.
401 ****************************************************************************/
403 size_t tdb_pack_va(char *buf
, int bufsize
, const char *fmt
, va_list ap
)
414 const char *fmt0
= fmt
;
415 int bufsize0
= bufsize
;
418 switch ((c
= *fmt
++)) {
419 case 'b': /* unsigned 8-bit integer */
421 bt
= (uint8
)va_arg(ap
, int);
422 if (bufsize
&& bufsize
>= len
)
425 case 'w': /* unsigned 16-bit integer */
427 w
= (uint16
)va_arg(ap
, int);
428 if (bufsize
&& bufsize
>= len
)
431 case 'd': /* signed 32-bit integer (standard int in most systems) */
433 d
= va_arg(ap
, uint32
);
434 if (bufsize
&& bufsize
>= len
)
437 case 'p': /* pointer */
439 p
= va_arg(ap
, void *);
441 if (bufsize
&& bufsize
>= len
)
444 case 'P': /* null-terminated string */
445 s
= va_arg(ap
,char *);
448 if (bufsize
&& bufsize
>= len
)
451 case 'f': /* null-terminated string */
452 s
= va_arg(ap
,char *);
455 if (bufsize
&& bufsize
>= len
)
458 case 'B': /* fixed-length string */
460 s
= va_arg(ap
, char *);
462 if (bufsize
&& bufsize
>= len
) {
468 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
481 DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n",
482 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
484 return PTR_DIFF(buf
, buf0
);
487 size_t tdb_pack(char *buf
, int bufsize
, const char *fmt
, ...)
493 result
= tdb_pack_va(buf
, bufsize
, fmt
, ap
);
498 BOOL
tdb_pack_append(TALLOC_CTX
*mem_ctx
, uint8
**buf
, size_t *len
,
499 const char *fmt
, ...)
505 len1
= tdb_pack_va(NULL
, 0, fmt
, ap
);
508 if (mem_ctx
!= NULL
) {
509 *buf
= TALLOC_REALLOC_ARRAY(mem_ctx
, *buf
, uint8
,
512 *buf
= SMB_REALLOC_ARRAY(*buf
, uint8
, (*len
) + len1
);
520 len2
= tdb_pack_va((char *)(*buf
)+(*len
), len1
, fmt
, ap
);
532 /****************************************************************************
533 Useful pair of routines for packing/unpacking data consisting of
534 integers and strings.
535 ****************************************************************************/
537 int tdb_unpack(char *buf
, int bufsize
, const char *fmt
, ...)
549 const char *fmt0
= fmt
;
550 int bufsize0
= bufsize
;
555 switch ((c
=*fmt
++)) {
558 bt
= va_arg(ap
, uint8
*);
565 w
= va_arg(ap
, uint16
*);
572 d
= va_arg(ap
, uint32
*);
579 p
= va_arg(ap
, void **);
583 * This isn't a real pointer - only a token (1 or 0)
584 * to mark the fact a pointer is present.
587 *p
= (void *)(IVAL(buf
, 0) ? (void *)1 : NULL
);
590 s
= va_arg(ap
,char *);
591 len
= strlen(buf
) + 1;
592 if (bufsize
< len
|| len
> sizeof(pstring
))
597 s
= va_arg(ap
,char *);
598 len
= strlen(buf
) + 1;
599 if (bufsize
< len
|| len
> sizeof(fstring
))
604 i
= va_arg(ap
, int *);
605 b
= va_arg(ap
, char **);
617 *b
= (char *)SMB_MALLOC(*i
);
620 memcpy(*b
, buf
+4, *i
);
623 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
636 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
637 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
639 return PTR_DIFF(buf
, buf0
);
646 /****************************************************************************
647 Log tdb messages via DEBUG().
648 ****************************************************************************/
650 static void tdb_log(TDB_CONTEXT
*tdb
, enum tdb_debug_level level
, const char *format
, ...)
655 va_start(ap
, format
);
656 vasprintf(&ptr
, format
, ap
);
662 DEBUG((int)level
, ("tdb(%s): %s", tdb_name(tdb
) ? tdb_name(tdb
) : "unnamed", ptr
));
666 /****************************************************************************
667 Like tdb_open() but also setup a logging function that redirects to
668 the samba DEBUG() system.
669 ****************************************************************************/
671 TDB_CONTEXT
*tdb_open_log(const char *name
, int hash_size
, int tdb_flags
,
672 int open_flags
, mode_t mode
)
675 struct tdb_logging_context log_ctx
;
678 tdb_flags
|= TDB_NOMMAP
;
680 log_ctx
.log_fn
= tdb_log
;
681 log_ctx
.log_private
= NULL
;
683 tdb
= tdb_open_ex(name
, hash_size
, tdb_flags
,
684 open_flags
, mode
, &log_ctx
, NULL
);
691 /****************************************************************************
692 Allow tdb_delete to be used as a tdb_traversal_fn.
693 ****************************************************************************/
695 int tdb_traverse_delete_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA key
, TDB_DATA dbuf
,
698 return tdb_delete(the_tdb
, key
);
704 * Search across the whole tdb for keys that match the given pattern
705 * return the result as a list of keys
707 * @param tdb pointer to opened tdb file context
708 * @param pattern searching pattern used by fnmatch(3) functions
710 * @return list of keys found by looking up with given pattern
712 TDB_LIST_NODE
*tdb_search_keys(TDB_CONTEXT
*tdb
, const char* pattern
)
715 TDB_LIST_NODE
*list
= NULL
;
716 TDB_LIST_NODE
*rec
= NULL
;
718 for (key
= tdb_firstkey(tdb
); key
.dptr
; key
= next
) {
719 /* duplicate key string to ensure null-termination */
720 char *key_str
= (char*) SMB_STRNDUP(key
.dptr
, key
.dsize
);
722 DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
723 smb_panic("strndup failed!\n");
726 DEBUG(18, ("checking %s for match to pattern %s\n", key_str
, pattern
));
728 next
= tdb_nextkey(tdb
, key
);
730 /* do the pattern checking */
731 if (fnmatch(pattern
, key_str
, 0) == 0) {
732 rec
= SMB_MALLOC_P(TDB_LIST_NODE
);
737 DLIST_ADD_END(list
, rec
, TDB_LIST_NODE
*);
739 DEBUG(18, ("checking %s matched pattern %s\n", key_str
, pattern
));
744 /* free duplicated key string */
754 * Free the list returned by tdb_search_keys
756 * @param node list of results found by tdb_search_keys
758 void tdb_search_list_free(TDB_LIST_NODE
* node
)
760 TDB_LIST_NODE
*next_node
;
763 next_node
= node
->next
;
764 SAFE_FREE(node
->node_key
.dptr
);
770 /****************************************************************************
771 tdb_store, wrapped in a transaction. This way we make sure that a process
772 that dies within writing does not leave a corrupt tdb behind.
773 ****************************************************************************/
775 int tdb_trans_store(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA dbuf
,
780 if ((res
= tdb_transaction_start(tdb
)) != 0) {
781 DEBUG(5, ("tdb_transaction_start failed\n"));
785 if ((res
= tdb_store(tdb
, key
, dbuf
, flag
)) != 0) {
786 DEBUG(10, ("tdb_store failed\n"));
787 if (tdb_transaction_cancel(tdb
) != 0) {
788 smb_panic("Cancelling transaction failed\n");
793 if ((res
= tdb_transaction_commit(tdb
)) != 0) {
794 DEBUG(5, ("tdb_transaction_commit failed\n"));
800 /****************************************************************************
801 tdb_delete, wrapped in a transaction. This way we make sure that a process
802 that dies within deleting does not leave a corrupt tdb behind.
803 ****************************************************************************/
805 int tdb_trans_delete(struct tdb_context
*tdb
, TDB_DATA key
)
809 if ((res
= tdb_transaction_start(tdb
)) != 0) {
810 DEBUG(5, ("tdb_transaction_start failed\n"));
814 if ((res
= tdb_delete(tdb
, key
)) != 0) {
815 DEBUG(10, ("tdb_delete failed\n"));
816 if (tdb_transaction_cancel(tdb
) != 0) {
817 smb_panic("Cancelling transaction failed\n");
822 if ((res
= tdb_transaction_commit(tdb
)) != 0) {
823 DEBUG(5, ("tdb_transaction_commit failed\n"));
830 Log tdb messages via DEBUG().
832 static void tdb_wrap_log(TDB_CONTEXT
*tdb
, enum tdb_debug_level level
,
833 const char *format
, ...) PRINTF_ATTRIBUTE(3,4);
835 static void tdb_wrap_log(TDB_CONTEXT
*tdb
, enum tdb_debug_level level
,
836 const char *format
, ...)
842 va_start(ap
, format
);
843 vasprintf(&ptr
, format
, ap
);
847 case TDB_DEBUG_FATAL
:
850 case TDB_DEBUG_ERROR
:
853 case TDB_DEBUG_WARNING
:
856 case TDB_DEBUG_TRACE
:
864 const char *name
= tdb_name(tdb
);
865 DEBUG(debuglevel
, ("tdb(%s): %s", name
? name
: "unnamed", ptr
));
870 static struct tdb_wrap
*tdb_list
;
872 /* destroy the last connection to a tdb */
873 static int tdb_wrap_destructor(struct tdb_wrap
*w
)
876 DLIST_REMOVE(tdb_list
, w
);
881 wrapped connection to a tdb database
882 to close just talloc_free() the tdb_wrap pointer
884 struct tdb_wrap
*tdb_wrap_open(TALLOC_CTX
*mem_ctx
,
885 const char *name
, int hash_size
, int tdb_flags
,
886 int open_flags
, mode_t mode
)
889 struct tdb_logging_context log_ctx
;
890 log_ctx
.log_fn
= tdb_wrap_log
;
892 for (w
=tdb_list
;w
;w
=w
->next
) {
893 if (strcmp(name
, w
->name
) == 0) {
895 * Yes, talloc_reference is exactly what we want
896 * here. Otherwise we would have to implement our own
897 * reference counting.
899 return talloc_reference(mem_ctx
, w
);
903 w
= talloc(mem_ctx
, struct tdb_wrap
);
908 if (!(w
->name
= talloc_strdup(w
, name
))) {
913 w
->tdb
= tdb_open_ex(name
, hash_size
, tdb_flags
,
914 open_flags
, mode
, &log_ctx
, NULL
);
915 if (w
->tdb
== NULL
) {
920 talloc_set_destructor(w
, tdb_wrap_destructor
);
922 DLIST_ADD(tdb_list
, w
);