LCOV - code coverage report
Current view: top level - lib/util - server_id_db.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 153 181 84.5 %
Date: 2024-01-11 09:59:51 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /*
       2             :  * Map names to server_ids
       3             :  *
       4             :  * Copyright Volker Lendecke <vl@samba.org> 2014
       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 "replace.h"
      21             : #include "system/filesys.h"
      22             : #include "lib/util/server_id.h"
      23             : #include "lib/util/server_id_db.h"
      24             : #include "lib/tdb_wrap/tdb_wrap.h"
      25             : #include "lib/util/strv.h"
      26             : #include "lib/util/util_tdb.h"
      27             : #include "lib/util/samba_util.h"
      28             : 
      29       30297 : static TDB_DATA talloc_tdb_data(void *ptr)
      30             : {
      31       30297 :         return (TDB_DATA) { .dptr = ptr, .dsize = talloc_get_size(ptr) };
      32             : }
      33             : 
      34             : struct server_id_db {
      35             :         struct server_id pid;
      36             :         struct tdb_wrap *tdb;
      37             :         char *names;
      38             : };
      39             : 
      40             : static int server_id_db_destructor(struct server_id_db *db);
      41             : 
      42      413409 : struct server_id_db *server_id_db_init(TALLOC_CTX *mem_ctx,
      43             :                                        struct server_id pid,
      44             :                                        const char *base_path,
      45             :                                        int hash_size, int tdb_flags)
      46      413409 : {
      47       17196 :         struct server_id_db *db;
      48      413409 :         size_t pathlen = strlen(base_path) + 11;
      49      413409 :         char path[pathlen];
      50             : 
      51      413409 :         db = talloc(mem_ctx, struct server_id_db);
      52      413409 :         if (db == NULL) {
      53           0 :                 return NULL;
      54             :         }
      55      413409 :         db->pid = pid;
      56      413409 :         db->names = NULL;
      57             : 
      58      413409 :         snprintf(path, pathlen, "%s/names.tdb", base_path);
      59             : 
      60      413409 :         db->tdb = tdb_wrap_open(db, path, hash_size, tdb_flags,
      61             :                                 O_RDWR|O_CREAT, 0660);
      62      413409 :         if (db->tdb == NULL) {
      63           0 :                 TALLOC_FREE(db);
      64           0 :                 return NULL;
      65             :         }
      66             : 
      67      413409 :         talloc_set_destructor(db, server_id_db_destructor);
      68             : 
      69      413409 :         return db;
      70             : }
      71             : 
      72       88918 : void server_id_db_reinit(struct server_id_db *db, struct server_id pid)
      73             : {
      74       88918 :         db->pid = pid;
      75       88918 :         TALLOC_FREE(db->names);
      76       88918 : }
      77             : 
      78           0 : struct server_id server_id_db_pid(struct server_id_db *db)
      79             : {
      80           0 :         return db->pid;
      81             : }
      82             : 
      83      487493 : static int server_id_db_destructor(struct server_id_db *db)
      84             : {
      85      487493 :         char *name = NULL;
      86             : 
      87      518889 :         while ((name = strv_next(db->names, name)) != NULL) {
      88       31396 :                 server_id_db_remove(db, name);
      89             :         }
      90             : 
      91      487493 :         return 0;
      92             : }
      93             : 
      94       31677 : int server_id_db_add(struct server_id_db *db, const char *name)
      95             : {
      96       31677 :         struct tdb_context *tdb = db->tdb->tdb;
      97         198 :         TDB_DATA key;
      98         198 :         char *n;
      99         198 :         int ret;
     100             : 
     101       31677 :         n = strv_find(db->names, name);
     102       31677 :         if (n != NULL) {
     103           0 :                 return EEXIST;
     104             :         }
     105             : 
     106       31677 :         ret = strv_add(db, &db->names, name);
     107       31677 :         if (ret != 0) {
     108           0 :                 return ret;
     109             :         }
     110             : 
     111       31677 :         key = string_term_tdb_data(name);
     112             : 
     113       31677 :         {
     114       31677 :                 size_t idlen = server_id_str_buf_unique(db->pid, NULL, 0);
     115       31677 :                 char idbuf[idlen];
     116             : 
     117       31677 :                 server_id_str_buf_unique(db->pid, idbuf, idlen);
     118             : 
     119       31875 :                 ret = tdb_append(
     120             :                         tdb, key,
     121       31677 :                         (TDB_DATA) { .dptr = (uint8_t *)idbuf, .dsize = idlen });
     122             :         }
     123             : 
     124       31677 :         if (ret != 0) {
     125           0 :                 enum TDB_ERROR err = tdb_error(tdb);
     126           0 :                 strv_delete(&db->names, strv_find(db->names, name));
     127           0 :                 return map_unix_error_from_tdb(err);
     128             :         }
     129             : 
     130       31479 :         return 0;
     131             : }
     132             : 
     133       32405 : int server_id_db_prune_name(struct server_id_db *db, const char *name,
     134             :                             struct server_id server)
     135       32405 : {
     136       32405 :         struct tdb_context *tdb = db->tdb->tdb;
     137       32405 :         size_t idbuf_len = server_id_str_buf_unique(server, NULL, 0);
     138       32405 :         char idbuf[idbuf_len];
     139         262 :         TDB_DATA key;
     140         262 :         uint8_t *data;
     141         262 :         size_t datalen;
     142         262 :         char *ids, *id;
     143         262 :         int ret;
     144             : 
     145       32405 :         key = string_term_tdb_data(name);
     146       32405 :         server_id_str_buf_unique(server, idbuf, idbuf_len);
     147             : 
     148       32405 :         ret = tdb_chainlock(tdb, key);
     149       32405 :         if (ret == -1) {
     150           0 :                 enum TDB_ERROR err = tdb_error(tdb);
     151           0 :                 return map_unix_error_from_tdb(err);
     152             :         }
     153             : 
     154       32405 :         ret = tdb_fetch_talloc(tdb, key, db, &data);
     155       32405 :         if (ret != 0) {
     156         705 :                 tdb_chainunlock(tdb, key);
     157         705 :                 return ret;
     158             :         }
     159             : 
     160       31700 :         datalen = talloc_get_size(data);
     161       31700 :         if ((datalen == 0) || (data[datalen-1] != '\0')) {
     162           0 :                 tdb_chainunlock(tdb, key);
     163           0 :                 TALLOC_FREE(data);
     164           0 :                 return EINVAL;
     165             :         }
     166             : 
     167       31700 :         ids = (char *)data;
     168             : 
     169       31700 :         id = strv_find(ids, idbuf);
     170       31700 :         if (id == NULL) {
     171          99 :                 tdb_chainunlock(tdb, key);
     172          99 :                 TALLOC_FREE(data);
     173          99 :                 return ENOENT;
     174             :         }
     175             : 
     176       31601 :         strv_delete(&ids, id);
     177             : 
     178       31601 :         if (talloc_get_size(ids) == 0) {
     179        1304 :                 ret = tdb_delete(tdb, key);
     180             :         } else {
     181       30297 :                 ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY);
     182             :         }
     183       31601 :         TALLOC_FREE(data);
     184             : 
     185       31601 :         tdb_chainunlock(tdb, key);
     186             : 
     187       31601 :         if (ret == -1) {
     188           0 :                 enum TDB_ERROR err = tdb_error(tdb);
     189           0 :                 return map_unix_error_from_tdb(err);
     190             :         }
     191             : 
     192       31403 :         return 0;
     193             : }
     194             : 
     195       31454 : int server_id_db_remove(struct server_id_db *db, const char *name)
     196             : {
     197         188 :         char *n;
     198         188 :         int ret;
     199             : 
     200       31454 :         n = strv_find(db->names, name);
     201       31454 :         if (n == NULL) {
     202           0 :                 return ENOENT;
     203             :         }
     204             : 
     205       31454 :         ret = server_id_db_prune_name(db, name, db->pid);
     206       31454 :         if (ret != 0) {
     207         740 :                 return ret;
     208             :         }
     209             : 
     210       30650 :         strv_delete(&db->names, n);
     211       30650 :         return 0;
     212             : }
     213             : 
     214      752554 : int server_id_db_lookup(struct server_id_db *db, const char *name,
     215             :                         TALLOC_CTX *mem_ctx, unsigned *pnum_servers,
     216             :                         struct server_id **pservers)
     217             : {
     218      752554 :         struct tdb_context *tdb = db->tdb->tdb;
     219       18597 :         TDB_DATA key;
     220       18597 :         uint8_t *data;
     221       18597 :         size_t datalen;
     222       18597 :         char *ids, *id;
     223       18597 :         unsigned num_servers;
     224       18597 :         struct server_id *servers;
     225       18597 :         int i, ret;
     226             : 
     227      752554 :         key = string_term_tdb_data(name);
     228             : 
     229      752554 :         ret = tdb_fetch_talloc(tdb, key, mem_ctx, &data);
     230      752554 :         if (ret != 0) {
     231      702194 :                 return ret;
     232             :         }
     233             : 
     234       32129 :         datalen = talloc_get_size(data);
     235       32129 :         if ((datalen == 0) || (data[datalen-1] != '\0')) {
     236           0 :                 TALLOC_FREE(data);
     237           0 :                 return EINVAL;
     238             :         }
     239             : 
     240       32129 :         ids = (char *)data;
     241       32129 :         num_servers = strv_count(ids);
     242             : 
     243       32129 :         servers = talloc_array(mem_ctx, struct server_id, num_servers);
     244       32129 :         if (servers == NULL) {
     245           0 :                 TALLOC_FREE(data);
     246           0 :                 return ENOMEM;
     247             :         }
     248             : 
     249       31763 :         i = 0;
     250             : 
     251       64348 :         for (id = ids; id != NULL; id = strv_next(ids, id)) {
     252       32219 :                 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
     253             :         }
     254             : 
     255       32129 :         TALLOC_FREE(data);
     256             : 
     257       32129 :         *pnum_servers = num_servers;
     258       32129 :         *pservers = servers;
     259             : 
     260       32129 :         return 0;
     261             : }
     262             : 
     263       20346 : bool server_id_db_lookup_one(struct server_id_db *db, const char *name,
     264             :                              struct server_id *server)
     265             : {
     266         344 :         int ret;
     267         344 :         unsigned num_servers;
     268         344 :         struct server_id *servers;
     269             : 
     270       20346 :         ret = server_id_db_lookup(db, name, db, &num_servers, &servers);
     271       20346 :         if (ret != 0) {
     272           2 :                 return false;
     273             :         }
     274       20344 :         if (num_servers == 0) {
     275           0 :                 TALLOC_FREE(servers);
     276           0 :                 return false;
     277             :         }
     278       20344 :         *server = servers[0];
     279       20344 :         TALLOC_FREE(servers);
     280       20344 :         return true;
     281             : }
     282             : 
     283             : struct server_id_db_traverse_state {
     284             :         TALLOC_CTX *mem_ctx;
     285             :         int (*fn)(const char *name,
     286             :                   unsigned num_servers,
     287             :                   const struct server_id *servers,
     288             :                   void *private_data);
     289             :         void *private_data;
     290             : };
     291             : 
     292       22221 : static int server_id_db_traverse_fn(struct tdb_context *tdb,
     293             :                                     TDB_DATA key, TDB_DATA data,
     294             :                                     void *private_data)
     295             : {
     296       22221 :         struct server_id_db_traverse_state *state = private_data;
     297        1142 :         const char *name;
     298        1142 :         char *ids, *id;
     299        1142 :         unsigned num_servers;
     300        1142 :         struct server_id *servers;
     301        1142 :         int i, ret;
     302             : 
     303       22221 :         if (key.dsize == 0) {
     304           0 :                 return 0;
     305             :         }
     306       22221 :         if (key.dptr[key.dsize-1] != '\0') {
     307           0 :                 return 0;
     308             :         }
     309       22221 :         name = (const char *)key.dptr;
     310             : 
     311       22221 :         ids = (char *)talloc_memdup(state->mem_ctx, data.dptr, data.dsize);
     312       22221 :         if (ids == NULL) {
     313           0 :                 return 0;
     314             :         }
     315             : 
     316       22221 :         num_servers = strv_count(ids);
     317       22221 :         servers = talloc_array(ids, struct server_id, num_servers);
     318             : 
     319       22221 :         i = 0;
     320             : 
     321       49803 :         for (id = ids; id != NULL; id = strv_next(ids, id)) {
     322       26440 :                 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
     323             :         }
     324             : 
     325       22221 :         ret = state->fn(name, num_servers, servers, state->private_data);
     326             : 
     327       22221 :         TALLOC_FREE(ids);
     328             : 
     329       22221 :         return ret;
     330             : }
     331             : 
     332        1031 : int server_id_db_traverse_read(struct server_id_db *db,
     333             :                                int (*fn)(const char *name,
     334             :                                          unsigned num_servers,
     335             :                                          const struct server_id *servers,
     336             :                                          void *private_data),
     337             :                                void *private_data)
     338             : {
     339          60 :         struct server_id_db_traverse_state state;
     340          60 :         int ret;
     341             : 
     342        1091 :         state = (struct server_id_db_traverse_state) {
     343             :                 .fn = fn, .private_data = private_data,
     344        1031 :                 .mem_ctx = talloc_new(db)
     345             :         };
     346             : 
     347        1031 :         if (state.mem_ctx == NULL) {
     348           0 :                 return ENOMEM;
     349             :         }
     350             : 
     351        1031 :         ret = tdb_traverse_read(db->tdb->tdb, server_id_db_traverse_fn,
     352             :                                 &state);
     353        1031 :         TALLOC_FREE(state.mem_ctx);
     354         971 :         return ret;
     355             : }

Generated by: LCOV version 1.14