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 TDB_DATA
make_tdb_data(const char *dptr
, size_t dsize
)
46 ret
.dptr
= CONST_DISCARD(char *, dptr
);
51 TDB_DATA
string_tdb_data(const char *string
)
53 return make_tdb_data(string
, strlen(string
));
56 /****************************************************************************
57 Lock a chain with timeout (in seconds).
58 ****************************************************************************/
60 static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
, int rw_type
)
62 /* Allow tdb_chainlock to be interrupted by an alarm. */
65 tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm
));
68 CatchSignal(SIGALRM
, SIGNAL_CAST gotalarm_sig
);
72 if (rw_type
== F_RDLCK
)
73 ret
= tdb_chainlock_read(tdb
, key
);
75 ret
= tdb_chainlock(tdb
, key
);
79 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_IGN
);
81 DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",
82 timeout
, key
.dptr
, tdb
->name
));
83 /* TODO: If we time out waiting for a lock, it might
84 * be nice to use F_GETLK to get the pid of the
85 * process currently holding the lock and print that
86 * as part of the debugging message. -- mbp */
94 /****************************************************************************
95 Write lock a chain. Return -1 if timeout or lock failed.
96 ****************************************************************************/
98 int tdb_chainlock_with_timeout( TDB_CONTEXT
*tdb
, TDB_DATA key
, unsigned int timeout
)
100 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_WRLCK
);
103 /****************************************************************************
104 Lock a chain by string. Return -1 if timeout or lock failed.
105 ****************************************************************************/
107 int tdb_lock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
109 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
111 return tdb_chainlock(tdb
, key
);
114 int tdb_lock_bystring_with_timeout(TDB_CONTEXT
*tdb
, const char *keyval
,
117 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
119 return tdb_chainlock_with_timeout(tdb
, key
, timeout
);
122 /****************************************************************************
123 Unlock a chain by string.
124 ****************************************************************************/
126 void tdb_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
128 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
130 tdb_chainunlock(tdb
, key
);
133 /****************************************************************************
134 Read lock a chain by string. Return -1 if timeout or lock failed.
135 ****************************************************************************/
137 int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT
*tdb
, const char *keyval
, unsigned int timeout
)
139 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
141 return tdb_chainlock_with_timeout_internal(tdb
, key
, timeout
, F_RDLCK
);
144 /****************************************************************************
145 Read unlock a chain by string.
146 ****************************************************************************/
148 void tdb_read_unlock_bystring(TDB_CONTEXT
*tdb
, const char *keyval
)
150 TDB_DATA key
= make_tdb_data(keyval
, strlen(keyval
)+1);
152 tdb_chainunlock_read(tdb
, key
);
156 /****************************************************************************
157 Fetch a int32 value by a arbitrary blob key, return -1 if not found.
158 Output is int32 in native byte order.
159 ****************************************************************************/
161 int32
tdb_fetch_int32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
)
163 TDB_DATA key
= make_tdb_data(keyval
, len
);
167 data
= tdb_fetch(tdb
, key
);
168 if (!data
.dptr
|| data
.dsize
!= sizeof(int32
)) {
169 SAFE_FREE(data
.dptr
);
173 ret
= IVAL(data
.dptr
,0);
174 SAFE_FREE(data
.dptr
);
178 /****************************************************************************
179 Fetch a int32 value by string key, return -1 if not found.
180 Output is int32 in native byte order.
181 ****************************************************************************/
183 int32
tdb_fetch_int32(TDB_CONTEXT
*tdb
, const char *keystr
)
185 return tdb_fetch_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1);
188 /****************************************************************************
189 Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
190 Input is int32 in native byte order. Output in tdb is in little-endian.
191 ****************************************************************************/
193 int tdb_store_int32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, int32 v
)
195 TDB_DATA key
= make_tdb_data(keystr
, len
);
200 data
.dptr
= (void *)&v_store
;
201 data
.dsize
= sizeof(int32
);
203 return tdb_store(tdb
, key
, data
, TDB_REPLACE
);
206 /****************************************************************************
207 Store a int32 value by string key, return 0 on success, -1 on failure.
208 Input is int32 in native byte order. Output in tdb is in little-endian.
209 ****************************************************************************/
211 int tdb_store_int32(TDB_CONTEXT
*tdb
, const char *keystr
, int32 v
)
213 return tdb_store_int32_byblob(tdb
, keystr
, strlen(keystr
) + 1, v
);
216 /****************************************************************************
217 Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
218 Output is uint32 in native byte order.
219 ****************************************************************************/
221 BOOL
tdb_fetch_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keyval
, size_t len
, uint32
*value
)
223 TDB_DATA key
= make_tdb_data(keyval
, len
);
226 data
= tdb_fetch(tdb
, key
);
227 if (!data
.dptr
|| data
.dsize
!= sizeof(uint32
)) {
228 SAFE_FREE(data
.dptr
);
232 *value
= IVAL(data
.dptr
,0);
233 SAFE_FREE(data
.dptr
);
237 /****************************************************************************
238 Fetch a uint32 value by string key, return -1 if not found.
239 Output is uint32 in native byte order.
240 ****************************************************************************/
242 BOOL
tdb_fetch_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*value
)
244 return tdb_fetch_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
247 /****************************************************************************
248 Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
249 Input is uint32 in native byte order. Output in tdb is in little-endian.
250 ****************************************************************************/
252 BOOL
tdb_store_uint32_byblob(TDB_CONTEXT
*tdb
, const char *keystr
, size_t len
, uint32 value
)
254 TDB_DATA key
= make_tdb_data(keystr
, len
);
259 SIVAL(&v_store
, 0, value
);
260 data
.dptr
= (void *)&v_store
;
261 data
.dsize
= sizeof(uint32
);
263 if (tdb_store(tdb
, key
, data
, TDB_REPLACE
) == -1)
269 /****************************************************************************
270 Store a uint32 value by string key, return 0 on success, -1 on failure.
271 Input is uint32 in native byte order. Output in tdb is in little-endian.
272 ****************************************************************************/
274 BOOL
tdb_store_uint32(TDB_CONTEXT
*tdb
, const char *keystr
, uint32 value
)
276 return tdb_store_uint32_byblob(tdb
, keystr
, strlen(keystr
) + 1, value
);
278 /****************************************************************************
279 Store a buffer by a null terminated string key. Return 0 on success, -1
281 ****************************************************************************/
283 int tdb_store_bystring(TDB_CONTEXT
*tdb
, const char *keystr
, TDB_DATA data
, int flags
)
285 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
287 return tdb_store(tdb
, key
, data
, flags
);
290 /****************************************************************************
291 Fetch a buffer using a null terminated string key. Don't forget to call
292 free() on the result dptr.
293 ****************************************************************************/
295 TDB_DATA
tdb_fetch_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
297 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
299 return tdb_fetch(tdb
, key
);
302 /****************************************************************************
303 Delete an entry using a null terminated string key.
304 ****************************************************************************/
306 int tdb_delete_bystring(TDB_CONTEXT
*tdb
, const char *keystr
)
308 TDB_DATA key
= make_tdb_data(keystr
, strlen(keystr
)+1);
310 return tdb_delete(tdb
, key
);
313 /****************************************************************************
314 Atomic integer change. Returns old value. To create, set initial value in *oldval.
315 ****************************************************************************/
317 int32
tdb_change_int32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, int32
*oldval
, int32 change_val
)
322 if (tdb_lock_bystring(tdb
, keystr
) == -1)
325 if ((val
= tdb_fetch_int32(tdb
, keystr
)) == -1) {
326 /* The lookup failed */
327 if (tdb_error(tdb
) != TDB_ERR_NOEXIST
) {
328 /* but not because it didn't exist */
332 /* Start with 'old' value */
336 /* It worked, set return value (oldval) to tdb data */
340 /* Increment value for storage and return next time */
343 if (tdb_store_int32(tdb
, keystr
, val
) == -1)
350 tdb_unlock_bystring(tdb
, keystr
);
354 /****************************************************************************
355 Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval.
356 ****************************************************************************/
358 BOOL
tdb_change_uint32_atomic(TDB_CONTEXT
*tdb
, const char *keystr
, uint32
*oldval
, uint32 change_val
)
363 if (tdb_lock_bystring(tdb
, keystr
) == -1)
366 if (!tdb_fetch_uint32(tdb
, keystr
, &val
)) {
368 if (tdb_error(tdb
) != TDB_ERR_NOEXIST
) {
369 /* and not because it didn't exist */
373 /* Start with 'old' value */
377 /* it worked, set return value (oldval) to tdb data */
382 /* get a new value to store */
385 if (!tdb_store_uint32(tdb
, keystr
, val
))
392 tdb_unlock_bystring(tdb
, keystr
);
396 /****************************************************************************
397 Useful pair of routines for packing/unpacking data consisting of
398 integers and strings.
399 ****************************************************************************/
401 size_t tdb_pack_va(char *buf
, int bufsize
, const char *fmt
, va_list ap
)
412 const char *fmt0
= fmt
;
413 int bufsize0
= bufsize
;
416 switch ((c
= *fmt
++)) {
417 case 'b': /* unsigned 8-bit integer */
419 bt
= (uint8
)va_arg(ap
, int);
420 if (bufsize
&& bufsize
>= len
)
423 case 'w': /* unsigned 16-bit integer */
425 w
= (uint16
)va_arg(ap
, int);
426 if (bufsize
&& bufsize
>= len
)
429 case 'd': /* signed 32-bit integer (standard int in most systems) */
431 d
= va_arg(ap
, uint32
);
432 if (bufsize
&& bufsize
>= len
)
435 case 'p': /* pointer */
437 p
= va_arg(ap
, void *);
439 if (bufsize
&& bufsize
>= len
)
442 case 'P': /* null-terminated string */
443 s
= va_arg(ap
,char *);
446 if (bufsize
&& bufsize
>= len
)
449 case 'f': /* null-terminated string */
450 s
= va_arg(ap
,char *);
453 if (bufsize
&& bufsize
>= len
)
456 case 'B': /* fixed-length string */
458 s
= va_arg(ap
, char *);
460 if (bufsize
&& bufsize
>= len
) {
466 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
479 DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n",
480 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
482 return PTR_DIFF(buf
, buf0
);
485 size_t tdb_pack(char *buf
, int bufsize
, const char *fmt
, ...)
491 result
= tdb_pack_va(buf
, bufsize
, fmt
, ap
);
496 BOOL
tdb_pack_append(TALLOC_CTX
*mem_ctx
, uint8
**buf
, size_t *len
,
497 const char *fmt
, ...)
503 len1
= tdb_pack_va(NULL
, 0, fmt
, ap
);
506 if (mem_ctx
!= NULL
) {
507 *buf
= TALLOC_REALLOC_ARRAY(mem_ctx
, *buf
, uint8
,
510 *buf
= SMB_REALLOC_ARRAY(*buf
, uint8
, (*len
) + len1
);
518 len2
= tdb_pack_va((char *)(*buf
)+(*len
), len1
, fmt
, ap
);
530 /****************************************************************************
531 Useful pair of routines for packing/unpacking data consisting of
532 integers and strings.
533 ****************************************************************************/
535 int tdb_unpack(char *buf
, int bufsize
, const char *fmt
, ...)
547 const char *fmt0
= fmt
;
548 int bufsize0
= bufsize
;
553 switch ((c
=*fmt
++)) {
556 bt
= va_arg(ap
, uint8
*);
563 w
= va_arg(ap
, uint16
*);
570 d
= va_arg(ap
, uint32
*);
577 p
= va_arg(ap
, void **);
581 * This isn't a real pointer - only a token (1 or 0)
582 * to mark the fact a pointer is present.
585 *p
= (void *)(IVAL(buf
, 0) ? (void *)1 : NULL
);
588 s
= va_arg(ap
,char *);
589 len
= strlen(buf
) + 1;
590 if (bufsize
< len
|| len
> sizeof(pstring
))
595 s
= va_arg(ap
,char *);
596 len
= strlen(buf
) + 1;
597 if (bufsize
< len
|| len
> sizeof(fstring
))
602 i
= va_arg(ap
, int *);
603 b
= va_arg(ap
, char **);
615 *b
= (char *)SMB_MALLOC(*i
);
618 memcpy(*b
, buf
+4, *i
);
621 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
634 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
635 fmt0
, bufsize0
, (int)PTR_DIFF(buf
, buf0
)));
637 return PTR_DIFF(buf
, buf0
);
645 * Pack SID passed by pointer
647 * @param pack_buf pointer to buffer which is to be filled with packed data
648 * @param bufsize size of packing buffer
649 * @param sid pointer to sid to be packed
651 * @return length of the packed representation of the whole structure
653 size_t tdb_sid_pack(char* pack_buf
, int bufsize
, DOM_SID
* sid
)
658 if (!sid
|| !pack_buf
) return -1;
660 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "bb", sid
->sid_rev_num
,
663 for (idx
= 0; idx
< 6; idx
++) {
664 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "b", sid
->id_auth
[idx
]);
667 for (idx
= 0; idx
< MAXSUBAUTHS
; idx
++) {
668 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "d", sid
->sub_auths
[idx
]);
676 * Unpack SID into a pointer
678 * @param pack_buf pointer to buffer with packed representation
679 * @param bufsize size of the buffer
680 * @param sid pointer to sid structure to be filled with unpacked data
682 * @return size of structure unpacked from buffer
684 size_t tdb_sid_unpack(char* pack_buf
, int bufsize
, DOM_SID
* sid
)
688 if (!sid
|| !pack_buf
) return -1;
690 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "bb",
691 &sid
->sid_rev_num
, &sid
->num_auths
);
693 for (idx
= 0; idx
< 6; idx
++) {
694 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "b", &sid
->id_auth
[idx
]);
697 for (idx
= 0; idx
< MAXSUBAUTHS
; idx
++) {
698 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "d", &sid
->sub_auths
[idx
]);
706 * Pack TRUSTED_DOM_PASS passed by pointer
708 * @param pack_buf pointer to buffer which is to be filled with packed data
709 * @param bufsize size of the buffer
710 * @param pass pointer to trusted domain password to be packed
712 * @return length of the packed representation of the whole structure
714 size_t tdb_trusted_dom_pass_pack(char* pack_buf
, int bufsize
, TRUSTED_DOM_PASS
* pass
)
718 if (!pack_buf
|| !pass
) return -1;
720 /* packing unicode domain name and password */
721 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "d", pass
->uni_name_len
);
723 for (idx
= 0; idx
< 32; idx
++)
724 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "w", pass
->uni_name
[idx
]);
726 len
+= tdb_pack(pack_buf
+ len
, bufsize
- len
, "dPd", pass
->pass_len
,
727 pass
->pass
, pass
->mod_time
);
729 /* packing SID structure */
730 len
+= tdb_sid_pack(pack_buf
+ len
, bufsize
- len
, &pass
->domain_sid
);
737 * Unpack TRUSTED_DOM_PASS passed by pointer
739 * @param pack_buf pointer to buffer with packed representation
740 * @param bufsize size of the buffer
741 * @param pass pointer to trusted domain password to be filled with unpacked data
743 * @return size of structure unpacked from buffer
745 size_t tdb_trusted_dom_pass_unpack(char* pack_buf
, int bufsize
, TRUSTED_DOM_PASS
* pass
)
749 if (!pack_buf
|| !pass
) return -1;
751 /* unpack unicode domain name and plaintext password */
752 len
+= tdb_unpack(pack_buf
, bufsize
- len
, "d", &pass
->uni_name_len
);
754 for (idx
= 0; idx
< 32; idx
++)
755 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "w", &pass
->uni_name
[idx
]);
757 len
+= tdb_unpack(pack_buf
+ len
, bufsize
- len
, "dPd", &pass
->pass_len
, &pass
->pass
,
760 /* unpack domain sid */
761 len
+= tdb_sid_unpack(pack_buf
+ len
, bufsize
- len
, &pass
->domain_sid
);
767 /****************************************************************************
768 Log tdb messages via DEBUG().
769 ****************************************************************************/
771 static void tdb_log(TDB_CONTEXT
*tdb
, int level
, const char *format
, ...)
776 va_start(ap
, format
);
777 vasprintf(&ptr
, format
, ap
);
783 DEBUG(level
, ("tdb(%s): %s", tdb
->name
? tdb
->name
: "unnamed", ptr
));
787 /****************************************************************************
788 Like tdb_open() but also setup a logging function that redirects to
789 the samba DEBUG() system.
790 ****************************************************************************/
792 TDB_CONTEXT
*tdb_open_log(const char *name
, int hash_size
, int tdb_flags
,
793 int open_flags
, mode_t mode
)
798 tdb_flags
|= TDB_NOMMAP
;
800 tdb
= tdb_open_ex(name
, hash_size
, tdb_flags
,
801 open_flags
, mode
, tdb_log
, NULL
);
808 /****************************************************************************
809 return the name of the current tdb file useful for external logging
811 ****************************************************************************/
812 const char *tdb_name(struct tdb_context
*tdb
)
817 /****************************************************************************
818 Allow tdb_delete to be used as a tdb_traversal_fn.
819 ****************************************************************************/
821 int tdb_traverse_delete_fn(TDB_CONTEXT
*the_tdb
, TDB_DATA key
, TDB_DATA dbuf
,
824 return tdb_delete(the_tdb
, key
);
830 * Search across the whole tdb for keys that match the given pattern
831 * return the result as a list of keys
833 * @param tdb pointer to opened tdb file context
834 * @param pattern searching pattern used by fnmatch(3) functions
836 * @return list of keys found by looking up with given pattern
838 TDB_LIST_NODE
*tdb_search_keys(TDB_CONTEXT
*tdb
, const char* pattern
)
841 TDB_LIST_NODE
*list
= NULL
;
842 TDB_LIST_NODE
*rec
= NULL
;
843 TDB_LIST_NODE
*tmp
= NULL
;
845 for (key
= tdb_firstkey(tdb
); key
.dptr
; key
= next
) {
846 /* duplicate key string to ensure null-termination */
847 char *key_str
= (char*) SMB_STRNDUP(key
.dptr
, key
.dsize
);
849 DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
850 smb_panic("strndup failed!\n");
853 DEBUG(18, ("checking %s for match to pattern %s\n", key_str
, pattern
));
855 next
= tdb_nextkey(tdb
, key
);
857 /* do the pattern checking */
858 if (fnmatch(pattern
, key_str
, 0) == 0) {
859 rec
= SMB_MALLOC_P(TDB_LIST_NODE
);
864 DLIST_ADD_END(list
, rec
, tmp
);
866 DEBUG(18, ("checking %s matched pattern %s\n", key_str
, pattern
));
871 /* free duplicated key string */
881 * Free the list returned by tdb_search_keys
883 * @param node list of results found by tdb_search_keys
885 void tdb_search_list_free(TDB_LIST_NODE
* node
)
887 TDB_LIST_NODE
*next_node
;
890 next_node
= node
->next
;
891 SAFE_FREE(node
->node_key
.dptr
);