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.
22
#include "tdb_private.h"
25
/***************************************************************
26
Allow a caller to set a "alarm" flag that tdb can check to abort
27
a blocking lock on SIGALRM.
28
***************************************************************/
30
static sig_atomic_t *palarm_fired;
32
static void tdb_set_lock_alarm(sig_atomic_t *palarm)
34
palarm_fired = palarm;
37
/* these are little tdb utility functions that are meant to make
38
dealing with a tdb database a little less cumbersome in Samba */
40
static SIG_ATOMIC_T gotalarm;
42
/***************************************************************
43
Signal function to tell us we timed out.
44
****************************************************************/
46
static void gotalarm_sig(void)
51
/***************************************************************
52
Make a TDB_DATA and keep the const warning in one place
53
****************************************************************/
55
TDB_DATA make_tdb_data(const char *dptr, size_t dsize)
58
ret.dptr = CONST_DISCARD(char *, dptr);
63
TDB_DATA string_tdb_data(const char *string)
65
return make_tdb_data(string, strlen(string));
68
/****************************************************************************
69
Lock a chain with timeout (in seconds).
70
****************************************************************************/
72
static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type)
74
/* Allow tdb_chainlock to be interrupted by an alarm. */
77
tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm));
80
CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
84
if (rw_type == F_RDLCK)
85
ret = tdb_chainlock_read(tdb, key);
87
ret = tdb_chainlock(tdb, key);
91
CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
93
DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",
94
timeout, key.dptr, tdb->name ));
95
/* TODO: If we time out waiting for a lock, it might
96
* be nice to use F_GETLK to get the pid of the
97
* process currently holding the lock and print that
98
* as part of the debugging message. -- mbp */
106
/****************************************************************************
107
Write lock a chain. Return -1 if timeout or lock failed.
108
****************************************************************************/
110
int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout)
112
return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK);
115
/****************************************************************************
116
Lock a chain by string. Return -1 if timeout or lock failed.
117
****************************************************************************/
119
int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval)
121
TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
123
return tdb_chainlock(tdb, key);
126
int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
129
TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
131
return tdb_chainlock_with_timeout(tdb, key, timeout);
134
/****************************************************************************
135
Unlock a chain by string.
136
****************************************************************************/
138
void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval)
140
TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
142
tdb_chainunlock(tdb, key);
145
/****************************************************************************
146
Read lock a chain by string. Return -1 if timeout or lock failed.
147
****************************************************************************/
149
int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout)
151
TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
153
return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK);
156
/****************************************************************************
157
Read unlock a chain by string.
158
****************************************************************************/
160
void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval)
162
TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
164
tdb_chainunlock_read(tdb, key);
168
/****************************************************************************
169
Fetch a int32 value by a arbitrary blob key, return -1 if not found.
170
Output is int32 in native byte order.
171
****************************************************************************/
173
int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len)
175
TDB_DATA key = make_tdb_data(keyval, len);
179
data = tdb_fetch(tdb, key);
180
if (!data.dptr || data.dsize != sizeof(int32)) {
181
SAFE_FREE(data.dptr);
185
ret = IVAL(data.dptr,0);
186
SAFE_FREE(data.dptr);
190
/****************************************************************************
191
Fetch a int32 value by string key, return -1 if not found.
192
Output is int32 in native byte order.
193
****************************************************************************/
195
int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr)
197
return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1);
200
/****************************************************************************
201
Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
202
Input is int32 in native byte order. Output in tdb is in little-endian.
203
****************************************************************************/
205
int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v)
207
TDB_DATA key = make_tdb_data(keystr, len);
212
data.dptr = (void *)&v_store;
213
data.dsize = sizeof(int32);
215
return tdb_store(tdb, key, data, TDB_REPLACE);
218
/****************************************************************************
219
Store a int32 value by string key, return 0 on success, -1 on failure.
220
Input is int32 in native byte order. Output in tdb is in little-endian.
221
****************************************************************************/
223
int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v)
225
return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v);
228
/****************************************************************************
229
Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
230
Output is uint32 in native byte order.
231
****************************************************************************/
233
BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value)
235
TDB_DATA key = make_tdb_data(keyval, len);
238
data = tdb_fetch(tdb, key);
239
if (!data.dptr || data.dsize != sizeof(uint32)) {
240
SAFE_FREE(data.dptr);
244
*value = IVAL(data.dptr,0);
245
SAFE_FREE(data.dptr);
249
/****************************************************************************
250
Fetch a uint32 value by string key, return -1 if not found.
251
Output is uint32 in native byte order.
252
****************************************************************************/
254
BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value)
256
return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
259
/****************************************************************************
260
Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
261
Input is uint32 in native byte order. Output in tdb is in little-endian.
262
****************************************************************************/
264
BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value)
266
TDB_DATA key = make_tdb_data(keystr, len);
271
SIVAL(&v_store, 0, value);
272
data.dptr = (void *)&v_store;
273
data.dsize = sizeof(uint32);
275
if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
281
/****************************************************************************
282
Store a uint32 value by string key, return 0 on success, -1 on failure.
283
Input is uint32 in native byte order. Output in tdb is in little-endian.
284
****************************************************************************/
286
BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value)
288
return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
290
/****************************************************************************
291
Store a buffer by a null terminated string key. Return 0 on success, -1
293
****************************************************************************/
295
int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags)
297
TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
299
return tdb_store(tdb, key, data, flags);
302
/****************************************************************************
303
Fetch a buffer using a null terminated string key. Don't forget to call
304
free() on the result dptr.
305
****************************************************************************/
307
TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr)
309
TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
311
return tdb_fetch(tdb, key);
314
/****************************************************************************
315
Delete an entry using a null terminated string key.
316
****************************************************************************/
318
int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr)
320
TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
322
return tdb_delete(tdb, key);
325
/****************************************************************************
326
Atomic integer change. Returns old value. To create, set initial value in *oldval.
327
****************************************************************************/
329
int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val)
334
if (tdb_lock_bystring(tdb, keystr) == -1)
337
if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
338
/* The lookup failed */
339
if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
340
/* but not because it didn't exist */
344
/* Start with 'old' value */
348
/* It worked, set return value (oldval) to tdb data */
352
/* Increment value for storage and return next time */
355
if (tdb_store_int32(tdb, keystr, val) == -1)
362
tdb_unlock_bystring(tdb, keystr);
366
/****************************************************************************
367
Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
368
****************************************************************************/
370
BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val)
375
if (tdb_lock_bystring(tdb, keystr) == -1)
378
if (!tdb_fetch_uint32(tdb, keystr, &val)) {
380
if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
381
/* and not because it didn't exist */
385
/* Start with 'old' value */
389
/* it worked, set return value (oldval) to tdb data */
394
/* get a new value to store */
397
if (!tdb_store_uint32(tdb, keystr, val))
404
tdb_unlock_bystring(tdb, keystr);
408
/****************************************************************************
409
Useful pair of routines for packing/unpacking data consisting of
410
integers and strings.
411
****************************************************************************/
413
size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap)
424
const char *fmt0 = fmt;
425
int bufsize0 = bufsize;
428
switch ((c = *fmt++)) {
429
case 'b': /* unsigned 8-bit integer */
431
bt = (uint8)va_arg(ap, int);
432
if (bufsize && bufsize >= len)
435
case 'w': /* unsigned 16-bit integer */
437
w = (uint16)va_arg(ap, int);
438
if (bufsize && bufsize >= len)
441
case 'd': /* signed 32-bit integer (standard int in most systems) */
443
d = va_arg(ap, uint32);
444
if (bufsize && bufsize >= len)
447
case 'p': /* pointer */
449
p = va_arg(ap, void *);
451
if (bufsize && bufsize >= len)
454
case 'P': /* null-terminated string */
455
s = va_arg(ap,char *);
458
if (bufsize && bufsize >= len)
461
case 'f': /* null-terminated string */
462
s = va_arg(ap,char *);
465
if (bufsize && bufsize >= len)
468
case 'B': /* fixed-length string */
470
s = va_arg(ap, char *);
472
if (bufsize && bufsize >= len) {
478
DEBUG(0,("Unknown tdb_pack format %c in %s\n",
491
DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n",
492
fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
494
return PTR_DIFF(buf, buf0);
497
size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
503
result = tdb_pack_va(buf, bufsize, fmt, ap);
508
BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len,
509
const char *fmt, ...)
515
len1 = tdb_pack_va(NULL, 0, fmt, ap);
518
if (mem_ctx != NULL) {
519
*buf = TALLOC_REALLOC_ARRAY(mem_ctx, *buf, uint8,
522
*buf = SMB_REALLOC_ARRAY(*buf, uint8, (*len) + len1);
530
len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap);
542
/****************************************************************************
543
Useful pair of routines for packing/unpacking data consisting of
544
integers and strings.
545
****************************************************************************/
547
int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
559
const char *fmt0 = fmt;
560
int bufsize0 = bufsize;
565
switch ((c=*fmt++)) {
568
bt = va_arg(ap, uint8 *);
575
w = va_arg(ap, uint16 *);
582
d = va_arg(ap, uint32 *);
589
p = va_arg(ap, void **);
593
* This isn't a real pointer - only a token (1 or 0)
594
* to mark the fact a pointer is present.
597
*p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL);
600
s = va_arg(ap,char *);
601
len = strlen(buf) + 1;
602
if (bufsize < len || len > sizeof(pstring))
607
s = va_arg(ap,char *);
608
len = strlen(buf) + 1;
609
if (bufsize < len || len > sizeof(fstring))
614
i = va_arg(ap, int *);
615
b = va_arg(ap, char **);
627
*b = (char *)SMB_MALLOC(*i);
630
memcpy(*b, buf+4, *i);
633
DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
646
DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
647
fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
649
return PTR_DIFF(buf, buf0);
656
/****************************************************************************
657
Log tdb messages via DEBUG().
658
****************************************************************************/
660
static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
665
va_start(ap, format);
666
vasprintf(&ptr, format, ap);
672
DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr));
676
/****************************************************************************
677
Like tdb_open() but also setup a logging function that redirects to
678
the samba DEBUG() system.
679
****************************************************************************/
681
TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
682
int open_flags, mode_t mode)
687
tdb_flags |= TDB_NOMMAP;
689
tdb = tdb_open_ex(name, hash_size, tdb_flags,
690
open_flags, mode, tdb_log, NULL);
697
/****************************************************************************
698
Allow tdb_delete to be used as a tdb_traversal_fn.
699
****************************************************************************/
701
int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
704
return tdb_delete(the_tdb, key);
710
* Search across the whole tdb for keys that match the given pattern
711
* return the result as a list of keys
713
* @param tdb pointer to opened tdb file context
714
* @param pattern searching pattern used by fnmatch(3) functions
716
* @return list of keys found by looking up with given pattern
718
TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
721
TDB_LIST_NODE *list = NULL;
722
TDB_LIST_NODE *rec = NULL;
723
TDB_LIST_NODE *tmp = NULL;
725
for (key = tdb_firstkey(tdb); key.dptr; key = next) {
726
/* duplicate key string to ensure null-termination */
727
char *key_str = (char*) SMB_STRNDUP(key.dptr, key.dsize);
729
DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
730
smb_panic("strndup failed!\n");
733
DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern));
735
next = tdb_nextkey(tdb, key);
737
/* do the pattern checking */
738
if (fnmatch(pattern, key_str, 0) == 0) {
739
rec = SMB_MALLOC_P(TDB_LIST_NODE);
744
DLIST_ADD_END(list, rec, tmp);
746
DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
751
/* free duplicated key string */
761
* Free the list returned by tdb_search_keys
763
* @param node list of results found by tdb_search_keys
765
void tdb_search_list_free(TDB_LIST_NODE* node)
767
TDB_LIST_NODE *next_node;
770
next_node = node->next;
771
SAFE_FREE(node->node_key.dptr);
777
size_t tdb_map_size(struct tdb_context *tdb)
779
return tdb->map_size;
782
int tdb_get_flags(struct tdb_context *tdb)
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
****************************************************************************/
792
int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
797
if ((res = tdb_transaction_start(tdb)) != 0) {
798
DEBUG(5, ("tdb_transaction_start failed\n"));
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");
810
if ((res = tdb_transaction_commit(tdb)) != 0) {
811
DEBUG(5, ("tdb_transaction_commit failed\n"));