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 abartlet/fix-coverage dd10fb34 Lines: 48 62 77.4 %
Date: 2021-09-23 10:06:22 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         686 : static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
      29             : {
      30             :         va_list ap;
      31         686 :         const char *name = tdb_name(tdb);
      32         686 :         struct ldb_context *ldb = talloc_get_type(tdb_get_logging_private(tdb), struct ldb_context);
      33             :         enum ldb_debug_level ldb_level;
      34             :         char *message; 
      35             : 
      36         686 :         if (ldb == NULL)
      37           0 :                 return;
      38             : 
      39         686 :         va_start(ap, fmt);
      40         686 :         message = talloc_vasprintf(ldb, fmt, ap);
      41         686 :         va_end(ap);
      42             : 
      43         685 :         switch (level) {
      44           0 :         case TDB_DEBUG_FATAL:
      45           0 :                 ldb_level = LDB_DEBUG_FATAL;
      46           0 :                 break;
      47           5 :         case TDB_DEBUG_ERROR:
      48           5 :                 ldb_level = LDB_DEBUG_ERROR;
      49           5 :                 break;
      50         680 :         case TDB_DEBUG_WARNING:
      51         680 :                 ldb_level = LDB_DEBUG_WARNING;
      52         680 :                 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         686 :         ldb_debug(ldb, ldb_level, "ltdb: tdb(%s): %s", name, message);
      61         686 :         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      177756 : static int ltdb_wrap_destructor(struct ltdb_wrap *w)
      84             : {
      85      177756 :         tdb_close(w->tdb);
      86      177756 :         DLIST_REMOVE(tdb_list, w);
      87      177756 :         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      576188 : 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             :         struct ltdb_wrap *w;
     103             :         struct tdb_logging_context lctx;
     104             :         struct stat st;
     105             : 
     106      576188 :         if (stat(path, &st) == 0) {
     107     2254981 :                 for (w=tdb_list;w;w=w->next) {
     108     2162955 :                         if (st.st_dev == w->device && st.st_ino == w->inode) {
     109      478192 :                                 pid_t pid = getpid();
     110             :                                 int ret;
     111      478192 :                                 if (!talloc_reference(mem_ctx, w)) {
     112           0 :                                         return NULL;
     113             :                                 }
     114      478192 :                                 if (w->pid != pid) {
     115      104589 :                                         ret = tdb_reopen(w->tdb);
     116      104589 :                                         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      104588 :                                         w->pid = pid;
     127             :                                 }
     128      478191 :                                 return w->tdb;
     129             :                         }
     130             :                 }
     131             :         }
     132             : 
     133       97996 :         w = talloc(mem_ctx, struct ltdb_wrap);
     134       97996 :         if (w == NULL) {
     135           0 :                 return NULL;
     136             :         }
     137             : 
     138       97996 :         lctx.log_fn = ltdb_log_fn;
     139       97996 :         lctx.log_private = ldb;
     140       97996 :         w->tdb = tdb_open_ex(path, hash_size, tdb_flags, open_flags, mode,
     141             :                              &lctx, NULL);
     142       97996 :         if (w->tdb == NULL) {
     143         682 :                 talloc_free(w);
     144         682 :                 return NULL;
     145             :         }
     146             : 
     147      101658 :         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       97314 :         w->device = st.st_dev;
     154       97314 :         w->inode  = st.st_ino;
     155       97314 :         w->pid    = getpid();
     156             : 
     157       97314 :         talloc_set_destructor(w, ltdb_wrap_destructor);
     158             : 
     159       97314 :         DLIST_ADD(tdb_list, w);
     160             :         
     161       97314 :         return w->tdb;
     162             : }

Generated by: LCOV version 1.13