LCOV - code coverage report
Current view: top level - ini - ini_get_value.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 152 185 82.2 %
Date: 2014-04-01 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /*
       2             :     INI LIBRARY
       3             : 
       4             :     Value interpretation functions for single values
       5             :     and corresponding memory cleanup functions.
       6             : 
       7             :     Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
       8             : 
       9             :     INI Library is free software: you can redistribute it and/or modify
      10             :     it under the terms of the GNU Lesser General Public License as published by
      11             :     the Free Software Foundation, either version 3 of the License, or
      12             :     (at your option) any later version.
      13             : 
      14             :     INI Library is distributed in the hope that it will be useful,
      15             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :     GNU Lesser General Public License for more details.
      18             : 
      19             :     You should have received a copy of the GNU Lesser General Public License
      20             :     along with INI Library.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "config.h"
      24             : #include <stdio.h>
      25             : #include <errno.h>
      26             : #include <string.h>
      27             : #include <stdlib.h>
      28             : #include <ctype.h>
      29             : #include "trace.h"
      30             : #include "collection.h"
      31             : #include "collection_tools.h"
      32             : #include "ini_defines.h"
      33             : #include "ini_config.h"
      34             : 
      35             : /* Function to get value from the configuration handle */
      36          24 : int get_config_item(const char *section,
      37             :                     const char *name,
      38             :                     struct collection_item *ini_config,
      39             :                     struct collection_item **item)
      40             : {
      41          24 :     int error = EOK;
      42          24 :     struct collection_item *section_handle = NULL;
      43             :     const char *to_find;
      44          24 :     char default_section[] = INI_DEFAULT_SECTION;
      45             : 
      46             :     TRACE_FLOW_STRING("get_config_item", "Entry");
      47             : 
      48             :     /* Do we have the accepting memory ? */
      49          24 :     if (item == NULL) {
      50             :         TRACE_ERROR_NUMBER("No buffer - invalid argument.", EINVAL);
      51             :         return EINVAL;
      52             :     }
      53             : 
      54             :     /* Is the collection of a right type */
      55          32 :     if ((col_is_of_class(ini_config, COL_CLASS_INI_CONFIG) == 0) &&
      56           8 :         (col_is_of_class(ini_config, COL_CLASS_INI_META) == 0)) {
      57             :         TRACE_ERROR_NUMBER("Wrong collection type", EINVAL);
      58             :         return EINVAL;
      59             :     }
      60             : 
      61          24 :     *item = NULL;
      62             : 
      63          24 :     if (section == NULL) to_find = default_section;
      64          24 :     else to_find = section;
      65             : 
      66             :     TRACE_INFO_STRING("Getting Name:", name);
      67             :     TRACE_INFO_STRING("In Section:", section);
      68             : 
      69             :     /* Get Subcollection */
      70          24 :     error = col_get_collection_reference(ini_config, &section_handle, to_find);
      71             :     /* Check error */
      72          24 :     if (error && (error != ENOENT)) {
      73             :         TRACE_ERROR_NUMBER("Failed to get section", error);
      74             :         return error;
      75             :     }
      76             : 
      77             :     /* Did we find a section */
      78          24 :     if ((error == ENOENT) || (section_handle == NULL)) {
      79             :         /* We have not found section - return success */
      80             :         TRACE_FLOW_STRING("get_value_from_config", "No such section");
      81             :         return EOK;
      82             :     }
      83             : 
      84             :     /* Get item */
      85          23 :     error = col_get_item(section_handle, name,
      86             :                          COL_TYPE_STRING, COL_TRAVERSE_ONELEVEL, item);
      87             : 
      88             :     /* Make sure we free the section we found */
      89          23 :     col_destroy_collection(section_handle);
      90             : 
      91             :     TRACE_FLOW_NUMBER("get_config_item returning", error);
      92          23 :     return error;
      93             : }
      94             : 
      95             : /* Get long long value from config item */
      96           6 : static long long get_llong_config_value(struct collection_item *item,
      97             :                                         int strict,
      98             :                                         long long def,
      99             :                                         int *error)
     100             : {
     101             :     int err;
     102             :     const char *str;
     103             :     char *endptr;
     104           6 :     long long val = 0;
     105             : 
     106             :     TRACE_FLOW_STRING("get_llong_config_value", "Entry");
     107             : 
     108             :     /* Do we have the item ? */
     109          12 :     if ((item == NULL) ||
     110           6 :        (col_get_item_type(item) != COL_TYPE_STRING)) {
     111             :         TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
     112           0 :         if (error) *error = EINVAL;
     113           0 :         return def;
     114             :     }
     115             : 
     116           6 :     if (error) *error = EOK;
     117             : 
     118             :     /* Try to parse the value */
     119           6 :     str = (const char *)col_get_item_data(item);
     120           6 :     errno = 0;
     121           6 :     val = strtoll(str, &endptr, 10);
     122           6 :     err = errno;
     123             : 
     124             :     /* Check for various possible errors */
     125           6 :     if (err != 0) {
     126             :         TRACE_ERROR_NUMBER("Conversion failed", err);
     127           0 :         if (error) *error = err;
     128           0 :         return def;
     129             :     }
     130             : 
     131             :     /* Other error cases */
     132           6 :     if ((endptr == str) || (strict && (*endptr != '\0'))) {
     133             :         TRACE_ERROR_NUMBER("More characters or nothing processed", EIO);
     134           1 :         if (error) *error = EIO;
     135           1 :         return def;
     136             :     }
     137             : 
     138             :     TRACE_FLOW_NUMBER("get_llong_config_value returning", (long)val);
     139             :     return val;
     140             : }
     141             : 
     142             : /* Get unsigned long long value from config item */
     143          12 : static unsigned long long get_ullong_config_value(struct collection_item *item,
     144             :                                                   int strict,
     145             :                                                   unsigned long long def,
     146             :                                                   int *error)
     147             : {
     148             :     int err;
     149             :     const char *str;
     150             :     char *endptr;
     151          12 :     unsigned long long val = 0;
     152             : 
     153             :     TRACE_FLOW_STRING("get_ullong_config_value", "Entry");
     154             : 
     155             :     /* Do we have the item ? */
     156          24 :     if ((item == NULL) ||
     157          12 :        (col_get_item_type(item) != COL_TYPE_STRING)) {
     158             :         TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
     159           0 :         if (error) *error = EINVAL;
     160           0 :         return def;
     161             :     }
     162             : 
     163          12 :     if (error) *error = EOK;
     164             : 
     165             :     /* Try to parse the value */
     166          12 :     str = (const char *)col_get_item_data(item);
     167          12 :     errno = 0;
     168          12 :     val = strtoull(str, &endptr, 10);
     169          12 :     err = errno;
     170             : 
     171             :     /* Check for various possible errors */
     172          12 :     if (err != 0) {
     173             :         TRACE_ERROR_NUMBER("Conversion failed", err);
     174           0 :         if (error) *error = err;
     175           0 :         return def;
     176             :     }
     177             : 
     178             :     /* Other error cases */
     179          12 :     if ((endptr == str) || (strict && (*endptr != '\0'))) {
     180             :         TRACE_ERROR_NUMBER("More characters or nothing processed", EIO);
     181           0 :         if (error) *error = EIO;
     182           0 :         return def;
     183             :     }
     184             : 
     185             :     TRACE_FLOW_NUMBER("get_ullong_config_value returning", val);
     186             :     return val;
     187             : }
     188             : 
     189             : 
     190             : /* Get integer value from config item */
     191           4 : int get_int_config_value(struct collection_item *item,
     192             :                          int strict,
     193             :                          int def,
     194             :                          int *error)
     195             : {
     196           4 :     long long val = 0;
     197           4 :     int err = 0;
     198             : 
     199             :     TRACE_FLOW_STRING("get_int_config_value", "Entry");
     200             : 
     201           4 :     val = get_llong_config_value(item, strict, def, &err);
     202           4 :     if (err == 0) {
     203           3 :         if ((val > INT_MAX) || (val < INT_MIN)) {
     204           0 :             val = def;
     205           0 :             err = ERANGE;
     206             :         }
     207             :     }
     208             : 
     209           4 :     if (error) *error = err;
     210             : 
     211             :     TRACE_FLOW_NUMBER("get_int_config_value returning", (int)val);
     212           4 :     return (int)val;
     213             : }
     214             : 
     215             : /* Get unsigned integer value from config item */
     216           2 : unsigned get_unsigned_config_value(struct collection_item *item,
     217             :                                    int strict,
     218             :                                    unsigned def,
     219             :                                    int *error)
     220             : {
     221           2 :     unsigned long long val = 0;
     222           2 :     int err = 0;
     223             : 
     224             :     TRACE_FLOW_STRING("get_unsigned_config_value", "Entry");
     225             : 
     226           2 :     val = get_ullong_config_value(item, strict, def, &err);
     227           2 :     if (err == 0) {
     228           2 :         if (val > UINT_MAX) {
     229           0 :             val = def;
     230           0 :             err = ERANGE;
     231             :         }
     232             :     }
     233             : 
     234           2 :     if (error) *error = err;
     235             : 
     236             :     TRACE_FLOW_NUMBER("get_unsigned_config_value returning",
     237             :                       (unsigned)val);
     238           2 :     return (unsigned)val;
     239             : }
     240             : 
     241             : /* Get long value from config item */
     242           1 : long get_long_config_value(struct collection_item *item,
     243             :                            int strict,
     244             :                            long def,
     245             :                            int *error)
     246             : {
     247           1 :     long long val = 0;
     248           1 :     int err = 0;
     249             : 
     250             :     TRACE_FLOW_STRING("get_long_config_value", "Entry");
     251             : 
     252           1 :     val = get_llong_config_value(item, strict, def, &err);
     253             :     if (err == 0) {
     254             :         if ((val > LONG_MAX) || (val < LONG_MIN)) {
     255             :             val = def;
     256             :             err = ERANGE;
     257             :         }
     258             :     }
     259             : 
     260           1 :     if (error) *error = err;
     261             : 
     262             :     TRACE_FLOW_NUMBER("get_long_config_value returning",
     263             :                       (long)val);
     264           1 :     return (long)val;
     265             : }
     266             : 
     267             : /* Get unsigned long value from config item */
     268           9 : unsigned long get_ulong_config_value(struct collection_item *item,
     269             :                                      int strict,
     270             :                                      unsigned long def,
     271             :                                      int *error)
     272             : {
     273           9 :     unsigned long long val = 0;
     274           9 :     int err = 0;
     275             : 
     276             :     TRACE_FLOW_STRING("get_ulong_config_value", "Entry");
     277             : 
     278           9 :     val = get_ullong_config_value(item, strict, def, &err);
     279             :     if (err == 0) {
     280             :         if (val > ULONG_MAX) {
     281             :             val = def;
     282             :             err = ERANGE;
     283             :         }
     284             :     }
     285             : 
     286           9 :     if (error) *error = err;
     287             : 
     288             :     TRACE_FLOW_NUMBER("get_ulong_config_value returning",
     289             :                       (unsigned long)val);
     290           9 :     return (unsigned long)val;
     291             : }
     292             : 
     293             : /* Get int32_t value from config item */
     294           1 : int32_t get_int32_config_value(struct collection_item *item,
     295             :                                int strict,
     296             :                                int32_t def,
     297             :                                int *error)
     298             : {
     299           1 :     int val = 0;
     300             : 
     301             :     TRACE_FLOW_STRING("get_int32_config_value", "Entry");
     302             : 
     303           1 :     val = get_int_config_value(item, strict, (int)def, error);
     304             : 
     305             :     TRACE_FLOW_SNUMBER("get_int32_config_value returning", (int32_t)val);
     306           1 :     return (int32_t)val;
     307             : }
     308             : 
     309             : /* Get uint32_t value from config item */
     310           1 : uint32_t get_uint32_config_value(struct collection_item *item,
     311             :                                  int strict,
     312             :                                  uint32_t def,
     313             :                                  int *error)
     314             : {
     315           1 :     unsigned val = 0;
     316             : 
     317             :     TRACE_FLOW_STRING("get_uint32_config_value", "Entry");
     318             : 
     319           1 :     val = get_unsigned_config_value(item, strict, (unsigned)def, error);
     320             : 
     321             :     TRACE_FLOW_NUMBER("get_uint32_config_value returning", (uint32_t)val);
     322           1 :     return (uint32_t)val;
     323             : }
     324             : 
     325             : /* Get int64_t value from config item */
     326           1 : int64_t get_int64_config_value(struct collection_item *item,
     327             :                                int strict,
     328             :                                int64_t def,
     329             :                                int *error)
     330             : {
     331           1 :     long long val = 0;
     332             : 
     333             :     TRACE_FLOW_STRING("get_int64_config_value", "Entry");
     334             : 
     335           1 :     val = get_llong_config_value(item, strict, (long long)def, error);
     336             : 
     337             :     TRACE_FLOW_SLNUMBER("get_int64_config_value returning", (int64_t)val);
     338           1 :     return (int64_t)val;
     339             : }
     340             : 
     341             : /* Get uint64_t value from config item */
     342           1 : uint64_t get_uint64_config_value(struct collection_item *item,
     343             :                                  int strict,
     344             :                                  uint64_t def,
     345             :                                  int *error)
     346             : {
     347           1 :     unsigned long long val = 0;
     348             : 
     349             :     TRACE_FLOW_STRING("get_uint64_config_value", "Entry");
     350             : 
     351           1 :     val = get_ullong_config_value(item,
     352             :                                   strict,
     353             :                                   (unsigned long long)def,
     354             :                                   error);
     355             : 
     356             :     TRACE_FLOW_LNUMBER("get_uint64_config_value returning", (uint64_t)val);
     357           1 :     return (uint64_t)val;
     358             : }
     359             : 
     360             : /* Get double value */
     361           1 : double get_double_config_value(struct collection_item *item,
     362             :                                int strict, double def, int *error)
     363             : {
     364             :     const char *str;
     365             :     char *endptr;
     366           1 :     double val = 0;
     367             : 
     368             :     TRACE_FLOW_STRING("get_double_config_value", "Entry");
     369             : 
     370             :     /* Do we have the item ? */
     371           2 :     if ((item == NULL) ||
     372           1 :         (col_get_item_type(item) != COL_TYPE_STRING)) {
     373             :         TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
     374           0 :         if (error) *error = EINVAL;
     375           0 :         return def;
     376             :     }
     377             : 
     378           1 :     if (error) *error = EOK;
     379             : 
     380             :     /* Try to parse the value */
     381           1 :     str = (const char *)col_get_item_data(item);
     382           1 :     errno = 0;
     383           1 :     val = strtod(str, &endptr);
     384             : 
     385             :     /* Check for various possible errors */
     386           1 :     if ((errno == ERANGE) ||
     387           1 :         ((errno != 0) && (val == 0)) ||
     388           1 :         (endptr == str)) {
     389             :         TRACE_ERROR_NUMBER("Conversion failed", EIO);
     390           0 :         if (error) *error = EIO;
     391           0 :         return def;
     392             :     }
     393             : 
     394           1 :     if (strict && (*endptr != '\0')) {
     395             :         TRACE_ERROR_NUMBER("More characters than expected", EIO);
     396           0 :         if (error) *error = EIO;
     397           0 :         val = def;
     398             :     }
     399             : 
     400             :     TRACE_FLOW_DOUBLE("get_double_config_value returning", val);
     401           1 :     return val;
     402             : }
     403             : 
     404             : /* Get boolean value */
     405           2 : unsigned char get_bool_config_value(struct collection_item *item,
     406             :                                     unsigned char def, int *error)
     407             : {
     408             :     const char *str;
     409             :     int len;
     410             : 
     411             :     TRACE_FLOW_STRING("get_bool_config_value", "Entry");
     412             : 
     413             :     /* Do we have the item ? */
     414           4 :     if ((item == NULL) ||
     415           2 :         (col_get_item_type(item) != COL_TYPE_STRING)) {
     416             :         TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
     417           0 :         if (error) *error = EINVAL;
     418           0 :         return def;
     419             :     }
     420             : 
     421           2 :     if (error) *error = EOK;
     422             : 
     423           2 :     str = (const char *)col_get_item_data(item);
     424           2 :     len = col_get_item_length(item);
     425             : 
     426             :     /* Try to parse the value */
     427           4 :     if ((strncasecmp(str, "true", len) == 0) ||
     428           2 :         (strncasecmp(str, "yes", len) == 0)) {
     429             :         TRACE_FLOW_STRING("Returning", "true");
     430             :         return '\1';
     431             :     }
     432           3 :     else if ((strncasecmp(str, "false", len) == 0) ||
     433           1 :              (strncasecmp(str, "no", len) == 0)) {
     434             :         TRACE_FLOW_STRING("Returning", "false");
     435             :         return '\0';
     436             :     }
     437             : 
     438             :     TRACE_ERROR_STRING("Returning", "error");
     439           1 :     if (error) *error = EIO;
     440           1 :     return def;
     441             : }
     442             : 
     443             : /* Return a string out of the value */
     444           1 : char *get_string_config_value(struct collection_item *item,
     445             :                               int *error)
     446             : {
     447           1 :     char *str = NULL;
     448             : 
     449             :     TRACE_FLOW_STRING("get_string_config_value", "Entry");
     450             : 
     451             :     /* Do we have the item ? */
     452           2 :     if ((item == NULL) ||
     453           1 :         (col_get_item_type(item) != COL_TYPE_STRING)) {
     454             :         TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
     455           0 :         if (error) *error = EINVAL;
     456             :         return NULL;
     457             :     }
     458             : 
     459           1 :     str = strdup((const char *)col_get_item_data(item));
     460           1 :     if (str == NULL) {
     461             :         TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM);
     462           0 :         if (error) *error = ENOMEM;
     463             :         return NULL;
     464             :     }
     465             : 
     466           1 :     if (error) *error = EOK;
     467             : 
     468             :     TRACE_FLOW_STRING("get_string_config_value returning", str);
     469           1 :     return str;
     470             : }
     471             : 
     472             : /* Get string from item */
     473           2 : const char *get_const_string_config_value(struct collection_item *item, int *error)
     474             : {
     475             :     const char *str;
     476             : 
     477             :     TRACE_FLOW_STRING("get_const_string_config_value", "Entry");
     478             : 
     479             :     /* Do we have the item ? */
     480           3 :     if ((item == NULL) ||
     481           1 :         (col_get_item_type(item) != COL_TYPE_STRING)) {
     482             :         TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
     483           1 :         if (error) *error = EINVAL;
     484             :         return NULL;
     485             :     }
     486             : 
     487           1 :     str = (const char *)col_get_item_data(item);
     488             : 
     489           1 :     if (error) *error = EOK;
     490             : 
     491             :     TRACE_FLOW_STRING("get_const_string_config_value returning", str);
     492           1 :     return str;
     493             : }
     494             : 
     495             : /* A special hex format is assumed.
     496             :  * The string should be taken in single quotes
     497             :  * and consist of hex encoded value two hex digits per byte.
     498             :  * Example: '0A2BFECC'
     499             :  * Case does not matter.
     500             :  */
     501           1 : char *get_bin_config_value(struct collection_item *item,
     502             :                            int *length, int *error)
     503             : {
     504             :     int i;
     505           1 :     char *value = NULL;
     506             :     const char *buff;
     507           1 :     int size = 0;
     508             :     unsigned char hex;
     509             :     int len;
     510             :     const char *str;
     511             : 
     512             :     TRACE_FLOW_STRING("get_bin_config_value", "Entry");
     513             : 
     514             :     /* Do we have the item ? */
     515           2 :     if ((item == NULL) ||
     516           1 :         (col_get_item_type(item) != COL_TYPE_STRING)) {
     517             :         TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
     518           0 :         if (error) *error = EINVAL;
     519             :         return NULL;
     520             :     }
     521             : 
     522             :     /* Check the length */
     523           1 :     len = col_get_item_length(item)-1;
     524           1 :     if ((len%2) != 0) {
     525             :         TRACE_ERROR_STRING("Invalid length for binary data", "");
     526           0 :         if (error) *error = EINVAL;
     527             :         return NULL;
     528             :     }
     529             : 
     530           1 :     str = (const char *)col_get_item_data(item);
     531             : 
     532             :     /* Is the format correct ? */
     533           2 :     if ((*str != '\'') ||
     534           1 :         (str[len -1] != '\'')) {
     535             :         TRACE_ERROR_STRING("String is not escaped","");
     536           0 :         if (error) *error = EIO;
     537             :         return NULL;
     538             :     }
     539             : 
     540             :     /* Check that all the symbols are ok */
     541           1 :     buff = str + 1;
     542           1 :     len -= 2;
     543           4 :     for (i = 0; i < len; i += 2) {
     544           3 :         if (!isxdigit(buff[i]) || !isxdigit(buff[i + 1])) {
     545             :             TRACE_ERROR_STRING("Invalid encoding for binary data", buff + i);
     546           0 :             if (error) *error = EIO;
     547             :             return NULL;
     548             :         }
     549             :     }
     550             : 
     551             :     /* The value is good so we can allocate memory for it */
     552           1 :     value = malloc(len / 2);
     553           1 :     if (value == NULL) {
     554             :         TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM);
     555           0 :         if (error) *error = ENOMEM;
     556             :         return NULL;
     557             :     }
     558             : 
     559             :     /* Convert the value */
     560           3 :     for (i = 0; i < len; i += 2) {
     561           3 :         if (isdigit(buff[i])) {
     562           3 :             if (isdigit(buff[i+1]))
     563           3 :                 hex = 16 * (buff[i] - '0') + (buff[i+1] - '0');
     564             :             else
     565           0 :                 hex = 16 * (buff[i] - '0') + (tolower(buff[i+1]) - 'a' + 10);
     566             :         }
     567             :         else {
     568           0 :             if (isdigit(buff[i+1]))
     569           0 :                 hex = 16 * (tolower(buff[i]) - 'a') + (buff[i+1] - '0');
     570             :             else
     571           0 :                 hex = 16 * (tolower(buff[i]) - 'a' + 10) + (tolower(buff[i+1]) - 'a' + 10);
     572             :         }
     573             : 
     574           3 :         value[size] = (char)(hex);
     575           3 :         size++;
     576             :     }
     577             : 
     578           1 :     if (error) *error = EOK;
     579           1 :     if (length) *length = size;
     580             :     TRACE_FLOW_STRING("get_bin_config_value", "Exit");
     581           1 :     return value;
     582             : }
     583             : 
     584             : /* Function to free binary configuration value */
     585           1 : void free_bin_config_value(char *value)
     586             : {
     587           1 :     if (value) free(value);
     588           1 : }

Generated by: LCOV version 1.10