LCOV - code coverage report
Current view: top level - lib/dbwrap - dbwrap.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 140 267 52.4 %
Date: 2024-06-13 04:01:37 Functions: 29 45 64.4 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Database interface wrapper
       4             :    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
       5             : 
       6             :    Major code contributions from Aleksey Fedoseev (fedoseev@ru.ibm.com)
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "replace.h"
      23             : #include "lib/util/debug.h"
      24             : #include "lib/util/fault.h"
      25             : #include "lib/util/talloc_stack.h"
      26             : #include "dbwrap/dbwrap.h"
      27             : #include "dbwrap/dbwrap_private.h"
      28             : #include "lib/util/util_tdb.h"
      29             : #include "lib/util/tevent_ntstatus.h"
      30             : 
      31             : /*
      32             :  * Fall back using fetch if no genuine exists operation is provided
      33             :  */
      34             : 
      35           0 : static int dbwrap_fallback_exists(struct db_context *db, TDB_DATA key)
      36             : {
      37           0 :         NTSTATUS status = dbwrap_parse_record(db, key, NULL, NULL);
      38           0 :         return NT_STATUS_IS_OK(status) ? 1 : 0;
      39             : }
      40             : 
      41           0 : static int delete_record(struct db_record *rec, void *data)
      42             : {
      43           0 :         NTSTATUS status = dbwrap_record_delete(rec);
      44           0 :         return NT_STATUS_IS_OK(status) ? 0 : -1;
      45             : }
      46             : 
      47             : /*
      48             :  * Fallback wipe implementation using traverse and delete if no genuine
      49             :  * wipe operation is provided
      50             :  */
      51           0 : static int dbwrap_fallback_wipe(struct db_context *db)
      52             : {
      53           0 :         NTSTATUS status = dbwrap_trans_traverse(db, delete_record, NULL);
      54           0 :         return NT_STATUS_IS_OK(status) ? 0 : -1;
      55             : }
      56             : 
      57           0 : static int do_nothing(struct db_record *rec, void *unused)
      58             : {
      59           0 :         return 0;
      60             : }
      61             : 
      62             : /*
      63             :  * Fallback check operation: just traverse.
      64             :  */
      65           0 : static int dbwrap_fallback_check(struct db_context *db)
      66             : {
      67           0 :         NTSTATUS status = dbwrap_traverse_read(db, do_nothing, NULL, NULL);
      68           0 :         return NT_STATUS_IS_OK(status) ? 0 : -1;
      69             : }
      70             : 
      71             : /*
      72             :  * Wrapper functions for the backend methods
      73             :  */
      74             : 
      75      380388 : TDB_DATA dbwrap_record_get_key(const struct db_record *rec)
      76             : {
      77      380388 :         return rec->key;
      78             : }
      79             : 
      80     8238206 : TDB_DATA dbwrap_record_get_value(const struct db_record *rec)
      81             : {
      82     8238206 :         SMB_ASSERT(rec->value_valid);
      83     8238206 :         return rec->value;
      84             : }
      85             : 
      86     1936167 : NTSTATUS dbwrap_record_storev(struct db_record *rec,
      87             :                               const TDB_DATA *dbufs, int num_dbufs, int flags)
      88             : {
      89             :         NTSTATUS status;
      90             : 
      91             :         /*
      92             :          * Invalidate before rec->storev() is called, give
      93             :          * rec->storev() the chance to re-validate rec->value.
      94             :          */
      95     1936167 :         rec->value_valid = false;
      96             : 
      97     1936167 :         status = rec->storev(rec, dbufs, num_dbufs, flags);
      98     1936167 :         if (!NT_STATUS_IS_OK(status)) {
      99           0 :                 return status;
     100             :         }
     101     1936167 :         return NT_STATUS_OK;
     102             : }
     103             : 
     104     1735066 : NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
     105             : {
     106     1735066 :         return dbwrap_record_storev(rec, &data, 1, flags);
     107             : }
     108             : 
     109      360967 : NTSTATUS dbwrap_record_delete(struct db_record *rec)
     110             : {
     111             :         NTSTATUS status;
     112             : 
     113      360967 :         status = rec->delete_rec(rec);
     114      360967 :         if (!NT_STATUS_IS_OK(status)) {
     115       35684 :                 return status;
     116             :         }
     117             : 
     118      325283 :         rec->value = tdb_null;
     119             : 
     120      325283 :         return NT_STATUS_OK;
     121             : }
     122             : 
     123             : const char *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
     124             : 
     125      137812 : static void debug_lock_order(int level)
     126             : {
     127             :         int i;
     128      137812 :         DEBUG(level, ("lock order: "));
     129      689060 :         for (i=0; i<DBWRAP_LOCK_ORDER_MAX; i++) {
     130      551248 :                 DEBUGADD(level,
     131             :                          (" %d:%s",
     132             :                           i + 1,
     133             :                           locked_dbs[i] ? locked_dbs[i] : "<none>"));
     134             :         }
     135      137812 :         DEBUGADD(level, ("\n"));
     136      137812 : }
     137             : 
     138      137812 : void dbwrap_lock_order_lock(const char *db_name,
     139             :                             enum dbwrap_lock_order lock_order)
     140             : {
     141             :         int idx;
     142             : 
     143      137812 :         DBG_INFO("check lock order %d for %s\n",
     144             :                  (int)lock_order,
     145             :                  db_name);
     146             : 
     147      137812 :         if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
     148           0 :                 DBG_ERR("Invalid lock order %d of %s\n",
     149             :                         lock_order,
     150             :                         db_name);
     151           0 :                 smb_panic("lock order violation");
     152             :         }
     153             : 
     154      674906 :         for (idx=lock_order-1; idx<DBWRAP_LOCK_ORDER_MAX; idx++) {
     155      537094 :                 if (locked_dbs[idx] != NULL) {
     156           0 :                         DBG_ERR("Lock order violation: Trying %s at %d while "
     157             :                                 "%s at %d is locked\n",
     158             :                                 db_name,
     159             :                                 (int)lock_order,
     160             :                                 locked_dbs[idx],
     161             :                                 idx + 1);
     162           0 :                         debug_lock_order(0);
     163           0 :                         smb_panic("lock order violation");
     164             :                 }
     165             :         }
     166             : 
     167      137812 :         locked_dbs[lock_order-1] = db_name;
     168             : 
     169      137812 :         debug_lock_order(10);
     170      137812 : }
     171             : 
     172      137812 : void dbwrap_lock_order_unlock(const char *db_name,
     173             :                               enum dbwrap_lock_order lock_order)
     174             : {
     175      137812 :         DBG_INFO("release lock order %d for %s\n",
     176             :                  (int)lock_order,
     177             :                  db_name);
     178             : 
     179      137812 :         if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
     180           0 :                 DBG_ERR("Invalid lock order %d of %s\n",
     181             :                         lock_order,
     182             :                         db_name);
     183           0 :                 smb_panic("lock order violation");
     184             :         }
     185             : 
     186      137812 :         if (locked_dbs[lock_order-1] == NULL) {
     187           0 :                 DBG_ERR("db %s at order %d unlocked\n",
     188             :                         db_name,
     189             :                         (int)lock_order);
     190           0 :                 smb_panic("lock order violation");
     191             :         }
     192             : 
     193      137812 :         if (locked_dbs[lock_order-1] != db_name) {
     194           0 :                 DBG_ERR("locked db at lock order %d is %s, expected %s\n",
     195             :                         (int)lock_order,
     196             :                         locked_dbs[lock_order-1],
     197             :                         db_name);
     198           0 :                 smb_panic("lock order violation");
     199             :         }
     200             : 
     201      137812 :         locked_dbs[lock_order-1] = NULL;
     202      137812 : }
     203             : 
     204             : struct dbwrap_lock_order_state {
     205             :         struct db_context *db;
     206             : };
     207             : 
     208      101145 : static int dbwrap_lock_order_state_destructor(
     209             :         struct dbwrap_lock_order_state *s)
     210             : {
     211      101145 :         struct db_context *db = s->db;
     212      101145 :         dbwrap_lock_order_unlock(db->name, db->lock_order);
     213      101145 :         return 0;
     214             : }
     215             : 
     216      101145 : static struct dbwrap_lock_order_state *dbwrap_check_lock_order(
     217             :         struct db_context *db, TALLOC_CTX *mem_ctx)
     218             : {
     219             :         struct dbwrap_lock_order_state *state;
     220             : 
     221      101145 :         state = talloc(mem_ctx, struct dbwrap_lock_order_state);
     222      101145 :         if (state == NULL) {
     223           0 :                 DBG_WARNING("talloc failed\n");
     224           0 :                 return NULL;
     225             :         }
     226      101145 :         state->db = db;
     227             : 
     228      101145 :         dbwrap_lock_order_lock(db->name, db->lock_order);
     229      101145 :         talloc_set_destructor(state, dbwrap_lock_order_state_destructor);
     230             : 
     231      101145 :         return state;
     232             : }
     233             : 
     234     9668428 : static struct db_record *dbwrap_fetch_locked_internal(
     235             :         struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key,
     236             :         struct db_record *(*db_fn)(struct db_context *db, TALLOC_CTX *mem_ctx,
     237             :                                    TDB_DATA key))
     238             : {
     239             :         struct db_record *rec;
     240     9668428 :         struct dbwrap_lock_order_state *lock_order = NULL;
     241             : 
     242     9668428 :         if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     243      101145 :                 lock_order = dbwrap_check_lock_order(db, mem_ctx);
     244      101145 :                 if (lock_order == NULL) {
     245           0 :                         return NULL;
     246             :                 }
     247             :         }
     248     9668428 :         rec = db_fn(db, mem_ctx, key);
     249     9668428 :         if (rec == NULL) {
     250           0 :                 TALLOC_FREE(lock_order);
     251           0 :                 return NULL;
     252             :         }
     253     9668428 :         (void)talloc_steal(rec, lock_order);
     254     9668428 :         rec->db = db;
     255     9668428 :         return rec;
     256             : }
     257             : 
     258     9668428 : struct db_record *dbwrap_fetch_locked(struct db_context *db,
     259             :                                       TALLOC_CTX *mem_ctx,
     260             :                                       TDB_DATA key)
     261             : {
     262     9668428 :         return dbwrap_fetch_locked_internal(db, mem_ctx, key,
     263             :                                             db->fetch_locked);
     264             : }
     265             : 
     266      135060 : struct db_context *dbwrap_record_get_db(struct db_record *rec)
     267             : {
     268      135060 :         return rec->db;
     269             : }
     270             : 
     271             : struct dbwrap_fetch_state {
     272             :         TALLOC_CTX *mem_ctx;
     273             :         TDB_DATA data;
     274             : };
     275             : 
     276      619705 : static void dbwrap_fetch_parser(TDB_DATA key, TDB_DATA data,
     277             :                                 void *private_data)
     278             : {
     279      619705 :         struct dbwrap_fetch_state *state =
     280             :                 (struct dbwrap_fetch_state *)private_data;
     281             : 
     282      619705 :         state->data.dsize = data.dsize;
     283      619705 :         state->data.dptr = (uint8_t *)talloc_memdup(state->mem_ctx, data.dptr,
     284             :                                                     data.dsize);
     285      619705 : }
     286             : 
     287     1418367 : NTSTATUS dbwrap_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
     288             :                       TDB_DATA key, TDB_DATA *value)
     289             : {
     290             :         struct dbwrap_fetch_state state;
     291             :         NTSTATUS status;
     292             : 
     293     1418367 :         if (value == NULL) {
     294           0 :                 return NT_STATUS_INVALID_PARAMETER;
     295             :         }
     296             : 
     297     1418367 :         state.mem_ctx = mem_ctx;
     298             : 
     299     1418367 :         status = dbwrap_parse_record(db, key, dbwrap_fetch_parser, &state);
     300     1418367 :         if (!NT_STATUS_IS_OK(status)) {
     301      798662 :                 return status;
     302             :         }
     303      619705 :         if ((state.data.dsize != 0) && (state.data.dptr == NULL)) {
     304           0 :                 return NT_STATUS_NO_MEMORY;
     305             :         }
     306      619705 :         *value = state.data;
     307      619705 :         return NT_STATUS_OK;
     308             : }
     309             : 
     310      790706 : bool dbwrap_exists(struct db_context *db, TDB_DATA key)
     311             : {
     312             :         int result;
     313      790706 :         if (db->exists != NULL) {
     314      790706 :                 result = db->exists(db, key);
     315             :         } else {
     316           0 :                 result = dbwrap_fallback_exists(db,key);
     317             :         }
     318      790706 :         return (result == 1);
     319             : }
     320             : 
     321             : struct dbwrap_store_state {
     322             :         TDB_DATA data;
     323             :         int flags;
     324             :         NTSTATUS status;
     325             : };
     326             : 
     327     1409864 : static void dbwrap_store_fn(
     328             :         struct db_record *rec,
     329             :         TDB_DATA value,
     330             :         void *private_data)
     331             : {
     332     1409864 :         struct dbwrap_store_state *state = private_data;
     333     1409864 :         state->status = dbwrap_record_store(rec, state->data, state->flags);
     334     1409864 : }
     335             : 
     336     1409864 : NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
     337             :                       TDB_DATA data, int flags)
     338             : {
     339     1409864 :         struct dbwrap_store_state state = { .data = data, .flags = flags };
     340             :         NTSTATUS status;
     341             : 
     342     1409864 :         status = dbwrap_do_locked(db, key, dbwrap_store_fn, &state);
     343     1409864 :         if (!NT_STATUS_IS_OK(status)) {
     344           0 :                 return status;
     345             :         }
     346             : 
     347     1409864 :         return state.status;
     348             : }
     349             : 
     350             : struct dbwrap_delete_state {
     351             :         NTSTATUS status;
     352             : };
     353             : 
     354       65507 : static void dbwrap_delete_fn(
     355             :         struct db_record *rec,
     356             :         TDB_DATA value,
     357             :         void *private_data)
     358             : {
     359       65507 :         struct dbwrap_delete_state *state = private_data;
     360       65507 :         state->status = dbwrap_record_delete(rec);
     361       65507 : }
     362             : 
     363       65507 : NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key)
     364             : {
     365       65507 :         struct dbwrap_delete_state state = { .status = NT_STATUS_NOT_FOUND };
     366             :         NTSTATUS status;
     367             : 
     368       65507 :         status = dbwrap_do_locked(db, key, dbwrap_delete_fn, &state);
     369       65507 :         if (!NT_STATUS_IS_OK(status)) {
     370           0 :                 return status;
     371             :         }
     372             : 
     373       65507 :         return state.status;
     374             : }
     375             : 
     376       16048 : NTSTATUS dbwrap_traverse(struct db_context *db,
     377             :                          int (*f)(struct db_record*, void*),
     378             :                          void *private_data,
     379             :                          int *count)
     380             : {
     381       16048 :         int ret = db->traverse(db, f, private_data);
     382             : 
     383       16048 :         if (ret < 0) {
     384           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     385             :         }
     386             : 
     387       16048 :         if (count != NULL) {
     388       15852 :                 *count = ret;
     389             :         }
     390             : 
     391       16048 :         return NT_STATUS_OK;
     392             : }
     393             : 
     394        3310 : NTSTATUS dbwrap_traverse_read(struct db_context *db,
     395             :                               int (*f)(struct db_record*, void*),
     396             :                               void *private_data,
     397             :                               int *count)
     398             : {
     399        3310 :         int ret = db->traverse_read(db, f, private_data);
     400             : 
     401        3310 :         if (ret < 0) {
     402           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     403             :         }
     404             : 
     405        3310 :         if (count != NULL) {
     406         277 :                 *count = ret;
     407             :         }
     408             : 
     409        3310 :         return NT_STATUS_OK;
     410             : }
     411             : 
     412           0 : static void dbwrap_null_parser(TDB_DATA key, TDB_DATA val, void* data)
     413             : {
     414           0 :         return;
     415             : }
     416             : 
     417     4293040 : NTSTATUS dbwrap_parse_record(struct db_context *db, TDB_DATA key,
     418             :                              void (*parser)(TDB_DATA key, TDB_DATA data,
     419             :                                             void *private_data),
     420             :                              void *private_data)
     421             : {
     422     4293040 :         if (parser == NULL) {
     423           0 :                 parser = dbwrap_null_parser;
     424             :         }
     425     4293040 :         return db->parse_record(db, key, parser, private_data);
     426             : }
     427             : 
     428             : struct dbwrap_parse_record_state {
     429             :         struct db_context *db;
     430             :         TDB_DATA key;
     431             :         uint8_t _keybuf[64];
     432             : };
     433             : 
     434             : static void dbwrap_parse_record_done(struct tevent_req *subreq);
     435             : 
     436           0 : struct tevent_req *dbwrap_parse_record_send(
     437             :         TALLOC_CTX *mem_ctx,
     438             :         struct tevent_context *ev,
     439             :         struct db_context *db,
     440             :         TDB_DATA key,
     441             :         void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data),
     442             :         void *private_data,
     443             :         enum dbwrap_req_state *req_state)
     444             : {
     445           0 :         struct tevent_req *req = NULL;
     446           0 :         struct tevent_req *subreq = NULL;
     447           0 :         struct dbwrap_parse_record_state *state = NULL;
     448             :         NTSTATUS status;
     449             : 
     450           0 :         req = tevent_req_create(mem_ctx, &state, struct dbwrap_parse_record_state);
     451           0 :         if (req == NULL) {
     452           0 :                 *req_state = DBWRAP_REQ_ERROR;
     453           0 :                 return NULL;
     454             :         }
     455             : 
     456           0 :         *state = (struct dbwrap_parse_record_state) {
     457             :                 .db = db,
     458             :         };
     459             : 
     460           0 :         if (parser == NULL) {
     461           0 :                 parser = dbwrap_null_parser;
     462             :         }
     463             : 
     464           0 :         *req_state = DBWRAP_REQ_INIT;
     465             : 
     466           0 :         if (db->parse_record_send == NULL) {
     467             :                 /*
     468             :                  * Backend doesn't implement async version, call sync one
     469             :                  */
     470           0 :                 status = db->parse_record(db, key, parser, private_data);
     471           0 :                 if (tevent_req_nterror(req, status)) {
     472           0 :                         *req_state = DBWRAP_REQ_DONE;
     473           0 :                         return tevent_req_post(req, ev);
     474             :                 }
     475             : 
     476           0 :                 *req_state = DBWRAP_REQ_DONE;
     477           0 :                 tevent_req_done(req);
     478           0 :                 return tevent_req_post(req, ev);
     479             :         }
     480             : 
     481             :         /*
     482             :          * Copy the key into our state ensuring the key data buffer is always
     483             :          * available to all the dbwrap backends over the entire lifetime of the
     484             :          * async request. Otherwise the caller might have free'd the key buffer.
     485             :          */
     486           0 :         if (key.dsize > sizeof(state->_keybuf)) {
     487           0 :                 state->key.dptr = talloc_memdup(state, key.dptr, key.dsize);
     488           0 :                 if (tevent_req_nomem(state->key.dptr, req)) {
     489           0 :                         return tevent_req_post(req, ev);
     490             :                 }
     491             :         } else {
     492           0 :                 memcpy(state->_keybuf, key.dptr, key.dsize);
     493           0 :                 state->key.dptr = state->_keybuf;
     494             :         }
     495           0 :         state->key.dsize = key.dsize;
     496             : 
     497           0 :         subreq = db->parse_record_send(state,
     498             :                                        ev,
     499             :                                        db,
     500           0 :                                        state->key,
     501             :                                        parser,
     502             :                                        private_data,
     503             :                                        req_state);
     504           0 :         if (tevent_req_nomem(subreq, req)) {
     505           0 :                 *req_state = DBWRAP_REQ_ERROR;
     506           0 :                 return tevent_req_post(req, ev);
     507             :         }
     508             : 
     509           0 :         tevent_req_set_callback(subreq,
     510             :                                 dbwrap_parse_record_done,
     511             :                                 req);
     512           0 :         return req;
     513             : }
     514             : 
     515           0 : static void dbwrap_parse_record_done(struct tevent_req *subreq)
     516             : {
     517           0 :         struct tevent_req *req = tevent_req_callback_data(
     518             :                 subreq, struct tevent_req);
     519           0 :         struct dbwrap_parse_record_state *state = tevent_req_data(
     520             :                 req, struct dbwrap_parse_record_state);
     521             :         NTSTATUS status;
     522             : 
     523           0 :         status = state->db->parse_record_recv(subreq);
     524           0 :         TALLOC_FREE(subreq);
     525           0 :         if (!NT_STATUS_IS_OK(status)) {
     526           0 :                 tevent_req_nterror(req, status);
     527           0 :                 return;
     528             :         }
     529             : 
     530           0 :         tevent_req_done(req);
     531             : }
     532             : 
     533           0 : NTSTATUS dbwrap_parse_record_recv(struct tevent_req *req)
     534             : {
     535           0 :         return tevent_req_simple_recv_ntstatus(req);
     536             : }
     537             : 
     538     1669950 : NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
     539             :                           void (*fn)(struct db_record *rec,
     540             :                                      TDB_DATA value,
     541             :                                      void *private_data),
     542             :                           void *private_data)
     543             : {
     544             :         struct db_record *rec;
     545             : 
     546     1669950 :         if (db->do_locked != NULL) {
     547             :                 NTSTATUS status;
     548             : 
     549      254053 :                 if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     550       10781 :                         dbwrap_lock_order_lock(db->name, db->lock_order);
     551             :                 }
     552             : 
     553      254053 :                 status = db->do_locked(db, key, fn, private_data);
     554             : 
     555      254053 :                 if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     556       10781 :                         dbwrap_lock_order_unlock(db->name, db->lock_order);
     557             :                 }
     558             : 
     559      254053 :                 return status;
     560             :         }
     561             : 
     562     1415897 :         rec = dbwrap_fetch_locked(db, db, key);
     563     1415897 :         if (rec == NULL) {
     564           0 :                 return NT_STATUS_NO_MEMORY;
     565             :         }
     566             : 
     567             :         /*
     568             :          * Invalidate rec->value, nobody shall assume it's set from
     569             :          * within dbwrap_do_locked().
     570             :          */
     571     1415897 :         rec->value_valid = false;
     572             : 
     573     1415897 :         fn(rec, rec->value, private_data);
     574             : 
     575     1415897 :         TALLOC_FREE(rec);
     576             : 
     577     1415897 :         return NT_STATUS_OK;
     578             : }
     579             : 
     580           0 : int dbwrap_wipe(struct db_context *db)
     581             : {
     582           0 :         if (db->wipe == NULL) {
     583           0 :                 return dbwrap_fallback_wipe(db);
     584             :         }
     585           0 :         return db->wipe(db);
     586             : }
     587             : 
     588           0 : int dbwrap_check(struct db_context *db)
     589             : {
     590           0 :         if (db->check == NULL) {
     591           0 :                 return dbwrap_fallback_check(db);
     592             :         }
     593           0 :         return db->check(db);
     594             : }
     595             : 
     596      241690 : int dbwrap_get_seqnum(struct db_context *db)
     597             : {
     598      241690 :         return db->get_seqnum(db);
     599             : }
     600             : 
     601       17191 : int dbwrap_transaction_start(struct db_context *db)
     602             : {
     603       17191 :         if (!db->persistent) {
     604             :                 /*
     605             :                  * dbwrap_ctdb has two different data models for persistent
     606             :                  * and non-persistent databases. Transactions are supported
     607             :                  * only for the persistent databases. This check is here to
     608             :                  * prevent breakages of the cluster case, autobuild at this
     609             :                  * point only tests non-clustered Samba. Before removing this
     610             :                  * check, please make sure that this facility has also been
     611             :                  * added to dbwrap_ctdb.
     612             :                  *
     613             :                  * Thanks, vl
     614             :                  */
     615           0 :                 DEBUG(1, ("transactions not supported on non-persistent "
     616             :                           "database %s\n", db->name));
     617           0 :                 return -1;
     618             :         }
     619       17191 :         return db->transaction_start(db);
     620             : }
     621             : 
     622           0 : NTSTATUS dbwrap_transaction_start_nonblock(struct db_context *db)
     623             : {
     624           0 :         if (db->transaction_start_nonblock) {
     625           0 :                 return db->transaction_start_nonblock(db);
     626             :         } else {
     627           0 :                 return dbwrap_transaction_start(db) == 0 ? NT_STATUS_OK
     628           0 :                         : NT_STATUS_UNSUCCESSFUL;
     629             :         }
     630             : }
     631             : 
     632       17172 : int dbwrap_transaction_commit(struct db_context *db)
     633             : {
     634       17172 :         return db->transaction_commit(db);
     635             : }
     636             : 
     637          19 : int dbwrap_transaction_cancel(struct db_context *db)
     638             : {
     639          19 :         return db->transaction_cancel(db);
     640             : }
     641             : 
     642           0 : size_t dbwrap_db_id(struct db_context *db, uint8_t *id, size_t idlen)
     643             : {
     644           0 :         return db->id(db, id, idlen);
     645             : }
     646             : 
     647           0 : bool dbwrap_is_persistent(struct db_context *db)
     648             : {
     649           0 :         return db->persistent;
     650             : }
     651             : 
     652       52015 : const char *dbwrap_name(struct db_context *db)
     653             : {
     654       52015 :         return db->name;
     655             : }
     656             : 
     657           0 : static ssize_t tdb_data_buf(const TDB_DATA *dbufs, int num_dbufs,
     658             :                             uint8_t *buf, size_t buflen)
     659             : {
     660           0 :         size_t needed = 0;
     661           0 :         uint8_t *p = buf;
     662             :         int i;
     663             : 
     664           0 :         for (i=0; i<num_dbufs; i++) {
     665           0 :                 size_t thislen = dbufs[i].dsize;
     666             : 
     667           0 :                 needed += thislen;
     668           0 :                 if (needed < thislen) {
     669             :                         /* wrap */
     670           0 :                         return -1;
     671             :                 }
     672             : 
     673           0 :                 if (p != NULL && (thislen != 0) && (needed <= buflen)) {
     674           0 :                         memcpy(p, dbufs[i].dptr, thislen);
     675           0 :                         p += thislen;
     676             :                 }
     677             :         }
     678             : 
     679           0 :         return needed;
     680             : }
     681             : 
     682             : 
     683           0 : TDB_DATA dbwrap_merge_dbufs(TALLOC_CTX *mem_ctx,
     684             :                             const TDB_DATA *dbufs, int num_dbufs)
     685             : {
     686           0 :         ssize_t len = tdb_data_buf(dbufs, num_dbufs, NULL, 0);
     687             :         uint8_t *buf;
     688             : 
     689           0 :         if (len == -1) {
     690           0 :                 return (TDB_DATA) {0};
     691             :         }
     692             : 
     693           0 :         buf = talloc_array(mem_ctx, uint8_t, len);
     694           0 :         if (buf == NULL) {
     695           0 :                 return (TDB_DATA) {0};
     696             :         }
     697             : 
     698           0 :         tdb_data_buf(dbufs, num_dbufs, buf, len);
     699             : 
     700           0 :         return (TDB_DATA) { .dptr = buf, .dsize = len };
     701             : }

Generated by: LCOV version 1.13