LCOV - code coverage report
Current view: top level - lib/conf - conf.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 306 0.0 %
Date: 2024-12-13 10:57:40 Functions: 0 31 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
       3             :  *   Copyright (C) 2016 Intel Corporation.
       4             :  *   All rights reserved.
       5             :  */
       6             : 
       7             : #include "spdk/stdinc.h"
       8             : 
       9             : #include "spdk/conf.h"
      10             : #include "spdk/string.h"
      11             : #include "spdk/log.h"
      12             : 
      13             : struct spdk_conf_value {
      14             :         struct spdk_conf_value *next;
      15             :         char *value;
      16             : };
      17             : 
      18             : struct spdk_conf_item {
      19             :         struct spdk_conf_item *next;
      20             :         char *key;
      21             :         struct spdk_conf_value *val;
      22             : };
      23             : 
      24             : struct spdk_conf_section {
      25             :         struct spdk_conf_section *next;
      26             :         char *name;
      27             :         int num;
      28             :         struct spdk_conf_item *item;
      29             : };
      30             : 
      31             : struct spdk_conf {
      32             :         char *file;
      33             :         struct spdk_conf_section *current_section;
      34             :         struct spdk_conf_section *section;
      35             :         bool merge_sections;
      36             : };
      37             : 
      38             : #define CF_DELIM " \t"
      39             : #define CF_DELIM_KEY " \t="
      40             : 
      41             : #define LIB_MAX_TMPBUF 1024
      42             : 
      43             : static struct spdk_conf *default_config = NULL;
      44             : 
      45             : struct spdk_conf *
      46           0 : spdk_conf_allocate(void)
      47             : {
      48           0 :         struct spdk_conf *ret = calloc(1, sizeof(struct spdk_conf));
      49             : 
      50           0 :         if (ret) {
      51           0 :                 ret->merge_sections = true;
      52             :         }
      53             : 
      54           0 :         return ret;
      55             : }
      56             : 
      57             : static void
      58           0 : free_conf_value(struct spdk_conf_value *vp)
      59             : {
      60           0 :         if (vp == NULL) {
      61           0 :                 return;
      62             :         }
      63             : 
      64           0 :         if (vp->value) {
      65           0 :                 free(vp->value);
      66             :         }
      67             : 
      68           0 :         free(vp);
      69             : }
      70             : 
      71             : static void
      72           0 : free_all_conf_value(struct spdk_conf_value *vp)
      73             : {
      74             :         struct spdk_conf_value *next;
      75             : 
      76           0 :         if (vp == NULL) {
      77           0 :                 return;
      78             :         }
      79             : 
      80           0 :         while (vp != NULL) {
      81           0 :                 next = vp->next;
      82           0 :                 free_conf_value(vp);
      83           0 :                 vp = next;
      84             :         }
      85             : }
      86             : 
      87             : static void
      88           0 : free_conf_item(struct spdk_conf_item *ip)
      89             : {
      90           0 :         if (ip == NULL) {
      91           0 :                 return;
      92             :         }
      93             : 
      94           0 :         if (ip->val != NULL) {
      95           0 :                 free_all_conf_value(ip->val);
      96             :         }
      97             : 
      98           0 :         if (ip->key != NULL) {
      99           0 :                 free(ip->key);
     100             :         }
     101             : 
     102           0 :         free(ip);
     103             : }
     104             : 
     105             : static void
     106           0 : free_all_conf_item(struct spdk_conf_item *ip)
     107             : {
     108             :         struct spdk_conf_item *next;
     109             : 
     110           0 :         if (ip == NULL) {
     111           0 :                 return;
     112             :         }
     113             : 
     114           0 :         while (ip != NULL) {
     115           0 :                 next = ip->next;
     116           0 :                 free_conf_item(ip);
     117           0 :                 ip = next;
     118             :         }
     119             : }
     120             : 
     121             : static void
     122           0 : free_conf_section(struct spdk_conf_section *sp)
     123             : {
     124           0 :         if (sp == NULL) {
     125           0 :                 return;
     126             :         }
     127             : 
     128           0 :         if (sp->item) {
     129           0 :                 free_all_conf_item(sp->item);
     130             :         }
     131             : 
     132           0 :         if (sp->name) {
     133           0 :                 free(sp->name);
     134             :         }
     135             : 
     136           0 :         free(sp);
     137             : }
     138             : 
     139             : static void
     140           0 : free_all_conf_section(struct spdk_conf_section *sp)
     141             : {
     142             :         struct spdk_conf_section *next;
     143             : 
     144           0 :         if (sp == NULL) {
     145           0 :                 return;
     146             :         }
     147             : 
     148           0 :         while (sp != NULL) {
     149           0 :                 next = sp->next;
     150           0 :                 free_conf_section(sp);
     151           0 :                 sp = next;
     152             :         }
     153             : }
     154             : 
     155             : void
     156           0 : spdk_conf_free(struct spdk_conf *cp)
     157             : {
     158           0 :         if (cp == NULL) {
     159           0 :                 return;
     160             :         }
     161             : 
     162           0 :         if (cp->section != NULL) {
     163           0 :                 free_all_conf_section(cp->section);
     164             :         }
     165             : 
     166           0 :         if (cp->file != NULL) {
     167           0 :                 free(cp->file);
     168             :         }
     169             : 
     170           0 :         free(cp);
     171             : }
     172             : 
     173             : static struct spdk_conf_section *
     174           0 : allocate_cf_section(void)
     175             : {
     176           0 :         return calloc(1, sizeof(struct spdk_conf_section));
     177             : }
     178             : 
     179             : static struct spdk_conf_item *
     180           0 : allocate_cf_item(void)
     181             : {
     182           0 :         return calloc(1, sizeof(struct spdk_conf_item));
     183             : }
     184             : 
     185             : static struct spdk_conf_value *
     186           0 : allocate_cf_value(void)
     187             : {
     188           0 :         return calloc(1, sizeof(struct spdk_conf_value));
     189             : }
     190             : 
     191             : 
     192             : #define CHECK_CP_OR_USE_DEFAULT(cp) (((cp) == NULL) && (default_config != NULL)) ? default_config : (cp)
     193             : 
     194             : struct spdk_conf_section *
     195           0 : spdk_conf_find_section(struct spdk_conf *cp, const char *name)
     196             : {
     197             :         struct spdk_conf_section *sp;
     198             : 
     199           0 :         if (name == NULL || name[0] == '\0') {
     200           0 :                 return NULL;
     201             :         }
     202             : 
     203           0 :         cp = CHECK_CP_OR_USE_DEFAULT(cp);
     204           0 :         if (cp == NULL) {
     205           0 :                 return NULL;
     206             :         }
     207             : 
     208           0 :         for (sp = cp->section; sp != NULL; sp = sp->next) {
     209           0 :                 if (sp->name != NULL && sp->name[0] == name[0]
     210           0 :                     && strcasecmp(sp->name, name) == 0) {
     211           0 :                         return sp;
     212             :                 }
     213             :         }
     214             : 
     215           0 :         return NULL;
     216             : }
     217             : 
     218             : struct spdk_conf_section *
     219           0 : spdk_conf_first_section(struct spdk_conf *cp)
     220             : {
     221           0 :         cp = CHECK_CP_OR_USE_DEFAULT(cp);
     222           0 :         if (cp == NULL) {
     223           0 :                 return NULL;
     224             :         }
     225             : 
     226           0 :         return cp->section;
     227             : }
     228             : 
     229             : struct spdk_conf_section *
     230           0 : spdk_conf_next_section(struct spdk_conf_section *sp)
     231             : {
     232           0 :         if (sp == NULL) {
     233           0 :                 return NULL;
     234             :         }
     235             : 
     236           0 :         return sp->next;
     237             : }
     238             : 
     239             : static void
     240           0 : append_cf_section(struct spdk_conf *cp, struct spdk_conf_section *sp)
     241             : {
     242             :         struct spdk_conf_section *last;
     243             : 
     244           0 :         cp = CHECK_CP_OR_USE_DEFAULT(cp);
     245           0 :         if (cp == NULL) {
     246           0 :                 SPDK_ERRLOG("cp == NULL\n");
     247           0 :                 return;
     248             :         }
     249             : 
     250           0 :         if (cp->section == NULL) {
     251           0 :                 cp->section = sp;
     252           0 :                 return;
     253             :         }
     254             : 
     255           0 :         for (last = cp->section; last->next != NULL; last = last->next)
     256             :                 ;
     257           0 :         last->next = sp;
     258             : }
     259             : 
     260             : static struct spdk_conf_item *
     261           0 : find_cf_nitem(struct spdk_conf_section *sp, const char *key, int idx)
     262             : {
     263             :         struct spdk_conf_item *ip;
     264             :         int i;
     265             : 
     266           0 :         if (key == NULL || key[0] == '\0') {
     267           0 :                 return NULL;
     268             :         }
     269             : 
     270           0 :         i = 0;
     271           0 :         for (ip = sp->item; ip != NULL; ip = ip->next) {
     272           0 :                 if (ip->key != NULL && ip->key[0] == key[0]
     273           0 :                     && strcasecmp(ip->key, key) == 0) {
     274           0 :                         if (i == idx) {
     275           0 :                                 return ip;
     276             :                         }
     277           0 :                         i++;
     278             :                 }
     279             :         }
     280             : 
     281           0 :         return NULL;
     282             : }
     283             : 
     284             : static void
     285           0 : append_cf_item(struct spdk_conf_section *sp, struct spdk_conf_item *ip)
     286             : {
     287             :         struct spdk_conf_item *last;
     288             : 
     289           0 :         if (sp == NULL) {
     290           0 :                 return;
     291             :         }
     292             : 
     293           0 :         if (sp->item == NULL) {
     294           0 :                 sp->item = ip;
     295           0 :                 return;
     296             :         }
     297             : 
     298           0 :         for (last = sp->item; last->next != NULL; last = last->next)
     299             :                 ;
     300           0 :         last->next = ip;
     301             : }
     302             : 
     303             : static void
     304           0 : append_cf_value(struct spdk_conf_item *ip, struct spdk_conf_value *vp)
     305             : {
     306             :         struct spdk_conf_value *last;
     307             : 
     308           0 :         if (ip == NULL) {
     309           0 :                 return;
     310             :         }
     311             : 
     312           0 :         if (ip->val == NULL) {
     313           0 :                 ip->val = vp;
     314           0 :                 return;
     315             :         }
     316             : 
     317           0 :         for (last = ip->val; last->next != NULL; last = last->next)
     318             :                 ;
     319           0 :         last->next = vp;
     320             : }
     321             : 
     322             : bool
     323           0 : spdk_conf_section_match_prefix(const struct spdk_conf_section *sp, const char *name_prefix)
     324             : {
     325           0 :         return strncasecmp(sp->name, name_prefix, strlen(name_prefix)) == 0;
     326             : }
     327             : 
     328             : const char *
     329           0 : spdk_conf_section_get_name(const struct spdk_conf_section *sp)
     330             : {
     331           0 :         return sp->name;
     332             : }
     333             : 
     334             : int
     335           0 : spdk_conf_section_get_num(const struct spdk_conf_section *sp)
     336             : {
     337           0 :         return sp->num;
     338             : }
     339             : 
     340             : char *
     341           0 : spdk_conf_section_get_nmval(struct spdk_conf_section *sp, const char *key, int idx1, int idx2)
     342             : {
     343             :         struct spdk_conf_item *ip;
     344             :         struct spdk_conf_value *vp;
     345             :         int i;
     346             : 
     347           0 :         ip = find_cf_nitem(sp, key, idx1);
     348           0 :         if (ip == NULL) {
     349           0 :                 return NULL;
     350             :         }
     351             : 
     352           0 :         vp = ip->val;
     353           0 :         if (vp == NULL) {
     354           0 :                 return NULL;
     355             :         }
     356             : 
     357           0 :         for (i = 0; vp != NULL; vp = vp->next, i++) {
     358           0 :                 if (i == idx2) {
     359           0 :                         return vp->value;
     360             :                 }
     361             :         }
     362             : 
     363           0 :         return NULL;
     364             : }
     365             : 
     366             : char *
     367           0 : spdk_conf_section_get_nval(struct spdk_conf_section *sp, const char *key, int idx)
     368             : {
     369             :         struct spdk_conf_item *ip;
     370             :         struct spdk_conf_value *vp;
     371             : 
     372           0 :         ip = find_cf_nitem(sp, key, idx);
     373           0 :         if (ip == NULL) {
     374           0 :                 return NULL;
     375             :         }
     376             : 
     377           0 :         vp = ip->val;
     378           0 :         if (vp == NULL) {
     379           0 :                 return NULL;
     380             :         }
     381             : 
     382           0 :         return vp->value;
     383             : }
     384             : 
     385             : char *
     386           0 : spdk_conf_section_get_val(struct spdk_conf_section *sp, const char *key)
     387             : {
     388           0 :         return spdk_conf_section_get_nval(sp, key, 0);
     389             : }
     390             : 
     391             : int
     392           0 : spdk_conf_section_get_intval(struct spdk_conf_section *sp, const char *key)
     393             : {
     394             :         const char *v;
     395             :         int value;
     396             : 
     397           0 :         v = spdk_conf_section_get_nval(sp, key, 0);
     398           0 :         if (v == NULL) {
     399           0 :                 return -1;
     400             :         }
     401             : 
     402           0 :         value = (int)spdk_strtol(v, 10);
     403           0 :         return value;
     404             : }
     405             : 
     406             : bool
     407           0 : spdk_conf_section_get_boolval(struct spdk_conf_section *sp, const char *key, bool default_val)
     408             : {
     409             :         const char *v;
     410             : 
     411           0 :         v = spdk_conf_section_get_nval(sp, key, 0);
     412           0 :         if (v == NULL) {
     413           0 :                 return default_val;
     414             :         }
     415             : 
     416           0 :         if (!strcasecmp(v, "Yes") || !strcasecmp(v, "Y") || !strcasecmp(v, "True")) {
     417           0 :                 return true;
     418             :         }
     419             : 
     420           0 :         if (!strcasecmp(v, "No") || !strcasecmp(v, "N") || !strcasecmp(v, "False")) {
     421           0 :                 return false;
     422             :         }
     423             : 
     424           0 :         return default_val;
     425             : }
     426             : 
     427             : static int
     428           0 : parse_line(struct spdk_conf *cp, char *lp)
     429             : {
     430             :         struct spdk_conf_section *sp;
     431             :         struct spdk_conf_item *ip;
     432             :         struct spdk_conf_value *vp;
     433             :         char *arg;
     434             :         char *key;
     435             :         char *val;
     436             :         char *p;
     437             :         int num;
     438             : 
     439           0 :         arg = spdk_str_trim(lp);
     440           0 :         if (arg == NULL) {
     441           0 :                 SPDK_ERRLOG("no section\n");
     442           0 :                 return -1;
     443             :         }
     444             : 
     445           0 :         if (arg[0] == '[') {
     446             :                 /* section */
     447           0 :                 arg++;
     448           0 :                 key = spdk_strsepq(&arg, "]");
     449           0 :                 if (key == NULL || arg != NULL) {
     450           0 :                         SPDK_ERRLOG("broken section\n");
     451           0 :                         return -1;
     452             :                 }
     453             :                 /* determine section number */
     454           0 :                 for (p = key; *p != '\0' && !isdigit((int) *p); p++)
     455             :                         ;
     456           0 :                 if (*p != '\0') {
     457           0 :                         num = (int)spdk_strtol(p, 10);
     458             :                 } else {
     459           0 :                         num = 0;
     460             :                 }
     461             : 
     462           0 :                 if (cp->merge_sections) {
     463           0 :                         sp = spdk_conf_find_section(cp, key);
     464             :                 } else {
     465           0 :                         sp = NULL;
     466             :                 }
     467             : 
     468           0 :                 if (sp == NULL) {
     469           0 :                         sp = allocate_cf_section();
     470           0 :                         if (sp == NULL) {
     471           0 :                                 SPDK_ERRLOG("cannot allocate cf section\n");
     472           0 :                                 return -1;
     473             :                         }
     474           0 :                         append_cf_section(cp, sp);
     475             : 
     476           0 :                         sp->name = strdup(key);
     477           0 :                         if (sp->name == NULL) {
     478           0 :                                 SPDK_ERRLOG("cannot duplicate %s to sp->name\n", key);
     479           0 :                                 return -1;
     480             :                         }
     481             :                 }
     482           0 :                 cp->current_section = sp;
     483             : 
     484             : 
     485           0 :                 sp->num = num;
     486             :         } else {
     487             :                 /* parameters */
     488           0 :                 sp = cp->current_section;
     489           0 :                 if (sp == NULL) {
     490           0 :                         SPDK_ERRLOG("unknown section\n");
     491           0 :                         return -1;
     492             :                 }
     493           0 :                 key = spdk_strsepq(&arg, CF_DELIM_KEY);
     494           0 :                 if (key == NULL) {
     495           0 :                         SPDK_ERRLOG("broken key\n");
     496           0 :                         return -1;
     497             :                 }
     498             : 
     499           0 :                 ip = allocate_cf_item();
     500           0 :                 if (ip == NULL) {
     501           0 :                         SPDK_ERRLOG("cannot allocate cf item\n");
     502           0 :                         return -1;
     503             :                 }
     504           0 :                 append_cf_item(sp, ip);
     505           0 :                 ip->key = strdup(key);
     506           0 :                 if (ip->key == NULL) {
     507           0 :                         SPDK_ERRLOG("cannot make duplicate of %s\n", key);
     508           0 :                         return -1;
     509             :                 }
     510           0 :                 ip->val = NULL;
     511           0 :                 if (arg != NULL) {
     512             :                         /* key has value(s) */
     513           0 :                         while (arg != NULL) {
     514           0 :                                 val = spdk_strsepq(&arg, CF_DELIM);
     515           0 :                                 vp = allocate_cf_value();
     516           0 :                                 if (vp == NULL) {
     517           0 :                                         SPDK_ERRLOG("cannot allocate cf value\n");
     518           0 :                                         return -1;
     519             :                                 }
     520           0 :                                 append_cf_value(ip, vp);
     521           0 :                                 vp->value = strdup(val);
     522           0 :                                 if (vp->value == NULL) {
     523           0 :                                         SPDK_ERRLOG("cannot duplicate %s to vp->value\n", val);
     524           0 :                                         return -1;
     525             :                                 }
     526             :                         }
     527             :                 }
     528             :         }
     529             : 
     530           0 :         return 0;
     531             : }
     532             : 
     533             : static char *
     534           0 : fgets_line(FILE *fp)
     535             : {
     536             :         char *dst, *dst2, *p;
     537             :         size_t total, len;
     538             : 
     539           0 :         dst = p = malloc(LIB_MAX_TMPBUF);
     540           0 :         if (!dst) {
     541           0 :                 return NULL;
     542             :         }
     543             : 
     544           0 :         dst[0] = '\0';
     545           0 :         total = 0;
     546             : 
     547           0 :         while (fgets(p, LIB_MAX_TMPBUF, fp) != NULL) {
     548           0 :                 len = strlen(p);
     549           0 :                 total += len;
     550           0 :                 if (len + 1 < LIB_MAX_TMPBUF || dst[total - 1] == '\n') {
     551           0 :                         dst2 = realloc(dst, total + 1);
     552           0 :                         if (!dst2) {
     553           0 :                                 free(dst);
     554           0 :                                 return NULL;
     555             :                         } else {
     556           0 :                                 return dst2;
     557             :                         }
     558             :                 }
     559             : 
     560           0 :                 dst2 = realloc(dst, total + LIB_MAX_TMPBUF);
     561           0 :                 if (!dst2) {
     562           0 :                         free(dst);
     563           0 :                         return NULL;
     564             :                 } else {
     565           0 :                         dst = dst2;
     566             :                 }
     567             : 
     568           0 :                 p = dst + total;
     569             :         }
     570             : 
     571           0 :         if (feof(fp) && total != 0) {
     572           0 :                 dst2 = realloc(dst, total + 2);
     573           0 :                 if (!dst2) {
     574           0 :                         free(dst);
     575           0 :                         return NULL;
     576             :                 } else {
     577           0 :                         dst = dst2;
     578             :                 }
     579             : 
     580           0 :                 dst[total] = '\n';
     581           0 :                 dst[total + 1] = '\0';
     582           0 :                 return dst;
     583             :         }
     584             : 
     585           0 :         free(dst);
     586             : 
     587           0 :         return NULL;
     588             : }
     589             : 
     590             : int
     591           0 : spdk_conf_read(struct spdk_conf *cp, const char *file)
     592             : {
     593             :         FILE *fp;
     594             :         char *lp, *p;
     595             :         char *lp2, *q;
     596             :         int line;
     597             :         int n, n2;
     598             : 
     599           0 :         if (file == NULL || file[0] == '\0') {
     600           0 :                 return -1;
     601             :         }
     602             : 
     603           0 :         fp = fopen(file, "r");
     604           0 :         if (fp == NULL) {
     605           0 :                 SPDK_ERRLOG("open error: %s\n", file);
     606           0 :                 return -1;
     607             :         }
     608             : 
     609           0 :         cp->file = strdup(file);
     610           0 :         if (cp->file == NULL) {
     611           0 :                 SPDK_ERRLOG("cannot duplicate %s to cp->file\n", file);
     612           0 :                 fclose(fp);
     613           0 :                 return -1;
     614             :         }
     615             : 
     616           0 :         line = 1;
     617           0 :         while ((lp = fgets_line(fp)) != NULL) {
     618             :                 /* skip spaces */
     619           0 :                 for (p = lp; *p != '\0' && isspace((int) *p); p++)
     620             :                         ;
     621             :                 /* skip comment, empty line */
     622           0 :                 if (p[0] == '#' || p[0] == '\0') {
     623           0 :                         goto next_line;
     624             :                 }
     625             : 
     626             :                 /* concatenate line end with '\' */
     627           0 :                 n = strlen(p);
     628           0 :                 while (n > 2 && p[n - 1] == '\n' && p[n - 2] == '\\') {
     629           0 :                         n -= 2;
     630           0 :                         lp2 = fgets_line(fp);
     631           0 :                         if (lp2 == NULL) {
     632           0 :                                 break;
     633             :                         }
     634             : 
     635           0 :                         line++;
     636           0 :                         n2 = strlen(lp2);
     637             : 
     638           0 :                         q = malloc(n + n2 + 1);
     639           0 :                         if (!q) {
     640           0 :                                 free(lp2);
     641           0 :                                 free(lp);
     642           0 :                                 SPDK_ERRLOG("malloc failed at line %d of %s\n", line, cp->file);
     643           0 :                                 fclose(fp);
     644           0 :                                 return -1;
     645             :                         }
     646             : 
     647           0 :                         memcpy(q, p, n);
     648           0 :                         memcpy(q + n, lp2, n2);
     649           0 :                         q[n + n2] = '\0';
     650           0 :                         free(lp2);
     651           0 :                         free(lp);
     652           0 :                         p = lp = q;
     653           0 :                         n += n2;
     654             :                 }
     655             : 
     656             :                 /* parse one line */
     657           0 :                 if (parse_line(cp, p) < 0) {
     658           0 :                         SPDK_ERRLOG("parse error at line %d of %s\n", line, cp->file);
     659             :                 }
     660           0 : next_line:
     661           0 :                 line++;
     662           0 :                 free(lp);
     663             :         }
     664             : 
     665           0 :         fclose(fp);
     666           0 :         return 0;
     667             : }
     668             : 
     669             : void
     670           0 : spdk_conf_set_as_default(struct spdk_conf *cp)
     671             : {
     672           0 :         default_config = cp;
     673           0 : }
     674             : 
     675             : void
     676           0 : spdk_conf_disable_sections_merge(struct spdk_conf *cp)
     677             : {
     678           0 :         cp->merge_sections = false;
     679           0 : }

Generated by: LCOV version 1.15