From 329651039032f044b4e1e13d0fc338e4d174b980 Mon Sep 17 00:00:00 2001 From: Dmitri Pal Date: Wed, 8 Apr 2009 17:27:44 -0400 Subject: INI component: Fixed issues introduced by cleanup. Added a few new functions. Cleaned code that was subject to conditional build. Fixed the floating point conversion. Keep const values as const. --- common/collection/collection.c | 7 +- common/collection/collection.h | 4 +- common/ini/ini.d/real.conf | 5 +- common/ini/ini_config.c | 227 ++++++++++++++++++++++++++++++----------- common/ini/ini_config.h | 20 ++-- common/ini/ini_config_ut.c | 47 +++++++-- 6 files changed, 228 insertions(+), 82 deletions(-) (limited to 'common') diff --git a/common/collection/collection.c b/common/collection/collection.c index f63a48f52..e2816e638 100644 --- a/common/collection/collection.c +++ b/common/collection/collection.c @@ -576,7 +576,7 @@ static int walk_items(struct collection_item *ci, void *custom_data) { struct collection_item *current; - struct collection_item *parent; + struct collection_item *parent = NULL; struct collection_item *sub; int stop = 0; int error = EOK; @@ -2550,7 +2550,7 @@ inline int is_of_class(struct collection_item *item, unsigned cclass) } /* Get propery */ -inline char *get_item_property(struct collection_item *ci,int *property_len) +inline const char *get_item_property(struct collection_item *ci,int *property_len) { if (property_len != NULL) *property_len = ci->property_len; return ci->property; @@ -2569,7 +2569,7 @@ inline int get_item_length(struct collection_item *ci) } /* Get data */ -void *get_item_data(struct collection_item *ci) +inline const void *get_item_data(struct collection_item *ci) { return ci->data; } @@ -2656,4 +2656,3 @@ int set_timestamp(struct collection_item *ci, TRACE_FLOW_STRING("set_timestamp", "Exit point"); return EOK; } - diff --git a/common/collection/collection.h b/common/collection/collection.h index 9ccf159ea..687f468d7 100644 --- a/common/collection/collection.h +++ b/common/collection/collection.h @@ -390,10 +390,10 @@ int get_item(struct collection_item *ci, /* Collection to find things in * /* Group of functions that allows retrieving individual elements of the collection_item * hiding the internal implementation. */ -char *get_item_property(struct collection_item *ci,int *property_len); +const char *get_item_property(struct collection_item *ci,int *property_len); int get_item_type(struct collection_item *ci); int get_item_length(struct collection_item *ci); -void *get_item_data(struct collection_item *ci); +const void *get_item_data(struct collection_item *ci); /* If you want to modify the item that you got as a result of iterating through collection * or by calling get_item(). If you want to rename item provide a new name in the property diff --git a/common/ini/ini.d/real.conf b/common/ini/ini.d/real.conf index f026bd896..41f91c79e 100644 --- a/common/ini/ini.d/real.conf +++ b/common/ini/ini.d/real.conf @@ -31,7 +31,7 @@ description = InfoPipe Configuration command = ./sbin/sssd_info [domains] -domainsOrder = LOCAL, EXAMPLE.COM , SOMEOTHER.COM +domainsOrder = , LOCAL, , EXAMPLE.COM, , SOMEOTHER.COM , , [domains/LOCAL] description = Reserved domain for local configurations @@ -46,7 +46,8 @@ server = ipabackupserver.example.com legacy = FALSE enumerate = 0 binary_test = '010203' -long_array = 1, 2; 4' ;8p .16/ 32? +long_array = 1 2; 4' ;8p .16/ 32? +double_array = 1.1 2.222222; .4' . ;8p .16/ -32? diff --git a/common/ini/ini_config.c b/common/ini/ini_config.c index c3e83fb39..b4b4b25fd 100644 --- a/common/ini/ini_config.c +++ b/common/ini/ini_config.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "config.h" /* For error text */ #include @@ -61,9 +62,6 @@ #define RET_EOF 5 #define RET_ERROR 6 -/* STATIC INTERNAL FUNCTIONS */ -#ifdef HAVE_PARSE_ERROR - /* Function to return parsing error */ inline const char *parsing_error_str(int parsing_error) @@ -85,16 +83,6 @@ inline const char *parsing_error_str(int parsing_error) return str_error[parsing_error-1]; } -#else - - -inline const char *parsing_error_str(int parsing_error) -{ - const char *placeholder= _("Parsing errors are not compiled."); - return placeholder; -} - -#endif int read_line(FILE *file,char **key,char **value, int *length, int *ext_error); @@ -623,7 +611,7 @@ int read_line(FILE *file, char **key,char **value, int *length, int *ext_error) if (eq == NULL) { TRACE_ERROR_STRING("No equal sign", buf); *ext_error = ERR_NOEQUAL; - return RET_BEST_EFFORT; + return RET_INVALID; } len -= eq-buffer; @@ -634,14 +622,14 @@ int read_line(FILE *file, char **key,char **value, int *length, int *ext_error) if (i < 0) { TRACE_ERROR_STRING("No key", buf); *ext_error = ERR_NOKEY; - return RET_BEST_EFFORT; + return RET_INVALID; } /* Copy key into provided buffer */ if(i >= MAX_KEY) { TRACE_ERROR_STRING("Section name is too long", buf); *ext_error = ERR_LONGKEY; - return RET_BEST_EFFORT; + return RET_INVALID; } *key = buffer; buffer[i + 1] = '\0'; @@ -865,7 +853,8 @@ int get_config_item(const char *section, long get_long_config_value(struct collection_item *item, int strict, long def, int *error) { - char *endptr, *str; + const char *str; + char *endptr; long val = 0; TRACE_FLOW_STRING("get_long_config_value", "Entry"); @@ -881,7 +870,7 @@ long get_long_config_value(struct collection_item *item, if (error) *error = EOK; /* Try to parse the value */ - str = (char *)get_item_data(item); + str = (const char *)get_item_data(item); errno = 0; val = strtol(str, &endptr, 10); @@ -931,7 +920,8 @@ unsigned long get_ulong_config_value(struct collection_item *item, double get_double_config_value(struct collection_item *item, int strict, double def, int *error) { - char *endptr, *str; + const char *str; + char *endptr; double val = 0; TRACE_FLOW_STRING("get_double_config_value", "Entry"); @@ -947,7 +937,7 @@ double get_double_config_value(struct collection_item *item, if (error) *error = EOK; /* Try to parse the value */ - str = (char *)get_item_data(item); + str = (const char *)get_item_data(item); errno = 0; val = strtod(str, &endptr); @@ -974,7 +964,7 @@ double get_double_config_value(struct collection_item *item, unsigned char get_bool_config_value(struct collection_item *item, unsigned char def, int *error) { - char *str; + const char *str; int len; TRACE_FLOW_STRING("get_bool_config_value", "Entry"); @@ -989,7 +979,7 @@ unsigned char get_bool_config_value(struct collection_item *item, if (error) *error = EOK; - str = (char *)get_item_data(item); + str = (const char *)get_item_data(item); len = get_item_length(item); /* Try to parse the value */ @@ -1011,7 +1001,7 @@ unsigned char get_bool_config_value(struct collection_item *item, /* Return a string out of the value */ char *get_string_config_value(struct collection_item *item, - int dup, int *error) + int *error) { char *str = NULL; @@ -1025,21 +1015,40 @@ char *get_string_config_value(struct collection_item *item, return NULL; } - /* If we are told to dup the value */ - if (dup) { - errno = 0; - str = strdup((char *)get_item_data(item)); - if (str == NULL) { - TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); - if (error) *error = ENOMEM; - return NULL; - } + errno = 0; + str = strdup((const char *)get_item_data(item)); + if (str == NULL) { + TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); + if (error) *error = ENOMEM; + return NULL; + } + + if (error) *error = EOK; + + TRACE_FLOW_STRING("get_string_config_value returning", str); + return str; +} + +/* Get string from item */ +const char *get_const_string_config_value(struct collection_item *item, int *error) +{ + const char *str; + + TRACE_FLOW_STRING("get_const_string_config_value", "Entry"); + + /* Do we have the item ? */ + if ((item == NULL) || + (get_item_type(item) != COL_TYPE_STRING)) { + TRACE_ERROR_NUMBER("Invalid argument.", EINVAL); + if (error) *error = EINVAL; + return NULL; } - else str = (char *)get_item_data(item); + + str = (const char *)get_item_data(item); if (error) *error = EOK; - TRACE_FLOW_STRING("get_string_config_value", "Exit"); + TRACE_FLOW_STRING("get_const_string_config_value returning", str); return str; } @@ -1054,11 +1063,11 @@ char *get_bin_config_value(struct collection_item *item, { int i; char *value = NULL; - char *buff; + const char *buff; int size = 0; unsigned char hex; int len; - char *str; + const char *str; TRACE_FLOW_STRING("get_bin_config_value", "Entry"); @@ -1078,7 +1087,7 @@ char *get_bin_config_value(struct collection_item *item, return NULL; } - str = (char *)get_item_data(item); + str = (const char *)get_item_data(item); /* Is the format correct ? */ if ((*str != '\'') || @@ -1154,6 +1163,7 @@ char **get_string_config_array(struct collection_item *item, char *start; int i, j, k; int growlen = 0; + int dlen; TRACE_FLOW_STRING("get_string_config_array", "Entry"); @@ -1181,7 +1191,8 @@ char **get_string_config_array(struct collection_item *item, dest = copy; buff = item->data; start = buff; - for(i = 0; i < item->length; i++) { + dlen = item->length - 1; + for(i = 0; i < dlen; i++) { growlen = 1; for(j = 0; j < lensep; j++) { if(buff[i] == sep[j]) { @@ -1199,20 +1210,34 @@ char **get_string_config_array(struct collection_item *item, *dest = '\0'; dest++; len = 0; - /* Move forward and trim spaces if any */ - start += resume_len + 1; - i++; + } + /* Move forward and trim spaces if any */ + start += resume_len + 1; + i++; + TRACE_INFO_STRING("Other pointer :", buff + i); + k = 0; + while(1) { TRACE_INFO_STRING("Remaining buffer :", start); - TRACE_INFO_STRING("Other pointer :", buff + i); - k = 0; - while (((i + k) < item->length) && (isspace(*start))) { + while (((i + k) < dlen) && (isspace(*start))) { k++; start++; } - TRACE_INFO_STRING("Remaining buffer after triming spaces:", start); - if (k) i += k - 1; - /* Next iteration of the loop will add 1 */ + /* May be we have another separator */ + TRACE_INFO_STRING("Remaining before sep check :", start); + if(*start && strchr(sep, *start)) { + TRACE_INFO_NUMBER("Found separator:", *start); + start++; + k++; + } + else { + break; + } } + + TRACE_INFO_STRING("Remaining buffer after triming spaces:", start); + + if (k) i += k - 1; + /* Next iteration of the loop will add 1 */ /* Break out of the inner loop */ growlen = 0; break; @@ -1221,12 +1246,16 @@ char **get_string_config_array(struct collection_item *item, if (growlen) len++; } - /* Copy the remaining piece */ - memcpy(dest, start, len); - count++; - dest += len; - dest = '\0'; - dest++; + TRACE_INFO_STRING("Last part :", start); + TRACE_INFO_NUMBER("Length :", len); + if(len) { + /* Copy the remaining piece */ + memcpy(dest, start, len); + count++; + dest += len; + dest = '\0'; + dest++; + } /* Now we know how many items are there in the list */ array = malloc((count + 1) * sizeof(char *)); @@ -1240,8 +1269,11 @@ char **get_string_config_array(struct collection_item *item, /* Loop again to fill in the pointers */ start = copy; for (i = 0; i < count; i++) { + TRACE_INFO_STRING("Token :", start); + TRACE_INFO_NUMBER("Item :", i); array[i] = start; - while (start) start++; + /* Move to next item */ + while(*start) start++; start++; } array[count] = NULL; @@ -1268,7 +1300,8 @@ void free_string_config_array(char **str_config) /* Get an array of long values */ long *get_long_config_array(struct collection_item *item, int *size, int *error) { - char *endptr, *str; + const char *str; + char *endptr; long val = 0; long *array; int count = 0; @@ -1293,8 +1326,8 @@ long *get_long_config_array(struct collection_item *item, int *size, int *error) } /* Now parse the string */ - str = (char *)get_item_data(item); - while (str) { + str = (const char *)get_item_data(item); + while (*str) { errno = 0; val = strtol(str, &endptr, 10); if (((errno == ERANGE) && @@ -1314,7 +1347,7 @@ long *get_long_config_array(struct collection_item *item, int *size, int *error) if (*endptr == 0) break; /* Advance to the next valid number */ for (str = endptr; *str; str++) { - if (isdigit(*str) || (*str != '-') || (*str != '+')) break; + if (isdigit(*str) || (*str == '-') || (*str == '+')) break; } } @@ -1326,9 +1359,87 @@ long *get_long_config_array(struct collection_item *item, int *size, int *error) } +/* Get an array of double values */ +double *get_double_config_array(struct collection_item *item, int *size, int *error) +{ + const char *str; + char *endptr; + double val = 0; + double *array; + int count = 0; + struct lconv *loc; + + TRACE_FLOW_STRING("get_double_config_array", "Entry"); + + /* Do we have the item ? */ + if ((item == NULL) || + (get_item_type(item) != COL_TYPE_STRING) || + (size == NULL)) { + TRACE_ERROR_NUMBER("Invalid argument.", EINVAL); + if (error) *error = EINVAL; + return NULL; + } + + /* Assume that we have maximum number of different numbers */ + array = (double *)malloc(sizeof(double) * get_item_length(item)/2); + if (array == NULL) { + TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); + if (error) *error = ENOMEM; + return NULL; + } + + /* Get locale information so that we can check for decimal point character. + * Based on the man pages it is unclear if this is an allocated memory or not. + * Seems like it is a static thread or process local structure so + * I will not try to free it after use. + */ + loc = localeconv(); + + /* Now parse the string */ + str = (const char *)get_item_data(item); + while (*str) { + errno = 0; + TRACE_INFO_STRING("String to convert",str); + val = strtod(str, &endptr); + if ((errno == ERANGE) || + ((errno != 0) && (val == 0)) || + (endptr == str)) { + TRACE_ERROR_NUMBER("Conversion failed", EIO); + free(array); + if (error) *error = EIO; + return NULL; + } + /* Save value */ + array[count] = val; + count++; + /* Are we done? */ + if (*endptr == 0) break; + TRACE_INFO_STRING("End pointer after conversion",endptr); + /* Advance to the next valid number */ + for (str = endptr; *str; str++) { + if (isdigit(*str) || (*str == '-') || (*str == '+') || + /* It is ok to do this since the string is null terminated */ + ((*str == *(loc->decimal_point)) && isdigit(str[1]))) break; + } + } + + *size = count; + if (error) *error = EOK; + + TRACE_FLOW_NUMBER("get_double_config_value returning", val); + return array; + +} + + /* Special function to free long config array */ inline void free_long_config_array(long *array) { if (array != NULL) free(array); } +/* Special function to free double config array */ +inline void free_double_config_array(double *array) +{ + if (array != NULL) free(array); +} diff --git a/common/ini/ini_config.h b/common/ini/ini_config.h index 21b912b92..2a9aa52a8 100644 --- a/common/ini/ini_config.h +++ b/common/ini/ini_config.h @@ -54,11 +54,6 @@ #define ERR_MAXPARSE ERR_LONGKEY -#ifdef HAVE_INI_BEST_EFFORT /* Ignore bad lines in the INI files */ -#define RET_BEST_EFFORT RET_INVALID -#else -#define RET_BEST_EFFORT RET_ERROR -#endif /* Internal sizes */ /* FIXME - make them configurable via config.h */ @@ -79,7 +74,7 @@ int config_from_file(const char *application, /* Name of the appli const char *config_file, /* Name of the config file - if NULL the collection will be empty */ struct collection_item **ini_config, /* If *ini_config is NULL a new ini object will be allocated, */ /* otherwise the one that is pointed to will be updated. */ - int error_level, /* Error level - break for erros, warnings or best effort (don't break) */ + int error_level, /* Error level - break for errors, warnings or best effort (don't break) */ struct collection_item **error_list); /* List of errors for a file */ @@ -125,10 +120,10 @@ unsigned long get_ulong_config_value(struct collection_item *item, int strict, u double get_double_config_value(struct collection_item *item, int strict, double def, int *error); unsigned char get_bool_config_value(struct collection_item *item, unsigned char def, int *error); -/* Function get_string_config_value returns pointer to the string out of item. - * If 'dup' is not 0 it makes a copyof the string otherwise it does not. - */ -char *get_string_config_value(struct collection_item *item, int dup, int *error); +/* Function get_string_config_value returns a newly allocated pointer to the string out of item.*/ +char *get_string_config_value(struct collection_item *item, int *error); +/* Function returns the string stored in the item */ +const char *get_const_string_config_value(struct collection_item *item, int *error); /* A get_bin_value and get_xxx_array functions allocate memory. * It is the responsibility of the caller to free it after use. @@ -151,10 +146,15 @@ char **get_string_config_array(struct collection_item *item, char *sep, int *siz /* Array of long values - separators are detected automatically. */ /* The length of the allocated array is returned in "size" */ long *get_long_config_array(struct collection_item *item, int *size, int *error); +/* Array of double values - separators are detected automatically. */ +/* The length of the allocated array is returned in "size" */ +double *get_double_config_array(struct collection_item *item, int *size, int *error); /* Special function to free string config array */ void free_string_config_array(char **str_config); /* Special function to free long config array */ void free_long_config_array(long *array); +/* Special function to free double config array */ +void free_double_config_array(double *array); #endif diff --git a/common/ini/ini_config_ut.c b/common/ini/ini_config_ut.c index 642f268b3..4968a0ac2 100644 --- a/common/ini/ini_config_ut.c +++ b/common/ini/ini_config_ut.c @@ -217,6 +217,8 @@ int get_test() unsigned long number_ulong; unsigned char logical; char *str; + const char *cstr; + const char *cstrn; void *binary; int length; int i; @@ -224,6 +226,7 @@ int get_test() char **strptr; int size; long *array; + double *darray; printf("\n\n===== GET TEST START ======\n"); printf("Reading collection\n"); @@ -298,9 +301,8 @@ int get_test() /* Get a string without duplicication */ /* Negative test */ - error = 0; - str = get_string_config_value(NULL, 0, &error); - if(!error) { + cstrn = get_const_string_config_value(NULL, NULL); + if(cstrn != NULL) { printf("Expected error got success.\n"); destroy_collection(ini_config); return -1; @@ -310,21 +312,21 @@ int get_test() /* Now get string from the right item */ error = 0; - str = get_string_config_value(item, 0, &error); + cstr = get_const_string_config_value(item, &error); if(error) { printf("Expected success got error %d.\n",error); destroy_collection(ini_config); return error; } - printf("Value: [%s]\n",str); + printf("Value: [%s]\n",cstr); /* Same thing but create a dup */ printf("Get item as string with duplication from correct item.\n"); error = 0; - str = get_string_config_value(item, 1, &error); + str = get_string_config_value(item, &error); if(error) { printf("Expected success got error %d.\n",error); destroy_collection(ini_config); @@ -677,6 +679,39 @@ int get_test() free_long_config_array(array); + printf("Get double array item\n"); + + item = (struct collection_item *)(NULL); + error = get_config_item("domains/EXAMPLE.COM","double_array", ini_config, &item); + if(error) { + printf("Expected success but got error! %d\n",error); + destroy_collection(ini_config); + return error; + } + + /* Item should be found */ + if(item == (struct collection_item *)(NULL)) { + printf("Expected success but got NULL.\n"); + destroy_collection(ini_config); + return -1; + } + + debug_item(item); + + error = 0; + size = 0; /* Here size is not optional!!! */ + darray = get_double_config_array(item, &size, &error); + if(error) { + printf("Expect success got error %d.\n",error); + destroy_collection(ini_config); + return error; + } + + /* Can be used with this cycle */ + for(i=0;i