00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "includes.h"
00023 #undef malloc
00024 #undef realloc
00025 #undef calloc
00026 #undef strdup
00027
00028
00029
00030
00031 static SIG_ATOMIC_T gotalarm;
00032
00033
00034
00035
00036
00037 static void gotalarm_sig(void)
00038 {
00039 gotalarm = 1;
00040 }
00041
00042
00043
00044
00045
00046 TDB_DATA make_tdb_data(const char *dptr, size_t dsize)
00047 {
00048 TDB_DATA ret;
00049 ret.dptr = CONST_DISCARD(char *, dptr);
00050 ret.dsize = dsize;
00051 return ret;
00052 }
00053
00054 TDB_DATA string_tdb_data(const char *string)
00055 {
00056 return make_tdb_data(string, strlen(string));
00057 }
00058
00059
00060
00061
00062
00063 static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type)
00064 {
00065
00066 int ret;
00067 gotalarm = 0;
00068
00069 if (timeout) {
00070 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
00071 tdb_setalarm_sigptr(tdb, &gotalarm);
00072 alarm(timeout);
00073 }
00074
00075 if (rw_type == F_RDLCK)
00076 ret = tdb_chainlock_read(tdb, key);
00077 else
00078 ret = tdb_chainlock(tdb, key);
00079
00080 if (timeout) {
00081 alarm(0);
00082 tdb_setalarm_sigptr(tdb, NULL);
00083 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
00084 if (gotalarm) {
00085 DEBUG(0,("tdb_chainlock_with_timeout_internal: alarm (%u) timed out for key %s in tdb %s\n",
00086 timeout, key.dptr, tdb_name(tdb)));
00087
00088
00089
00090
00091 return -1;
00092 }
00093 }
00094
00095 return ret;
00096 }
00097
00098
00099
00100
00101
00102 int tdb_chainlock_with_timeout( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout)
00103 {
00104 return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_WRLCK);
00105 }
00106
00107
00108
00109
00110
00111 int tdb_lock_bystring(TDB_CONTEXT *tdb, const char *keyval)
00112 {
00113 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
00114
00115 return tdb_chainlock(tdb, key);
00116 }
00117
00118 int tdb_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval,
00119 int timeout)
00120 {
00121 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
00122
00123 return tdb_chainlock_with_timeout(tdb, key, timeout);
00124 }
00125
00126
00127
00128
00129
00130 void tdb_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval)
00131 {
00132 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
00133
00134 tdb_chainunlock(tdb, key);
00135 }
00136
00137
00138
00139
00140
00141 int tdb_read_lock_bystring_with_timeout(TDB_CONTEXT *tdb, const char *keyval, unsigned int timeout)
00142 {
00143 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
00144
00145 return tdb_chainlock_with_timeout_internal(tdb, key, timeout, F_RDLCK);
00146 }
00147
00148
00149
00150
00151
00152 void tdb_read_unlock_bystring(TDB_CONTEXT *tdb, const char *keyval)
00153 {
00154 TDB_DATA key = make_tdb_data(keyval, strlen(keyval)+1);
00155
00156 tdb_chainunlock_read(tdb, key);
00157 }
00158
00159
00160
00161
00162
00163
00164
00165 int32 tdb_fetch_int32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len)
00166 {
00167 TDB_DATA key = make_tdb_data(keyval, len);
00168 TDB_DATA data;
00169 int32 ret;
00170
00171 data = tdb_fetch(tdb, key);
00172 if (!data.dptr || data.dsize != sizeof(int32)) {
00173 SAFE_FREE(data.dptr);
00174 return -1;
00175 }
00176
00177 ret = IVAL(data.dptr,0);
00178 SAFE_FREE(data.dptr);
00179 return ret;
00180 }
00181
00182
00183
00184
00185
00186
00187 int32 tdb_fetch_int32(TDB_CONTEXT *tdb, const char *keystr)
00188 {
00189 return tdb_fetch_int32_byblob(tdb, keystr, strlen(keystr) + 1);
00190 }
00191
00192
00193
00194
00195
00196
00197 int tdb_store_int32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, int32 v)
00198 {
00199 TDB_DATA key = make_tdb_data(keystr, len);
00200 TDB_DATA data;
00201 int32 v_store;
00202
00203 SIVAL(&v_store,0,v);
00204 data.dptr = (char *)&v_store;
00205 data.dsize = sizeof(int32);
00206
00207 return tdb_store(tdb, key, data, TDB_REPLACE);
00208 }
00209
00210
00211
00212
00213
00214
00215 int tdb_store_int32(TDB_CONTEXT *tdb, const char *keystr, int32 v)
00216 {
00217 return tdb_store_int32_byblob(tdb, keystr, strlen(keystr) + 1, v);
00218 }
00219
00220
00221
00222
00223
00224
00225 BOOL tdb_fetch_uint32_byblob(TDB_CONTEXT *tdb, const char *keyval, size_t len, uint32 *value)
00226 {
00227 TDB_DATA key = make_tdb_data(keyval, len);
00228 TDB_DATA data;
00229
00230 data = tdb_fetch(tdb, key);
00231 if (!data.dptr || data.dsize != sizeof(uint32)) {
00232 SAFE_FREE(data.dptr);
00233 return False;
00234 }
00235
00236 *value = IVAL(data.dptr,0);
00237 SAFE_FREE(data.dptr);
00238 return True;
00239 }
00240
00241
00242
00243
00244
00245
00246 BOOL tdb_fetch_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 *value)
00247 {
00248 return tdb_fetch_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
00249 }
00250
00251
00252
00253
00254
00255
00256 BOOL tdb_store_uint32_byblob(TDB_CONTEXT *tdb, const char *keystr, size_t len, uint32 value)
00257 {
00258 TDB_DATA key = make_tdb_data(keystr, len);
00259 TDB_DATA data;
00260 uint32 v_store;
00261 BOOL ret = True;
00262
00263 SIVAL(&v_store, 0, value);
00264 data.dptr = (char *)&v_store;
00265 data.dsize = sizeof(uint32);
00266
00267 if (tdb_store(tdb, key, data, TDB_REPLACE) == -1)
00268 ret = False;
00269
00270 return ret;
00271 }
00272
00273
00274
00275
00276
00277
00278 BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value)
00279 {
00280 return tdb_store_uint32_byblob(tdb, keystr, strlen(keystr) + 1, value);
00281 }
00282
00283
00284
00285
00286
00287 int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags)
00288 {
00289 TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
00290
00291 return tdb_store(tdb, key, data, flags);
00292 }
00293
00294
00295
00296
00297
00298
00299 TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr)
00300 {
00301 TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
00302
00303 return tdb_fetch(tdb, key);
00304 }
00305
00306
00307
00308
00309
00310 int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr)
00311 {
00312 TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1);
00313
00314 return tdb_delete(tdb, key);
00315 }
00316
00317
00318
00319
00320
00321 int32 tdb_change_int32_atomic(TDB_CONTEXT *tdb, const char *keystr, int32 *oldval, int32 change_val)
00322 {
00323 int32 val;
00324 int32 ret = -1;
00325
00326 if (tdb_lock_bystring(tdb, keystr) == -1)
00327 return -1;
00328
00329 if ((val = tdb_fetch_int32(tdb, keystr)) == -1) {
00330
00331 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
00332
00333 goto err_out;
00334 }
00335
00336
00337 val = *oldval;
00338
00339 } else {
00340
00341 *oldval = val;
00342 }
00343
00344
00345 val += change_val;
00346
00347 if (tdb_store_int32(tdb, keystr, val) == -1)
00348 goto err_out;
00349
00350 ret = 0;
00351
00352 err_out:
00353
00354 tdb_unlock_bystring(tdb, keystr);
00355 return ret;
00356 }
00357
00358
00359
00360
00361
00362 BOOL tdb_change_uint32_atomic(TDB_CONTEXT *tdb, const char *keystr, uint32 *oldval, uint32 change_val)
00363 {
00364 uint32 val;
00365 BOOL ret = False;
00366
00367 if (tdb_lock_bystring(tdb, keystr) == -1)
00368 return False;
00369
00370 if (!tdb_fetch_uint32(tdb, keystr, &val)) {
00371
00372 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
00373
00374 goto err_out;
00375 }
00376
00377
00378 val = *oldval;
00379
00380 } else {
00381
00382 *oldval = val;
00383
00384 }
00385
00386
00387 val += change_val;
00388
00389 if (!tdb_store_uint32(tdb, keystr, val))
00390 goto err_out;
00391
00392 ret = True;
00393
00394 err_out:
00395
00396 tdb_unlock_bystring(tdb, keystr);
00397 return ret;
00398 }
00399
00400
00401
00402
00403
00404
00405 size_t tdb_pack_va(char *buf, int bufsize, const char *fmt, va_list ap)
00406 {
00407 uint8 bt;
00408 uint16 w;
00409 uint32 d;
00410 int i;
00411 void *p;
00412 int len;
00413 char *s;
00414 char c;
00415 char *buf0 = buf;
00416 const char *fmt0 = fmt;
00417 int bufsize0 = bufsize;
00418
00419 while (*fmt) {
00420 switch ((c = *fmt++)) {
00421 case 'b':
00422 len = 1;
00423 bt = (uint8)va_arg(ap, int);
00424 if (bufsize && bufsize >= len)
00425 SSVAL(buf, 0, bt);
00426 break;
00427 case 'w':
00428 len = 2;
00429 w = (uint16)va_arg(ap, int);
00430 if (bufsize && bufsize >= len)
00431 SSVAL(buf, 0, w);
00432 break;
00433 case 'd':
00434 len = 4;
00435 d = va_arg(ap, uint32);
00436 if (bufsize && bufsize >= len)
00437 SIVAL(buf, 0, d);
00438 break;
00439 case 'p':
00440 len = 4;
00441 p = va_arg(ap, void *);
00442 d = p?1:0;
00443 if (bufsize && bufsize >= len)
00444 SIVAL(buf, 0, d);
00445 break;
00446 case 'P':
00447 s = va_arg(ap,char *);
00448 w = strlen(s);
00449 len = w + 1;
00450 if (bufsize && bufsize >= len)
00451 memcpy(buf, s, len);
00452 break;
00453 case 'f':
00454 s = va_arg(ap,char *);
00455 w = strlen(s);
00456 len = w + 1;
00457 if (bufsize && bufsize >= len)
00458 memcpy(buf, s, len);
00459 break;
00460 case 'B':
00461 i = va_arg(ap, int);
00462 s = va_arg(ap, char *);
00463 len = 4+i;
00464 if (bufsize && bufsize >= len) {
00465 SIVAL(buf, 0, i);
00466 memcpy(buf+4, s, i);
00467 }
00468 break;
00469 default:
00470 DEBUG(0,("Unknown tdb_pack format %c in %s\n",
00471 c, fmt));
00472 len = 0;
00473 break;
00474 }
00475
00476 buf += len;
00477 if (bufsize)
00478 bufsize -= len;
00479 if (bufsize < 0)
00480 bufsize = 0;
00481 }
00482
00483 DEBUG(18,("tdb_pack_va(%s, %d) -> %d\n",
00484 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
00485
00486 return PTR_DIFF(buf, buf0);
00487 }
00488
00489 size_t tdb_pack(char *buf, int bufsize, const char *fmt, ...)
00490 {
00491 va_list ap;
00492 size_t result;
00493
00494 va_start(ap, fmt);
00495 result = tdb_pack_va(buf, bufsize, fmt, ap);
00496 va_end(ap);
00497 return result;
00498 }
00499
00500 BOOL tdb_pack_append(TALLOC_CTX *mem_ctx, uint8 **buf, size_t *len,
00501 const char *fmt, ...)
00502 {
00503 va_list ap;
00504 size_t len1, len2;
00505
00506 va_start(ap, fmt);
00507 len1 = tdb_pack_va(NULL, 0, fmt, ap);
00508 va_end(ap);
00509
00510 if (mem_ctx != NULL) {
00511 *buf = TALLOC_REALLOC_ARRAY(mem_ctx, *buf, uint8,
00512 (*len) + len1);
00513 } else {
00514 *buf = SMB_REALLOC_ARRAY(*buf, uint8, (*len) + len1);
00515 }
00516
00517 if (*buf == NULL) {
00518 return False;
00519 }
00520
00521 va_start(ap, fmt);
00522 len2 = tdb_pack_va((char *)(*buf)+(*len), len1, fmt, ap);
00523 va_end(ap);
00524
00525 if (len1 != len2) {
00526 return False;
00527 }
00528
00529 *len += len2;
00530
00531 return True;
00532 }
00533
00534
00535
00536
00537
00538
00539 int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
00540 {
00541 va_list ap;
00542 uint8 *bt;
00543 uint16 *w;
00544 uint32 *d;
00545 int len;
00546 int *i;
00547 void **p;
00548 char *s, **b;
00549 char c;
00550 char *buf0 = buf;
00551 const char *fmt0 = fmt;
00552 int bufsize0 = bufsize;
00553
00554 va_start(ap, fmt);
00555
00556 while (*fmt) {
00557 switch ((c=*fmt++)) {
00558 case 'b':
00559 len = 1;
00560 bt = va_arg(ap, uint8 *);
00561 if (bufsize < len)
00562 goto no_space;
00563 *bt = SVAL(buf, 0);
00564 break;
00565 case 'w':
00566 len = 2;
00567 w = va_arg(ap, uint16 *);
00568 if (bufsize < len)
00569 goto no_space;
00570 *w = SVAL(buf, 0);
00571 break;
00572 case 'd':
00573 len = 4;
00574 d = va_arg(ap, uint32 *);
00575 if (bufsize < len)
00576 goto no_space;
00577 *d = IVAL(buf, 0);
00578 break;
00579 case 'p':
00580 len = 4;
00581 p = va_arg(ap, void **);
00582 if (bufsize < len)
00583 goto no_space;
00584
00585
00586
00587
00588
00589 *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL);
00590 break;
00591 case 'P':
00592 s = va_arg(ap,char *);
00593 len = strlen(buf) + 1;
00594 if (bufsize < len || len > sizeof(pstring))
00595 goto no_space;
00596 memcpy(s, buf, len);
00597 break;
00598 case 'f':
00599 s = va_arg(ap,char *);
00600 len = strlen(buf) + 1;
00601 if (bufsize < len || len > sizeof(fstring))
00602 goto no_space;
00603 memcpy(s, buf, len);
00604 break;
00605 case 'B':
00606 i = va_arg(ap, int *);
00607 b = va_arg(ap, char **);
00608 len = 4;
00609 if (bufsize < len)
00610 goto no_space;
00611 *i = IVAL(buf, 0);
00612 if (! *i) {
00613 *b = NULL;
00614 break;
00615 }
00616 len += *i;
00617 if (bufsize < len)
00618 goto no_space;
00619 *b = (char *)SMB_MALLOC(*i);
00620 if (! *b)
00621 goto no_space;
00622 memcpy(*b, buf+4, *i);
00623 break;
00624 default:
00625 DEBUG(0,("Unknown tdb_unpack format %c in %s\n",
00626 c, fmt));
00627
00628 len = 0;
00629 break;
00630 }
00631
00632 buf += len;
00633 bufsize -= len;
00634 }
00635
00636 va_end(ap);
00637
00638 DEBUG(18,("tdb_unpack(%s, %d) -> %d\n",
00639 fmt0, bufsize0, (int)PTR_DIFF(buf, buf0)));
00640
00641 return PTR_DIFF(buf, buf0);
00642
00643 no_space:
00644 return -1;
00645 }
00646
00647
00648
00649
00650
00651
00652 static void tdb_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...)
00653 {
00654 va_list ap;
00655 char *ptr = NULL;
00656
00657 va_start(ap, format);
00658 vasprintf(&ptr, format, ap);
00659 va_end(ap);
00660
00661 if (!ptr || !*ptr)
00662 return;
00663
00664 DEBUG((int)level, ("tdb(%s): %s", tdb_name(tdb) ? tdb_name(tdb) : "unnamed", ptr));
00665 SAFE_FREE(ptr);
00666 }
00667
00668
00669
00670
00671
00672
00673 TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
00674 int open_flags, mode_t mode)
00675 {
00676 TDB_CONTEXT *tdb;
00677 struct tdb_logging_context log_ctx;
00678
00679 if (!lp_use_mmap())
00680 tdb_flags |= TDB_NOMMAP;
00681
00682 log_ctx.log_fn = tdb_log;
00683 log_ctx.log_private = NULL;
00684
00685 tdb = tdb_open_ex(name, hash_size, tdb_flags,
00686 open_flags, mode, &log_ctx, NULL);
00687 if (!tdb)
00688 return NULL;
00689
00690 return tdb;
00691 }
00692
00693
00694
00695
00696
00697 int tdb_traverse_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf,
00698 void *state)
00699 {
00700 return tdb_delete(the_tdb, key);
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
00715 {
00716 TDB_DATA key, next;
00717 TDB_LIST_NODE *list = NULL;
00718 TDB_LIST_NODE *rec = NULL;
00719
00720 for (key = tdb_firstkey(tdb); key.dptr; key = next) {
00721
00722 char *key_str = (char*) SMB_STRNDUP(key.dptr, key.dsize);
00723 if (!key_str) {
00724 DEBUG(0, ("tdb_search_keys: strndup() failed!\n"));
00725 smb_panic("strndup failed!\n");
00726 }
00727
00728 DEBUG(18, ("checking %s for match to pattern %s\n", key_str, pattern));
00729
00730 next = tdb_nextkey(tdb, key);
00731
00732
00733 if (fnmatch(pattern, key_str, 0) == 0) {
00734 rec = SMB_MALLOC_P(TDB_LIST_NODE);
00735 ZERO_STRUCTP(rec);
00736
00737 rec->node_key = key;
00738
00739 DLIST_ADD_END(list, rec, TDB_LIST_NODE *);
00740
00741 DEBUG(18, ("checking %s matched pattern %s\n", key_str, pattern));
00742 } else {
00743 free(key.dptr);
00744 }
00745
00746
00747 free(key_str);
00748 }
00749
00750 return list;
00751
00752 }
00753
00754
00755
00756
00757
00758
00759
00760 void tdb_search_list_free(TDB_LIST_NODE* node)
00761 {
00762 TDB_LIST_NODE *next_node;
00763
00764 while (node) {
00765 next_node = node->next;
00766 SAFE_FREE(node->node_key.dptr);
00767 SAFE_FREE(node);
00768 node = next_node;
00769 };
00770 }
00771
00772
00773
00774
00775
00776
00777 int tdb_trans_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf,
00778 int flag)
00779 {
00780 int res;
00781
00782 if ((res = tdb_transaction_start(tdb)) != 0) {
00783 DEBUG(5, ("tdb_transaction_start failed\n"));
00784 return res;
00785 }
00786
00787 if ((res = tdb_store(tdb, key, dbuf, flag)) != 0) {
00788 DEBUG(10, ("tdb_store failed\n"));
00789 if (tdb_transaction_cancel(tdb) != 0) {
00790 smb_panic("Cancelling transaction failed\n");
00791 }
00792 return res;
00793 }
00794
00795 if ((res = tdb_transaction_commit(tdb)) != 0) {
00796 DEBUG(5, ("tdb_transaction_commit failed\n"));
00797 }
00798
00799 return res;
00800 }
00801
00802
00803
00804
00805
00806
00807 int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key)
00808 {
00809 int res;
00810
00811 if ((res = tdb_transaction_start(tdb)) != 0) {
00812 DEBUG(5, ("tdb_transaction_start failed\n"));
00813 return res;
00814 }
00815
00816 if ((res = tdb_delete(tdb, key)) != 0) {
00817 DEBUG(10, ("tdb_delete failed\n"));
00818 if (tdb_transaction_cancel(tdb) != 0) {
00819 smb_panic("Cancelling transaction failed\n");
00820 }
00821 return res;
00822 }
00823
00824 if ((res = tdb_transaction_commit(tdb)) != 0) {
00825 DEBUG(5, ("tdb_transaction_commit failed\n"));
00826 }
00827
00828 return res;
00829 }
00830
00831
00832
00833
00834 static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
00835 const char *format, ...) PRINTF_ATTRIBUTE(3,4);
00836
00837 static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level,
00838 const char *format, ...)
00839 {
00840 va_list ap;
00841 char *ptr = NULL;
00842 int debuglevel = 0;
00843
00844 va_start(ap, format);
00845 vasprintf(&ptr, format, ap);
00846 va_end(ap);
00847
00848 switch (level) {
00849 case TDB_DEBUG_FATAL:
00850 debuglevel = 0;
00851 break;
00852 case TDB_DEBUG_ERROR:
00853 debuglevel = 1;
00854 break;
00855 case TDB_DEBUG_WARNING:
00856 debuglevel = 2;
00857 break;
00858 case TDB_DEBUG_TRACE:
00859 debuglevel = 5;
00860 break;
00861 default:
00862 debuglevel = 0;
00863 }
00864
00865 if (ptr != NULL) {
00866 const char *name = tdb_name(tdb);
00867 DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr));
00868 free(ptr);
00869 }
00870 }
00871
00872 static struct tdb_wrap *tdb_list;
00873
00874
00875 static int tdb_wrap_destructor(struct tdb_wrap *w)
00876 {
00877 tdb_close(w->tdb);
00878 DLIST_REMOVE(tdb_list, w);
00879 return 0;
00880 }
00881
00882
00883
00884
00885
00886 struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx,
00887 const char *name, int hash_size, int tdb_flags,
00888 int open_flags, mode_t mode)
00889 {
00890 struct tdb_wrap *w;
00891 struct tdb_logging_context log_ctx;
00892 log_ctx.log_fn = tdb_wrap_log;
00893
00894 for (w=tdb_list;w;w=w->next) {
00895 if (strcmp(name, w->name) == 0) {
00896
00897
00898
00899
00900
00901 return talloc_reference(mem_ctx, w);
00902 }
00903 }
00904
00905 w = talloc(mem_ctx, struct tdb_wrap);
00906 if (w == NULL) {
00907 return NULL;
00908 }
00909
00910 if (!(w->name = talloc_strdup(w, name))) {
00911 talloc_free(w);
00912 return NULL;
00913 }
00914
00915 w->tdb = tdb_open_ex(name, hash_size, tdb_flags,
00916 open_flags, mode, &log_ctx, NULL);
00917 if (w->tdb == NULL) {
00918 talloc_free(w);
00919 return NULL;
00920 }
00921
00922 talloc_set_destructor(w, tdb_wrap_destructor);
00923
00924 DLIST_ADD(tdb_list, w);
00925
00926 return w;
00927 }