LCOV - code coverage report
Current view: top level - lib/dbwrap - dbwrap_util.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 225 327 68.8 %
Date: 2024-02-28 12:06:22 Functions: 33 41 80.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Utility functions for the dbwrap API
       4             :    Copyright (C) Volker Lendecke 2007
       5             :    Copyright (C) Michael Adam 2009
       6             :    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006
       7             : 
       8             :    Major code contributions from Aleksey Fedoseev (fedoseev@ru.ibm.com)
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 2 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program; if not, write to the Free Software
      22             :    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include "dbwrap.h"
      27             : #include "lib/util/util_tdb.h"
      28             : 
      29             : struct dbwrap_fetch_int32_state {
      30             :         NTSTATUS status;
      31             :         int32_t result;
      32             : };
      33             : 
      34       27325 : static void dbwrap_fetch_int32_parser(TDB_DATA key, TDB_DATA data,
      35             :                                       void *private_data)
      36             : {
      37       27325 :         struct dbwrap_fetch_int32_state *state =
      38             :                 (struct dbwrap_fetch_int32_state *)private_data;
      39             : 
      40       27325 :         if (data.dsize != sizeof(state->result)) {
      41           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
      42           0 :                 return;
      43             :         }
      44       27325 :         state->result = IVAL(data.dptr, 0);
      45       27325 :         state->status = NT_STATUS_OK;
      46             : }
      47             : 
      48       29912 : NTSTATUS dbwrap_fetch_int32(struct db_context *db, TDB_DATA key,
      49             :                             int32_t *result)
      50             : {
      51         278 :         struct dbwrap_fetch_int32_state state;
      52         278 :         NTSTATUS status;
      53             : 
      54       29912 :         if (result == NULL) {
      55           0 :                 return NT_STATUS_INVALID_PARAMETER;
      56             :         }
      57             : 
      58       29912 :         state.status = NT_STATUS_INTERNAL_ERROR;
      59             : 
      60       29912 :         status = dbwrap_parse_record(db, key, dbwrap_fetch_int32_parser, &state);
      61       29912 :         if (!NT_STATUS_IS_OK(status)) {
      62        2587 :                 return status;
      63             :         }
      64             : 
      65       27325 :         if (NT_STATUS_IS_OK(state.status)) {
      66       27325 :                 *result = state.result;
      67             :         }
      68       27325 :         return state.status;
      69             : }
      70             : 
      71       27731 : NTSTATUS dbwrap_fetch_int32_bystring(struct db_context *db, const char *keystr,
      72             :                                      int32_t *result)
      73             : {
      74       27731 :         return dbwrap_fetch_int32(db, string_term_tdb_data(keystr), result);
      75             : }
      76             : 
      77         382 : NTSTATUS dbwrap_store_int32_bystring(struct db_context *db, const char *keystr,
      78             :                                      int32_t v)
      79             : {
      80          22 :         uint8_t v_store[sizeof(int32_t)];
      81         382 :         TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
      82          22 :         NTSTATUS status;
      83             : 
      84         382 :         SIVAL(v_store, 0, v);
      85             : 
      86         382 :         status = dbwrap_store(db, string_term_tdb_data(keystr), data,
      87             :                               TDB_REPLACE);
      88         382 :         return status;
      89             : }
      90             : 
      91             : struct dbwrap_fetch_uint32_state {
      92             :         NTSTATUS status;
      93             :         uint32_t result;
      94             : };
      95             : 
      96      297058 : static void dbwrap_fetch_uint32_parser(TDB_DATA key, TDB_DATA data,
      97             :                                        void *private_data)
      98             : {
      99      297058 :         struct dbwrap_fetch_uint32_state *state =
     100             :                 (struct dbwrap_fetch_uint32_state *)private_data;
     101             : 
     102      297058 :         if (data.dsize != sizeof(state->result)) {
     103           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     104           0 :                 return;
     105             :         }
     106      297058 :         state->result = IVAL(data.dptr, 0);
     107      297058 :         state->status = NT_STATUS_OK;
     108             : }
     109             : 
     110      298294 : NTSTATUS dbwrap_fetch_uint32_bystring(struct db_context *db,
     111             :                                       const char *keystr, uint32_t *val)
     112             : {
     113         231 :         struct dbwrap_fetch_uint32_state state;
     114         231 :         NTSTATUS status;
     115             : 
     116      298294 :         if (val == NULL) {
     117           0 :                 return NT_STATUS_INVALID_PARAMETER;
     118             :         }
     119             : 
     120      298294 :         state.status = NT_STATUS_INTERNAL_ERROR;
     121             : 
     122      298294 :         status = dbwrap_parse_record(db, string_term_tdb_data(keystr),
     123             :                                      dbwrap_fetch_uint32_parser, &state);
     124      298294 :         if (!NT_STATUS_IS_OK(status)) {
     125        1236 :                 return status;
     126             :         }
     127      297058 :         if (NT_STATUS_IS_OK(state.status)) {
     128      297058 :                 *val = state.result;
     129             :         }
     130      297058 :         return state.status;
     131             : }
     132             : 
     133         162 : NTSTATUS dbwrap_store_uint32_bystring(struct db_context *db,
     134             :                                       const char *keystr, uint32_t v)
     135             : {
     136           8 :         uint8_t v_store[sizeof(uint32_t)];
     137         162 :         TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
     138           8 :         NTSTATUS status;
     139             : 
     140         162 :         SIVAL(v_store, 0, v);
     141             : 
     142         162 :         status = dbwrap_store(db, string_term_tdb_data(keystr), data,
     143             :                               TDB_REPLACE);
     144         162 :         return status;
     145             : }
     146             : 
     147             : /**
     148             :  * Atomic unsigned integer change (addition):
     149             :  *
     150             :  * if value does not exist yet in the db, use *oldval as initial old value.
     151             :  * return old value in *oldval.
     152             :  * store *oldval + change_val to db.
     153             :  */
     154             : 
     155             : struct dbwrap_change_uint32_atomic_context {
     156             :         const char *keystr;
     157             :         uint32_t *oldval;
     158             :         uint32_t change_val;
     159             :         NTSTATUS status;
     160             : };
     161             : 
     162        1274 : static void dbwrap_change_uint32_atomic_action_fn(struct db_record *rec,
     163             :                                                   TDB_DATA value,
     164             :                                                   void *private_data)
     165             : {
     166        1274 :         struct dbwrap_change_uint32_atomic_context *state = private_data;
     167         108 :         uint8_t v_store[4];
     168        1274 :         TDB_DATA data = {
     169             :                 .dptr = v_store,
     170             :                 .dsize = sizeof(v_store),
     171             :         };
     172        1274 :         uint32_t val = UINT32_MAX;
     173             : 
     174        1274 :         if (value.dptr == NULL) {
     175           0 :                 val = *(state->oldval);
     176        1274 :         } else if (value.dsize == sizeof(val)) {
     177        1274 :                 val = PULL_LE_U32(value.dptr, 0);
     178        1274 :                 *(state->oldval) = val;
     179             :         } else {
     180           0 :                 state->status = NT_STATUS_UNSUCCESSFUL;
     181           0 :                 return;
     182             :         }
     183             : 
     184        1274 :         val += state->change_val;
     185        1274 :         PUSH_LE_U32(v_store, 0, val);
     186             : 
     187        1274 :         state->status = dbwrap_record_store(rec, data, TDB_REPLACE);
     188             : }
     189             : 
     190        1274 : static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
     191             :                                                    void *private_data)
     192             : {
     193        1274 :         struct dbwrap_change_uint32_atomic_context *state = private_data;
     194         108 :         NTSTATUS status;
     195             : 
     196        1274 :         status = dbwrap_do_locked(db,
     197             :                                   string_term_tdb_data(state->keystr),
     198             :                                   dbwrap_change_uint32_atomic_action_fn,
     199             :                                   state);
     200        1274 :         if (!NT_STATUS_IS_OK(status)) {
     201           0 :                 DBG_DEBUG("dbwrap_do_locked() failed: %s\n",
     202             :                           nt_errstr(status));
     203           0 :                 return status;
     204             :         }
     205        1274 :         if (!NT_STATUS_IS_OK(state->status)) {
     206           0 :                 DBG_DEBUG("dbwrap_change_uint32_atomic_action_fn() "
     207             :                           "failed: %s\n",
     208             :                           nt_errstr(status));
     209           0 :                 return status;
     210             :         }
     211        1274 :         return NT_STATUS_OK;
     212             : }
     213             : 
     214         108 : NTSTATUS dbwrap_change_uint32_atomic_bystring(struct db_context *db,
     215             :                                               const char *keystr,
     216             :                                               uint32_t *oldval,
     217             :                                               uint32_t change_val)
     218             : {
     219         108 :         NTSTATUS ret;
     220         108 :         struct dbwrap_change_uint32_atomic_context state;
     221             : 
     222         108 :         state.keystr = keystr;
     223         108 :         state.oldval = oldval;
     224         108 :         state.change_val = change_val;
     225             : 
     226         108 :         ret = dbwrap_change_uint32_atomic_action(db, &state);
     227             : 
     228         108 :         return ret;
     229             : }
     230             : 
     231        1166 : NTSTATUS dbwrap_trans_change_uint32_atomic_bystring(struct db_context *db,
     232             :                                                     const char *keystr,
     233             :                                                     uint32_t *oldval,
     234             :                                                     uint32_t change_val)
     235             : {
     236           0 :         NTSTATUS ret;
     237           0 :         struct dbwrap_change_uint32_atomic_context state;
     238             : 
     239        1166 :         state.keystr = keystr;
     240        1166 :         state.oldval = oldval;
     241        1166 :         state.change_val = change_val;
     242             : 
     243        1166 :         ret = dbwrap_trans_do(db, dbwrap_change_uint32_atomic_action, &state);
     244             : 
     245        1166 :         return ret;
     246             : }
     247             : 
     248             : /**
     249             :  * Atomic integer change (addition):
     250             :  *
     251             :  * if value does not exist yet in the db, use *oldval as initial old value.
     252             :  * return old value in *oldval.
     253             :  * store *oldval + change_val to db.
     254             :  */
     255             : 
     256             : struct dbwrap_change_int32_atomic_context {
     257             :         TDB_DATA key;
     258             :         int32_t *oldval;
     259             :         int32_t change_val;
     260             :         NTSTATUS status;
     261             : };
     262             : 
     263        5610 : static void dbwrap_change_int32_atomic_action_fn(struct db_record *rec,
     264             :                                                  TDB_DATA value,
     265             :                                                  void *private_data)
     266             : {
     267        5610 :         struct dbwrap_change_int32_atomic_context *state = private_data;
     268          36 :         uint8_t v_store[4];
     269        5610 :         TDB_DATA data = {
     270             :                 .dptr = v_store,
     271             :                 .dsize = sizeof(v_store),
     272             :         };
     273        5610 :         int32_t val = -1;
     274             : 
     275        5610 :         if (value.dptr == NULL) {
     276         407 :                 val = *(state->oldval);
     277        5203 :         } else if (value.dsize == sizeof(val)) {
     278        5203 :                 val = PULL_LE_U32(value.dptr, 0);
     279        5203 :                 *(state->oldval) = val;
     280             :         } else {
     281           0 :                 state->status = NT_STATUS_UNSUCCESSFUL;
     282           0 :                 return;
     283             :         }
     284             : 
     285        5610 :         val += state->change_val;
     286        5610 :         PUSH_LE_U32(v_store, 0, val);
     287             : 
     288        5610 :         state->status = dbwrap_record_store(rec, data, TDB_REPLACE);
     289             : }
     290             : 
     291        5610 : static NTSTATUS dbwrap_change_int32_atomic_action(struct db_context *db,
     292             :                                                   void *private_data)
     293             : {
     294        5610 :         struct dbwrap_change_int32_atomic_context *state = private_data;
     295          36 :         NTSTATUS status;
     296             : 
     297        5610 :         status = dbwrap_do_locked(db,
     298             :                                   state->key,
     299             :                                   dbwrap_change_int32_atomic_action_fn,
     300             :                                   state);
     301        5610 :         if (!NT_STATUS_IS_OK(status)) {
     302           0 :                 DBG_DEBUG("dbwrap_do_locked() failed: %s\n",
     303             :                           nt_errstr(status));
     304           0 :                 return status;
     305             :         }
     306        5610 :         if (!NT_STATUS_IS_OK(state->status)) {
     307           0 :                 DBG_DEBUG("dbwrap_change_int32_atomic_action_fn() "
     308             :                           "failed: %s\n",
     309             :                           nt_errstr(status));
     310           0 :                 return status;
     311             :         }
     312        5610 :         return NT_STATUS_OK;
     313             : }
     314             : 
     315        5610 : NTSTATUS dbwrap_change_int32_atomic(struct db_context *db,
     316             :                                     TDB_DATA key,
     317             :                                     int32_t *oldval,
     318             :                                     int32_t change_val)
     319             : {
     320          36 :         NTSTATUS ret;
     321          36 :         struct dbwrap_change_int32_atomic_context state;
     322             : 
     323        5610 :         state.key = key;
     324        5610 :         state.oldval = oldval;
     325        5610 :         state.change_val = change_val;
     326             : 
     327        5610 :         ret = dbwrap_change_int32_atomic_action(db, &state);
     328             : 
     329        5610 :         return ret;
     330             : }
     331             : 
     332           0 : NTSTATUS dbwrap_change_int32_atomic_bystring(struct db_context *db,
     333             :                                              const char *keystr,
     334             :                                              int32_t *oldval,
     335             :                                              int32_t change_val)
     336             : {
     337           0 :         return dbwrap_change_int32_atomic(db, string_term_tdb_data(keystr),
     338             :                                           oldval, change_val);
     339             : }
     340             : 
     341           0 : NTSTATUS dbwrap_trans_change_int32_atomic_bystring(struct db_context *db,
     342             :                                                    const char *keystr,
     343             :                                                    int32_t *oldval,
     344             :                                                    int32_t change_val)
     345             : {
     346           0 :         NTSTATUS ret;
     347           0 :         struct dbwrap_change_int32_atomic_context state;
     348             : 
     349           0 :         state.key = string_term_tdb_data(keystr);
     350           0 :         state.oldval = oldval;
     351           0 :         state.change_val = change_val;
     352             : 
     353           0 :         ret = dbwrap_trans_do(db, dbwrap_change_int32_atomic_action, &state);
     354             : 
     355           0 :         return ret;
     356             : }
     357             : 
     358             : struct dbwrap_store_context {
     359             :         TDB_DATA *key;
     360             :         TDB_DATA *dbuf;
     361             :         int flag;
     362             : };
     363             : 
     364       20898 : static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
     365             : {
     366         219 :         NTSTATUS status;
     367         219 :         struct dbwrap_store_context *store_ctx;
     368             : 
     369       20898 :         store_ctx = (struct dbwrap_store_context *)private_data;
     370             : 
     371       20898 :         status = dbwrap_store(db, *(store_ctx->key), *(store_ctx->dbuf),
     372             :                               store_ctx->flag);
     373       20898 :         if (!NT_STATUS_IS_OK(status)) {
     374           0 :                 DEBUG(5, ("store returned %s\n", nt_errstr(status)));
     375             :         }
     376             : 
     377       20898 :         return status;
     378             : }
     379             : 
     380       20898 : NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
     381             :                             int flag)
     382             : {
     383         219 :         NTSTATUS status;
     384         219 :         struct dbwrap_store_context store_ctx;
     385             : 
     386       20898 :         store_ctx.key = &key;
     387       20898 :         store_ctx.dbuf = &dbuf;
     388       20898 :         store_ctx.flag = flag;
     389             : 
     390       20898 :         status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
     391             : 
     392       20898 :         return status;
     393             : }
     394             : 
     395         521 : static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
     396             : {
     397           9 :         NTSTATUS status;
     398         521 :         TDB_DATA *key = (TDB_DATA *)private_data;
     399             : 
     400         521 :         status = dbwrap_delete(db, *key);
     401         521 :         if (!NT_STATUS_IS_OK(status)) {
     402           7 :                 DBG_INFO("dbwrap_record_delete returned %s\n",
     403             :                          nt_errstr(status));
     404             :         }
     405         521 :         return  status;
     406             : }
     407             : 
     408         521 : NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
     409             : {
     410           9 :         NTSTATUS status;
     411             : 
     412         521 :         status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
     413             : 
     414         521 :         return status;
     415             : }
     416             : 
     417          15 : NTSTATUS dbwrap_trans_store_int32_bystring(struct db_context *db,
     418             :                                            const char *keystr,
     419             :                                            int32_t v)
     420             : {
     421           1 :         int32_t v_store;
     422             : 
     423          15 :         SIVAL(&v_store, 0, v);
     424             : 
     425          15 :         return dbwrap_trans_store(db, string_term_tdb_data(keystr),
     426             :                                   make_tdb_data((const uint8_t *)&v_store,
     427             :                                                 sizeof(v_store)),
     428             :                                   TDB_REPLACE);
     429             : }
     430             : 
     431        1002 : NTSTATUS dbwrap_trans_store_uint32_bystring(struct db_context *db,
     432             :                                             const char *keystr,
     433             :                                             uint32_t v)
     434             : {
     435          20 :         uint32_t v_store;
     436             : 
     437        1002 :         SIVAL(&v_store, 0, v);
     438             : 
     439        1002 :         return dbwrap_trans_store(db, string_term_tdb_data(keystr),
     440             :                                   make_tdb_data((const uint8_t *)&v_store,
     441             :                                                 sizeof(v_store)),
     442             :                                   TDB_REPLACE);
     443             : }
     444             : 
     445       16581 : NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
     446             :                                      TDB_DATA data, int flags)
     447             : {
     448       16581 :         return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
     449             : }
     450             : 
     451           2 : NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
     452             : {
     453           2 :         return dbwrap_trans_delete(db, string_term_tdb_data(key));
     454             : }
     455             : 
     456             : /**
     457             :  * Wrap db action(s) into a transaction.
     458             :  */
     459       46417 : NTSTATUS dbwrap_trans_do(struct db_context *db,
     460             :                          NTSTATUS (*action)(struct db_context *, void *),
     461             :                          void *private_data)
     462             : {
     463         488 :         int res;
     464         488 :         NTSTATUS status;
     465             : 
     466       46417 :         res = dbwrap_transaction_start(db);
     467       46417 :         if (res != 0) {
     468           0 :                 DEBUG(5, ("transaction_start failed\n"));
     469           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     470             :         }
     471             : 
     472       46417 :         status = action(db, private_data);
     473       46417 :         if (!NT_STATUS_IS_OK(status)) {
     474          11 :                 if (dbwrap_transaction_cancel(db) != 0) {
     475           0 :                         smb_panic("Cancelling transaction failed");
     476             :                 }
     477          11 :                 return status;
     478             :         }
     479             : 
     480       46406 :         res = dbwrap_transaction_commit(db);
     481       46406 :         if (res == 0) {
     482       46406 :                 return NT_STATUS_OK;
     483             :         }
     484             : 
     485           0 :         DEBUG(2, ("transaction_commit failed\n"));
     486           0 :         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     487             : }
     488             : 
     489             : struct dbwrap_trans_traverse_action_ctx {
     490             :         int (*f)(struct db_record* rec, void* private_data);
     491             :         void* private_data;
     492             : };
     493             : 
     494             : 
     495           0 : static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
     496             : {
     497           0 :         struct dbwrap_trans_traverse_action_ctx* ctx =
     498             :                 (struct dbwrap_trans_traverse_action_ctx*)private_data;
     499             : 
     500           0 :         NTSTATUS status = dbwrap_traverse(db, ctx->f, ctx->private_data, NULL);
     501             : 
     502           0 :         return status;
     503             : }
     504             : 
     505           0 : NTSTATUS dbwrap_trans_traverse(struct db_context *db,
     506             :                                int (*f)(struct db_record*, void*),
     507             :                                void *private_data)
     508             : {
     509           0 :         struct dbwrap_trans_traverse_action_ctx ctx = {
     510             :                 .f = f,
     511             :                 .private_data = private_data,
     512             :         };
     513           0 :         return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
     514             : }
     515             : 
     516        8594 : NTSTATUS dbwrap_purge(struct db_context *db, TDB_DATA key)
     517             : {
     518          33 :         NTSTATUS status;
     519             : 
     520        8594 :         status = dbwrap_delete(db, key);
     521        8594 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     522        2150 :                 status = NT_STATUS_OK;
     523             :         }
     524             : 
     525        8594 :         return status;
     526             : }
     527             : 
     528        8483 : NTSTATUS dbwrap_purge_bystring(struct db_context *db, const char *key)
     529             : {
     530        8483 :         return dbwrap_purge(db, string_term_tdb_data(key));
     531             : }
     532             : 
     533      146088 : NTSTATUS dbwrap_delete_bystring(struct db_context *db, const char *key)
     534             : {
     535      146088 :         return dbwrap_delete(db, string_term_tdb_data(key));
     536             : }
     537             : 
     538     1706911 : NTSTATUS dbwrap_store_bystring(struct db_context *db, const char *key,
     539             :                                TDB_DATA data, int flags)
     540             : {
     541     1706911 :         return dbwrap_store(db, string_term_tdb_data(key), data, flags);
     542             : }
     543             : 
     544    11083503 : NTSTATUS dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx,
     545             :                                const char *key, TDB_DATA *value)
     546             : {
     547    11083503 :         return dbwrap_fetch(db, mem_ctx, string_term_tdb_data(key), value);
     548             : }
     549             : 
     550             : 
     551             : 
     552        1594 : NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
     553             : {
     554          11 :         char *key_upper;
     555          11 :         NTSTATUS status;
     556             : 
     557        1594 :         key_upper = talloc_strdup_upper(talloc_tos(), key);
     558        1594 :         if (key_upper == NULL) {
     559           0 :                 return NT_STATUS_NO_MEMORY;
     560             :         }
     561             : 
     562        1594 :         status = dbwrap_delete_bystring(db, key_upper);
     563             : 
     564        1594 :         talloc_free(key_upper);
     565        1594 :         return status;
     566             : }
     567             : 
     568     1469124 : NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
     569             :                                      TDB_DATA data, int flags)
     570             : {
     571         506 :         char *key_upper;
     572         506 :         NTSTATUS status;
     573             : 
     574     1469124 :         key_upper = talloc_strdup_upper(talloc_tos(), key);
     575     1469124 :         if (key_upper == NULL) {
     576           0 :                 return NT_STATUS_NO_MEMORY;
     577             :         }
     578             : 
     579     1469124 :         status = dbwrap_store_bystring(db, key_upper, data, flags);
     580             : 
     581     1469124 :         talloc_free(key_upper);
     582     1469124 :         return status;
     583             : }
     584             : 
     585     1067142 : NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
     586             :                                      const char *key, TDB_DATA *value)
     587             : {
     588         318 :         char *key_upper;
     589         318 :         NTSTATUS status;
     590             : 
     591     1067142 :         key_upper = talloc_strdup_upper(talloc_tos(), key);
     592     1067142 :         if (key_upper == NULL) {
     593           0 :                 return NT_STATUS_NO_MEMORY;
     594             :         }
     595             : 
     596     1067142 :         status = dbwrap_fetch_bystring(db, mem_ctx, key_upper, value);
     597             : 
     598     1067142 :         talloc_free(key_upper);
     599     1067142 :         return status;
     600             : }
     601             : 
     602             : struct dbwrap_marshall_state {
     603             :         uint8_t *buf;
     604             :         size_t bufsize;
     605             :         size_t dbsize;
     606             : };
     607             : 
     608           0 : static int dbwrap_marshall_fn(struct db_record *rec, void *private_data)
     609             : {
     610           0 :         struct dbwrap_marshall_state *state = private_data;
     611           0 :         TDB_DATA key, value;
     612           0 :         size_t new_dbsize;
     613             : 
     614           0 :         key = dbwrap_record_get_key(rec);
     615           0 :         value = dbwrap_record_get_value(rec);
     616             : 
     617           0 :         new_dbsize = state->dbsize;
     618           0 :         new_dbsize += 8 + key.dsize;
     619           0 :         new_dbsize += 8 + value.dsize;
     620             : 
     621           0 :         if (new_dbsize <= state->bufsize) {
     622           0 :                 uint8_t *p = state->buf + state->dbsize;
     623             : 
     624           0 :                 SBVAL(p, 0, key.dsize);
     625           0 :                 p += 8;
     626           0 :                 memcpy(p, key.dptr, key.dsize);
     627           0 :                 p += key.dsize;
     628             : 
     629           0 :                 SBVAL(p, 0, value.dsize);
     630           0 :                 p += 8;
     631           0 :                 memcpy(p, value.dptr, value.dsize);
     632             :         }
     633           0 :         state->dbsize = new_dbsize;
     634           0 :         return 0;
     635             : }
     636             : 
     637           0 : size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize)
     638             : {
     639           0 :         struct dbwrap_marshall_state state;
     640             : 
     641           0 :         state.bufsize = bufsize;
     642           0 :         state.buf = buf;
     643           0 :         state.dbsize = 0;
     644             : 
     645           0 :         dbwrap_traverse_read(db, dbwrap_marshall_fn, &state, NULL);
     646             : 
     647           0 :         return state.dbsize;
     648             : }
     649             : 
     650          15 : static ssize_t dbwrap_unmarshall_get_data(const uint8_t *buf, size_t buflen,
     651             :                                           size_t ofs, TDB_DATA *pdata)
     652             : {
     653           0 :         uint64_t space, len;
     654           0 :         const uint8_t *p;
     655             : 
     656          15 :         if (ofs == buflen) {
     657           9 :                 return 0;
     658             :         }
     659           6 :         if (ofs > buflen) {
     660           0 :                 return -1;
     661             :         }
     662             : 
     663           6 :         space = buflen - ofs;
     664           6 :         if (space < 8) {
     665           0 :                 return -1;
     666             :         }
     667             : 
     668           6 :         p = buf + ofs;
     669           6 :         len = BVAL(p, 0);
     670             : 
     671           6 :         p += 8;
     672           6 :         space -= 8;
     673             : 
     674           6 :         if (len > space) {
     675           0 :                 return -1;
     676             :         }
     677             : 
     678           6 :         *pdata = (TDB_DATA) { .dptr = discard_const_p(uint8_t, p),
     679             :                               .dsize = len };
     680           6 :         return len + 8;
     681             : }
     682             : 
     683           9 : NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen,
     684             :                                    bool (*fn)(TDB_DATA key, TDB_DATA value,
     685             :                                               void *private_data),
     686             :                                    void *private_data)
     687             : {
     688           9 :         size_t ofs = 0;
     689             : 
     690           3 :         while (true) {
     691           0 :                 ssize_t len;
     692           0 :                 TDB_DATA key, value;
     693           0 :                 bool ok;
     694             : 
     695          12 :                 len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &key);
     696          12 :                 if (len == 0) {
     697           9 :                         break;
     698             :                 }
     699           3 :                 if (len == -1) {
     700           0 :                         return NT_STATUS_INVALID_PARAMETER;
     701             :                 }
     702           3 :                 ofs += len;
     703             : 
     704           3 :                 len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &value);
     705           3 :                 if (len == 0) {
     706           0 :                         break;
     707             :                 }
     708           3 :                 if (len == -1) {
     709           0 :                         return NT_STATUS_INVALID_PARAMETER;
     710             :                 }
     711           3 :                 ofs += len;
     712             : 
     713           3 :                 ok = fn(key, value, private_data);
     714           3 :                 if (!ok) {
     715           0 :                         break;
     716             :                 }
     717             :         }
     718             : 
     719           9 :         return NT_STATUS_OK;
     720             : }
     721             : 
     722             : struct dbwrap_unmarshall_state {
     723             :         struct db_context *db;
     724             :         NTSTATUS ret;
     725             : };
     726             : 
     727           0 : static bool dbwrap_unmarshall_fn(TDB_DATA key, TDB_DATA value,
     728             :                                  void *private_data)
     729             : {
     730           0 :         struct dbwrap_unmarshall_state *state = private_data;
     731           0 :         NTSTATUS status;
     732             : 
     733           0 :         status = dbwrap_store(state->db, key, value, 0);
     734           0 :         if (!NT_STATUS_IS_OK(status)) {
     735           0 :                 DBG_DEBUG("dbwrap_record_store failed: %s\n",
     736             :                           nt_errstr(status));
     737           0 :                 state->ret = status;
     738           0 :                 return false;
     739             :         }
     740             : 
     741           0 :         return true;
     742             : }
     743             : 
     744           0 : NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf,
     745             :                            size_t buflen)
     746             : {
     747           0 :         struct dbwrap_unmarshall_state state = { .db = db };
     748           0 :         NTSTATUS status;
     749             : 
     750           0 :         status = dbwrap_parse_marshall_buf(buf, buflen,
     751             :                                            dbwrap_unmarshall_fn, &state);
     752           0 :         if (!NT_STATUS_IS_OK(status)) {
     753           0 :                 return status;
     754             :         }
     755           0 :         return state.ret;
     756             : }

Generated by: LCOV version 1.14