LCOV - code coverage report
Current view: top level - lib/dbwrap - dbwrap.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 192 296 64.9 %
Date: 2024-04-21 15:09:00 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     8738221 : TDB_DATA dbwrap_record_get_key(const struct db_record *rec)
      76             : {
      77     8738221 :         return rec->key;
      78             : }
      79             : 
      80    22940026 : TDB_DATA dbwrap_record_get_value(const struct db_record *rec)
      81             : {
      82    22940026 :         SMB_ASSERT(rec->value_valid);
      83    22940026 :         return rec->value;
      84             : }
      85             : 
      86     8100446 : NTSTATUS dbwrap_record_storev(struct db_record *rec,
      87             :                               const TDB_DATA *dbufs, int num_dbufs, int flags)
      88             : {
      89       66848 :         NTSTATUS status;
      90             : 
      91             :         /*
      92             :          * Invalidate before rec->storev() is called, give
      93             :          * rec->storev() the chance to re-validate rec->value.
      94             :          */
      95     8100446 :         rec->value_valid = false;
      96             : 
      97     8100446 :         status = rec->storev(rec, dbufs, num_dbufs, flags);
      98     8100446 :         if (!NT_STATUS_IS_OK(status)) {
      99           2 :                 return status;
     100             :         }
     101     8100444 :         return NT_STATUS_OK;
     102             : }
     103             : 
     104     5532063 : NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
     105             : {
     106     5532063 :         return dbwrap_record_storev(rec, &data, 1, flags);
     107             : }
     108             : 
     109     2383712 : NTSTATUS dbwrap_record_delete(struct db_record *rec)
     110             : {
     111       13860 :         NTSTATUS status;
     112             : 
     113     2383712 :         status = rec->delete_rec(rec);
     114     2383712 :         if (!NT_STATUS_IS_OK(status)) {
     115      217317 :                 return status;
     116             :         }
     117             : 
     118     2166395 :         rec->value = tdb_null;
     119             : 
     120     2166395 :         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     4126355 : static void debug_lock_order(int level)
     155             : {
     156       19387 :         int i;
     157     4126355 :         DEBUG(level, ("lock order:"));
     158    20631775 :         for (i=0; i<DBWRAP_LOCK_ORDER_MAX; i++) {
     159    16505420 :                 DEBUGADD(level,
     160             :                          (" %d:%s",
     161             :                           i + 1,
     162             :                           locked_dbs[i] ? locked_dbs[i] : "<none>"));
     163             :         }
     164     4126355 :         DEBUGADD(level, ("\n"));
     165     4126355 : }
     166             : 
     167     4126355 : void dbwrap_lock_order_lock(const char *db_name,
     168             :                             enum dbwrap_lock_order lock_order)
     169             : {
     170       19387 :         int idx;
     171             : 
     172     4126355 :         DBG_INFO("check lock order %d for %s\n",
     173             :                  (int)lock_order,
     174             :                  db_name);
     175             : 
     176     4126355 :         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    19500497 :         for (idx=lock_order-1; idx<DBWRAP_LOCK_ORDER_MAX; idx++) {
     184    15374142 :                 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     4126355 :         locked_dbs[lock_order-1] = db_name;
     197             : 
     198     4126355 :         debug_lock_order(10);
     199     4126355 : }
     200             : 
     201     4126354 : void dbwrap_lock_order_unlock(const char *db_name,
     202             :                               enum dbwrap_lock_order lock_order)
     203             : {
     204     4126354 :         DBG_INFO("release lock order %d for %s\n",
     205             :                  (int)lock_order,
     206             :                  db_name);
     207             : 
     208     4126354 :         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     4126354 :         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     4126354 :         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     4126354 :         locked_dbs[lock_order-1] = NULL;
     231     4126354 : }
     232             : 
     233             : struct dbwrap_lock_order_state {
     234             :         struct db_context *db;
     235             : };
     236             : 
     237     1515420 : static int dbwrap_lock_order_state_destructor(
     238             :         struct dbwrap_lock_order_state *s)
     239             : {
     240     1515420 :         struct db_context *db = s->db;
     241     1515420 :         dbwrap_lock_order_unlock(db->name, db->lock_order);
     242     1515420 :         return 0;
     243             : }
     244             : 
     245     1515421 : 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     1515421 :         state = talloc(mem_ctx, struct dbwrap_lock_order_state);
     251     1515421 :         if (state == NULL) {
     252           0 :                 DBG_WARNING("talloc failed\n");
     253           0 :                 return NULL;
     254             :         }
     255     1515421 :         state->db = db;
     256             : 
     257     1515421 :         dbwrap_lock_order_lock(db->name, db->lock_order);
     258     1515421 :         talloc_set_destructor(state, dbwrap_lock_order_state_destructor);
     259             : 
     260     1515421 :         return state;
     261             : }
     262             : 
     263    23493573 : 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       70501 :         struct db_record *rec;
     269    23493573 :         struct dbwrap_lock_order_state *lock_order = NULL;
     270             : 
     271    23493573 :         if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     272     1515421 :                 lock_order = dbwrap_check_lock_order(db, mem_ctx);
     273     1515421 :                 if (lock_order == NULL) {
     274           0 :                         return NULL;
     275             :                 }
     276             :         }
     277    23493573 :         rec = db_fn(db, mem_ctx, key);
     278    23493573 :         if (rec == NULL) {
     279           0 :                 TALLOC_FREE(lock_order);
     280           0 :                 return NULL;
     281             :         }
     282    23493573 :         (void)talloc_steal(rec, lock_order);
     283    23493573 :         rec->db = db;
     284    23493573 :         return rec;
     285             : }
     286             : 
     287    23493573 : struct db_record *dbwrap_fetch_locked(struct db_context *db,
     288             :                                       TALLOC_CTX *mem_ctx,
     289             :                                       TDB_DATA key)
     290             : {
     291    23493573 :         return dbwrap_fetch_locked_internal(db, mem_ctx, key,
     292             :                                             db->fetch_locked);
     293             : }
     294             : 
     295     1868472 : struct db_context *dbwrap_record_get_db(struct db_record *rec)
     296             : {
     297     1868472 :         return rec->db;
     298             : }
     299             : 
     300             : struct dbwrap_fetch_state {
     301             :         TALLOC_CTX *mem_ctx;
     302             :         TDB_DATA data;
     303             : };
     304             : 
     305    25479023 : static void dbwrap_fetch_parser(TDB_DATA key, TDB_DATA data,
     306             :                                 void *private_data)
     307             : {
     308    25479023 :         struct dbwrap_fetch_state *state =
     309             :                 (struct dbwrap_fetch_state *)private_data;
     310             : 
     311    25479023 :         state->data.dsize = data.dsize;
     312    25479023 :         state->data.dptr = (uint8_t *)talloc_memdup(state->mem_ctx, data.dptr,
     313             :                                                     data.dsize);
     314    25479023 : }
     315             : 
     316    34668723 : NTSTATUS dbwrap_fetch(struct db_context *db, TALLOC_CTX *mem_ctx,
     317             :                       TDB_DATA key, TDB_DATA *value)
     318             : {
     319      106194 :         struct dbwrap_fetch_state state;
     320      106194 :         NTSTATUS status;
     321             : 
     322    34668723 :         if (value == NULL) {
     323           0 :                 return NT_STATUS_INVALID_PARAMETER;
     324             :         }
     325             : 
     326    34668723 :         state.mem_ctx = mem_ctx;
     327             : 
     328    34668723 :         status = dbwrap_parse_record(db, key, dbwrap_fetch_parser, &state);
     329    34668723 :         if (!NT_STATUS_IS_OK(status)) {
     330     9189700 :                 return status;
     331             :         }
     332    25479023 :         if ((state.data.dsize != 0) && (state.data.dptr == NULL)) {
     333           0 :                 return NT_STATUS_NO_MEMORY;
     334             :         }
     335    25479023 :         *value = state.data;
     336    25479023 :         return NT_STATUS_OK;
     337             : }
     338             : 
     339      966203 : bool dbwrap_exists(struct db_context *db, TDB_DATA key)
     340             : {
     341        2594 :         int result;
     342      966203 :         if (db->exists != NULL) {
     343      966203 :                 result = db->exists(db, key);
     344             :         } else {
     345           0 :                 result = dbwrap_fallback_exists(db,key);
     346             :         }
     347      966203 :         return (result == 1);
     348             : }
     349             : 
     350             : struct dbwrap_store_state {
     351             :         TDB_DATA data;
     352             :         int flags;
     353             :         NTSTATUS status;
     354             : };
     355             : 
     356     3550492 : static void dbwrap_store_fn(
     357             :         struct db_record *rec,
     358             :         TDB_DATA value,
     359             :         void *private_data)
     360             : {
     361     3550492 :         struct dbwrap_store_state *state = private_data;
     362     3550492 :         state->status = dbwrap_record_store(rec, state->data, state->flags);
     363     3550492 : }
     364             : 
     365     3550492 : NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
     366             :                       TDB_DATA data, int flags)
     367             : {
     368     3550492 :         struct dbwrap_store_state state = { .data = data, .flags = flags };
     369       43571 :         NTSTATUS status;
     370             : 
     371     3550492 :         status = dbwrap_do_locked(db, key, dbwrap_store_fn, &state);
     372     3550492 :         if (!NT_STATUS_IS_OK(status)) {
     373           0 :                 return status;
     374             :         }
     375             : 
     376     3550492 :         return state.status;
     377             : }
     378             : 
     379             : struct dbwrap_delete_state {
     380             :         NTSTATUS status;
     381             : };
     382             : 
     383      221390 : static void dbwrap_delete_fn(
     384             :         struct db_record *rec,
     385             :         TDB_DATA value,
     386             :         void *private_data)
     387             : {
     388      221390 :         struct dbwrap_delete_state *state = private_data;
     389      221390 :         state->status = dbwrap_record_delete(rec);
     390      221390 : }
     391             : 
     392      221390 : NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key)
     393             : {
     394      221390 :         struct dbwrap_delete_state state = { .status = NT_STATUS_NOT_FOUND };
     395        3033 :         NTSTATUS status;
     396             : 
     397      221390 :         status = dbwrap_do_locked(db, key, dbwrap_delete_fn, &state);
     398      221390 :         if (!NT_STATUS_IS_OK(status)) {
     399           0 :                 return status;
     400             :         }
     401             : 
     402      221390 :         return state.status;
     403             : }
     404             : 
     405       74748 : NTSTATUS dbwrap_traverse(struct db_context *db,
     406             :                          int (*f)(struct db_record*, void*),
     407             :                          void *private_data,
     408             :                          int *count)
     409             : {
     410       74748 :         int ret = db->traverse(db, f, private_data);
     411             : 
     412       74748 :         if (ret < 0) {
     413           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     414             :         }
     415             : 
     416       74748 :         if (count != NULL) {
     417       74372 :                 *count = ret;
     418             :         }
     419             : 
     420       74748 :         return NT_STATUS_OK;
     421             : }
     422             : 
     423      238111 : NTSTATUS dbwrap_traverse_read(struct db_context *db,
     424             :                               int (*f)(struct db_record*, void*),
     425             :                               void *private_data,
     426             :                               int *count)
     427             : {
     428      238111 :         int ret = db->traverse_read(db, f, private_data);
     429             : 
     430      238111 :         if (ret < 0) {
     431           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     432             :         }
     433             : 
     434      238111 :         if (count != NULL) {
     435       12824 :                 *count = ret;
     436             :         }
     437             : 
     438      238111 :         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    46508877 : 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    46508877 :         if (parser == NULL) {
     452           1 :                 parser = dbwrap_null_parser;
     453             :         }
     454    46508877 :         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     8158271 : 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       58282 :         struct db_record *rec;
     574             : 
     575     8158271 :         if (db->do_locked != NULL) {
     576       16732 :                 NTSTATUS status;
     577             : 
     578     4498234 :                 if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     579     1183127 :                         dbwrap_lock_order_lock(db->name, db->lock_order);
     580             :                 }
     581             : 
     582     4498234 :                 status = db->do_locked(db, key, fn, private_data);
     583             : 
     584     4498234 :                 if (db->lock_order != DBWRAP_LOCK_ORDER_NONE) {
     585     1183127 :                         dbwrap_lock_order_unlock(db->name, db->lock_order);
     586             :                 }
     587             : 
     588     4498234 :                 return status;
     589             :         }
     590             : 
     591     3660037 :         rec = dbwrap_fetch_locked(db, db, key);
     592     3660037 :         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     3660037 :         rec->value_valid = false;
     601             : 
     602     3660037 :         fn(rec, rec->value, private_data);
     603             : 
     604     3660037 :         TALLOC_FREE(rec);
     605             : 
     606     3660037 :         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     2670237 : int dbwrap_get_seqnum(struct db_context *db)
     626             : {
     627     2670237 :         return db->get_seqnum(db);
     628             : }
     629             : 
     630      117485 : int dbwrap_transaction_start(struct db_context *db)
     631             : {
     632      117485 :         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      117485 :         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      117257 : int dbwrap_transaction_commit(struct db_context *db)
     662             : {
     663      117257 :         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     2856021 : const char *dbwrap_name(struct db_context *db)
     682             : {
     683     2856021 :         return db->name;
     684             : }
     685             : 
     686     1513224 : static ssize_t tdb_data_buf(const TDB_DATA *dbufs, int num_dbufs,
     687             :                             uint8_t *buf, size_t buflen)
     688             : {
     689     1513224 :         size_t needed = 0;
     690     1513224 :         uint8_t *p = buf;
     691        3830 :         int i;
     692             : 
     693     5538882 :         for (i=0; i<num_dbufs; i++) {
     694     4025658 :                 size_t thislen = dbufs[i].dsize;
     695             : 
     696     4025658 :                 needed += thislen;
     697     4025658 :                 if (needed < thislen) {
     698             :                         /* wrap */
     699           0 :                         return -1;
     700             :                 }
     701             : 
     702     4025658 :                 if (p != NULL && (thislen != 0) && (needed <= buflen)) {
     703     1570550 :                         memcpy(p, dbufs[i].dptr, thislen);
     704     1570550 :                         p += thislen;
     705             :                 }
     706             :         }
     707             : 
     708     1513224 :         return needed;
     709             : }
     710             : 
     711             : 
     712      756612 : NTSTATUS dbwrap_merge_dbufs(TDB_DATA *buf, TALLOC_CTX *mem_ctx,
     713             :                             const TDB_DATA *dbufs, int num_dbufs)
     714             : {
     715      756612 :         ssize_t len = tdb_data_buf(dbufs, num_dbufs, NULL, 0);
     716             : 
     717      756612 :         if (len == -1) {
     718           0 :                 return NT_STATUS_INVALID_PARAMETER;
     719             :         }
     720             : 
     721      756612 :         if (buf->dsize != len) {
     722        1375 :                 uint8_t *tmp;
     723             : 
     724      514217 :                 tmp = talloc_realloc(mem_ctx, buf->dptr, uint8_t, len);
     725      514217 :                 if (tmp == NULL && len != 0) {
     726           0 :                         return NT_STATUS_NO_MEMORY;
     727             :                 }
     728             : 
     729      514217 :                 buf->dptr = tmp;
     730      514217 :                 buf->dsize = len;
     731             :         }
     732             : 
     733      756612 :         tdb_data_buf(dbufs, num_dbufs, buf->dptr, buf->dsize);
     734             : 
     735      756612 :         return NT_STATUS_OK;
     736             : }

Generated by: LCOV version 1.14