LCOV - code coverage report
Current view: top level - lib/ldb/ldb_tdb - ldb_tdb_wrap.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 55 69 79.7 %
Date: 2024-04-21 15:09:00 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* 
       2             :    ldb database library
       3             : 
       4             :    Copyright (C) Andrew Tridgell  2005
       5             : 
       6             :      ** NOTE! The following LGPL license applies to the ldb
       7             :      ** library. This does NOT imply that all of Samba is released
       8             :      ** under the LGPL
       9             :    
      10             :    This library is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU Lesser General Public
      12             :    License as published by the Free Software Foundation; either
      13             :    version 3 of the License, or (at your option) any later version.
      14             : 
      15             :    This library is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    Lesser General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU Lesser General Public
      21             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "ldb_tdb.h"
      25             : #include "dlinklist.h"
      26             : 
      27             : static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
      28        1015 : static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
      29             : {
      30           4 :         va_list ap;
      31        1015 :         const char *name = tdb_name(tdb);
      32        1015 :         struct ldb_context *ldb = talloc_get_type(tdb_get_logging_private(tdb), struct ldb_context);
      33           4 :         enum ldb_debug_level ldb_level;
      34           4 :         char *message; 
      35             : 
      36        1015 :         if (ldb == NULL)
      37           0 :                 return;
      38             : 
      39        1015 :         va_start(ap, fmt);
      40        1015 :         message = talloc_vasprintf(ldb, fmt, ap);
      41        1015 :         va_end(ap);
      42             : 
      43        1015 :         switch (level) {
      44           0 :         case TDB_DEBUG_FATAL:
      45           0 :                 ldb_level = LDB_DEBUG_FATAL;
      46           0 :                 break;
      47           4 :         case TDB_DEBUG_ERROR:
      48           4 :                 ldb_level = LDB_DEBUG_ERROR;
      49           4 :                 break;
      50        1007 :         case TDB_DEBUG_WARNING:
      51        1007 :                 ldb_level = LDB_DEBUG_WARNING;
      52        1007 :                 break;
      53           0 :         case TDB_DEBUG_TRACE:
      54           0 :                 ldb_level = LDB_DEBUG_TRACE;
      55           0 :                 break;
      56           0 :         default:
      57           0 :                 ldb_level = LDB_DEBUG_FATAL;
      58             :         }
      59             : 
      60        1015 :         ldb_debug(ldb, ldb_level, "ltdb: tdb(%s): %s", name, message);
      61        1015 :         talloc_free(message);
      62             : }
      63             : 
      64             : /*
      65             :   the purpose of this code is to work around the braindead posix locking
      66             :   rules, to allow us to have a ldb open more than once while allowing
      67             :   locking to work
      68             : 
      69             :   TDB2 handles multiple opens, so we don't have this problem there.
      70             : */
      71             : 
      72             : struct ltdb_wrap {
      73             :         struct ltdb_wrap *next, *prev;
      74             :         struct tdb_context *tdb;
      75             :         dev_t device;
      76             :         ino_t inode;
      77             :         pid_t pid;
      78             : };
      79             : 
      80             : static struct ltdb_wrap *tdb_list;
      81             : 
      82             : /* destroy the last connection to a tdb */
      83      226494 : static int ltdb_wrap_destructor(struct ltdb_wrap *w)
      84             : {
      85      226494 :         tdb_close(w->tdb);
      86      226494 :         DLIST_REMOVE(tdb_list, w);
      87      226494 :         return 0;
      88             : }
      89             : 
      90             : /*
      91             :   wrapped connection to a tdb database. The caller should _not_ free
      92             :   this as it is not a talloc structure (as tdb does not use talloc
      93             :   yet). It will auto-close when the caller frees the mem_ctx that is
      94             :   passed to this call
      95             :  */
      96      724449 : struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx,
      97             :                                    const char *path, int hash_size, 
      98             :                                    int tdb_flags,
      99             :                                    int open_flags, mode_t mode, 
     100             :                                    struct ldb_context *ldb)
     101             : {
     102       12197 :         struct ltdb_wrap *w;
     103       12197 :         struct tdb_logging_context lctx;
     104       12197 :         struct stat st;
     105             : 
     106      724449 :         if (stat(path, &st) == 0) {
     107     2767179 :                 for (w=tdb_list;w;w=w->next) {
     108     2650486 :                         if (st.st_dev == w->device && st.st_ino == w->inode) {
     109      602118 :                                 pid_t pid = getpid();
     110        6539 :                                 int ret;
     111      602118 :                                 if (!talloc_reference(mem_ctx, w)) {
     112           0 :                                         return NULL;
     113             :                                 }
     114      602118 :                                 if (w->pid != pid) {
     115      131983 :                                         ret = tdb_reopen(w->tdb);
     116      131983 :                                         if (ret != 0) {
     117             :                                                 /*
     118             :                                                  * Avoid use-after-free:
     119             :                                                  * on fail the TDB
     120             :                                                  * is closed!
     121             :                                                  */
     122           1 :                                                 DLIST_REMOVE(tdb_list,
     123             :                                                              w);
     124           1 :                                                 return NULL;
     125             :                                         }
     126      131982 :                                         w->pid = pid;
     127             :                                 }
     128      602117 :                                 return w->tdb;
     129             :                         }
     130             :                 }
     131             :         }
     132             : 
     133      122331 :         w = talloc(mem_ctx, struct ltdb_wrap);
     134      122331 :         if (w == NULL) {
     135           0 :                 return NULL;
     136             :         }
     137             : 
     138      122331 :         lctx.log_fn = ltdb_log_fn;
     139      122331 :         lctx.log_private = ldb;
     140      122331 :         w->tdb = tdb_open_ex(path, hash_size, tdb_flags, open_flags, mode,
     141             :                              &lctx, NULL);
     142      122331 :         if (w->tdb == NULL) {
     143        1011 :                 talloc_free(w);
     144        1011 :                 return NULL;
     145             :         }
     146             : 
     147      121320 :         if (fstat(tdb_fd(w->tdb), &st) != 0) {
     148           0 :                 tdb_close(w->tdb);
     149           0 :                 talloc_free(w);
     150           0 :                 return NULL;
     151             :         }
     152             : 
     153      121320 :         w->device = st.st_dev;
     154      121320 :         w->inode  = st.st_ino;
     155      121320 :         w->pid    = getpid();
     156             : 
     157      121320 :         talloc_set_destructor(w, ltdb_wrap_destructor);
     158             : 
     159      121320 :         DLIST_ADD(tdb_list, w);
     160             :         
     161      121320 :         return w->tdb;
     162             : }

Generated by: LCOV version 1.14