LCOV - code coverage report
Current view: top level - source3/rpc_server/fss - srv_fss_state.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 282 370 76.2 %
Date: 2024-04-21 15:09:00 Functions: 12 14 85.7 %

          Line data    Source code
       1             : /*
       2             :  * File Server Remote VSS Protocol (FSRVP) persistent server state
       3             :  *
       4             :  * Copyright (C) David Disseldorp       2012-2015
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "source3/include/includes.h"
      21             : #include <fcntl.h>
      22             : #include "source3/include/util_tdb.h"
      23             : #include "lib/dbwrap/dbwrap.h"
      24             : #include "lib/dbwrap/dbwrap_open.h"
      25             : #include "librpc/ndr/libndr.h"
      26             : #include "librpc/gen_ndr/ndr_fsrvp_state.h"
      27             : #include "srv_fss_private.h"
      28             : 
      29             : #define FSS_DB_KEY_VERSION "db_version"
      30             : #define FSS_DB_KEY_CONTEXT "context"
      31             : #define FSS_DB_KEY_SC_SET_COUNT "sc_set_count"
      32             : #define FSS_DB_KEY_PFX_SC_SET "sc_set/"
      33             : #define FSS_DB_KEY_PFX_SC "sc/"
      34             : #define FSS_DB_KEY_PFX_SMAP "smap/"
      35             : 
      36          94 : static NTSTATUS fss_state_smap_store(TALLOC_CTX *mem_ctx,
      37             :                                      struct db_context *db,
      38             :                                      const char *sc_key_str,
      39             :                                      struct fss_sc_smap *smap)
      40             : {
      41           4 :         NTSTATUS status;
      42           4 :         TDB_DATA val;
      43           4 :         const char *smap_key_str;
      44           4 :         struct fsrvp_state_smap smap_state;
      45           4 :         enum ndr_err_code ndr_ret;
      46           4 :         DATA_BLOB smap_state_blob;
      47             : 
      48             :         /* becomes sc_set/@sc_set_id/sc/@sc_id/smap/@sc_share_name */
      49          94 :         smap_key_str = talloc_asprintf(mem_ctx, "%s/%s%s", sc_key_str,
      50             :                                        FSS_DB_KEY_PFX_SMAP,
      51             :                                        smap->sc_share_name);
      52          94 :         if (smap_key_str == NULL) {
      53           0 :                 return NT_STATUS_NO_MEMORY;
      54             :         }
      55             : 
      56          94 :         smap_state.share_name = smap->share_name;
      57          94 :         smap_state.sc_share_name = smap->sc_share_name;
      58             :         /* @smap->sc_share_comment may be null if not exposed. */
      59          94 :         if (smap->sc_share_comment != NULL) {
      60          78 :                 smap_state.sc_share_comment = smap->sc_share_comment;
      61             :         } else {
      62          16 :                 smap_state.sc_share_comment = "";
      63             :         }
      64          94 :         smap_state.is_exposed = smap->is_exposed;
      65             : 
      66          94 :         ndr_ret = ndr_push_struct_blob(&smap_state_blob, mem_ctx,
      67             :                                        &smap_state,
      68             :                                 (ndr_push_flags_fn_t)ndr_push_fsrvp_state_smap);
      69          94 :         if (ndr_ret != NDR_ERR_SUCCESS) {
      70           0 :                 return NT_STATUS_INTERNAL_ERROR;
      71             :         }
      72             : 
      73          94 :         val.dsize = smap_state_blob.length;
      74          94 :         val.dptr = smap_state_blob.data;
      75             : 
      76          94 :         status = dbwrap_store(db, string_term_tdb_data(smap_key_str), val, 0);
      77          94 :         if (!NT_STATUS_IS_OK(status)) {
      78           0 :                 return status;
      79             :         }
      80             : 
      81          94 :         return NT_STATUS_OK;
      82             : }
      83             : 
      84          93 : static NTSTATUS fss_state_sc_store(TALLOC_CTX *mem_ctx,
      85             :                                    struct db_context *db,
      86             :                                    const char *sc_set_key_str,
      87             :                                    struct fss_sc *sc)
      88             : {
      89           3 :         NTSTATUS status;
      90           3 :         TDB_DATA val;
      91           3 :         const char *sc_key_str;
      92           3 :         struct fsrvp_state_sc sc_state;
      93           3 :         struct fss_sc_smap *smap;
      94           3 :         enum ndr_err_code ndr_ret;
      95           3 :         DATA_BLOB sc_state_blob;
      96             : 
      97             :         /* becomes sc_set/@sc_set.id/sc/@sc_id */
      98          93 :         sc_key_str = talloc_asprintf(mem_ctx, "%s/%s%s", sc_set_key_str,
      99             :                                      FSS_DB_KEY_PFX_SC, sc->id_str);
     100          93 :         if (sc_key_str == NULL) {
     101           0 :                 return NT_STATUS_NO_MEMORY;
     102             :         }
     103             : 
     104          93 :         sc_state.id_str = sc->id_str;
     105          93 :         sc_state.volume_name = sc->volume_name;
     106             :         /* @sc->sc_path may be null if not committed, store empty str */
     107          93 :         sc_state.sc_path = (sc->sc_path ? sc->sc_path : "");
     108          93 :         sc_state.create_ts = sc->create_ts;
     109          93 :         sc_state.smaps_count = sc->smaps_count;
     110             : 
     111          93 :         ndr_ret = ndr_push_struct_blob(&sc_state_blob, mem_ctx,
     112             :                                        &sc_state,
     113             :                                 (ndr_push_flags_fn_t)ndr_push_fsrvp_state_sc);
     114          93 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     115           0 :                 return NT_STATUS_INTERNAL_ERROR;
     116             :         }
     117             : 
     118          93 :         val.dsize = sc_state_blob.length;
     119          93 :         val.dptr = sc_state_blob.data;
     120             : 
     121          93 :         status = dbwrap_store(db, string_term_tdb_data(sc_key_str), val, 0);
     122          93 :         if (!NT_STATUS_IS_OK(status)) {
     123           0 :                 return status;
     124             :         }
     125             : 
     126         187 :         for (smap = sc->smaps; smap; smap = smap->next) {
     127          94 :                 status = fss_state_smap_store(mem_ctx, db, sc_key_str, smap);
     128          94 :                 if (!NT_STATUS_IS_OK(status)) {
     129           0 :                         return status;
     130             :                 }
     131             :         }
     132             : 
     133          93 :         return NT_STATUS_OK;
     134             : }
     135             : 
     136          93 : static NTSTATUS fss_state_sc_set_store(TALLOC_CTX *mem_ctx,
     137             :                                        struct db_context *db,
     138             :                                        struct fss_sc_set *sc_set)
     139             : {
     140           3 :         NTSTATUS status;
     141           3 :         TDB_DATA val;
     142           3 :         const char *sc_set_key_str;
     143           3 :         struct fss_sc *sc;
     144           3 :         struct fsrvp_state_sc_set sc_set_state;
     145           3 :         DATA_BLOB sc_set_state_blob;
     146           3 :         enum ndr_err_code ndr_ret;
     147             : 
     148          93 :         sc_set_key_str = talloc_asprintf(mem_ctx, "%s%s",
     149             :                                          FSS_DB_KEY_PFX_SC_SET,
     150             :                                          sc_set->id_str);
     151          93 :         if (sc_set_key_str == NULL) {
     152           0 :                 return NT_STATUS_NO_MEMORY;
     153             :         }
     154             : 
     155          93 :         sc_set_state.id_str = sc_set->id_str;
     156          93 :         sc_set_state.state = sc_set->state;
     157          93 :         sc_set_state.context = sc_set->context;
     158          93 :         sc_set_state.scs_count = sc_set->scs_count;
     159             : 
     160          93 :         ndr_ret = ndr_push_struct_blob(&sc_set_state_blob, mem_ctx,
     161             :                                        &sc_set_state,
     162             :                         (ndr_push_flags_fn_t)ndr_push_fsrvp_state_sc_set);
     163          93 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     164           0 :                 return NT_STATUS_INTERNAL_ERROR;
     165             :         }
     166             : 
     167          93 :         val.dsize = sc_set_state_blob.length;
     168          93 :         val.dptr = sc_set_state_blob.data;
     169             : 
     170          93 :         status = dbwrap_store(db, string_term_tdb_data(sc_set_key_str), val, 0);
     171          93 :         if (!NT_STATUS_IS_OK(status)) {
     172           0 :                 return status;
     173             :         }
     174             : 
     175         186 :         for (sc = sc_set->scs; sc; sc = sc->next) {
     176          93 :                 status = fss_state_sc_store(mem_ctx, db, sc_set_key_str, sc);
     177          93 :                 if (!NT_STATUS_IS_OK(status)) {
     178           0 :                         return status;
     179             :                 }
     180             :         }
     181             : 
     182          93 :         return NT_STATUS_OK;
     183             : }
     184             : 
     185             : /*
     186             :  * write out the current fsrvp server state to a TDB. This clears any content
     187             :  * currently written to the TDB.
     188             :  */
     189          45 : _PRIVATE_ NTSTATUS fss_state_store(TALLOC_CTX *mem_ctx,
     190             :                          struct fss_sc_set *sc_sets,
     191             :                          uint32_t sc_sets_count,
     192             :                          const char *db_path)
     193             : {
     194           3 :         TALLOC_CTX *tmp_ctx;
     195           3 :         struct db_context *db;
     196           3 :         NTSTATUS status;
     197           3 :         int ret;
     198           3 :         struct fss_sc_set *sc_set;
     199             : 
     200          45 :         tmp_ctx = talloc_new(mem_ctx);
     201          45 :         if (tmp_ctx == NULL) {
     202           0 :                 return NT_STATUS_NO_MEMORY;
     203             :         }
     204             : 
     205          45 :         db = db_open(tmp_ctx, db_path, 0, TDB_DEFAULT,  O_RDWR | O_CREAT,
     206             :                      0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
     207          45 :         if (db == NULL) {
     208           0 :                 DEBUG(0, ("Failed to open fss state database %s\n", db_path));
     209           0 :                 status = NT_STATUS_ACCESS_DENIED;
     210           0 :                 goto err_ctx_free;
     211             :         }
     212             : 
     213          45 :         ret = dbwrap_wipe(db);
     214          45 :         if (ret != 0) {
     215           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     216           0 :                 goto err_db_free;
     217             :         }
     218             : 
     219          45 :         status = dbwrap_store_int32_bystring(db, FSS_DB_KEY_VERSION,
     220             :                                              FSRVP_STATE_DB_VERSION);
     221          45 :         if (!NT_STATUS_IS_OK(status)) {
     222           0 :                 goto err_db_free;
     223             :         }
     224             : 
     225          45 :         ret = dbwrap_transaction_start(db);
     226          45 :         if (ret != 0) {
     227           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     228           0 :                 goto err_db_free;
     229             :         }
     230             : 
     231          45 :         status = dbwrap_store_int32_bystring(db, FSS_DB_KEY_SC_SET_COUNT,
     232             :                                              sc_sets_count);
     233          45 :         if (!NT_STATUS_IS_OK(status)) {
     234           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     235           0 :                 goto err_trans_cancel;
     236             :         }
     237             : 
     238         138 :         for (sc_set = sc_sets; sc_set; sc_set = sc_set->next) {
     239          93 :                 status = fss_state_sc_set_store(tmp_ctx, db, sc_set);
     240          93 :                 if (!NT_STATUS_IS_OK(status)) {
     241           0 :                         goto err_trans_cancel;
     242             :                 }
     243             :         }
     244             : 
     245          45 :         ret = dbwrap_transaction_commit(db);
     246          45 :         if (ret != 0) {
     247           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     248           0 :                 goto err_trans_cancel;
     249             :         }
     250             : 
     251          45 :         talloc_free(db);
     252          45 :         talloc_free(tmp_ctx);
     253          45 :         return NT_STATUS_OK;
     254             : 
     255           0 : err_trans_cancel:
     256           0 :         dbwrap_transaction_cancel(db);
     257           0 : err_db_free:
     258           0 :         talloc_free(db);
     259           0 : err_ctx_free:
     260           0 :         talloc_free(tmp_ctx);
     261           0 :         return status;
     262             : }
     263             : 
     264           4 : static NTSTATUS fss_state_smap_retrieve(TALLOC_CTX *mem_ctx,
     265             :                                         TDB_DATA *key,
     266             :                                         TDB_DATA *val,
     267             :                                         struct fss_sc_smap **smap_out)
     268             : {
     269           4 :         struct fss_sc_smap *smap;
     270           4 :         struct fsrvp_state_smap smap_state;
     271           4 :         DATA_BLOB smap_state_blob;
     272           4 :         enum ndr_err_code ndr_ret;
     273             : 
     274           4 :         smap_state_blob.length = val->dsize;
     275           4 :         smap_state_blob.data = val->dptr;
     276             : 
     277           4 :         ndr_ret = ndr_pull_struct_blob(&smap_state_blob, mem_ctx, &smap_state,
     278             :                                 (ndr_pull_flags_fn_t)ndr_pull_fsrvp_state_smap);
     279           4 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     280           0 :                 return NT_STATUS_INTERNAL_ERROR;
     281             :         }
     282             : 
     283           4 :         smap = talloc_zero(mem_ctx, struct fss_sc_smap);
     284           4 :         if (smap == NULL) {
     285           0 :                 return NT_STATUS_NO_MEMORY;
     286             :         }
     287             : 
     288           4 :         smap->share_name = talloc_strdup(smap, smap_state.share_name);
     289           4 :         if (smap->share_name == NULL) {
     290           0 :                 return NT_STATUS_NO_MEMORY;
     291             :         }
     292             : 
     293             :         /* store the full path so that the hierarchy can be rebuilt */
     294           4 :         smap->sc_share_name = talloc_strdup(smap, (char *)key->dptr);
     295           4 :         if (smap->sc_share_name == NULL) {
     296           0 :                 return NT_STATUS_NO_MEMORY;
     297             :         }
     298             : 
     299             :         /* sc_share_comment may be empty, keep null in such a case */
     300           4 :         if (strlen(smap_state.sc_share_comment) > 0) {
     301           4 :                 smap->sc_share_comment = talloc_strdup(smap,
     302             :                                                 smap_state.sc_share_comment);
     303           4 :                 if (smap->sc_share_comment == NULL) {
     304           0 :                         return NT_STATUS_NO_MEMORY;
     305             :                 }
     306             :         }
     307             : 
     308           4 :         smap->is_exposed = smap_state.is_exposed;
     309             : 
     310           4 :         *smap_out = smap;
     311           4 :         return NT_STATUS_OK;
     312             : }
     313             : 
     314           3 : static NTSTATUS fss_state_sc_retrieve(TALLOC_CTX *mem_ctx,
     315             :                                       TDB_DATA *key,
     316             :                                       TDB_DATA *val,
     317             :                                       struct fss_sc **sc_out)
     318             : {
     319           3 :         struct fss_sc *sc;
     320           3 :         struct fsrvp_state_sc sc_state;
     321           3 :         DATA_BLOB sc_state_blob;
     322           3 :         enum ndr_err_code ndr_ret;
     323             : 
     324           3 :         sc_state_blob.length = val->dsize;
     325           3 :         sc_state_blob.data = val->dptr;
     326             : 
     327           3 :         ndr_ret = ndr_pull_struct_blob(&sc_state_blob, mem_ctx, &sc_state,
     328             :                                 (ndr_pull_flags_fn_t)ndr_pull_fsrvp_state_sc);
     329           3 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     330           0 :                 return NT_STATUS_INTERNAL_ERROR;
     331             :         }
     332             : 
     333           3 :         sc = talloc_zero(mem_ctx, struct fss_sc);
     334           3 :         if (sc == NULL) {
     335           0 :                 return NT_STATUS_NO_MEMORY;
     336             :         }
     337             : 
     338             :         /* store the full path so that the hierarchy can be rebuilt */
     339           3 :         sc->id_str = talloc_strdup(sc, (char *)key->dptr);
     340           3 :         if (sc->id_str == NULL) {
     341           0 :                 return NT_STATUS_NO_MEMORY;
     342             :         }
     343             : 
     344           3 :         sc->volume_name = talloc_strdup(sc, sc_state.volume_name);
     345           3 :         if (sc->volume_name == NULL) {
     346           0 :                 return NT_STATUS_NO_MEMORY;
     347             :         }
     348             : 
     349             :         /* sc_path may be empty, keep null in such a case */
     350           3 :         if (strlen(sc_state.sc_path) > 0) {
     351           0 :                 sc->sc_path = talloc_strdup(sc, sc_state.sc_path);
     352           0 :                 if (sc->sc_path == NULL) {
     353           0 :                         return NT_STATUS_NO_MEMORY;
     354             :                 }
     355             :         }
     356           3 :         sc->create_ts = sc_state.create_ts;
     357           3 :         sc->smaps_count = sc_state.smaps_count;
     358             : 
     359           3 :         *sc_out = sc;
     360           3 :         return NT_STATUS_OK;
     361             : }
     362             : 
     363           3 : static NTSTATUS fss_state_sc_set_retrieve(TALLOC_CTX *mem_ctx,
     364             :                                           TDB_DATA *key,
     365             :                                           TDB_DATA *val,
     366             :                                           struct fss_sc_set **sc_set_out)
     367             : {
     368           3 :         struct fss_sc_set *sc_set;
     369           3 :         struct fsrvp_state_sc_set sc_set_state;
     370           3 :         DATA_BLOB sc_set_state_blob;
     371           3 :         enum ndr_err_code ndr_ret;
     372             : 
     373           3 :         sc_set_state_blob.length = val->dsize;
     374           3 :         sc_set_state_blob.data = val->dptr;
     375             : 
     376           3 :         ndr_ret = ndr_pull_struct_blob(&sc_set_state_blob, mem_ctx,
     377             :                                        &sc_set_state,
     378             :                         (ndr_pull_flags_fn_t)ndr_pull_fsrvp_state_sc_set);
     379           3 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     380           0 :                 return NT_STATUS_INTERNAL_ERROR;
     381             :         }
     382             : 
     383           3 :         sc_set = talloc_zero(mem_ctx, struct fss_sc_set);
     384           3 :         if (sc_set == NULL) {
     385           0 :                 return NT_STATUS_NO_MEMORY;
     386             :         }
     387             : 
     388             :         /* store the full path so that the hierarchy can be rebuilt */
     389           3 :         sc_set->id_str = talloc_strdup(sc_set, (char *)key->dptr);
     390           3 :         if (sc_set->id_str == NULL) {
     391           0 :                 return NT_STATUS_NO_MEMORY;
     392             :         }
     393           3 :         sc_set->state = sc_set_state.state;
     394           3 :         sc_set->context = sc_set_state.context;
     395           3 :         sc_set->scs_count = sc_set_state.scs_count;
     396             : 
     397           3 :         *sc_set_out = sc_set;
     398           3 :         return NT_STATUS_OK;
     399             : }
     400             : 
     401             : struct fss_traverse_state {
     402             :         TALLOC_CTX *mem_ctx;
     403             :         struct fss_sc_smap *smaps;
     404             :         uint32_t smaps_count;
     405             :         struct fss_sc *scs;
     406             :         uint32_t scs_count;
     407             :         struct fss_sc_set *sc_sets;
     408             :         uint32_t sc_sets_count;
     409             :         NTSTATUS (*smap_retrieve)(TALLOC_CTX *mem_ctx,
     410             :                                   TDB_DATA *key,
     411             :                                   TDB_DATA *val,
     412             :                                   struct fss_sc_smap **smap_out);
     413             :         NTSTATUS (*sc_retrieve)(TALLOC_CTX *mem_ctx,
     414             :                                 TDB_DATA *key,
     415             :                                 TDB_DATA *val,
     416             :                                 struct fss_sc **sc_out);
     417             :         NTSTATUS (*sc_set_retrieve)(TALLOC_CTX *mem_ctx,
     418             :                                     TDB_DATA *key,
     419             :                                     TDB_DATA *val,
     420             :                                     struct fss_sc_set **sc_set_out);
     421             : };
     422             : 
     423          16 : static int fss_state_retrieve_traverse(struct db_record *rec,
     424             :                                        void *private_data)
     425             : {
     426          16 :         NTSTATUS status;
     427          16 :         struct fss_traverse_state *trv_state
     428             :                         = (struct fss_traverse_state *)private_data;
     429          16 :         TDB_DATA key = dbwrap_record_get_key(rec);
     430          16 :         TDB_DATA val = dbwrap_record_get_value(rec);
     431             : 
     432             :         /* order of checking is important here */
     433          16 :         if (strstr((char *)key.dptr, FSS_DB_KEY_PFX_SMAP) != NULL) {
     434           4 :                 struct fss_sc_smap *smap;
     435           4 :                 status = trv_state->smap_retrieve(trv_state->mem_ctx,
     436             :                                                   &key, &val, &smap);
     437           4 :                 if (!NT_STATUS_IS_OK(status)) {
     438           0 :                         return -1;
     439             :                 }
     440           4 :                 DLIST_ADD_END(trv_state->smaps, smap);
     441           4 :                 trv_state->smaps_count++;
     442          12 :         } else if (strstr((char *)key.dptr, FSS_DB_KEY_PFX_SC) != NULL) {
     443           3 :                 struct fss_sc *sc;
     444           3 :                 status = trv_state->sc_retrieve(trv_state->mem_ctx,
     445             :                                                 &key, &val, &sc);
     446           3 :                 if (!NT_STATUS_IS_OK(status)) {
     447           0 :                         return -1;
     448             :                 }
     449           3 :                 DLIST_ADD_END(trv_state->scs, sc);
     450           3 :                 trv_state->scs_count++;
     451           9 :         } else if (strstr((char *)key.dptr, FSS_DB_KEY_PFX_SC_SET) != NULL) {
     452           3 :                 struct fss_sc_set *sc_set;
     453           3 :                 status = trv_state->sc_set_retrieve(trv_state->mem_ctx,
     454             :                                                     &key, &val, &sc_set);
     455           3 :                 if (!NT_STATUS_IS_OK(status)) {
     456           0 :                         return -1;
     457             :                 }
     458           3 :                 DLIST_ADD_END(trv_state->sc_sets, sc_set);
     459           3 :                 trv_state->sc_sets_count++;
     460             :         } else {
     461             :                 /* global context and db vers */
     462           6 :                 DEBUG(4, ("Ignoring fss srv db entry with key %s\n", key.dptr));
     463             :         }
     464             : 
     465           0 :         return 0;
     466             : }
     467             : 
     468           5 : static bool fss_state_smap_is_child(struct fss_sc *sc,
     469             :                                     struct fss_sc_smap *smap)
     470             : {
     471           5 :         return (strstr(smap->sc_share_name, sc->id_str) != NULL);
     472             : }
     473             : 
     474           3 : static NTSTATUS fss_state_hierarchize_smaps(struct fss_traverse_state *trv_state,
     475             :                                             struct fss_sc *sc)
     476             : {
     477           3 :         struct fss_sc_smap *smap;
     478           3 :         struct fss_sc_smap *smap_n;
     479           3 :         uint32_t smaps_moved = 0;
     480             : 
     481           8 :         for (smap = trv_state->smaps; smap; smap = smap_n) {
     482           5 :                 smap_n = smap->next;
     483           5 :                 if (!fss_state_smap_is_child(sc, smap))
     484           1 :                         continue;
     485             : 
     486             :                 /* smap mem should be owned by parent sc */
     487           4 :                 talloc_steal(sc, smap);
     488           4 :                 DLIST_REMOVE(trv_state->smaps, smap);
     489           4 :                 trv_state->smaps_count--;
     490           4 :                 DLIST_ADD_END(sc->smaps, smap);
     491           4 :                 smaps_moved++;
     492             : 
     493             :                 /* last component of the tdb key path is the sc share name */
     494           4 :                 SMB_ASSERT(strrchr(smap->sc_share_name, '/') != NULL);
     495           4 :                 smap->sc_share_name = strrchr(smap->sc_share_name, '/') + 1;
     496             :         }
     497             : 
     498           3 :         if (sc->smaps_count != smaps_moved) {
     499           0 :                 DEBUG(0, ("Inconsistent smaps_count, expected %u, moved %u\n",
     500             :                           sc->smaps_count, smaps_moved));
     501           0 :                 return NT_STATUS_UNSUCCESSFUL;
     502             :         }
     503             : 
     504           3 :         return NT_STATUS_OK;
     505             : }
     506             : 
     507           5 : static bool fss_state_sc_is_child(struct fss_sc_set *sc_set,
     508             :                                   struct fss_sc *sc)
     509             : {
     510           5 :         return (strstr(sc->id_str, sc_set->id_str) != NULL);
     511             : }
     512             : 
     513           3 : static NTSTATUS fss_state_hierarchize_scs(struct fss_traverse_state *trv_state,
     514             :                                           struct fss_sc_set *sc_set)
     515             : {
     516           3 :         NTSTATUS status;
     517           3 :         struct fss_sc *sc;
     518           3 :         struct fss_sc *sc_n;
     519           3 :         uint32_t scs_moved = 0;
     520             : 
     521           8 :         for (sc = trv_state->scs; sc; sc = sc_n) {
     522           5 :                 sc_n = sc->next;
     523           5 :                 if (!fss_state_sc_is_child(sc_set, sc))
     524           2 :                         continue;
     525             : 
     526             :                 /* sc mem should be owned by parent sc_set */
     527           3 :                 talloc_steal(sc_set, sc);
     528           3 :                 DLIST_REMOVE(trv_state->scs, sc);
     529           3 :                 trv_state->scs_count--;
     530           3 :                 DLIST_ADD_END(sc_set->scs, sc);
     531           3 :                 scs_moved++;
     532             : 
     533           3 :                 sc->sc_set = sc_set;
     534             : 
     535             :                 /* last component of the tdb key path is the sc GUID str */
     536           3 :                 SMB_ASSERT(strrchr(sc->id_str, '/') != NULL);
     537           3 :                 sc->id_str = strrchr(sc->id_str, '/') + 1;
     538             : 
     539           3 :                 status = GUID_from_string(sc->id_str, &sc->id);
     540           3 :                 if (!NT_STATUS_IS_OK(status)) {
     541           0 :                         goto err_out;
     542             :                 }
     543             : 
     544           3 :                 status = fss_state_hierarchize_smaps(trv_state, sc);
     545           3 :                 if (!NT_STATUS_IS_OK(status)) {
     546           0 :                         goto err_out;
     547             :                 }
     548             :         }
     549             : 
     550           3 :         if (sc_set->scs_count != scs_moved) {
     551           0 :                 DEBUG(0, ("Inconsistent scs_count, expected %u, moved %u\n",
     552             :                           sc_set->scs_count, scs_moved));
     553           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     554           0 :                 goto err_out;
     555             :         }
     556             : 
     557           3 :         return NT_STATUS_OK;
     558             : 
     559           0 : err_out:
     560           0 :         return status;
     561             : }
     562             : 
     563           3 : static NTSTATUS fss_state_hierarchize(struct fss_traverse_state *trv_state,
     564             :                                       struct fss_sc_set **sc_sets,
     565             :                                       uint32_t *sc_sets_count)
     566             : {
     567           3 :         NTSTATUS status;
     568           3 :         struct fss_sc_set *sc_set;
     569           3 :         struct fss_sc_set *sc_set_n;
     570           3 :         uint32_t i = 0;
     571             : 
     572           3 :         *sc_sets = NULL;
     573           6 :         for (sc_set = trv_state->sc_sets; sc_set; sc_set = sc_set_n) {
     574           3 :                 sc_set_n = sc_set->next;
     575             :                 /* sc_set mem already owned by trv_state->mem_ctx */
     576           3 :                 DLIST_REMOVE(trv_state->sc_sets, sc_set);
     577           3 :                 trv_state->sc_sets_count--;
     578           3 :                 DLIST_ADD_END(*sc_sets, sc_set);
     579           3 :                 i++;
     580             : 
     581             :                 /* last component of the tdb key path is the sc_set GUID str */
     582           3 :                 SMB_ASSERT(strrchr(sc_set->id_str, '/') != NULL);
     583           3 :                 sc_set->id_str = strrchr(sc_set->id_str, '/') + 1;
     584             : 
     585           3 :                 status = GUID_from_string(sc_set->id_str, &sc_set->id);
     586           3 :                 if (!NT_STATUS_IS_OK(status)) {
     587           0 :                         goto err_out;
     588             :                 }
     589             : 
     590           3 :                 status = fss_state_hierarchize_scs(trv_state, sc_set);
     591           3 :                 if (!NT_STATUS_IS_OK(status)) {
     592           0 :                         goto err_out;
     593             :                 }
     594             :         }
     595           3 :         *sc_sets_count = i;
     596           3 :         return NT_STATUS_OK;
     597             : 
     598           0 : err_out:
     599           0 :         return status;
     600             : }
     601             : 
     602           8 : _PRIVATE_ NTSTATUS fss_state_retrieve(TALLOC_CTX *mem_ctx,
     603             :                             struct fss_sc_set **sc_sets,
     604             :                             uint32_t *sc_sets_count,
     605             :                             const char *db_path)
     606             : {
     607           4 :         struct db_context *db;
     608           4 :         NTSTATUS status;
     609           4 :         struct fss_traverse_state trv_state;
     610           4 :         int err;
     611           4 :         int rec_count;
     612           4 :         int vers;
     613           8 :         *sc_sets = NULL;
     614           8 :         *sc_sets_count = 0;
     615             : 
     616           8 :         memset(&trv_state, 0, sizeof(trv_state));
     617           8 :         trv_state.mem_ctx = talloc_new(mem_ctx);
     618           8 :         if (trv_state.mem_ctx == NULL) {
     619           0 :                 status = NT_STATUS_NO_MEMORY;
     620           0 :                 goto err_out;
     621             :         }
     622             : 
     623             :         /* set callbacks for unmarshalling on-disk structures */
     624           8 :         trv_state.smap_retrieve = fss_state_smap_retrieve;
     625           8 :         trv_state.sc_retrieve = fss_state_sc_retrieve;
     626           8 :         trv_state.sc_set_retrieve = fss_state_sc_set_retrieve;
     627             : 
     628           8 :         db = db_open(trv_state.mem_ctx, db_path, 0, TDB_DEFAULT,
     629             :                      O_RDONLY, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
     630           8 :         err = errno;
     631           8 :         if ((db == NULL) && (err == ENOENT)) {
     632           5 :                 DEBUG(4, ("fss state TDB does not exist for retrieval\n"));
     633           5 :                 status = NT_STATUS_OK;
     634           5 :                 goto err_ts_free;
     635           3 :         } else if (db == NULL) {
     636           0 :                 DEBUG(0, ("Failed to open fss state TDB: %s\n",
     637             :                           strerror(err)));
     638           0 :                 status = NT_STATUS_ACCESS_DENIED;
     639           0 :                 goto err_ts_free;
     640             :         }
     641             : 
     642           3 :         status = dbwrap_fetch_int32_bystring(db, FSS_DB_KEY_VERSION,
     643             :                                              &vers);
     644           3 :         if (!NT_STATUS_IS_OK(status)) {
     645           0 :                 DEBUG(0, ("failed to fetch version from fss state tdb: %s\n",
     646             :                           nt_errstr(status)));
     647           0 :                 goto err_db_free;
     648           3 :         } else if (vers != FSRVP_STATE_DB_VERSION) {
     649           0 :                 DEBUG(0, ("Unsupported fss tdb version %d, expected %d\n",
     650             :                           vers, FSRVP_STATE_DB_VERSION));
     651           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     652           0 :                 goto err_db_free;
     653             :         }
     654             : 
     655           3 :         status = dbwrap_traverse_read(db,
     656             :                                       fss_state_retrieve_traverse,
     657             :                                       &trv_state,
     658             :                                       &rec_count);
     659           3 :         if (!NT_STATUS_IS_OK(status)) {
     660           0 :                 goto err_db_free;
     661             :         }
     662             : 
     663           3 :         status = fss_state_hierarchize(&trv_state, sc_sets, sc_sets_count);
     664           3 :         if (!NT_STATUS_IS_OK(status)) {
     665           0 :                 DEBUG(0, ("Failed to form fss state hierarchy\n"));
     666           0 :                 goto err_db_free;
     667             :         }
     668             : 
     669             :         /* check whether anything was left without a parent */
     670           3 :         if (trv_state.sc_sets_count != 0) {
     671           0 :                 DEBUG(0, ("%d shadow copy set orphans in %s tdb\n",
     672             :                           trv_state.sc_sets_count, db_path));
     673           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     674           0 :                 goto err_db_free;
     675             :         }
     676           3 :         if (trv_state.scs_count != 0) {
     677           0 :                 DEBUG(0, ("%d shadow copy orphans in %s tdb\n",
     678             :                           trv_state.scs_count, db_path));
     679           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     680           0 :                 goto err_db_free;
     681             :         }
     682           3 :         if (trv_state.smaps_count != 0) {
     683           0 :                 DEBUG(0, ("%d share map orphans in %s tdb\n",
     684             :                           trv_state.smaps_count, db_path));
     685           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     686           0 :                 goto err_db_free;
     687             :         }
     688           3 :         talloc_free(db);
     689             : 
     690           3 :         return NT_STATUS_OK;
     691             : 
     692           0 : err_db_free:
     693           0 :         talloc_free(db);
     694           5 : err_ts_free:
     695           5 :         talloc_free(trv_state.mem_ctx);
     696           5 : err_out:
     697           5 :         return status;
     698             : }

Generated by: LCOV version 1.14