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 v4-17-test 1498b464 Lines: 0 315 0.0 %
Date: 2024-06-13 04:01:37 Functions: 0 14 0.0 %

          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           0 : 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             :         NTSTATUS status;
      42             :         TDB_DATA val;
      43             :         const char *smap_key_str;
      44             :         struct fsrvp_state_smap smap_state;
      45             :         enum ndr_err_code ndr_ret;
      46             :         DATA_BLOB smap_state_blob;
      47             : 
      48             :         /* becomes sc_set/@sc_set_id/sc/@sc_id/smap/@sc_share_name */
      49           0 :         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           0 :         if (smap_key_str == NULL) {
      53           0 :                 return NT_STATUS_NO_MEMORY;
      54             :         }
      55             : 
      56           0 :         smap_state.share_name = smap->share_name;
      57           0 :         smap_state.sc_share_name = smap->sc_share_name;
      58             :         /* @smap->sc_share_comment may be null if not exposed. */
      59           0 :         if (smap->sc_share_comment != NULL) {
      60           0 :                 smap_state.sc_share_comment = smap->sc_share_comment;
      61             :         } else {
      62           0 :                 smap_state.sc_share_comment = "";
      63             :         }
      64           0 :         smap_state.is_exposed = smap->is_exposed;
      65             : 
      66           0 :         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           0 :         if (ndr_ret != NDR_ERR_SUCCESS) {
      70           0 :                 return NT_STATUS_INTERNAL_ERROR;
      71             :         }
      72             : 
      73           0 :         val.dsize = smap_state_blob.length;
      74           0 :         val.dptr = smap_state_blob.data;
      75             : 
      76           0 :         status = dbwrap_store(db, string_term_tdb_data(smap_key_str), val, 0);
      77           0 :         if (!NT_STATUS_IS_OK(status)) {
      78           0 :                 return status;
      79             :         }
      80             : 
      81           0 :         return NT_STATUS_OK;
      82             : }
      83             : 
      84           0 : 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             :         NTSTATUS status;
      90             :         TDB_DATA val;
      91             :         const char *sc_key_str;
      92             :         struct fsrvp_state_sc sc_state;
      93             :         struct fss_sc_smap *smap;
      94             :         enum ndr_err_code ndr_ret;
      95             :         DATA_BLOB sc_state_blob;
      96             : 
      97             :         /* becomes sc_set/@sc_set.id/sc/@sc_id */
      98           0 :         sc_key_str = talloc_asprintf(mem_ctx, "%s/%s%s", sc_set_key_str,
      99             :                                      FSS_DB_KEY_PFX_SC, sc->id_str);
     100           0 :         if (sc_key_str == NULL) {
     101           0 :                 return NT_STATUS_NO_MEMORY;
     102             :         }
     103             : 
     104           0 :         sc_state.id_str = sc->id_str;
     105           0 :         sc_state.volume_name = sc->volume_name;
     106             :         /* @sc->sc_path may be null if not committed, store empty str */
     107           0 :         sc_state.sc_path = (sc->sc_path ? sc->sc_path : "");
     108           0 :         sc_state.create_ts = sc->create_ts;
     109           0 :         sc_state.smaps_count = sc->smaps_count;
     110             : 
     111           0 :         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           0 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     115           0 :                 return NT_STATUS_INTERNAL_ERROR;
     116             :         }
     117             : 
     118           0 :         val.dsize = sc_state_blob.length;
     119           0 :         val.dptr = sc_state_blob.data;
     120             : 
     121           0 :         status = dbwrap_store(db, string_term_tdb_data(sc_key_str), val, 0);
     122           0 :         if (!NT_STATUS_IS_OK(status)) {
     123           0 :                 return status;
     124             :         }
     125             : 
     126           0 :         for (smap = sc->smaps; smap; smap = smap->next) {
     127           0 :                 status = fss_state_smap_store(mem_ctx, db, sc_key_str, smap);
     128           0 :                 if (!NT_STATUS_IS_OK(status)) {
     129           0 :                         return status;
     130             :                 }
     131             :         }
     132             : 
     133           0 :         return NT_STATUS_OK;
     134             : }
     135             : 
     136           0 : 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             :         NTSTATUS status;
     141             :         TDB_DATA val;
     142             :         const char *sc_set_key_str;
     143             :         struct fss_sc *sc;
     144             :         struct fsrvp_state_sc_set sc_set_state;
     145             :         DATA_BLOB sc_set_state_blob;
     146             :         enum ndr_err_code ndr_ret;
     147             : 
     148           0 :         sc_set_key_str = talloc_asprintf(mem_ctx, "%s%s",
     149             :                                          FSS_DB_KEY_PFX_SC_SET,
     150             :                                          sc_set->id_str);
     151           0 :         if (sc_set_key_str == NULL) {
     152           0 :                 return NT_STATUS_NO_MEMORY;
     153             :         }
     154             : 
     155           0 :         sc_set_state.id_str = sc_set->id_str;
     156           0 :         sc_set_state.state = sc_set->state;
     157           0 :         sc_set_state.context = sc_set->context;
     158           0 :         sc_set_state.scs_count = sc_set->scs_count;
     159             : 
     160           0 :         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           0 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     164           0 :                 return NT_STATUS_INTERNAL_ERROR;
     165             :         }
     166             : 
     167           0 :         val.dsize = sc_set_state_blob.length;
     168           0 :         val.dptr = sc_set_state_blob.data;
     169             : 
     170           0 :         status = dbwrap_store(db, string_term_tdb_data(sc_set_key_str), val, 0);
     171           0 :         if (!NT_STATUS_IS_OK(status)) {
     172           0 :                 return status;
     173             :         }
     174             : 
     175           0 :         for (sc = sc_set->scs; sc; sc = sc->next) {
     176           0 :                 status = fss_state_sc_store(mem_ctx, db, sc_set_key_str, sc);
     177           0 :                 if (!NT_STATUS_IS_OK(status)) {
     178           0 :                         return status;
     179             :                 }
     180             :         }
     181             : 
     182           0 :         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           0 : _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             :         TALLOC_CTX *tmp_ctx;
     195             :         struct db_context *db;
     196             :         NTSTATUS status;
     197             :         int ret;
     198             :         struct fss_sc_set *sc_set;
     199             : 
     200           0 :         tmp_ctx = talloc_new(mem_ctx);
     201           0 :         if (tmp_ctx == NULL) {
     202           0 :                 return NT_STATUS_NO_MEMORY;
     203             :         }
     204             : 
     205           0 :         db = db_open(tmp_ctx, db_path, 0, TDB_DEFAULT,  O_RDWR | O_CREAT,
     206             :                      0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
     207           0 :         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           0 :         ret = dbwrap_wipe(db);
     214           0 :         if (ret != 0) {
     215           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     216           0 :                 goto err_db_free;
     217             :         }
     218             : 
     219           0 :         status = dbwrap_store_int32_bystring(db, FSS_DB_KEY_VERSION,
     220             :                                              FSRVP_STATE_DB_VERSION);
     221           0 :         if (!NT_STATUS_IS_OK(status)) {
     222           0 :                 goto err_db_free;
     223             :         }
     224             : 
     225           0 :         ret = dbwrap_transaction_start(db);
     226           0 :         if (ret != 0) {
     227           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     228           0 :                 goto err_db_free;
     229             :         }
     230             : 
     231           0 :         status = dbwrap_store_int32_bystring(db, FSS_DB_KEY_SC_SET_COUNT,
     232             :                                              sc_sets_count);
     233           0 :         if (!NT_STATUS_IS_OK(status)) {
     234           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     235           0 :                 goto err_trans_cancel;
     236             :         }
     237             : 
     238           0 :         for (sc_set = sc_sets; sc_set; sc_set = sc_set->next) {
     239           0 :                 status = fss_state_sc_set_store(tmp_ctx, db, sc_set);
     240           0 :                 if (!NT_STATUS_IS_OK(status)) {
     241           0 :                         goto err_trans_cancel;
     242             :                 }
     243             :         }
     244             : 
     245           0 :         ret = dbwrap_transaction_commit(db);
     246           0 :         if (ret != 0) {
     247           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     248           0 :                 goto err_trans_cancel;
     249             :         }
     250             : 
     251           0 :         talloc_free(db);
     252           0 :         talloc_free(tmp_ctx);
     253           0 :         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           0 : 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             :         struct fss_sc_smap *smap;
     270             :         struct fsrvp_state_smap smap_state;
     271             :         DATA_BLOB smap_state_blob;
     272             :         enum ndr_err_code ndr_ret;
     273             : 
     274           0 :         smap_state_blob.length = val->dsize;
     275           0 :         smap_state_blob.data = val->dptr;
     276             : 
     277           0 :         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           0 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     280           0 :                 return NT_STATUS_INTERNAL_ERROR;
     281             :         }
     282             : 
     283           0 :         smap = talloc_zero(mem_ctx, struct fss_sc_smap);
     284           0 :         if (smap == NULL) {
     285           0 :                 return NT_STATUS_NO_MEMORY;
     286             :         }
     287             : 
     288           0 :         smap->share_name = talloc_strdup(smap, smap_state.share_name);
     289           0 :         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           0 :         smap->sc_share_name = talloc_strdup(smap, (char *)key->dptr);
     295           0 :         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           0 :         if (strlen(smap_state.sc_share_comment) > 0) {
     301           0 :                 smap->sc_share_comment = talloc_strdup(smap,
     302             :                                                 smap_state.sc_share_comment);
     303           0 :                 if (smap->sc_share_comment == NULL) {
     304           0 :                         return NT_STATUS_NO_MEMORY;
     305             :                 }
     306             :         }
     307             : 
     308           0 :         smap->is_exposed = smap_state.is_exposed;
     309             : 
     310           0 :         *smap_out = smap;
     311           0 :         return NT_STATUS_OK;
     312             : }
     313             : 
     314           0 : 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             :         struct fss_sc *sc;
     320             :         struct fsrvp_state_sc sc_state;
     321             :         DATA_BLOB sc_state_blob;
     322             :         enum ndr_err_code ndr_ret;
     323             : 
     324           0 :         sc_state_blob.length = val->dsize;
     325           0 :         sc_state_blob.data = val->dptr;
     326             : 
     327           0 :         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           0 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     330           0 :                 return NT_STATUS_INTERNAL_ERROR;
     331             :         }
     332             : 
     333           0 :         sc = talloc_zero(mem_ctx, struct fss_sc);
     334           0 :         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           0 :         sc->id_str = talloc_strdup(sc, (char *)key->dptr);
     340           0 :         if (sc->id_str == NULL) {
     341           0 :                 return NT_STATUS_NO_MEMORY;
     342             :         }
     343             : 
     344           0 :         sc->volume_name = talloc_strdup(sc, sc_state.volume_name);
     345           0 :         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           0 :         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           0 :         sc->create_ts = sc_state.create_ts;
     357           0 :         sc->smaps_count = sc_state.smaps_count;
     358             : 
     359           0 :         *sc_out = sc;
     360           0 :         return NT_STATUS_OK;
     361             : }
     362             : 
     363           0 : 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             :         struct fss_sc_set *sc_set;
     369             :         struct fsrvp_state_sc_set sc_set_state;
     370             :         DATA_BLOB sc_set_state_blob;
     371             :         enum ndr_err_code ndr_ret;
     372             : 
     373           0 :         sc_set_state_blob.length = val->dsize;
     374           0 :         sc_set_state_blob.data = val->dptr;
     375             : 
     376           0 :         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           0 :         if (ndr_ret != NDR_ERR_SUCCESS) {
     380           0 :                 return NT_STATUS_INTERNAL_ERROR;
     381             :         }
     382             : 
     383           0 :         sc_set = talloc_zero(mem_ctx, struct fss_sc_set);
     384           0 :         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           0 :         sc_set->id_str = talloc_strdup(sc_set, (char *)key->dptr);
     390           0 :         if (sc_set->id_str == NULL) {
     391           0 :                 return NT_STATUS_NO_MEMORY;
     392             :         }
     393           0 :         sc_set->state = sc_set_state.state;
     394           0 :         sc_set->context = sc_set_state.context;
     395           0 :         sc_set->scs_count = sc_set_state.scs_count;
     396             : 
     397           0 :         *sc_set_out = sc_set;
     398           0 :         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           0 : static int fss_state_retrieve_traverse(struct db_record *rec,
     424             :                                        void *private_data)
     425             : {
     426             :         NTSTATUS status;
     427           0 :         struct fss_traverse_state *trv_state
     428             :                         = (struct fss_traverse_state *)private_data;
     429           0 :         TDB_DATA key = dbwrap_record_get_key(rec);
     430           0 :         TDB_DATA val = dbwrap_record_get_value(rec);
     431             : 
     432             :         /* order of checking is important here */
     433           0 :         if (strstr((char *)key.dptr, FSS_DB_KEY_PFX_SMAP) != NULL) {
     434             :                 struct fss_sc_smap *smap;
     435           0 :                 status = trv_state->smap_retrieve(trv_state->mem_ctx,
     436             :                                                   &key, &val, &smap);
     437           0 :                 if (!NT_STATUS_IS_OK(status)) {
     438           0 :                         return -1;
     439             :                 }
     440           0 :                 DLIST_ADD_END(trv_state->smaps, smap);
     441           0 :                 trv_state->smaps_count++;
     442           0 :         } else if (strstr((char *)key.dptr, FSS_DB_KEY_PFX_SC) != NULL) {
     443             :                 struct fss_sc *sc;
     444           0 :                 status = trv_state->sc_retrieve(trv_state->mem_ctx,
     445             :                                                 &key, &val, &sc);
     446           0 :                 if (!NT_STATUS_IS_OK(status)) {
     447           0 :                         return -1;
     448             :                 }
     449           0 :                 DLIST_ADD_END(trv_state->scs, sc);
     450           0 :                 trv_state->scs_count++;
     451           0 :         } else if (strstr((char *)key.dptr, FSS_DB_KEY_PFX_SC_SET) != NULL) {
     452             :                 struct fss_sc_set *sc_set;
     453           0 :                 status = trv_state->sc_set_retrieve(trv_state->mem_ctx,
     454             :                                                     &key, &val, &sc_set);
     455           0 :                 if (!NT_STATUS_IS_OK(status)) {
     456           0 :                         return -1;
     457             :                 }
     458           0 :                 DLIST_ADD_END(trv_state->sc_sets, sc_set);
     459           0 :                 trv_state->sc_sets_count++;
     460             :         } else {
     461             :                 /* global context and db vers */
     462           0 :                 DEBUG(4, ("Ignoring fss srv db entry with key %s\n", key.dptr));
     463             :         }
     464             : 
     465           0 :         return 0;
     466             : }
     467             : 
     468           0 : static bool fss_state_smap_is_child(struct fss_sc *sc,
     469             :                                     struct fss_sc_smap *smap)
     470             : {
     471           0 :         return (strstr(smap->sc_share_name, sc->id_str) != NULL);
     472             : }
     473             : 
     474           0 : static NTSTATUS fss_state_hierarchize_smaps(struct fss_traverse_state *trv_state,
     475             :                                             struct fss_sc *sc)
     476             : {
     477             :         struct fss_sc_smap *smap;
     478             :         struct fss_sc_smap *smap_n;
     479           0 :         uint32_t smaps_moved = 0;
     480             : 
     481           0 :         for (smap = trv_state->smaps; smap; smap = smap_n) {
     482           0 :                 smap_n = smap->next;
     483           0 :                 if (!fss_state_smap_is_child(sc, smap))
     484           0 :                         continue;
     485             : 
     486             :                 /* smap mem should be owned by parent sc */
     487           0 :                 talloc_steal(sc, smap);
     488           0 :                 DLIST_REMOVE(trv_state->smaps, smap);
     489           0 :                 trv_state->smaps_count--;
     490           0 :                 DLIST_ADD_END(sc->smaps, smap);
     491           0 :                 smaps_moved++;
     492             : 
     493             :                 /* last component of the tdb key path is the sc share name */
     494           0 :                 SMB_ASSERT(strrchr(smap->sc_share_name, '/') != NULL);
     495           0 :                 smap->sc_share_name = strrchr(smap->sc_share_name, '/') + 1;
     496             :         }
     497             : 
     498           0 :         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           0 :         return NT_STATUS_OK;
     505             : }
     506             : 
     507           0 : static bool fss_state_sc_is_child(struct fss_sc_set *sc_set,
     508             :                                   struct fss_sc *sc)
     509             : {
     510           0 :         return (strstr(sc->id_str, sc_set->id_str) != NULL);
     511             : }
     512             : 
     513           0 : static NTSTATUS fss_state_hierarchize_scs(struct fss_traverse_state *trv_state,
     514             :                                           struct fss_sc_set *sc_set)
     515             : {
     516             :         NTSTATUS status;
     517             :         struct fss_sc *sc;
     518             :         struct fss_sc *sc_n;
     519           0 :         uint32_t scs_moved = 0;
     520             : 
     521           0 :         for (sc = trv_state->scs; sc; sc = sc_n) {
     522           0 :                 sc_n = sc->next;
     523           0 :                 if (!fss_state_sc_is_child(sc_set, sc))
     524           0 :                         continue;
     525             : 
     526             :                 /* sc mem should be owned by parent sc_set */
     527           0 :                 talloc_steal(sc_set, sc);
     528           0 :                 DLIST_REMOVE(trv_state->scs, sc);
     529           0 :                 trv_state->scs_count--;
     530           0 :                 DLIST_ADD_END(sc_set->scs, sc);
     531           0 :                 scs_moved++;
     532             : 
     533           0 :                 sc->sc_set = sc_set;
     534             : 
     535             :                 /* last component of the tdb key path is the sc GUID str */
     536           0 :                 SMB_ASSERT(strrchr(sc->id_str, '/') != NULL);
     537           0 :                 sc->id_str = strrchr(sc->id_str, '/') + 1;
     538             : 
     539           0 :                 status = GUID_from_string(sc->id_str, &sc->id);
     540           0 :                 if (!NT_STATUS_IS_OK(status)) {
     541           0 :                         goto err_out;
     542             :                 }
     543             : 
     544           0 :                 status = fss_state_hierarchize_smaps(trv_state, sc);
     545           0 :                 if (!NT_STATUS_IS_OK(status)) {
     546           0 :                         goto err_out;
     547             :                 }
     548             :         }
     549             : 
     550           0 :         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           0 :         return NT_STATUS_OK;
     558             : 
     559           0 : err_out:
     560           0 :         return status;
     561             : }
     562             : 
     563           0 : 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             :         NTSTATUS status;
     568             :         struct fss_sc_set *sc_set;
     569             :         struct fss_sc_set *sc_set_n;
     570           0 :         uint32_t i = 0;
     571             : 
     572           0 :         *sc_sets = NULL;
     573           0 :         for (sc_set = trv_state->sc_sets; sc_set; sc_set = sc_set_n) {
     574           0 :                 sc_set_n = sc_set->next;
     575             :                 /* sc_set mem already owned by trv_state->mem_ctx */
     576           0 :                 DLIST_REMOVE(trv_state->sc_sets, sc_set);
     577           0 :                 trv_state->sc_sets_count--;
     578           0 :                 DLIST_ADD_END(*sc_sets, sc_set);
     579           0 :                 i++;
     580             : 
     581             :                 /* last component of the tdb key path is the sc_set GUID str */
     582           0 :                 SMB_ASSERT(strrchr(sc_set->id_str, '/') != NULL);
     583           0 :                 sc_set->id_str = strrchr(sc_set->id_str, '/') + 1;
     584             : 
     585           0 :                 status = GUID_from_string(sc_set->id_str, &sc_set->id);
     586           0 :                 if (!NT_STATUS_IS_OK(status)) {
     587           0 :                         goto err_out;
     588             :                 }
     589             : 
     590           0 :                 status = fss_state_hierarchize_scs(trv_state, sc_set);
     591           0 :                 if (!NT_STATUS_IS_OK(status)) {
     592           0 :                         goto err_out;
     593             :                 }
     594             :         }
     595           0 :         *sc_sets_count = i;
     596           0 :         return NT_STATUS_OK;
     597             : 
     598           0 : err_out:
     599           0 :         return status;
     600             : }
     601             : 
     602           0 : _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             :         struct db_context *db;
     608             :         NTSTATUS status;
     609             :         struct fss_traverse_state trv_state;
     610             :         int err;
     611             :         int rec_count;
     612             :         int vers;
     613           0 :         *sc_sets = NULL;
     614           0 :         *sc_sets_count = 0;
     615             : 
     616           0 :         memset(&trv_state, 0, sizeof(trv_state));
     617           0 :         trv_state.mem_ctx = talloc_new(mem_ctx);
     618           0 :         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           0 :         trv_state.smap_retrieve = fss_state_smap_retrieve;
     625           0 :         trv_state.sc_retrieve = fss_state_sc_retrieve;
     626           0 :         trv_state.sc_set_retrieve = fss_state_sc_set_retrieve;
     627             : 
     628           0 :         db = db_open(trv_state.mem_ctx, db_path, 0, TDB_DEFAULT,
     629             :                      O_RDONLY, 0600, DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
     630           0 :         err = errno;
     631           0 :         if ((db == NULL) && (err == ENOENT)) {
     632           0 :                 DEBUG(4, ("fss state TDB does not exist for retrieval\n"));
     633           0 :                 status = NT_STATUS_OK;
     634           0 :                 goto err_ts_free;
     635           0 :         } 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           0 :         status = dbwrap_fetch_int32_bystring(db, FSS_DB_KEY_VERSION,
     643             :                                              &vers);
     644           0 :         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           0 :         } 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           0 :         status = dbwrap_traverse_read(db,
     656             :                                       fss_state_retrieve_traverse,
     657             :                                       &trv_state,
     658             :                                       &rec_count);
     659           0 :         if (!NT_STATUS_IS_OK(status)) {
     660           0 :                 goto err_db_free;
     661             :         }
     662             : 
     663           0 :         status = fss_state_hierarchize(&trv_state, sc_sets, sc_sets_count);
     664           0 :         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           0 :         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           0 :         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           0 :         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           0 :         talloc_free(db);
     689             : 
     690           0 :         return NT_STATUS_OK;
     691             : 
     692           0 : err_db_free:
     693           0 :         talloc_free(db);
     694           0 : err_ts_free:
     695           0 :         talloc_free(trv_state.mem_ctx);
     696           0 : err_out:
     697           0 :         return status;
     698             : }

Generated by: LCOV version 1.13