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 /***************************************************************
29 Allow a caller to set a "alarm" flag that tdb can check to abort
30 a blocking lock on SIGALRM.
31 ***************************************************************/
33 static sig_atomic_t *palarm_fired
;
35 static void tdb_set_lock_alarm(sig_atomic_t *palarm
)
37 palarm_fired
= palarm
;
40 /* these are little tdb utility functions that are meant to make
41 dealing with a tdb database a little less cumbersome in Samba */
43 static SIG_ATOMIC_T gotalarm
;
45 /***************************************************************
46 Signal function to tell us we timed out.
47 ****************************************************************/
49 static void gotalarm_sig(void)
54 /***************************************************************
55 Make a TDB_DATA and keep the const warning in one place
56 ****************************************************************/
58 TDB_DATA
make_tdb_data(const char *dptr
, size_t dsize
)
61 ret
.dptr
= CONST_DISCARD(char *, dptr
);
66 TDB_DATA
string_tdb_data(const char *string
)
68 return make_tdb_data(string
, strlen(string
));
71 /****************************************************************************
72 Lock a chain with timeout (in seconds).
73 ****************************************************************************/
75 static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
, int rw_type
)
77 /* Allow tdb_chainlock to be interrupted by an alarm. */
80 tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm
));
83 CatchSignal(SIGALRM
, SIGNAL_CAST gotalarm_sig
);
87 if (rw_type
== F_RDLCK
)
88 ret
= tdb_chainlock_read(tdb
, key
);
90 ret
= tdb_chainlock(tdb
, key
);
94 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_IGN
);
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 */
109 /****************************************************************************
110 Write lock a chain. Return -1 if timeout or lock failed.
111 ****************************************************************************/
113 int tdb_chainlock_with_timeout( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
)
115 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_WRLCK
);
118 /****************************************************************************
119 Lock a chain by string. Return -1 if timeout or lock failed.
120 ****************************************************************************/
122 int tdb_lock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
124 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
126 return tdb_chainlock(tdb
, key
);
129 int tdb_lock_bystring_with_timeout(TDB_CONTEXT
*tdb
, const char *keyval
,
132 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
134 return tdb_chainlock_with_timeout(tdb
, key
, timeout
);
137 /****************************************************************************
138 Unlock a chain by string.
139 ****************************************************************************/
141 void tdb_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
143 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
145 tdb_chainunlock(tdb
, key
);
148 /****************************************************************************
149 Read lock a chain by string. Return -1 if timeout or lock failed.
150 ****************************************************************************/
152 int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT
*tdb
, const char *keyval
, unsigned int timeout
)
154 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
156 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_RDLCK
);
159 /****************************************************************************
160 Read unlock a chain by string.
161 ****************************************************************************/
163 void tdb_read_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
165 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
167 tdb_chainunlock_read(tdb
, key
);
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 ****************************************************************************/
176 int32
tdb_fetch_int32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
)
178 TDB_DATA key
= make_tdb_data(keyval
, len
);
182 data
= tdb_fetch(tdb
, key
);
183 if (!data
.dptr
|| data
.dsize
!= sizeof(int32
)) {
184 SAFE_FREE(data
.dptr
);
188 ret
= IVAL(data
.dptr
,0);
189 SAFE_FREE(data
.dptr
);
193 /****************************************************************************
194 Fetch a int32 value by string key, return -1 if not found.
195 Output is int32 in native byte order.
196 ****************************************************************************/
198 int32
tdb_fetch_int32(TDB_CONTEXT
*tdb
, const char *keystr
)
200 return tdb_fetch_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1);
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 ****************************************************************************/
208 int tdb_store_int32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, int32 v
)
210 TDB_DATA key
= make_tdb_data(keystr
, len
);
215 data
.dptr
= (char *)&v_store
;
216 data
.dsize
= sizeof(int32
);
218 return tdb_store(tdb
, key
, data
, TDB_REPLACE
);
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 ****************************************************************************/
226 int tdb_store_int32(TDB_CONTEXT
*tdb
, const char *keystr
, int32 v
)
228 return tdb_store_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1, v
);
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 ****************************************************************************/
236 BOOL
tdb_fetch_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
, uint32
*value
)
238 TDB_DATA key
= make_tdb_data(keyval
, len
);
241 data
= tdb_fetch(tdb
, key
);
242 if (!data
.dptr
|| data
.dsize
!= sizeof(uint32
)) {
243 SAFE_FREE(data
.dptr
);
247 *value
= IVAL(data
.dptr
,0);
248 SAFE_FREE(data
.dptr
);
252 /****************************************************************************
253 Fetch a uint32 value by string key, return -1 if not found.
254 Output is uint32 in native byte order.
255 ****************************************************************************/
257 BOOL
tdb_fetch_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*value
)
259 return tdb_fetch_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
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 ****************************************************************************/
267 BOOL
tdb_store_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, uint32 value
)
269 TDB_DATA key
= make_tdb_data(keystr
, len
);
274 SIVAL(&v_store
, 0, value
);
275 data
.dptr
= (char *)&v_store
;
276 data
.dsize
= sizeof(uint32
);
278 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) == -1)
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 ****************************************************************************/
289 BOOL
tdb_store_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32 value
)
291 return tdb_store_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
293 /****************************************************************************
294 Store a buffer by a null terminated string key. Return 0 on success, -1
296 ****************************************************************************/
298 int tdb_store_bystring(TDB_CONTEXT
*tdb
, const char *keystr
, TDB_DATA data
, int flags
)
300 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
302 return tdb_store(tdb
, key
, data
, flags
);
305 /****************************************************************************
306 Fetch a buffer using a null terminated string key. Don't forget to call
307 free() on the result dptr.
308 ****************************************************************************/
310 TDB_DATA
tdb_fetch_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
312 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
314 return tdb_fetch(tdb
, key
);
317 /****************************************************************************
318 Delete an entry using a null terminated string key.
319 ****************************************************************************/
321 int tdb_delete_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
323 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
325 return tdb_delete(tdb
, key
);
328 /****************************************************************************
329 Atomic integer change. Returns old value. To create, set initial value in *oldval.
330 ****************************************************************************/
332 int32
tdb_change_int32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, int32
*oldval
, int32 change_val
)
337 if (tdb_lock_bystring(tdb
, keystr
) == -1)
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 */
347 /* Start with 'old' value */
351 /* It worked, set return value (oldval) to tdb data */
355 /* Increment value for storage and return next time */
358 if (tdb_store_int32(tdb
, keystr
, val
) == -1)
365 tdb_unlock_bystring(tdb
, keystr
);
369 /****************************************************************************
370 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
371 ****************************************************************************/
373 BOOL
tdb_change_uint32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*oldval
, uint32 change_val
)
378 if (tdb_lock_bystring(tdb
, keystr
) == -1)
381 if (!tdb_fetch_uint32(tdb
, keystr
, &val
)) {
383 if (tdb_error(tdb
) != TDB_ERR_NOEXIST
) {
384 /* and not because it didn't exist */
388 /* Start with 'old' value */
392 /* it worked, set return value (oldval) to tdb data */
397 /* get a new value to store */
400 if (!tdb_store_uint32(tdb
, keystr
, val
))
407 tdb_unlock_bystring(tdb
, keystr
);
411 /****************************************************************************
412 Useful pair of routines for packing/unpacking data consisting of
413 integers and strings.
414 ****************************************************************************/
416 size_t tdb_pack_va(char *buf
, int bufsize
, const char *fmt
, va_list ap
)
427 const char *fmt0
= fmt
;
428 int bufsize0
= bufsize
;
431 switch ((c
= *fmt
++)) {
432 case 'b': /* unsigned 8-bit integer */
434 bt
= (uint8
)va_arg(ap
, int);
435 if (bufsize
&& bufsize
>= len
)
438 case 'w': /* unsigned 16-bit integer */
440 w
= (uint16
)va_arg(ap
, int);
441 if (bufsize
&& bufsize
>= len
)
444 case 'd': /* signed 32-bit integer (standard int in most systems) */
446 d
= va_arg(ap
, uint32
);
447 if (bufsize
&& bufsize
>= len
)
450 case 'p': /* pointer */
452 p
= va_arg(ap
, void *);
454 if (bufsize
&& bufsize
>= len
)
457 case 'P': /* null-terminated string */
458 s
= va_arg(ap
,char *);
461 if (bufsize
&& bufsize
>= len
)
464 case 'f': /* null-terminated string */
465 s
= va_arg(ap
,char *);
468 if (bufsize
&& bufsize
>= len
)
471 case 'B': /* fixed-length string */
473 s
= va_arg(ap
, char *);
475 if (bufsize
&& bufsize
>= len
) {
481 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
494 DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n",
495 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
497 return PTR_DIFF(buf
, buf0
);
500 size_t tdb_pack(char *buf
, int bufsize
, const char *fmt
, ...)
506 result
= tdb_pack_va(buf
, bufsize
, fmt
, ap
);
511 BOOL
tdb_pack_append(TALLOC_CTX
*mem_ctx
, uint8
**buf
, size_t *len
,
512 const char *fmt
, ...)
518 len1
= tdb_pack_va(NULL
, 0, fmt
, ap
);
521 if (mem_ctx
!= NULL
) {
522 *buf
= TALLOC_REALLOC_ARRAY(mem_ctx
, *buf
, uint8
,
525 *buf
= SMB_REALLOC_ARRAY(*buf
, uint8
, (*len
) + len1
);
533 len2
= tdb_pack_va((char *)(*buf
)+(*len
), len1
, fmt
, ap
);
545 /****************************************************************************
546 Useful pair of routines for packing/unpacking data consisting of
547 integers and strings.
548 ****************************************************************************/
550 int tdb_unpack(char *buf
, int bufsize
, const char *fmt
, ...)
562 const char *fmt0
= fmt
;
563 int bufsize0
= bufsize
;
568 switch ((c
=*fmt
++)) {
571 bt
= va_arg(ap
, uint8
*);
578 w
= va_arg(ap
, uint16
*);
585 d
= va_arg(ap
, uint32
*);
592 p
= va_arg(ap
, void **);
596 * This isn't a real pointer - only a token (1 or 0)
597 * to mark the fact a pointer is present.
600 *p
= (void *)(IVAL(buf
, 0) ? (void *)1 : NULL
);
603 s
= va_arg(ap
,char *);
604 len
= strlen(buf
) + 1;
605 if (bufsize
< len
|| len
> sizeof(pstring
))
610 s
= va_arg(ap
,char *);
611 len
= strlen(buf
) + 1;
612 if (bufsize
< len
|| len
> sizeof(fstring
))
617 i
= va_arg(ap
, int *);
618 b
= va_arg(ap
, char **);
630 *b
= (char *)SMB_MALLOC(*i
);
633 memcpy(*b
, buf
+4, *i
);
636 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
649 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
650 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
652 return PTR_DIFF(buf
, buf0
);
659 /****************************************************************************
660 Log tdb messages via DEBUG().
661 ****************************************************************************/
663 static void tdb_log(TDB_CONTEXT
*tdb
, enum tdb_debug_level level
, const char *format
, ...)
668 va_start(ap
, format
);
669 vasprintf(&ptr
, format
, ap
);
675 DEBUG((int)level
, ("tdb(%s): %s", tdb_name(tdb
) ? tdb_name(tdb
) : "unnamed", ptr
));
679 /****************************************************************************
680 Like tdb_open() but also setup a logging function that redirects to
681 the samba DEBUG() system.
682 ****************************************************************************/
684 TDB_CONTEXT
*tdb_open_log(const char *name
, int hash_size
, int tdb_flags
,
685 int open_flags
, mode_t mode
)
688 struct tdb_logging_context log_ctx
;
691 tdb_flags
|= TDB_NOMMAP
;
693 log_ctx
.log_fn
= tdb_log
;
694 log_ctx
.log_private
= NULL
;
696 tdb
= tdb_open_ex(name
, hash_size
, tdb_flags
,
697 open_flags
, mode
, &log_ctx
, NULL
);
704 /****************************************************************************
705 Allow tdb_delete to be used as a tdb_traversal_fn.
706 ****************************************************************************/
708 int tdb_traverse_delete_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA key
, TDB_DATA dbuf
,
711 return tdb_delete(the_tdb
, key
);
717 * Search across the whole tdb for keys that match the given pattern
718 * return the result as a list of keys
720 * @param tdb pointer to opened tdb file context
721 * @param pattern searching pattern used by fnmatch(3) functions
723 * @return list of keys found by looking up with given pattern
725 TDB_LIST_NODE
*tdb_search_keys(TDB_CONTEXT
*tdb
, const char* pattern
)
728 TDB_LIST_NODE
*list
= NULL
;
729 TDB_LIST_NODE
*rec
= NULL
;
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
);
735 DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
736 smb_panic("strndup failed!\n");
739 DEBUG(18, ("checking %s for match to pattern %s\n", key_str
, pattern
));
741 next
= tdb_nextkey(tdb
, key
);
743 /* do the pattern checking */
744 if (fnmatch(pattern
, key_str
, 0) == 0) {
745 rec
= SMB_MALLOC_P(TDB_LIST_NODE
);
750 DLIST_ADD_END(list
, rec
, TDB_LIST_NODE
*);
752 DEBUG(18, ("checking %s matched pattern %s\n", key_str
, pattern
));
757 /* free duplicated key string */
767 * Free the list returned by tdb_search_keys
769 * @param node list of results found by tdb_search_keys
771 void tdb_search_list_free(TDB_LIST_NODE
* node
)
773 TDB_LIST_NODE
*next_node
;
776 next_node
= node
->next
;
777 SAFE_FREE(node
->node_key
.dptr
);
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 ****************************************************************************/
788 int tdb_trans_store(struct tdb_context
*tdb
, TDB_DATA key
, TDB_DATA dbuf
,
793 if ((res
= tdb_transaction_start(tdb
)) != 0) {
794 DEBUG(5, ("tdb_transaction_start failed\n"));
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");
806 if ((res
= tdb_transaction_commit(tdb
)) != 0) {
807 DEBUG(5, ("tdb_transaction_commit failed\n"));