LCOV - code coverage report
Current view: top level - lib/dbwrap - dbwrap_util.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 154 272 56.6 %
Date: 2024-06-13 04:01:37 Functions: 27 39 69.2 %

          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        5159 : static void dbwrap_fetch_int32_parser(TDB_DATA key, TDB_DATA data,
      35             :                                       void *private_data)
      36             : {
      37        5159 :         struct dbwrap_fetch_int32_state *state =
      38             :                 (struct dbwrap_fetch_int32_state *)private_data;
      39             : 
      40        5159 :         if (data.dsize != sizeof(state->result)) {
      41           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
      42           0 :                 return;
      43             :         }
      44        5159 :         state->result = IVAL(data.dptr, 0);
      45        5159 :         state->status = NT_STATUS_OK;
      46             : }
      47             : 
      48        6452 : NTSTATUS dbwrap_fetch_int32(struct db_context *db, TDB_DATA key,
      49             :                             int32_t *result)
      50             : {
      51             :         struct dbwrap_fetch_int32_state state;
      52             :         NTSTATUS status;
      53             : 
      54        6452 :         if (result == NULL) {
      55           0 :                 return NT_STATUS_INVALID_PARAMETER;
      56             :         }
      57             : 
      58        6452 :         state.status = NT_STATUS_INTERNAL_ERROR;
      59             : 
      60        6452 :         status = dbwrap_parse_record(db, key, dbwrap_fetch_int32_parser, &state);
      61        6452 :         if (!NT_STATUS_IS_OK(status)) {
      62        1293 :                 return status;
      63             :         }
      64             : 
      65        5159 :         if (NT_STATUS_IS_OK(state.status)) {
      66        5159 :                 *result = state.result;
      67             :         }
      68        5159 :         return state.status;
      69             : }
      70             : 
      71        5413 : NTSTATUS dbwrap_fetch_int32_bystring(struct db_context *db, const char *keystr,
      72             :                                      int32_t *result)
      73             : {
      74        5413 :         return dbwrap_fetch_int32(db, string_term_tdb_data(keystr), result);
      75             : }
      76             : 
      77         196 : NTSTATUS dbwrap_store_int32_bystring(struct db_context *db, const char *keystr,
      78             :                                      int32_t v)
      79             : {
      80             :         uint8_t v_store[sizeof(int32_t)];
      81         196 :         TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
      82             :         NTSTATUS status;
      83             : 
      84         196 :         SIVAL(v_store, 0, v);
      85             : 
      86         196 :         status = dbwrap_store(db, string_term_tdb_data(keystr), data,
      87             :                               TDB_REPLACE);
      88         196 :         return status;
      89             : }
      90             : 
      91             : struct dbwrap_fetch_uint32_state {
      92             :         NTSTATUS status;
      93             :         uint32_t result;
      94             : };
      95             : 
      96        9125 : static void dbwrap_fetch_uint32_parser(TDB_DATA key, TDB_DATA data,
      97             :                                        void *private_data)
      98             : {
      99        9125 :         struct dbwrap_fetch_uint32_state *state =
     100             :                 (struct dbwrap_fetch_uint32_state *)private_data;
     101             : 
     102        9125 :         if (data.dsize != sizeof(state->result)) {
     103           0 :                 state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     104           0 :                 return;
     105             :         }
     106        9125 :         state->result = IVAL(data.dptr, 0);
     107        9125 :         state->status = NT_STATUS_OK;
     108             : }
     109             : 
     110       10126 : NTSTATUS dbwrap_fetch_uint32_bystring(struct db_context *db,
     111             :                                       const char *keystr, uint32_t *val)
     112             : {
     113             :         struct dbwrap_fetch_uint32_state state;
     114             :         NTSTATUS status;
     115             : 
     116       10126 :         if (val == NULL) {
     117           0 :                 return NT_STATUS_INVALID_PARAMETER;
     118             :         }
     119             : 
     120       10126 :         state.status = NT_STATUS_INTERNAL_ERROR;
     121             : 
     122       10126 :         status = dbwrap_parse_record(db, string_term_tdb_data(keystr),
     123             :                                      dbwrap_fetch_uint32_parser, &state);
     124       10126 :         if (!NT_STATUS_IS_OK(status)) {
     125        1001 :                 return status;
     126             :         }
     127        9125 :         if (NT_STATUS_IS_OK(state.status)) {
     128        9125 :                 *val = state.result;
     129             :         }
     130        9125 :         return state.status;
     131             : }
     132             : 
     133         110 : NTSTATUS dbwrap_store_uint32_bystring(struct db_context *db,
     134             :                                       const char *keystr, uint32_t v)
     135             : {
     136             :         uint8_t v_store[sizeof(uint32_t)];
     137         110 :         TDB_DATA data = { .dptr = v_store, .dsize = sizeof(v_store) };
     138             :         NTSTATUS status;
     139             : 
     140         110 :         SIVAL(v_store, 0, v);
     141             : 
     142         110 :         status = dbwrap_store(db, string_term_tdb_data(keystr), data,
     143             :                               TDB_REPLACE);
     144         110 :         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             : };
     160             : 
     161         293 : static NTSTATUS dbwrap_change_uint32_atomic_action(struct db_context *db,
     162             :                                                    void *private_data)
     163             : {
     164             :         struct db_record *rec;
     165         293 :         uint32_t val = (uint32_t)-1;
     166             :         uint32_t v_store;
     167             :         NTSTATUS ret;
     168             :         struct dbwrap_change_uint32_atomic_context *state;
     169             :         TDB_DATA value;
     170             : 
     171         293 :         state = (struct dbwrap_change_uint32_atomic_context *)private_data;
     172             : 
     173         293 :         rec = dbwrap_fetch_locked(db, talloc_tos(),
     174             :                                   string_term_tdb_data(state->keystr));
     175         293 :         if (!rec) {
     176           0 :                 return NT_STATUS_UNSUCCESSFUL;
     177             :         }
     178             : 
     179         293 :         value = dbwrap_record_get_value(rec);
     180             : 
     181         293 :         if (value.dptr == NULL) {
     182           0 :                 val = *(state->oldval);
     183         293 :         } else if (value.dsize == sizeof(val)) {
     184         293 :                 val = IVAL(value.dptr, 0);
     185         293 :                 *(state->oldval) = val;
     186             :         } else {
     187           0 :                 ret = NT_STATUS_UNSUCCESSFUL;
     188           0 :                 goto done;
     189             :         }
     190             : 
     191         293 :         val += state->change_val;
     192             : 
     193         293 :         SIVAL(&v_store, 0, val);
     194             : 
     195         293 :         ret = dbwrap_record_store(rec,
     196             :                                   make_tdb_data((const uint8_t *)&v_store,
     197             :                                                 sizeof(v_store)),
     198             :                                   TDB_REPLACE);
     199             : 
     200         293 : done:
     201         293 :         TALLOC_FREE(rec);
     202         293 :         return ret;
     203             : }
     204             : 
     205           0 : NTSTATUS dbwrap_change_uint32_atomic_bystring(struct db_context *db,
     206             :                                               const char *keystr,
     207             :                                               uint32_t *oldval,
     208             :                                               uint32_t change_val)
     209             : {
     210             :         NTSTATUS ret;
     211             :         struct dbwrap_change_uint32_atomic_context state;
     212             : 
     213           0 :         state.keystr = keystr;
     214           0 :         state.oldval = oldval;
     215           0 :         state.change_val = change_val;
     216             : 
     217           0 :         ret = dbwrap_change_uint32_atomic_action(db, &state);
     218             : 
     219           0 :         return ret;
     220             : }
     221             : 
     222         293 : NTSTATUS dbwrap_trans_change_uint32_atomic_bystring(struct db_context *db,
     223             :                                                     const char *keystr,
     224             :                                                     uint32_t *oldval,
     225             :                                                     uint32_t change_val)
     226             : {
     227             :         NTSTATUS ret;
     228             :         struct dbwrap_change_uint32_atomic_context state;
     229             : 
     230         293 :         state.keystr = keystr;
     231         293 :         state.oldval = oldval;
     232         293 :         state.change_val = change_val;
     233             : 
     234         293 :         ret = dbwrap_trans_do(db, dbwrap_change_uint32_atomic_action, &state);
     235             : 
     236         293 :         return ret;
     237             : }
     238             : 
     239             : /**
     240             :  * Atomic integer change (addition):
     241             :  *
     242             :  * if value does not exist yet in the db, use *oldval as initial old value.
     243             :  * return old value in *oldval.
     244             :  * store *oldval + change_val to db.
     245             :  */
     246             : 
     247             : struct dbwrap_change_int32_atomic_context {
     248             :         TDB_DATA key;
     249             :         int32_t *oldval;
     250             :         int32_t change_val;
     251             : };
     252             : 
     253          10 : static NTSTATUS dbwrap_change_int32_atomic_action(struct db_context *db,
     254             :                                                   void *private_data)
     255             : {
     256             :         struct db_record *rec;
     257          10 :         int32_t val = -1;
     258             :         int32_t v_store;
     259             :         NTSTATUS ret;
     260             :         struct dbwrap_change_int32_atomic_context *state;
     261             :         TDB_DATA value;
     262             : 
     263          10 :         state = (struct dbwrap_change_int32_atomic_context *)private_data;
     264             : 
     265          10 :         rec = dbwrap_fetch_locked(db, talloc_tos(), state->key);
     266          10 :         if (!rec) {
     267           0 :                 return NT_STATUS_UNSUCCESSFUL;
     268             :         }
     269             : 
     270          10 :         value = dbwrap_record_get_value(rec);
     271             : 
     272          10 :         if (value.dptr == NULL) {
     273           5 :                 val = *(state->oldval);
     274           5 :         } else if (value.dsize == sizeof(val)) {
     275           5 :                 val = IVAL(value.dptr, 0);
     276           5 :                 *(state->oldval) = val;
     277             :         } else {
     278           0 :                 ret = NT_STATUS_UNSUCCESSFUL;
     279           0 :                 goto done;
     280             :         }
     281             : 
     282          10 :         val += state->change_val;
     283             : 
     284          10 :         SIVAL(&v_store, 0, val);
     285             : 
     286          10 :         ret = dbwrap_record_store(rec,
     287             :                                   make_tdb_data((const uint8_t *)&v_store,
     288             :                                                 sizeof(v_store)),
     289             :                                   TDB_REPLACE);
     290             : 
     291          10 : done:
     292          10 :         TALLOC_FREE(rec);
     293          10 :         return ret;
     294             : }
     295             : 
     296          10 : NTSTATUS dbwrap_change_int32_atomic(struct db_context *db,
     297             :                                     TDB_DATA key,
     298             :                                     int32_t *oldval,
     299             :                                     int32_t change_val)
     300             : {
     301             :         NTSTATUS ret;
     302             :         struct dbwrap_change_int32_atomic_context state;
     303             : 
     304          10 :         state.key = key;
     305          10 :         state.oldval = oldval;
     306          10 :         state.change_val = change_val;
     307             : 
     308          10 :         ret = dbwrap_change_int32_atomic_action(db, &state);
     309             : 
     310          10 :         return ret;
     311             : }
     312             : 
     313           0 : NTSTATUS dbwrap_change_int32_atomic_bystring(struct db_context *db,
     314             :                                              const char *keystr,
     315             :                                              int32_t *oldval,
     316             :                                              int32_t change_val)
     317             : {
     318           0 :         return dbwrap_change_int32_atomic(db, string_term_tdb_data(keystr),
     319             :                                           oldval, change_val);
     320             : }
     321             : 
     322           0 : NTSTATUS dbwrap_trans_change_int32_atomic_bystring(struct db_context *db,
     323             :                                                    const char *keystr,
     324             :                                                    int32_t *oldval,
     325             :                                                    int32_t change_val)
     326             : {
     327             :         NTSTATUS ret;
     328             :         struct dbwrap_change_int32_atomic_context state;
     329             : 
     330           0 :         state.key = string_term_tdb_data(keystr);
     331           0 :         state.oldval = oldval;
     332           0 :         state.change_val = change_val;
     333             : 
     334           0 :         ret = dbwrap_trans_do(db, dbwrap_change_int32_atomic_action, &state);
     335             : 
     336           0 :         return ret;
     337             : }
     338             : 
     339             : struct dbwrap_store_context {
     340             :         TDB_DATA *key;
     341             :         TDB_DATA *dbuf;
     342             :         int flag;
     343             : };
     344             : 
     345        3317 : static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data)
     346             : {
     347             :         NTSTATUS status;
     348             :         struct dbwrap_store_context *store_ctx;
     349             : 
     350        3317 :         store_ctx = (struct dbwrap_store_context *)private_data;
     351             : 
     352        3317 :         status = dbwrap_store(db, *(store_ctx->key), *(store_ctx->dbuf),
     353             :                               store_ctx->flag);
     354        3317 :         if (!NT_STATUS_IS_OK(status)) {
     355           0 :                 DEBUG(5, ("store returned %s\n", nt_errstr(status)));
     356             :         }
     357             : 
     358        3317 :         return status;
     359             : }
     360             : 
     361        3317 : NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf,
     362             :                             int flag)
     363             : {
     364             :         NTSTATUS status;
     365             :         struct dbwrap_store_context store_ctx;
     366             : 
     367        3317 :         store_ctx.key = &key;
     368        3317 :         store_ctx.dbuf = &dbuf;
     369        3317 :         store_ctx.flag = flag;
     370             : 
     371        3317 :         status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx);
     372             : 
     373        3317 :         return status;
     374             : }
     375             : 
     376         105 : static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data)
     377             : {
     378             :         NTSTATUS status;
     379         105 :         TDB_DATA *key = (TDB_DATA *)private_data;
     380             : 
     381         105 :         status = dbwrap_delete(db, *key);
     382         105 :         if (!NT_STATUS_IS_OK(status)) {
     383           1 :                 DBG_INFO("dbwrap_record_delete returned %s\n",
     384             :                          nt_errstr(status));
     385             :         }
     386         105 :         return  status;
     387             : }
     388             : 
     389         105 : NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key)
     390             : {
     391             :         NTSTATUS status;
     392             : 
     393         105 :         status = dbwrap_trans_do(db, dbwrap_delete_action, &key);
     394             : 
     395         105 :         return status;
     396             : }
     397             : 
     398          38 : NTSTATUS dbwrap_trans_store_int32_bystring(struct db_context *db,
     399             :                                            const char *keystr,
     400             :                                            int32_t v)
     401             : {
     402             :         int32_t v_store;
     403             : 
     404          38 :         SIVAL(&v_store, 0, v);
     405             : 
     406          38 :         return dbwrap_trans_store(db, string_term_tdb_data(keystr),
     407             :                                   make_tdb_data((const uint8_t *)&v_store,
     408             :                                                 sizeof(v_store)),
     409             :                                   TDB_REPLACE);
     410             : }
     411             : 
     412         810 : NTSTATUS dbwrap_trans_store_uint32_bystring(struct db_context *db,
     413             :                                             const char *keystr,
     414             :                                             uint32_t v)
     415             : {
     416             :         uint32_t v_store;
     417             : 
     418         810 :         SIVAL(&v_store, 0, v);
     419             : 
     420         810 :         return dbwrap_trans_store(db, string_term_tdb_data(keystr),
     421             :                                   make_tdb_data((const uint8_t *)&v_store,
     422             :                                                 sizeof(v_store)),
     423             :                                   TDB_REPLACE);
     424             : }
     425             : 
     426         888 : NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key,
     427             :                                      TDB_DATA data, int flags)
     428             : {
     429         888 :         return dbwrap_trans_store(db, string_term_tdb_data(key), data, flags);
     430             : }
     431             : 
     432           0 : NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key)
     433             : {
     434           0 :         return dbwrap_trans_delete(db, string_term_tdb_data(key));
     435             : }
     436             : 
     437             : /**
     438             :  * Wrap db action(s) into a transaction.
     439             :  */
     440        7916 : NTSTATUS dbwrap_trans_do(struct db_context *db,
     441             :                          NTSTATUS (*action)(struct db_context *, void *),
     442             :                          void *private_data)
     443             : {
     444             :         int res;
     445             :         NTSTATUS status;
     446             : 
     447        7916 :         res = dbwrap_transaction_start(db);
     448        7916 :         if (res != 0) {
     449           0 :                 DEBUG(5, ("transaction_start failed\n"));
     450           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     451             :         }
     452             : 
     453        7916 :         status = action(db, private_data);
     454        7916 :         if (!NT_STATUS_IS_OK(status)) {
     455           1 :                 if (dbwrap_transaction_cancel(db) != 0) {
     456           0 :                         smb_panic("Cancelling transaction failed");
     457             :                 }
     458           1 :                 return status;
     459             :         }
     460             : 
     461        7915 :         res = dbwrap_transaction_commit(db);
     462        7915 :         if (res == 0) {
     463        7915 :                 return NT_STATUS_OK;
     464             :         }
     465             : 
     466           0 :         DEBUG(2, ("transaction_commit failed\n"));
     467           0 :         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     468             : }
     469             : 
     470             : struct dbwrap_trans_traverse_action_ctx {
     471             :         int (*f)(struct db_record* rec, void* private_data);
     472             :         void* private_data;
     473             : };
     474             : 
     475             : 
     476           0 : static NTSTATUS dbwrap_trans_traverse_action(struct db_context* db, void* private_data)
     477             : {
     478           0 :         struct dbwrap_trans_traverse_action_ctx* ctx =
     479             :                 (struct dbwrap_trans_traverse_action_ctx*)private_data;
     480             : 
     481           0 :         NTSTATUS status = dbwrap_traverse(db, ctx->f, ctx->private_data, NULL);
     482             : 
     483           0 :         return status;
     484             : }
     485             : 
     486           0 : NTSTATUS dbwrap_trans_traverse(struct db_context *db,
     487             :                                int (*f)(struct db_record*, void*),
     488             :                                void *private_data)
     489             : {
     490           0 :         struct dbwrap_trans_traverse_action_ctx ctx = {
     491             :                 .f = f,
     492             :                 .private_data = private_data,
     493             :         };
     494           0 :         return dbwrap_trans_do(db, dbwrap_trans_traverse_action, &ctx);
     495             : }
     496             : 
     497         291 : NTSTATUS dbwrap_purge(struct db_context *db, TDB_DATA key)
     498             : {
     499             :         NTSTATUS status;
     500             : 
     501         291 :         status = dbwrap_delete(db, key);
     502         291 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     503         161 :                 status = NT_STATUS_OK;
     504             :         }
     505             : 
     506         291 :         return status;
     507             : }
     508             : 
     509         255 : NTSTATUS dbwrap_purge_bystring(struct db_context *db, const char *key)
     510             : {
     511         255 :         return dbwrap_purge(db, string_term_tdb_data(key));
     512             : }
     513             : 
     514       29877 : NTSTATUS dbwrap_delete_bystring(struct db_context *db, const char *key)
     515             : {
     516       29877 :         return dbwrap_delete(db, string_term_tdb_data(key));
     517             : }
     518             : 
     519       75691 : NTSTATUS dbwrap_store_bystring(struct db_context *db, const char *key,
     520             :                                TDB_DATA data, int flags)
     521             : {
     522       75691 :         return dbwrap_store(db, string_term_tdb_data(key), data, flags);
     523             : }
     524             : 
     525      576474 : NTSTATUS dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx,
     526             :                                const char *key, TDB_DATA *value)
     527             : {
     528      576474 :         return dbwrap_fetch(db, mem_ctx, string_term_tdb_data(key), value);
     529             : }
     530             : 
     531             : 
     532             : 
     533          67 : NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key)
     534             : {
     535             :         char *key_upper;
     536             :         NTSTATUS status;
     537             : 
     538          67 :         key_upper = talloc_strdup_upper(talloc_tos(), key);
     539          67 :         if (key_upper == NULL) {
     540           0 :                 return NT_STATUS_NO_MEMORY;
     541             :         }
     542             : 
     543          67 :         status = dbwrap_delete_bystring(db, key_upper);
     544             : 
     545          67 :         talloc_free(key_upper);
     546          67 :         return status;
     547             : }
     548             : 
     549       15869 : NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key,
     550             :                                      TDB_DATA data, int flags)
     551             : {
     552             :         char *key_upper;
     553             :         NTSTATUS status;
     554             : 
     555       15869 :         key_upper = talloc_strdup_upper(talloc_tos(), key);
     556       15869 :         if (key_upper == NULL) {
     557           0 :                 return NT_STATUS_NO_MEMORY;
     558             :         }
     559             : 
     560       15869 :         status = dbwrap_store_bystring(db, key_upper, data, flags);
     561             : 
     562       15869 :         talloc_free(key_upper);
     563       15869 :         return status;
     564             : }
     565             : 
     566       10979 : NTSTATUS dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx,
     567             :                                      const char *key, TDB_DATA *value)
     568             : {
     569             :         char *key_upper;
     570             :         NTSTATUS status;
     571             : 
     572       10979 :         key_upper = talloc_strdup_upper(talloc_tos(), key);
     573       10979 :         if (key_upper == NULL) {
     574           0 :                 return NT_STATUS_NO_MEMORY;
     575             :         }
     576             : 
     577       10979 :         status = dbwrap_fetch_bystring(db, mem_ctx, key_upper, value);
     578             : 
     579       10979 :         talloc_free(key_upper);
     580       10979 :         return status;
     581             : }
     582             : 
     583             : struct dbwrap_marshall_state {
     584             :         uint8_t *buf;
     585             :         size_t bufsize;
     586             :         size_t dbsize;
     587             : };
     588             : 
     589           0 : static int dbwrap_marshall_fn(struct db_record *rec, void *private_data)
     590             : {
     591           0 :         struct dbwrap_marshall_state *state = private_data;
     592             :         TDB_DATA key, value;
     593             :         size_t new_dbsize;
     594             : 
     595           0 :         key = dbwrap_record_get_key(rec);
     596           0 :         value = dbwrap_record_get_value(rec);
     597             : 
     598           0 :         new_dbsize = state->dbsize;
     599           0 :         new_dbsize += 8 + key.dsize;
     600           0 :         new_dbsize += 8 + value.dsize;
     601             : 
     602           0 :         if (new_dbsize <= state->bufsize) {
     603           0 :                 uint8_t *p = state->buf + state->dbsize;
     604             : 
     605           0 :                 SBVAL(p, 0, key.dsize);
     606           0 :                 p += 8;
     607           0 :                 memcpy(p, key.dptr, key.dsize);
     608           0 :                 p += key.dsize;
     609             : 
     610           0 :                 SBVAL(p, 0, value.dsize);
     611           0 :                 p += 8;
     612           0 :                 memcpy(p, value.dptr, value.dsize);
     613             :         }
     614           0 :         state->dbsize = new_dbsize;
     615           0 :         return 0;
     616             : }
     617             : 
     618           0 : size_t dbwrap_marshall(struct db_context *db, uint8_t *buf, size_t bufsize)
     619             : {
     620             :         struct dbwrap_marshall_state state;
     621             : 
     622           0 :         state.bufsize = bufsize;
     623           0 :         state.buf = buf;
     624           0 :         state.dbsize = 0;
     625             : 
     626           0 :         dbwrap_traverse_read(db, dbwrap_marshall_fn, &state, NULL);
     627             : 
     628           0 :         return state.dbsize;
     629             : }
     630             : 
     631           0 : static ssize_t dbwrap_unmarshall_get_data(const uint8_t *buf, size_t buflen,
     632             :                                           size_t ofs, TDB_DATA *pdata)
     633             : {
     634             :         uint64_t space, len;
     635             :         const uint8_t *p;
     636             : 
     637           0 :         if (ofs == buflen) {
     638           0 :                 return 0;
     639             :         }
     640           0 :         if (ofs > buflen) {
     641           0 :                 return -1;
     642             :         }
     643             : 
     644           0 :         space = buflen - ofs;
     645           0 :         if (space < 8) {
     646           0 :                 return -1;
     647             :         }
     648             : 
     649           0 :         p = buf + ofs;
     650           0 :         len = BVAL(p, 0);
     651             : 
     652           0 :         p += 8;
     653           0 :         space -= 8;
     654             : 
     655           0 :         if (len > space) {
     656           0 :                 return -1;
     657             :         }
     658             : 
     659           0 :         *pdata = (TDB_DATA) { .dptr = discard_const_p(uint8_t, p),
     660             :                               .dsize = len };
     661           0 :         return len + 8;
     662             : }
     663             : 
     664           0 : NTSTATUS dbwrap_parse_marshall_buf(const uint8_t *buf, size_t buflen,
     665             :                                    bool (*fn)(TDB_DATA key, TDB_DATA value,
     666             :                                               void *private_data),
     667             :                                    void *private_data)
     668             : {
     669           0 :         size_t ofs = 0;
     670             : 
     671           0 :         while (true) {
     672             :                 ssize_t len;
     673             :                 TDB_DATA key, value;
     674             :                 bool ok;
     675             : 
     676           0 :                 len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &key);
     677           0 :                 if (len == 0) {
     678           0 :                         break;
     679             :                 }
     680           0 :                 if (len == -1) {
     681           0 :                         return NT_STATUS_INVALID_PARAMETER;
     682             :                 }
     683           0 :                 ofs += len;
     684             : 
     685           0 :                 len = dbwrap_unmarshall_get_data(buf, buflen, ofs, &value);
     686           0 :                 if (len == 0) {
     687           0 :                         break;
     688             :                 }
     689           0 :                 if (len == -1) {
     690           0 :                         return NT_STATUS_INVALID_PARAMETER;
     691             :                 }
     692           0 :                 ofs += len;
     693             : 
     694           0 :                 ok = fn(key, value, private_data);
     695           0 :                 if (!ok) {
     696           0 :                         break;
     697             :                 }
     698             :         }
     699             : 
     700           0 :         return NT_STATUS_OK;
     701             : }
     702             : 
     703             : struct dbwrap_unmarshall_state {
     704             :         struct db_context *db;
     705             :         NTSTATUS ret;
     706             : };
     707             : 
     708           0 : static bool dbwrap_unmarshall_fn(TDB_DATA key, TDB_DATA value,
     709             :                                  void *private_data)
     710             : {
     711           0 :         struct dbwrap_unmarshall_state *state = private_data;
     712             :         NTSTATUS status;
     713             : 
     714           0 :         status = dbwrap_store(state->db, key, value, 0);
     715           0 :         if (!NT_STATUS_IS_OK(status)) {
     716           0 :                 DBG_DEBUG("dbwrap_record_store failed: %s\n",
     717             :                           nt_errstr(status));
     718           0 :                 state->ret = status;
     719           0 :                 return false;
     720             :         }
     721             : 
     722           0 :         return true;
     723             : }
     724             : 
     725           0 : NTSTATUS dbwrap_unmarshall(struct db_context *db, const uint8_t *buf,
     726             :                            size_t buflen)
     727             : {
     728           0 :         struct dbwrap_unmarshall_state state = { .db = db };
     729             :         NTSTATUS status;
     730             : 
     731           0 :         status = dbwrap_parse_marshall_buf(buf, buflen,
     732             :                                            dbwrap_unmarshall_fn, &state);
     733           0 :         if (!NT_STATUS_IS_OK(status)) {
     734           0 :                 return status;
     735             :         }
     736           0 :         return state.ret;
     737             : }

Generated by: LCOV version 1.13