LCOV - code coverage report
Current view: top level - lib/dbwrap - dbwrap.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 192 296 64.9 %
Date: 2024-04-13 12:30:31 Functions: 35 47 74.5 %

          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     8710937 : TDB_DATA dbwrap_record_get_key(const struct db_record *rec)
      76             : {
      77     8710937 :         return rec->key;
      78             : }
      79             : 
      80    21584500 : TDB_DATA dbwrap_record_get_value(const struct db_record *rec)
      81             : {
      82    21584500 :         SMB_ASSERT(rec->value_valid);
      83    21584500 :         return rec->value;
      84             : }
      85             : 
      86     8101962 : NTSTATUS dbwrap_record_storev(struct db_record *rec,
      87             :                               const TDB_DATA *dbufs, int num_dbufs, int flags)
      88             : {
      89       66704 :         NTSTATUS status;
      90             : 
      91             :         /*
      92             :          * Invalidate before rec->storev() is called, give
      93             :          * rec->storev() the chance to re-validate rec->value.
      94             :          */
      95     8101962 :         rec->value_valid = false;
      96             : 
      97     8101962 :         status = rec->storev(rec, dbufs, num_dbufs, flags);
      98     8101962 :         if (!NT_STATUS_IS_OK(status)) {
      99           2 :                 return status;
     100             :         }
     101     8101960 :         return NT_STATUS_OK;
     102             : }
     103             : 
     104     5536203 : NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
     105             : {
     106     5536203 :         return dbwrap_record_storev(rec, &data, 1, flags);
     107             : }
     108             : 
     109     2374974 : NTSTATUS dbwrap_record_delete(struct db_record *rec)
     110             : {
     111       13860 :         NTSTATUS status;
     112             : 
     113     2374974 :         status = rec->delete_rec(rec);
     114     2374974 :         if (!NT_STATUS_IS_OK(status)) {
     115      216644 :                 return status;
     116             :         }
     117             : 
     118     2158330 :         rec->value = tdb_null;
     119             : 
     120     2158330 :         return NT_STATUS_OK;
     121             : }
     122             : 
     123             : struct dbwrap_merge_dbs_state {
     124             :         struct db_context *to;
     125             :         int flags;
     126             : };
     127             : 
     128             : /* Copy a single record to the db_context passed in private_data */
     129           4 : static int dbwrap_merge_dbs_copy_record(struct db_record *rec,
     130             :                                             void *private_data)
     131             : {
     132           4 :         struct dbwrap_merge_dbs_state *state = private_data;
     133             : 
     134           4 :         TDB_DATA data = dbwrap_record_get_value(rec);
     135           4 :         TDB_DATA key = dbwrap_record_get_key(rec);
     136           4 :         NTSTATUS status = dbwrap_store(state->to, key, data, state->flags);
     137             : 
     138           4 :         return NT_STATUS_IS_OK(status) ? 0 : 1;
     139             : }
     140             : 
     141             : NTSTATUS
     142           2 : dbwrap_merge_dbs(struct db_context *to, struct db_context *from, int flags)
     143             : {
     144           2 :         struct dbwrap_merge_dbs_state state = {.to = to, .flags = flags};
     145             : 
     146           2 :         return dbwrap_traverse(from,
     147             :                                dbwrap_merge_dbs_copy_record,
     148             :                                &state,
     149             :                                NULL);
     150             : }
     151             : 
     152             : const char *locked_dbs[DBWRAP_LOCK_ORDER_MAX];
     153             : 
     154     4120294 : static void debug_lock_order(int level)
     155             : {
     156       19401 :         int i;
     157     4120294 :         DEBUG(level, ("lock order:"));
     158    20601470 :         for (i=0; i<DBWRAP_LOCK_ORDER_MAX; i++) {
     159    16481176 :                 DEBUGADD(level,
     160             :                          (" %d:%s",
     161             :                           i + 1,
     162             :                           locked_dbs[i] ? locked_dbs[i] : "<none>"));
     163             :         }
     164     4120294 :         DEBUGADD(level, ("\n"));
     165     4120294 : }
     166             : 
     167     4120294 : void dbwrap_lock_order_lock(const char *db_name,
     168             :                             enum dbwrap_lock_order lock_order)
     169             : {
     170       19401 :         int idx;
     171             : 
     172     4120294 :         DBG_INFO("check lock order %d for %s\n",
     173             :                  (int)lock_order,
     174             :                  db_name);
     175             : 
     176     4120294 :         if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
     177           0 :                 DBG_ERR("Invalid lock order %d of %s\n",
     178             :                         lock_order,
     179             :                         db_name);
     180           0 :                 smb_panic("lock order violation");
     181             :         }
     182             : 
     183    19470194 :         for (idx=lock_order-1; idx<DBWRAP_LOCK_ORDER_MAX; idx++) {
     184    15349900 :                 if (locked_dbs[idx] != NULL) {
     185           0 :                         DBG_ERR("Lock order violation: Trying %s at %d while "
     186             :                                 "%s at %d is locked\n",
     187             :                                 db_name,
     188             :                                 (int)lock_order,
     189             :                                 locked_dbs[idx],
     190             :                                 idx + 1);
     191           0 :                         debug_lock_order(0);
     192           0 :                         smb_panic("lock order violation");
     193             :                 }
     194             :         }
     195             : 
     196     4120294 :         locked_dbs[lock_order-1] = db_name;
     197             : 
     198     4120294 :         debug_lock_order(10);
     199     4120294 : }
     200             : 
     201     4120293 : void dbwrap_lock_order_unlock(const char *db_name,
     202             :                               enum dbwrap_lock_order lock_order)
     203             : {
     204     4120293 :         DBG_INFO("release lock order %d for %s\n",
     205             :                  (int)lock_order,
     206             :                  db_name);
     207             : 
     208     4120293 :         if (!DBWRAP_LOCK_ORDER_VALID(lock_order)) {
     209           0 :                 DBG_ERR("Invalid lock order %d of %s\n",
     210             :                         lock_order,
     211             :                         db_name);
     212           0 :                 smb_panic("lock order violation");
     213             :         }
     214             : 
     215     4120293 :         if (locked_dbs[lock_order-1] == NULL) {
     216           0 :                 DBG_ERR("db %s at order %d unlocked\n",
     217             :                         db_name,
     218             :                         (int)lock_order);
     219           0 :                 smb_panic("lock order violation");
     220             :         }
     221             : 
     222     4120293 :         if (locked_dbs[lock_order-1] != db_name) {
     223           0 :                 DBG_ERR("locked db at lock order %d is %s, expected %s\n",
     224             :                         (int)lock_order,
     225             :                         locked_dbs[lock_order-1],
     226             :                         db_name);
     227           0 :                 smb_panic("lock order violation");
     228             :         }
     229             : 
     230     4120293 :         locked_dbs[lock_order-1] = NULL;
     231     4120293 : }
     232             : 
     233             : struct dbwrap_lock_order_state {
     234             :         struct db_context *db;
     235             : };
     236             : 
     237     1513136 : static int dbwrap_lock_order_state_destructor(
     238             :         struct dbwrap_lock_order_state *s)
     239             : {
     240     1513136 :         struct db_context *db = s->db;
     241     1513136 :         dbwrap_lock_order_unlock(db->name, db->lock_order);
     242     1513136 :         return 0;
     243             : }
     244             : 
     245     1513137 : static struct dbwrap_lock_order_state *dbwrap_check_lock_order(
     246             :         struct db_context *db, TALLOC_CTX *mem_ctx)
     247             : {
     248       11387 :         struct dbwrap_lock_order_state *state;
     249             : 
     250     1513137 :         state = talloc(mem_ctx, struct dbwrap_lock_order_state);
     251     1513137 :         if (state == NULL) {
     252           0 :                 DBG_WARNING("talloc failed\n");
     253           0 :                 return NULL;
     254             :         }
     255     1513137 :         state->db = db;
     256             : 
     257     1513137 :         dbwrap_lock_order_lock(db->name, db->lock_order);
     258     1513137 :         talloc_set_destructor(state, dbwrap_lock_order_state_destructor);
     259             : 
     260     1513137 :         return state;
     261             : }
     262             : 
     263    22161818 : static struct db_record *dbwrap_fetch_locked_internal(
     264             :         struct db_context *db, TALLOC_CTX *mem_ctx, TDB_DATA key,
     265             :         struct db_record *(*db_fn)(struct db_context *db, TALLOC_CTX *mem_ctx,
     266             :                                    TDB_DATA key))
     267             : {
     268       70505 :         struct db_record *rec;
     269    22161818 :         struct dbwrap_lock_order_state *lock_order = NULL;
     270             : 
     271    22161818 :         if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     272     1513137 :                 lock_order = dbwrap_check_lock_order(db, mem_ctx);
     273     1513137 :                 if (lock_order == NULL) {
     274           0 :                         return NULL;
     275             :                 }
     276             :         }
     277    22161818 :         rec = db_fn(db, mem_ctx, key);
     278    22161818 :         if (rec == NULL) {
     279           0 :                 TALLOC_FREE(lock_order);
     280           0 :                 return NULL;
     281             :         }
     282    22161818 :         (void)talloc_steal(rec, lock_order);
     283    22161818 :         rec->db = db;
     284    22161818 :         return rec;
     285             : }
     286             : 
     287    22161818 : struct db_record *dbwrap_fetch_locked(struct db_context *db,
     288             :                                       TALLOC_CTX *mem_ctx,
     289             :                                       TDB_DATA key)
     290             : {
     291    22161818 :         return dbwrap_fetch_locked_internal(db, mem_ctx, key,
     292             :                                             db->fetch_locked);
     293             : }
     294             : 
     295     1866518 : struct db_context *dbwrap_record_get_db(struct db_record *rec)
     296             : {
     297     1866518 :         return rec->db;
     298             : }
     299             : 
     300             : struct dbwrap_fetch_state {
     301             :         TALLOC_CTX *mem_ctx;
     302             :         TDB_DATA data;
     303             : };
     304             : 
     305    25252400 : static void dbwrap_fetch_parser(TDB_DATA key, TDB_DATA data,
     306             :                                 void *private_data)
     307             : {
     308    25252400 :         struct dbwrap_fetch_state *state =
     309             :                 (struct dbwrap_fetch_state *)private_data;
     310             : 
     311    25252400 :         state->data.dsize = data.dsize;
     312    25252400 :         state->data.dptr = (uint8_t *)talloc_memdup(state->mem_ctx, data.dptr,
     313             :                                                     data.dsize);
     314    25252400 : }
     315             : 
     316    34296152 : NTSTATUS dbwrap_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
     317             :                       TDB_DATA key, TDB_DATA *value)
     318             : {
     319      106241 :         struct dbwrap_fetch_state state;
     320      106241 :         NTSTATUS status;
     321             : 
     322    34296152 :         if (value == NULL) {
     323           0 :                 return NT_STATUS_INVALID_PARAMETER;
     324             :         }
     325             : 
     326    34296152 :         state.mem_ctx = mem_ctx;
     327             : 
     328    34296152 :         status = dbwrap_parse_record(db, key, dbwrap_fetch_parser, &state);
     329    34296152 :         if (!NT_STATUS_IS_OK(status)) {
     330     9043752 :                 return status;
     331             :         }
     332    25252400 :         if ((state.data.dsize != 0) && (state.data.dptr == NULL)) {
     333           0 :                 return NT_STATUS_NO_MEMORY;
     334             :         }
     335    25252400 :         *value = state.data;
     336    25252400 :         return NT_STATUS_OK;
     337             : }
     338             : 
     339      966087 : bool dbwrap_exists(struct db_context *db, TDB_DATA key)
     340             : {
     341        2594 :         int result;
     342      966087 :         if (db->exists != NULL) {
     343      966087 :                 result = db->exists(db, key);
     344             :         } else {
     345           0 :                 result = dbwrap_fallback_exists(db,key);
     346             :         }
     347      966087 :         return (result == 1);
     348             : }
     349             : 
     350             : struct dbwrap_store_state {
     351             :         TDB_DATA data;
     352             :         int flags;
     353             :         NTSTATUS status;
     354             : };
     355             : 
     356     3558104 : static void dbwrap_store_fn(
     357             :         struct db_record *rec,
     358             :         TDB_DATA value,
     359             :         void *private_data)
     360             : {
     361     3558104 :         struct dbwrap_store_state *state = private_data;
     362     3558104 :         state->status = dbwrap_record_store(rec, state->data, state->flags);
     363     3558104 : }
     364             : 
     365     3558104 : NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
     366             :                       TDB_DATA data, int flags)
     367             : {
     368     3558104 :         struct dbwrap_store_state state = { .data = data, .flags = flags };
     369       43427 :         NTSTATUS status;
     370             : 
     371     3558104 :         status = dbwrap_do_locked(db, key, dbwrap_store_fn, &state);
     372     3558104 :         if (!NT_STATUS_IS_OK(status)) {
     373           0 :                 return status;
     374             :         }
     375             : 
     376     3558104 :         return state.status;
     377             : }
     378             : 
     379             : struct dbwrap_delete_state {
     380             :         NTSTATUS status;
     381             : };
     382             : 
     383      205692 : static void dbwrap_delete_fn(
     384             :         struct db_record *rec,
     385             :         TDB_DATA value,
     386             :         void *private_data)
     387             : {
     388      205692 :         struct dbwrap_delete_state *state = private_data;
     389      205692 :         state->status = dbwrap_record_delete(rec);
     390      205692 : }
     391             : 
     392      205692 : NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key)
     393             : {
     394      205692 :         struct dbwrap_delete_state state = { .status = NT_STATUS_NOT_FOUND };
     395        2910 :         NTSTATUS status;
     396             : 
     397      205692 :         status = dbwrap_do_locked(db, key, dbwrap_delete_fn, &state);
     398      205692 :         if (!NT_STATUS_IS_OK(status)) {
     399           0 :                 return status;
     400             :         }
     401             : 
     402      205692 :         return state.status;
     403             : }
     404             : 
     405       74471 : NTSTATUS dbwrap_traverse(struct db_context *db,
     406             :                          int (*f)(struct db_record*, void*),
     407             :                          void *private_data,
     408             :                          int *count)
     409             : {
     410       74471 :         int ret = db->traverse(db, f, private_data);
     411             : 
     412       74471 :         if (ret < 0) {
     413           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     414             :         }
     415             : 
     416       74471 :         if (count != NULL) {
     417       74103 :                 *count = ret;
     418             :         }
     419             : 
     420       74471 :         return NT_STATUS_OK;
     421             : }
     422             : 
     423      234707 : NTSTATUS dbwrap_traverse_read(struct db_context *db,
     424             :                               int (*f)(struct db_record*, void*),
     425             :                               void *private_data,
     426             :                               int *count)
     427             : {
     428      234707 :         int ret = db->traverse_read(db, f, private_data);
     429             : 
     430      234707 :         if (ret < 0) {
     431           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     432             :         }
     433             : 
     434      234707 :         if (count != NULL) {
     435       12824 :                 *count = ret;
     436             :         }
     437             : 
     438      234707 :         return NT_STATUS_OK;
     439             : }
     440             : 
     441           0 : static void dbwrap_null_parser(TDB_DATA key, TDB_DATA val, void* data)
     442             : {
     443           0 :         return;
     444             : }
     445             : 
     446    46138860 : NTSTATUS dbwrap_parse_record(struct db_context *db, TDB_DATA key,
     447             :                              void (*parser)(TDB_DATA key, TDB_DATA data,
     448             :                                             void *private_data),
     449             :                              void *private_data)
     450             : {
     451    46138860 :         if (parser == NULL) {
     452           1 :                 parser = dbwrap_null_parser;
     453             :         }
     454    46138860 :         return db->parse_record(db, key, parser, private_data);
     455             : }
     456             : 
     457             : struct dbwrap_parse_record_state {
     458             :         struct db_context *db;
     459             :         TDB_DATA key;
     460             :         uint8_t _keybuf[64];
     461             : };
     462             : 
     463             : static void dbwrap_parse_record_done(struct tevent_req *subreq);
     464             : 
     465           0 : struct tevent_req *dbwrap_parse_record_send(
     466             :         TALLOC_CTX *mem_ctx,
     467             :         struct tevent_context *ev,
     468             :         struct db_context *db,
     469             :         TDB_DATA key,
     470             :         void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data),
     471             :         void *private_data,
     472             :         enum dbwrap_req_state *req_state)
     473             : {
     474           0 :         struct tevent_req *req = NULL;
     475           0 :         struct tevent_req *subreq = NULL;
     476           0 :         struct dbwrap_parse_record_state *state = NULL;
     477           0 :         NTSTATUS status;
     478             : 
     479           0 :         req = tevent_req_create(mem_ctx, &state, struct dbwrap_parse_record_state);
     480           0 :         if (req == NULL) {
     481           0 :                 *req_state = DBWRAP_REQ_ERROR;
     482           0 :                 return NULL;
     483             :         }
     484             : 
     485           0 :         *state = (struct dbwrap_parse_record_state) {
     486             :                 .db = db,
     487             :         };
     488             : 
     489           0 :         if (parser == NULL) {
     490           0 :                 parser = dbwrap_null_parser;
     491             :         }
     492             : 
     493           0 :         *req_state = DBWRAP_REQ_INIT;
     494             : 
     495           0 :         if (db->parse_record_send == NULL) {
     496             :                 /*
     497             :                  * Backend doesn't implement async version, call sync one
     498             :                  */
     499           0 :                 status = db->parse_record(db, key, parser, private_data);
     500           0 :                 if (tevent_req_nterror(req, status)) {
     501           0 :                         *req_state = DBWRAP_REQ_DONE;
     502           0 :                         return tevent_req_post(req, ev);
     503             :                 }
     504             : 
     505           0 :                 *req_state = DBWRAP_REQ_DONE;
     506           0 :                 tevent_req_done(req);
     507           0 :                 return tevent_req_post(req, ev);
     508             :         }
     509             : 
     510             :         /*
     511             :          * Copy the key into our state ensuring the key data buffer is always
     512             :          * available to all the dbwrap backends over the entire lifetime of the
     513             :          * async request. Otherwise the caller might have free'd the key buffer.
     514             :          */
     515           0 :         if (key.dsize > sizeof(state->_keybuf)) {
     516           0 :                 state->key.dptr = talloc_memdup(state, key.dptr, key.dsize);
     517           0 :                 if (tevent_req_nomem(state->key.dptr, req)) {
     518           0 :                         return tevent_req_post(req, ev);
     519             :                 }
     520             :         } else {
     521           0 :                 memcpy(state->_keybuf, key.dptr, key.dsize);
     522           0 :                 state->key.dptr = state->_keybuf;
     523             :         }
     524           0 :         state->key.dsize = key.dsize;
     525             : 
     526           0 :         subreq = db->parse_record_send(state,
     527             :                                        ev,
     528             :                                        db,
     529           0 :                                        state->key,
     530             :                                        parser,
     531             :                                        private_data,
     532             :                                        req_state);
     533           0 :         if (tevent_req_nomem(subreq, req)) {
     534           0 :                 *req_state = DBWRAP_REQ_ERROR;
     535           0 :                 return tevent_req_post(req, ev);
     536             :         }
     537             : 
     538           0 :         tevent_req_set_callback(subreq,
     539             :                                 dbwrap_parse_record_done,
     540             :                                 req);
     541           0 :         return req;
     542             : }
     543             : 
     544           0 : static void dbwrap_parse_record_done(struct tevent_req *subreq)
     545             : {
     546           0 :         struct tevent_req *req = tevent_req_callback_data(
     547             :                 subreq, struct tevent_req);
     548           0 :         struct dbwrap_parse_record_state *state = tevent_req_data(
     549             :                 req, struct dbwrap_parse_record_state);
     550           0 :         NTSTATUS status;
     551             : 
     552           0 :         status = state->db->parse_record_recv(subreq);
     553           0 :         TALLOC_FREE(subreq);
     554           0 :         if (!NT_STATUS_IS_OK(status)) {
     555           0 :                 tevent_req_nterror(req, status);
     556           0 :                 return;
     557             :         }
     558             : 
     559           0 :         tevent_req_done(req);
     560             : }
     561             : 
     562           0 : NTSTATUS dbwrap_parse_record_recv(struct tevent_req *req)
     563             : {
     564           0 :         return tevent_req_simple_recv_ntstatus(req);
     565             : }
     566             : 
     567     8145226 : NTSTATUS dbwrap_do_locked(struct db_context *db, TDB_DATA key,
     568             :                           void (*fn)(struct db_record *rec,
     569             :                                      TDB_DATA value,
     570             :                                      void *private_data),
     571             :                           void *private_data)
     572             : {
     573       58015 :         struct db_record *rec;
     574             : 
     575     8145226 :         if (db->do_locked != NULL) {
     576       16588 :                 NTSTATUS status;
     577             : 
     578     4491724 :                 if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     579     1181050 :                         dbwrap_lock_order_lock(db->name, db->lock_order);
     580             :                 }
     581             : 
     582     4491724 :                 status = db->do_locked(db, key, fn, private_data);
     583             : 
     584     4491724 :                 if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     585     1181050 :                         dbwrap_lock_order_unlock(db->name, db->lock_order);
     586             :                 }
     587             : 
     588     4491724 :                 return status;
     589             :         }
     590             : 
     591     3653502 :         rec = dbwrap_fetch_locked(db, db, key);
     592     3653502 :         if (rec == NULL) {
     593           0 :                 return NT_STATUS_NO_MEMORY;
     594             :         }
     595             : 
     596             :         /*
     597             :          * Invalidate rec->value, nobody shall assume it's set from
     598             :          * within dbwrap_do_locked().
     599             :          */
     600     3653502 :         rec->value_valid = false;
     601             : 
     602     3653502 :         fn(rec, rec->value, private_data);
     603             : 
     604     3653502 :         TALLOC_FREE(rec);
     605             : 
     606     3653502 :         return NT_STATUS_OK;
     607             : }
     608             : 
     609          45 : int dbwrap_wipe(struct db_context *db)
     610             : {
     611          45 :         if (db->wipe == NULL) {
     612           0 :                 return dbwrap_fallback_wipe(db);
     613             :         }
     614          45 :         return db->wipe(db);
     615             : }
     616             : 
     617           0 : int dbwrap_check(struct db_context *db)
     618             : {
     619           0 :         if (db->check == NULL) {
     620           0 :                 return dbwrap_fallback_check(db);
     621             :         }
     622           0 :         return db->check(db);
     623             : }
     624             : 
     625     2664704 : int dbwrap_get_seqnum(struct db_context *db)
     626             : {
     627     2664704 :         return db->get_seqnum(db);
     628             : }
     629             : 
     630      116631 : int dbwrap_transaction_start(struct db_context *db)
     631             : {
     632      116631 :         if (!db->persistent) {
     633             :                 /*
     634             :                  * dbwrap_ctdb has two different data models for persistent
     635             :                  * and non-persistent databases. Transactions are supported
     636             :                  * only for the persistent databases. This check is here to
     637             :                  * prevent breakages of the cluster case, autobuild at this
     638             :                  * point only tests non-clustered Samba. Before removing this
     639             :                  * check, please make sure that this facility has also been
     640             :                  * added to dbwrap_ctdb.
     641             :                  *
     642             :                  * Thanks, vl
     643             :                  */
     644           0 :                 DEBUG(1, ("transactions not supported on non-persistent "
     645             :                           "database %s\n", db->name));
     646           0 :                 return -1;
     647             :         }
     648      116631 :         return db->transaction_start(db);
     649             : }
     650             : 
     651           0 : NTSTATUS dbwrap_transaction_start_nonblock(struct db_context *db)
     652             : {
     653           0 :         if (db->transaction_start_nonblock) {
     654           0 :                 return db->transaction_start_nonblock(db);
     655             :         } else {
     656           0 :                 return dbwrap_transaction_start(db) == 0 ? NT_STATUS_OK
     657           0 :                         : NT_STATUS_UNSUCCESSFUL;
     658             :         }
     659             : }
     660             : 
     661      116403 : int dbwrap_transaction_commit(struct db_context *db)
     662             : {
     663      116403 :         return db->transaction_commit(db);
     664             : }
     665             : 
     666         227 : int dbwrap_transaction_cancel(struct db_context *db)
     667             : {
     668         227 :         return db->transaction_cancel(db);
     669             : }
     670             : 
     671           0 : size_t dbwrap_db_id(struct db_context *db, uint8_t *id, size_t idlen)
     672             : {
     673           0 :         return db->id(db, id, idlen);
     674             : }
     675             : 
     676          10 : bool dbwrap_is_persistent(struct db_context *db)
     677             : {
     678          10 :         return db->persistent;
     679             : }
     680             : 
     681     2852617 : const char *dbwrap_name(struct db_context *db)
     682             : {
     683     2852617 :         return db->name;
     684             : }
     685             : 
     686     1509402 : static ssize_t tdb_data_buf(const TDB_DATA *dbufs, int num_dbufs,
     687             :                             uint8_t *buf, size_t buflen)
     688             : {
     689     1509402 :         size_t needed = 0;
     690     1509402 :         uint8_t *p = buf;
     691        3830 :         int i;
     692             : 
     693     5525634 :         for (i=0; i<num_dbufs; i++) {
     694     4016232 :                 size_t thislen = dbufs[i].dsize;
     695             : 
     696     4016232 :                 needed += thislen;
     697     4016232 :                 if (needed < thislen) {
     698             :                         /* wrap */
     699           0 :                         return -1;
     700             :                 }
     701             : 
     702     4016232 :                 if (p != NULL && (thislen != 0) && (needed <= buflen)) {
     703     1566795 :                         memcpy(p, dbufs[i].dptr, thislen);
     704     1566795 :                         p += thislen;
     705             :                 }
     706             :         }
     707             : 
     708     1509402 :         return needed;
     709             : }
     710             : 
     711             : 
     712      754701 : NTSTATUS dbwrap_merge_dbufs(TDB_DATA *buf, TALLOC_CTX *mem_ctx,
     713             :                             const TDB_DATA *dbufs, int num_dbufs)
     714             : {
     715      754701 :         ssize_t len = tdb_data_buf(dbufs, num_dbufs, NULL, 0);
     716             : 
     717      754701 :         if (len == -1) {
     718           0 :                 return NT_STATUS_INVALID_PARAMETER;
     719             :         }
     720             : 
     721      754701 :         if (buf->dsize != len) {
     722        1375 :                 uint8_t *tmp;
     723             : 
     724      513052 :                 tmp = talloc_realloc(mem_ctx, buf->dptr, uint8_t, len);
     725      513052 :                 if (tmp == NULL && len != 0) {
     726           0 :                         return NT_STATUS_NO_MEMORY;
     727             :                 }
     728             : 
     729      513052 :                 buf->dptr = tmp;
     730      513052 :                 buf->dsize = len;
     731             :         }
     732             : 
     733      754701 :         tdb_data_buf(dbufs, num_dbufs, buf->dptr, buf->dsize);
     734             : 
     735      754701 :         return NT_STATUS_OK;
     736             : }

Generated by: LCOV version 1.14