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.
25 /* these are little tdb utility functions that are meant to make
26 dealing with a tdb database a little less cumbersome in Samba */
28 static SIG_ATOMIC_T gotalarm
;
30 /***************************************************************
31 Signal function to tell us we timed out.
32 ****************************************************************/
34 static void gotalarm_sig(void)
39 /***************************************************************
40 Make a TDB_DATA and keep the const warning in one place
41 ****************************************************************/
43 static TDB_DATA
make_tdb_data(const char *dptr
, size_t dsize
)
51 /****************************************************************************
52 Lock a chain with timeout (in seconds).
53 ****************************************************************************/
55 static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
, int rw_type
)
57 /* Allow tdb_chainlock to be interrupted by an alarm. */
60 tdb_set_lock_alarm(&gotalarm
);
63 CatchSignal(SIGALRM
, SIGNAL_CAST gotalarm_sig
);
67 if (rw_type
== F_RDLCK
)
68 ret
= tdb_chainlock_read(tdb
, key
);
70 ret
= tdb_chainlock(tdb
, key
);
74 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_IGN
);
76 DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",
77 timeout
, key
.dptr
, tdb
->name
));
78 /* TODO: If we time out waiting for a lock, it might
79 * be nice to use F_GETLK to get the pid of the
80 * process currently holding the lock and print that
81 * as part of the debugging message. -- mbp */
89 /****************************************************************************
90 Write lock a chain. Return -1 if timeout or lock failed.
91 ****************************************************************************/
93 int tdb_chainlock_with_timeout( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
)
95 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_WRLCK
);
98 /****************************************************************************
99 Lock a chain by string. Return -1 if timeout or lock failed.
100 ****************************************************************************/
102 int tdb_lock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
, unsigned int timeout
)
104 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
106 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_WRLCK
);
109 /****************************************************************************
110 Unlock a chain by string.
111 ****************************************************************************/
113 void tdb_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
115 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
117 tdb_chainunlock(tdb
, key
);
120 /****************************************************************************
121 Read lock a chain by string. Return -1 if timeout or lock failed.
122 ****************************************************************************/
124 int tdb_read_lock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
, unsigned int timeout
)
126 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
128 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_RDLCK
);
131 /****************************************************************************
132 Read unlock a chain by string.
133 ****************************************************************************/
135 void tdb_read_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
137 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
139 tdb_chainunlock_read(tdb
, key
);
143 /****************************************************************************
144 Fetch a int32 value by a arbitrary blob key, return -1 if not found.
145 Output is int32 in native byte order.
146 ****************************************************************************/
148 int32
tdb_fetch_int32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
)
150 TDB_DATA key
= make_tdb_data(keyval
, len
);
154 data
= tdb_fetch(tdb
, key
);
155 if (!data
.dptr
|| data
.dsize
!= sizeof(int32
)) {
156 SAFE_FREE(data
.dptr
);
160 ret
= IVAL(data
.dptr
,0);
161 SAFE_FREE(data
.dptr
);
165 /****************************************************************************
166 Fetch a int32 value by string key, return -1 if not found.
167 Output is int32 in native byte order.
168 ****************************************************************************/
170 int32
tdb_fetch_int32(TDB_CONTEXT
*tdb
, const char *keystr
)
172 return tdb_fetch_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1);
175 /****************************************************************************
176 Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
177 Input is int32 in native byte order. Output in tdb is in little-endian.
178 ****************************************************************************/
180 int tdb_store_int32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, int32 v
)
182 TDB_DATA key
= make_tdb_data(keystr
, len
);
187 data
.dptr
= (void *)&v_store
;
188 data
.dsize
= sizeof(int32
);
190 return tdb_store(tdb
, key
, data
, TDB_REPLACE
);
193 /****************************************************************************
194 Store a int32 value by string key, return 0 on success, -1 on failure.
195 Input is int32 in native byte order. Output in tdb is in little-endian.
196 ****************************************************************************/
198 int tdb_store_int32(TDB_CONTEXT
*tdb
, const char *keystr
, int32 v
)
200 return tdb_store_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1, v
);
203 /****************************************************************************
204 Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
205 Output is uint32 in native byte order.
206 ****************************************************************************/
208 BOOL
tdb_fetch_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
, uint32
*value
)
210 TDB_DATA key
= make_tdb_data(keyval
, len
);
213 data
= tdb_fetch(tdb
, key
);
214 if (!data
.dptr
|| data
.dsize
!= sizeof(uint32
)) {
215 SAFE_FREE(data
.dptr
);
219 *value
= IVAL(data
.dptr
,0);
220 SAFE_FREE(data
.dptr
);
224 /****************************************************************************
225 Fetch a uint32 value by string key, return -1 if not found.
226 Output is uint32 in native byte order.
227 ****************************************************************************/
229 BOOL
tdb_fetch_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*value
)
231 return tdb_fetch_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
234 /****************************************************************************
235 Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
236 Input is uint32 in native byte order. Output in tdb is in little-endian.
237 ****************************************************************************/
239 BOOL
tdb_store_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, uint32 value
)
241 TDB_DATA key
= make_tdb_data(keystr
, len
);
246 SIVAL(&v_store
, 0, value
);
247 data
.dptr
= (void *)&v_store
;
248 data
.dsize
= sizeof(uint32
);
250 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) == -1)
256 /****************************************************************************
257 Store a uint32 value by string key, return 0 on success, -1 on failure.
258 Input is uint32 in native byte order. Output in tdb is in little-endian.
259 ****************************************************************************/
261 BOOL
tdb_store_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32 value
)
263 return tdb_store_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
265 /****************************************************************************
266 Store a buffer by a null terminated string key. Return 0 on success, -1
268 ****************************************************************************/
270 int tdb_store_bystring(TDB_CONTEXT
*tdb
, const char *keystr
, TDB_DATA data
, int flags
)
272 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
274 return tdb_store(tdb
, key
, data
, flags
);
277 /****************************************************************************
278 Fetch a buffer using a null terminated string key. Don't forget to call
279 free() on the result dptr.
280 ****************************************************************************/
282 TDB_DATA
tdb_fetch_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
284 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
286 return tdb_fetch(tdb
, key
);
289 /****************************************************************************
290 Delete an entry using a null terminated string key.
291 ****************************************************************************/
293 int tdb_delete_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
295 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
297 return tdb_delete(tdb
, key
);
300 /****************************************************************************
301 Atomic integer change. Returns old value. To create, set initial value in *oldval.
302 ****************************************************************************/
304 int32
tdb_change_int32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, int32
*oldval
, int32 change_val
)
309 if (tdb_lock_bystring(tdb
, keystr
,0) == -1)
312 if ((val
= tdb_fetch_int32(tdb
, keystr
)) == -1) {
313 /* The lookup failed */
314 if (tdb_error(tdb
) != TDB_ERR_NOEXIST
) {
315 /* but not because it didn't exist */
319 /* Start with 'old' value */
323 /* It worked, set return value (oldval) to tdb data */
327 /* Increment value for storage and return next time */
330 if (tdb_store_int32(tdb
, keystr
, val
) == -1)
337 tdb_unlock_bystring(tdb
, keystr
);
341 /****************************************************************************
342 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
343 ****************************************************************************/
345 BOOL
tdb_change_uint32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*oldval
, uint32 change_val
)
350 if (tdb_lock_bystring(tdb
, keystr
,0) == -1)
353 if (!tdb_fetch_uint32(tdb
, keystr
, &val
)) {
355 if (tdb_error(tdb
) != TDB_ERR_NOEXIST
) {
356 /* and not because it didn't exist */
360 /* Start with 'old' value */
364 /* it worked, set return value (oldval) to tdb data */
369 /* get a new value to store */
372 if (!tdb_store_uint32(tdb
, keystr
, val
))
379 tdb_unlock_bystring(tdb
, keystr
);
383 /****************************************************************************
384 Useful pair of routines for packing/unpacking data consisting of
385 integers and strings.
386 ****************************************************************************/
388 size_t tdb_pack(char *buf
, int bufsize
, const char *fmt
, ...)
400 const char *fmt0
= fmt
;
401 int bufsize0
= bufsize
;
406 switch ((c
= *fmt
++)) {
407 case 'b': /* unsigned 8-bit integer */
409 bt
= (uint8
)va_arg(ap
, int);
410 if (bufsize
&& bufsize
>= len
)
413 case 'w': /* unsigned 16-bit integer */
415 w
= (uint16
)va_arg(ap
, int);
416 if (bufsize
&& bufsize
>= len
)
419 case 'd': /* signed 32-bit integer (standard int in most systems) */
421 d
= va_arg(ap
, uint32
);
422 if (bufsize
&& bufsize
>= len
)
425 case 'p': /* pointer */
427 p
= va_arg(ap
, void *);
429 if (bufsize
&& bufsize
>= len
)
432 case 'P': /* null-terminated string */
433 s
= va_arg(ap
,char *);
436 if (bufsize
&& bufsize
>= len
)
439 case 'f': /* null-terminated string */
440 s
= va_arg(ap
,char *);
443 if (bufsize
&& bufsize
>= len
)
446 case 'B': /* fixed-length string */
448 s
= va_arg(ap
, char *);
450 if (bufsize
&& bufsize
>= len
) {
456 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
471 DEBUG(18,("tdb_pack(%s, %d) -> %d\n",
472 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
474 return PTR_DIFF(buf
, buf0
);
477 /****************************************************************************
478 Useful pair of routines for packing/unpacking data consisting of
479 integers and strings.
480 ****************************************************************************/
482 int tdb_unpack(char *buf
, int bufsize
, const char *fmt
, ...)
494 const char *fmt0
= fmt
;
495 int bufsize0
= bufsize
;
500 switch ((c
=*fmt
++)) {
503 bt
= va_arg(ap
, uint8
*);
510 w
= va_arg(ap
, uint16
*);
517 d
= va_arg(ap
, uint32
*);
524 p
= va_arg(ap
, void **);
527 *p
= (void *)IVAL(buf
, 0);
530 s
= va_arg(ap
,char *);
531 len
= strlen(buf
) + 1;
532 if (bufsize
< len
|| len
> sizeof(pstring
))
537 s
= va_arg(ap
,char *);
538 len
= strlen(buf
) + 1;
539 if (bufsize
< len
|| len
> sizeof(fstring
))
544 i
= va_arg(ap
, int *);
545 b
= va_arg(ap
, char **);
557 *b
= (char *)malloc(*i
);
560 memcpy(*b
, buf
+4, *i
);
563 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
576 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
577 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
579 return PTR_DIFF(buf
, buf0
);
587 * Pack SID passed by pointer
589 * @param pack_buf pointer to buffer which is to be filled with packed data
590 * @param bufsize size of packing buffer
591 * @param sid pointer to sid to be packed
593 * @return length of the packed representation of the whole structure
595 size_t tdb_sid_pack(char* pack_buf
, int bufsize
, DOM_SID
* sid
)
600 if (!sid
|| !pack_buf
) return -1;
602 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "bb", sid
->sid_rev_num
,
605 for (idx
= 0; idx
< 6; idx
++) {
606 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "b", sid
->id_auth
[idx
]);
609 for (idx
= 0; idx
< MAXSUBAUTHS
; idx
++) {
610 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "d", sid
->sub_auths
[idx
]);
618 * Unpack SID into a pointer
620 * @param pack_buf pointer to buffer with packed representation
621 * @param bufsize size of the buffer
622 * @param sid pointer to sid structure to be filled with unpacked data
624 * @return size of structure unpacked from buffer
626 size_t tdb_sid_unpack(char* pack_buf
, int bufsize
, DOM_SID
* sid
)
630 if (!sid
|| !pack_buf
) return -1;
632 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "bb",
633 &sid
->sid_rev_num
, &sid
->num_auths
);
635 for (idx
= 0; idx
< 6; idx
++) {
636 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "b", &sid
->id_auth
[idx
]);
639 for (idx
= 0; idx
< MAXSUBAUTHS
; idx
++) {
640 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "d", &sid
->sub_auths
[idx
]);
648 * Pack TRUSTED_DOM_PASS passed by pointer
650 * @param pack_buf pointer to buffer which is to be filled with packed data
651 * @param bufsize size of the buffer
652 * @param pass pointer to trusted domain password to be packed
654 * @return length of the packed representation of the whole structure
656 size_t tdb_trusted_dom_pass_pack(char* pack_buf
, int bufsize
, TRUSTED_DOM_PASS
* pass
)
660 if (!pack_buf
|| !pass
) return -1;
662 /* packing unicode domain name and password */
663 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "d", pass
->uni_name_len
);
665 for (idx
= 0; idx
< 32; idx
++)
666 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "w", pass
->uni_name
[idx
]);
668 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "dPd", pass
->pass_len
,
669 pass
->pass
, pass
->mod_time
);
671 /* packing SID structure */
672 len
+= tdb_sid_pack(pack_buf
+ len
, bufsize
- len
, &pass
->domain_sid
);
679 * Unpack TRUSTED_DOM_PASS passed by pointer
681 * @param pack_buf pointer to buffer with packed representation
682 * @param bufsize size of the buffer
683 * @param pass pointer to trusted domain password to be filled with unpacked data
685 * @return size of structure unpacked from buffer
687 size_t tdb_trusted_dom_pass_unpack(char* pack_buf
, int bufsize
, TRUSTED_DOM_PASS
* pass
)
691 if (!pack_buf
|| !pass
) return -1;
693 /* unpack unicode domain name and plaintext password */
694 len
+= tdb_unpack(pack_buf
, bufsize
- len
, "d", &pass
->uni_name_len
);
696 for (idx
= 0; idx
< 32; idx
++)
697 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "w", &pass
->uni_name
[idx
]);
699 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "dPd", &pass
->pass_len
, &pass
->pass
,
702 /* unpack domain sid */
703 len
+= tdb_sid_unpack(pack_buf
+ len
, bufsize
- len
, &pass
->domain_sid
);
709 /****************************************************************************
710 Log tdb messages via DEBUG().
711 ****************************************************************************/
713 static void tdb_log(TDB_CONTEXT
*tdb
, int level
, const char *format
, ...)
718 va_start(ap
, format
);
719 vasprintf(&ptr
, format
, ap
);
725 DEBUG(level
, ("tdb(%s): %s", tdb
->name
? tdb
->name
: "unnamed", ptr
));
729 /****************************************************************************
730 Like tdb_open() but also setup a logging function that redirects to
731 the samba DEBUG() system.
732 ****************************************************************************/
734 TDB_CONTEXT
*tdb_open_log(const char *name
, int hash_size
, int tdb_flags
,
735 int open_flags
, mode_t mode
)
740 tdb_flags
|= TDB_NOMMAP
;
742 tdb
= tdb_open_ex(name
, hash_size
, tdb_flags
,
743 open_flags
, mode
, tdb_log
);
751 /****************************************************************************
752 Allow tdb_delete to be used as a tdb_traversal_fn.
753 ****************************************************************************/
755 int tdb_traverse_delete_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA key
, TDB_DATA dbuf
,
758 return tdb_delete(the_tdb
, key
);
764 * Search across the whole tdb for keys that match the given pattern
765 * return the result as a list of keys
767 * @param tdb pointer to opened tdb file context
768 * @param pattern searching pattern used by fnmatch(3) functions
770 * @return list of keys found by looking up with given pattern
772 TDB_LIST_NODE
*tdb_search_keys(TDB_CONTEXT
*tdb
, const char* pattern
)
775 TDB_LIST_NODE
*list
= NULL
;
776 TDB_LIST_NODE
*rec
= NULL
;
777 TDB_LIST_NODE
*tmp
= NULL
;
779 for (key
= tdb_firstkey(tdb
); key
.dptr
; key
= next
) {
780 /* duplicate key string to ensure null-termination */
781 char *key_str
= (char*) strndup(key
.dptr
, key
.dsize
);
783 DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
784 smb_panic("strndup failed!\n");
787 DEBUG(18, ("checking %s for match to pattern %s\n", key_str
, pattern
));
789 next
= tdb_nextkey(tdb
, key
);
791 /* do the pattern checking */
792 if (fnmatch(pattern
, key_str
, 0) == 0) {
793 rec
= (TDB_LIST_NODE
*) malloc(sizeof(*rec
));
798 DLIST_ADD_END(list
, rec
, tmp
);
800 DEBUG(18, ("checking %s matched pattern %s\n", key_str
, pattern
));
805 /* free duplicated key string */
815 * Free the list returned by tdb_search_keys
817 * @param node list of results found by tdb_search_keys
819 void tdb_search_list_free(TDB_LIST_NODE
* node
)
821 TDB_LIST_NODE
*next_node
;
824 next_node
= node
->next
;
825 SAFE_FREE(node
->node_key
.dptr
);