lib/util_tdb.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    tdb utility functions
00004    Copyright (C) Andrew Tridgell   1992-1998
00005    Copyright (C) Rafal Szczesniak  2002
00006    
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016    
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 
00022 #include "includes.h"
00023 #undef malloc
00024 #undef realloc
00025 #undef calloc
00026 #undef strdup
00027 
00028 /* these are little tdb utility functions that are meant to make
00029    dealing with a tdb database a little less cumbersome in Samba */
00030 
00031 static SIG_ATOMIC_T gotalarm;
00032 
00033 /***************************************************************
00034  Signal function to tell us we timed out.
00035 ****************************************************************/
00036 
00037 static void gotalarm_sig(void)
00038 {
00039         gotalarm = 1;
00040 }
00041 
00042 /***************************************************************
00043  Make a TDB_DATA and keep the const warning in one place
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  Lock a chain with timeout (in seconds).
00061 ****************************************************************************/
00062 
00063 static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, unsigned int timeout, int rw_type)
00064 {
00065         /* Allow tdb_chainlock to be interrupted by an alarm. */
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                         /* TODO: If we time out waiting for a lock, it might
00088                          * be nice to use F_GETLK to get the pid of the
00089                          * process currently holding the lock and print that
00090                          * as part of the debugging message. -- mbp */
00091                         return -1;
00092                 }
00093         }
00094 
00095         return ret;
00096 }
00097 
00098 /****************************************************************************
00099  Write lock a chain. Return -1 if timeout or lock failed.
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  Lock a chain by string. Return -1 if timeout or lock failed.
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  Unlock a chain by string.
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  Read lock a chain by string. Return -1 if timeout or lock failed.
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  Read unlock a chain by string.
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  Fetch a int32 value by a arbitrary blob key, return -1 if not found.
00162  Output is int32 in native byte order.
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  Fetch a int32 value by string key, return -1 if not found.
00184  Output is int32 in native byte order.
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  Store a int32 value by an arbitary blob key, return 0 on success, -1 on failure.
00194  Input is int32 in native byte order. Output in tdb is in little-endian.
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  Store a int32 value by string key, return 0 on success, -1 on failure.
00212  Input is int32 in native byte order. Output in tdb is in little-endian.
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  Fetch a uint32 value by a arbitrary blob key, return -1 if not found.
00222  Output is uint32 in native byte order.
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  Fetch a uint32 value by string key, return -1 if not found.
00243  Output is uint32 in native byte order.
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  Store a uint32 value by an arbitary blob key, return 0 on success, -1 on failure.
00253  Input is uint32 in native byte order. Output in tdb is in little-endian.
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  Store a uint32 value by string key, return 0 on success, -1 on failure.
00275  Input is uint32 in native byte order. Output in tdb is in little-endian.
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  Store a buffer by a null terminated string key.  Return 0 on success, -1
00284  on failure.
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  Fetch a buffer using a null terminated string key.  Don't forget to call
00296  free() on the result dptr.
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  Delete an entry using a null terminated string key. 
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  Atomic integer change. Returns old value. To create, set initial value in *oldval. 
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                 /* The lookup failed */
00331                 if (tdb_error(tdb) != TDB_ERR_NOEXIST) {
00332                         /* but not because it didn't exist */
00333                         goto err_out;
00334                 }
00335                 
00336                 /* Start with 'old' value */
00337                 val = *oldval;
00338 
00339         } else {
00340                 /* It worked, set return value (oldval) to tdb data */
00341                 *oldval = val;
00342         }
00343 
00344         /* Increment value for storage and return next time */
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  Atomic unsigned integer change. Returns old value. To create, set initial value in *oldval. 
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                 /* It failed */
00372                 if (tdb_error(tdb) != TDB_ERR_NOEXIST) { 
00373                         /* and not because it didn't exist */
00374                         goto err_out;
00375                 }
00376 
00377                 /* Start with 'old' value */
00378                 val = *oldval;
00379 
00380         } else {
00381                 /* it worked, set return value (oldval) to tdb data */
00382                 *oldval = val;
00383 
00384         }
00385 
00386         /* get a new value to store */
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  Useful pair of routines for packing/unpacking data consisting of
00402  integers and strings.
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': /* unsigned 8-bit integer */
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': /* unsigned 16-bit integer */
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': /* signed 32-bit integer (standard int in most systems) */
00434                         len = 4;
00435                         d = va_arg(ap, uint32);
00436                         if (bufsize && bufsize >= len)
00437                                 SIVAL(buf, 0, d);
00438                         break;
00439                 case 'p': /* pointer */
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': /* null-terminated string */
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': /* null-terminated string */
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': /* fixed-length string */
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  Useful pair of routines for packing/unpacking data consisting of
00536  integers and strings.
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                          * This isn't a real pointer - only a token (1 or 0)
00586                          * to mark the fact a pointer is present.
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  Log tdb messages via DEBUG().
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  Like tdb_open() but also setup a logging function that redirects to
00670  the samba DEBUG() system.
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  Allow tdb_delete to be used as a tdb_traversal_fn.
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  * Search across the whole tdb for keys that match the given pattern
00707  * return the result as a list of keys
00708  *
00709  * @param tdb pointer to opened tdb file context
00710  * @param pattern searching pattern used by fnmatch(3) functions
00711  *
00712  * @return list of keys found by looking up with given pattern
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                 /* duplicate key string to ensure null-termination */
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                 /* do the pattern checking */
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                 /* free duplicated key string */
00747                 free(key_str);
00748         }
00749         
00750         return list;
00751 
00752 }
00753 
00754 
00755 /**
00756  * Free the list returned by tdb_search_keys
00757  *
00758  * @param node list of results found by tdb_search_keys
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  tdb_store, wrapped in a transaction. This way we make sure that a process
00774  that dies within writing does not leave a corrupt tdb behind.
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  tdb_delete, wrapped in a transaction. This way we make sure that a process
00804  that dies within deleting does not leave a corrupt tdb behind.
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  Log tdb messages via DEBUG().
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 /* destroy the last connection to a tdb */
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   wrapped connection to a tdb database
00884   to close just talloc_free() the tdb_wrap pointer
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                          * Yes, talloc_reference is exactly what we want
00898                          * here. Otherwise we would have to implement our own
00899                          * reference counting.
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 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7