summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2010-08-02 21:44:15 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-09-22 14:57:53 -0400
commita54a8e53a97d104490966e36d40e9b0b419ad050 (patch)
tree0bffb1517c4daaa645a917d1938e067a44696322
parentfbaa3ff3a5e45bffea373d0bea4ccd206db37a45 (diff)
downloadding-libs-a54a8e53a97d104490966e36d40e9b0b419ad050.tar.gz
ding-libs-a54a8e53a97d104490966e36d40e9b0b419ad050.tar.xz
ding-libs-a54a8e53a97d104490966e36d40e9b0b419ad050.zip
Introducing configuration file object
The patch contains two major pieces of work: * The beginning of the new INI interface significantly re-thought and reworked. * The implementation of the file object. Parsing was adjusted to use this object.
-rw-r--r--Makefile.am1
-rw-r--r--ini/ini_config_priv.h40
-rw-r--r--ini/ini_configobj.c9
-rw-r--r--ini/ini_configobj.h920
-rw-r--r--ini/ini_defines.h29
-rw-r--r--ini/ini_fileobj.c271
-rw-r--r--ini/ini_parse.c87
-rw-r--r--ini/ini_parse_ut.c43
-rw-r--r--ini/ini_print.c22
-rw-r--r--ini/ini_serialize.c2
10 files changed, 1324 insertions, 100 deletions
diff --git a/Makefile.am b/Makefile.am
index f45e433..bcdfc79 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -231,6 +231,7 @@ libini_config_la_SOURCES = \
ini/ini_valueobj.c \
ini/ini_valueobj.h \
ini/ini_serialize.c \
+ ini/ini_fileobj.c \
ini/ini_configobj.c \
ini/ini_configobj.h \
ini/ini_config_priv.h \
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h
index 9dff6cd..9185e14 100644
--- a/ini/ini_config_priv.h
+++ b/ini/ini_config_priv.h
@@ -25,15 +25,51 @@
#include "collection.h"
/* Configuration object */
-struct configobj {
+struct ini_cfgobj {
/* For now just a collection */
struct collection_item *cfg;
- /* Boundary ? */
+ /* Boundary */
+ uint32_t boundary;
/*... */
/* Statistics? Timestamps? When created? Modified? - TBD */
/*... */
};
+
+/* Configuration file object */
+struct ini_cfgfile {
+ /***********************************/
+ /* Externally controlled variables */
+ /***********************************/
+ /* File name for the configuration file */
+ char *filename;
+ /* File stream */
+ FILE *file;
+ /* File descriptor that is passed in */
+ int fd;
+ /* Error level */
+ int error_level;
+ /* Collision flags - define how to merge things */
+ uint32_t collision_flags;
+ /* Collision flags - define how to merge things */
+ uint32_t metadata_flags;
+ /**********************/
+ /* Internal variables */
+ /**********************/
+ /* Collection of errors detected during parsing */
+ struct collection_item *error_list;
+ /* Metadata about the file */
+ struct collection_item *metadata;
+ /* Count of error lines */
+ unsigned count;
+};
+
+/* Parsing error */
+struct ini_parse_error {
+ unsigned line;
+ int error;
+};
+
/* Internal cleanup callback */
void ini_cleanup_cb(const char *property,
int property_len,
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c
index e75f093..4da9a7c 100644
--- a/ini/ini_configobj.c
+++ b/ini/ini_configobj.c
@@ -57,7 +57,7 @@ void ini_cleanup_cb(const char *property,
}
/* Traverse the collection and clean the object */
-void ini_config_destroy(struct configobj *ini_config)
+void ini_config_destroy(struct ini_cfgobj *ini_config)
{
TRACE_FLOW_ENTRY();
@@ -75,10 +75,10 @@ void ini_config_destroy(struct configobj *ini_config)
}
/* Create a config object */
-int ini_config_create(struct configobj **ini_config)
+int ini_config_create(struct ini_cfgobj **ini_config)
{
int error = EOK;
- struct configobj *new_co = NULL;
+ struct ini_cfgobj *new_co = NULL;
TRACE_FLOW_ENTRY();
@@ -88,7 +88,7 @@ int ini_config_create(struct configobj **ini_config)
}
errno = 0;
- new_co = malloc(sizeof(struct configobj));
+ new_co = malloc(sizeof(struct ini_cfgobj));
if (!new_co) {
error = errno;
TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM);
@@ -96,6 +96,7 @@ int ini_config_create(struct configobj **ini_config)
}
new_co->cfg = NULL;
+ new_co->boundary = INI_WRAP_BOUNDARY;
/* Create a collection to hold configuration data */
error = col_create_collection(&(new_co->cfg),
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h
index 4b1b31f..8ecb148 100644
--- a/ini/ini_configobj.h
+++ b/ini/ini_configobj.h
@@ -22,33 +22,933 @@
#ifndef INI_CONFIGOBJ_H
#define INI_CONFIGOBJ_H
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
#include <stdio.h>
#include "simplebuffer.h"
+/**
+ * @defgroup errorlevel Error tolerance constants
+ *
+ * Constants in this section define what to do if
+ * error or warning encountered while parsing the INI file.
+ *
+ * @{
+ */
+/** @brief Fail if any problem is detected. */
+#define INI_STOP_ON_ANY 0
+/** @brief Best effort - do not fail. */
+#define INI_STOP_ON_NONE 1
+/** @brief Fail on errors only. */
+#define INI_STOP_ON_ERROR 2
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup parseerr Parsing errors and warnings
+ *
+ * @{
+ */
+/** @brief Line is too long (Error). */
+#define ERR_LONGDATA 1
+/** @brief No closing bracket in section definition (Error). */
+#define ERR_NOCLOSESEC 2
+/** @brief Section name is missing (Error). */
+#define ERR_NOSECTION 3
+/** @brief Section name too long (Error). */
+#define ERR_SECTIONLONG 4
+/** @brief No equal sign (Error). */
+#define ERR_NOEQUAL 5
+/** @brief No key before equal sign (Error). */
+#define ERR_NOKEY 6
+/** @brief Key is too long (Error). */
+#define ERR_LONGKEY 7
+/** @brief Failed to read line (Error). */
+#define ERR_READ 8
+/** @brief Line starts with space when it should not (Error). */
+#define ERR_SPACE 9
+
+/** @brief Size of the error array. */
+#define ERR_MAXPARSE ERR_SPACE
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup structures Structures
+ * @{
+ */
+
+
+struct ini_cfgobj;
+struct ini_cfgfile;
+
+/** @brief Structure that holds error number and
+ * line number for the encountered error.
+ */
+struct ini_parse_error;
+
+
+/**
+ * @}
+ */
+
+
/********************************************************************/
/* THIS IS A BEGINNING OF THE THE NEW CONFIG OBJECT INTERFACE - TBD */
/* It will be moved to the ini_config.h when it is ready */
/********************************************************************/
-struct configobj;
/* Create a configuration object */
-int ini_config_create(struct configobj **ini_config);
+int ini_config_create(struct ini_cfgobj **ini_config);
/* Destroy a configuration object */
-void ini_config_destroy(struct configobj *ini_config);
+void ini_config_destroy(struct ini_cfgobj *ini_config);
+
+/* Create a file object for parsing a config file */
+int ini_config_file_open(const char *filename,
+ int error_level,
+ uint32_t collision_flags,
+ uint32_t metadata_flags,
+ struct ini_cfgfile **file_ctx);
+
+/* Close file context and destroy the object */
+void ini_config_file_close(struct ini_cfgfile *file_ctx);
+
+/* How many errors do we have in the list ? */
+unsigned ini_config_error_count(struct ini_cfgfile *file_ctx);
+
+/* Get the list of error strings */
+int ini_config_get_errors(struct ini_cfgfile *file_ctx,
+ char ***errors);
+
+/* Get the fully resolved file name */
+const char *ini_config_get_filename(struct ini_cfgfile *file_ctx);
+
+/* Free error strings */
+void ini_config_free_errors(char **errors);
+
+/* Parse the file and create a config object */
+int ini_config_parse(struct ini_cfgfile *file_ctx,
+ struct ini_cfgobj *ini_config);
+
+/* Function to print errors from the list */
+void ini_print_errors(FILE *file, char **error_list);
+
+
+/* TBD rename the function */
+/** @brief Function to return a parsing error as a string.
+ *
+ * @param[in] parsing_error Error code for the parsing error.
+ *
+ * @return Error string.
+ */
+const char *parsing_error_str(int parsing_error);
+
+
+/* Merge two configurations together creating a new one */
+int ini_config_merge(struct ini_cfgobj *first,
+ struct ini_cfgobj *second,
+ uint32_t collision_flags,
+ struct ini_cfgobj **result);
+
+/* Set the folding boundary for multiline values.
+ * Use before serializing and saving to a file if the
+ * default boundary of 80 characters does not work for you.
+ */
+int ini_config_set_wrap(struct ini_cfgobj *ini_config,
+ uint32_t boundary);
/* Serialize configuration object into provided buffer */
-int ini_config_serialize(struct configobj *ini_config,
+int ini_config_serialize(struct ini_cfgobj *ini_config,
struct simplebuffer *sbobj);
-int ini_config_parse(FILE *file,
- const char *config_filename,
- struct configobj *ini_config,
- int error_level,
- struct collection_item **error_list,
- uint32_t boundary);
+/* Check access */
+int ini_config_access_check(struct ini_cfgfile *file_ctx,
+ uint32_t flags,
+ uid_t uid,
+ gid_t gid,
+ mode_t mode,
+ mode_t mask);
+
+/* Determins if two file context different by comparing
+ * - time stamp
+ * - device ID
+ * - i-node
+ */
+int ini_config_changed(struct ini_cfgfile *file_ctx,
+ struct ini_cfgfile *file_ctx_saved,
+ int *changed);
+
+
+/****************************************************/
+/* VALUE MANAGEMENT */
+/****************************************************/
+
+/**
+ * @brief Get list of sections.
+ *
+ * Get list of sections from the configuration object
+ * as an array of strings.
+ * Function allocates memory for the array of the sections.
+ * Use \ref free_section_list() to free allocated memory.
+ *
+ * @param[in] ini_config Configuration object.
+ * @param[out] size If not NULL parameter will
+ * receive number of sections
+ * in the configuration.
+ * @param[out] error If not NULL parameter will
+ * receive the error code.
+ * 0 - Success.
+ * EINVAL - Invalid parameter.
+ * ENOMEM - No memory.
+ *
+ * @return Array of strings.
+ */
+char **get_section_list(struct ini_cfgobj *ini_config,
+ int *size,
+ int *error);
+
+/**
+ * @brief Free list of sections.
+ *
+ * The section array created by \ref get_section_list()
+ * should be freed using this function.
+ *
+ * @param[in] section_list Array of strings returned by
+ * \ref get_section_list() function.
+ */
+void free_section_list(char **section_list);
+
+/**
+ * @brief Get list of attributes.
+ *
+ * Get list of attributes in a section as an array of strings.
+ * Function allocates memory for the array of attributes.
+ * Use \ref free_attribute_list() to free allocated memory.
+ *
+ * @param[in] ini_config Configuration object.
+ * @param[in] section Section name.
+ * @param[out] size If not NULL parameter will
+ * receive number of attributes
+ * in the section.
+ * @param[out] error If not NULL parameter will
+ * receive the error code.
+ * 0 - Success.
+ * EINVAL - Invalid parameter.
+ * ENOMEM - No memory.
+ *
+ * @return Array of strings.
+ */
+char **get_attribute_list(struct ini_cfgobj *ini_config,
+ const char *section,
+ int *size,
+ int *error);
+
+/**
+ * @brief Free list of attributes.
+ *
+ * The attribute array created by \ref get_attribute_list()
+ * should be freed using this function.
+ *
+ * @param[in] attr_list Array of strings returned by
+ * \ref get_attribute_list() function.
+ */
+void free_attribute_list(char **attr_list);
+/**
+ * @brief Get an integer value from the configuration.
+ *
+ * Function looks up the section and key in
+ * in the configuration object and tries to convert
+ * into an integer number.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ * If "strict" parameter is non zero the function will fail
+ * if there are more characters after the last digit.
+ * The value range is from INT_MIN to INT_MAX.
+ *
+ * @param[in] ini_config Configuration object.
+ * @param[in] section Section of the configuration file.
+ * @param[in] name Key to look up inside the section.
+ * @param[in] strict Fail the function if
+ * the symbol after last digit
+ * is not valid.
+ * @param[in] def Default value to use if
+ * conversion failed.
+ * @param[out] value Fetched value or default
+ *
+ * In case of failure the function assignes default value
+ * to the resulting value and returns corresponging error code.
+ *
+ * @return 0 - Success.
+ * @return EINVAL - Argument is invalid.
+ * @return EIO - Conversion failed due invalid characters.
+ * @return ERANGE - Value is out of range.
+ * @return ENOKEY - Value is not found.
+ * @return ENOMEM - No memory.
+ */
+int get_int_config_value(struct ini_cfgobj *ini_config,
+ const char *section,
+ const char *name,
+ int strict,
+ int def,
+ int *value);
+
+/* Similar functions are below */
+int get_long_config_value(struct ini_cfgobj *ini_config,
+ const char *section,
+ const char *name,
+ int strict,
+ long def,
+ long *value);
+
+int get_unsigned_config_value(struct ini_cfgobj *ini_config,
+ const char *section,
+ const char *name,
+ int strict,
+ unsigned def,
+ unsigned *value);
+
+int get_ulong_config_value(struct ini_cfgobj *ini_config,
+ const char *section,
+ const char *name,
+ int strict,
+ unsigned long def,
+ unsigned long *value);
+
+
+
+
+
+
+
+#ifdef THE_PART_I_HAVE_PROCESSED
+
+
+
+
+
+
+/**
+ * @brief Convert item value to integer number.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an int32_t number. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ * If "strict" parameter is non zero the function will fail
+ * if there are more characters after the last digit.
+ * The value range is from INT_MIN to INT_MAX.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] strict Fail the function if
+ * the symbol after last digit
+ * is not valid.
+ * @param[in] def Default value to use if
+ * conversion failed.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed due
+ * invalid characters.
+ * - ERANGE - Value is out of range.
+ *
+ * @return Converted value.
+ * In case of failure the function returns default value and
+ * sets error code into the provided variable.
+ */
+int32_t get_int32_config_value(struct collection_item *item,
+ int strict,
+ int32_t def,
+ int *error);
+
+/**
+ * @brief Convert item value to integer number.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an uint32_t number. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ * If "strict" parameter is non zero the function will fail
+ * if there are more characters after the last digit.
+ * The value range is from 0 to ULONG_MAX.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] strict Fail the function if
+ * the symbol after last digit
+ * is not valid.
+ * @param[in] def Default value to use if
+ * conversion failed.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed due
+ * invalid characters.
+ * - ERANGE - Value is out of range.
+ *
+ * @return Converted value.
+ * In case of failure the function returns default value and
+ * sets error code into the provided variable.
+ */
+uint32_t get_uint32_config_value(struct collection_item *item,
+ int strict,
+ uint32_t def,
+ int *error);
+
+/**
+ * @brief Convert item value to integer number.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an int64_t number. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ * If "strict" parameter is non zero the function will fail
+ * if there are more characters after the last digit.
+ * The value range is from LLONG_MIN to LLONG_MAX.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] strict Fail the function if
+ * the symbol after last digit
+ * is not valid.
+ * @param[in] def Default value to use if
+ * conversion failed.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed due
+ * invalid characters.
+ * - ERANGE - Value is out of range.
+ *
+ * @return Converted value.
+ * In case of failure the function returns default value and
+ * sets error code into the provided variable.
+ */
+int64_t get_int64_config_value(struct collection_item *item,
+ int strict,
+ int64_t def,
+ int *error);
+
+/**
+ * @brief Convert item value to integer number.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an uint64_t number. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ * If "strict" parameter is non zero the function will fail
+ * if there are more characters after the last digit.
+ * The value range is from 0 to ULLONG_MAX.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] strict Fail the function if
+ * the symbol after last digit
+ * is not valid.
+ * @param[in] def Default value to use if
+ * conversion failed.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed due
+ * invalid characters.
+ * - ERANGE - Value is out of range.
+ *
+ * @return Converted value.
+ * In case of failure the function returns default value and
+ * sets error code into the provided variable.
+ */
+uint64_t get_uint64_config_value(struct collection_item *item,
+ int strict,
+ uint64_t def,
+ int *error);
+
+/**
+ * @brief Convert item value to floating point number.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into a floating point number. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ * If "strict" parameter is non zero the function will fail
+ * if there are more characters after the last digit.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] strict Fail the function if
+ * the symbol after last digit
+ * is not valid.
+ * @param[in] def Default value to use if
+ * conversion failed.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed due
+ * invalid characters.
+ *
+ * @return Converted value.
+ * In case of failure the function returns default value and
+ * sets error code into the provided variable.
+ */
+double get_double_config_value(struct collection_item *item,
+ int strict,
+ double def,
+ int *error);
+
+/**
+ * @brief Convert item value into a logical value.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into a Boolean. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] def Default value to use if
+ * conversion failed.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed due
+ * invalid characters.
+ *
+ * @return Converted value.
+ * In case of failure the function returns default value and
+ * sets error code into the provided variable.
+ */
+unsigned char get_bool_config_value(struct collection_item *item,
+ unsigned char def,
+ int *error);
+
+/**
+ * @brief Get string configuration value
+ *
+ * Function creates a copy of the string value stored in the item.
+ * Returned value needs to be freed after use.
+ * If error occurred the returned value will be NULL.
+ *
+ * @param[in] item Item to use.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - ENOMEM - No memory.
+ *
+ * @return Copy of the string or NULL.
+ */
+char *get_string_config_value(struct collection_item *item,
+ int *error);
+/**
+ * @brief Function returns the string stored in the item.
+ *
+ * Function returns a reference to the string value
+ * stored inside the item. This string can't be altered.
+ * The string will go out of scope if the item is deleted.
+ *
+ * @param[in] item Item to use.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ *
+ * @return String from the item.
+ */
+const char *get_const_string_config_value(struct collection_item *item,
+ int *error);
+
+/**
+ * @brief Convert item value into a binary sequence.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into a sequence of bytes.
+ * Any of the conversion functions
+ * can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ *
+ * The function allocates memory.
+ * It is the responsibility of the caller to free it after use.
+ * Use \ref free_bin_config_value() for this purpose.
+ * Functions will return NULL if conversion failed.
+ *
+ * Function assumes that the value being interpreted
+ * has a special format.
+ * The string should be taken in single quotes
+ * and consist of hex encoded value represented by
+ * two hex digits per byte.
+ * Case does not matter.
+ *
+ * Example: '0a2BFeCc'
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[out] length Variable that optionally receives
+ * the length of the binary
+ * sequence.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed due
+ * invalid characters.
+ * - ENOMEM - No memory.
+ *
+ * @return Converted value.
+ * In case of failure the function returns NULL.
+ */
+char *get_bin_config_value(struct collection_item *item,
+ int *length,
+ int *error);
+
+/**
+ * @brief Free binary buffer
+ *
+ * Free binary value returned by \ref get_bin_config_value().
+ *
+ * @param[in] bin Binary buffer to free.
+ *
+ */
+void free_bin_config_value(char *bin);
+
+/**
+ * @brief Convert value to an array of strings.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an array of strings. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ *
+ * Separator string includes up to three different separators.
+ * If separator NULL, comma is assumed.
+ * The spaces are trimmed automatically around separators
+ * in the string.
+ * The function drops empty tokens from the list.
+ * This means that the string like this: "apple, ,banana, ,orange ,"
+ * will be translated into the list of three items:
+ * "apple","banana" and "orange".
+ *
+ * The length of the allocated array is returned in "size".
+ * Size and error parameters can be NULL.
+ * Use \ref free_string_config_array() to free the array after use.
+ *
+ * The array is always NULL terminated so
+ * it is safe not to get size and just loop until
+ * array element is NULL.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] sep String cosisting of separator
+ * symbols. For example: ",.;" would mean
+ * that comma, dot and semicolon
+ * should be treated as separators
+ * in the value.
+ * @param[out] size Variable that optionally receives
+ * the size of the array.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed.
+ * - ENOMEM - No memory.
+ *
+ * @return Array of strings.
+ * In case of failure the function returns NULL.
+ */
+char **get_string_config_array(struct collection_item *item,
+ const char *sep,
+ int *size,
+ int *error);
+
+/**
+ * @brief Convert value to an array of strings.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an array of strings. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ *
+ * Separator string includes up to three different separators.
+ * If separator NULL, comma is assumed.
+ * The spaces are trimmed automatically around separators
+ * in the string.
+ * The function does not drop empty tokens from the list.
+ * This means that the string like this: "apple, ,banana, ,orange ,"
+ * will be translated into the list of five items:
+ * "apple", "", "banana", "" and "orange".
+ *
+ * The length of the allocated array is returned in "size".
+ * Size and error parameters can be NULL.
+ * Use \ref free_string_config_array() to free the array after use.
+ *
+ * The array is always NULL terminated so
+ * it is safe not to get size and just loop until
+ * array element is NULL.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[in] sep String cosisting of separator
+ * symbols. For example: ",.;" would mean
+ * that comma, dot and semicolon
+ * should be treated as separators
+ * in the value.
+ * @param[out] size Variable that optionally receives
+ * the size of the array.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed.
+ * - ENOMEM - No memory.
+ *
+ * @return Array of strings.
+ * In case of failure the function returns NULL.
+ */
+char **get_raw_string_config_array(struct collection_item *item,
+ const char *sep,
+ int *size,
+ int *error);
+
+/**
+ * @brief Convert value to an array of long values.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an array of long values. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ *
+ * Separators inside the string are detected automatically.
+ * The spaces are trimmed automatically around separators
+ * in the string.
+ *
+ * The length of the allocated array is returned in "size".
+ * Size parameter can't be NULL.
+ *
+ * Use \ref free_long_config_array() to free the array after use.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[out] size Variable that receives
+ * the size of the array.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed.
+ * - ERANGE - Value is out of range.
+ * - ENOMEM - No memory.
+ *
+ * @return Array of long values.
+ * In case of failure the function returns NULL.
+ */
+long *get_long_config_array(struct collection_item *item,
+ int *size,
+ int *error);
+
+/**
+ * @brief Convert value to an array of floating point values.
+ *
+ * This is a conversion function.
+ * It converts the value read from the INI file
+ * and stored in the configuration item
+ * into an array of floating point values. Any of the conversion
+ * functions can be used to try to convert the value
+ * stored as a string inside the item.
+ * The results can be different depending upon
+ * how the caller tries to interpret the value.
+ *
+ * Separators inside the string are detected automatically.
+ * The spaces are trimmed automatically around separators
+ * in the string.
+ *
+ * The length of the allocated array is returned in "size".
+ * Size parameter can't be NULL.
+ *
+ * Use \ref free_double_config_array() to free the array after use.
+ *
+ * @param[in] item Item to interpret.
+ * It must be retrieved using
+ * \ref get_config_item().
+ * @param[out] size Variable that receives
+ * the size of the array.
+ * @param[out] error Variable will get the value
+ * of the error code if
+ * error happened.
+ * Can be NULL. In this case
+ * function does not set
+ * the code.
+ * Codes:
+ * - 0 - Success.
+ * - EINVAL - Argument is invalid.
+ * - EIO - Conversion failed.
+ * - ENOMEM - No memory.
+ *
+ * @return Array of floating point values.
+ * In case of failure the function returns NULL.
+ */
+double *get_double_config_array(struct collection_item *item,
+ int *size,
+ int *error);
+
+/**
+ * @brief Free array of string values.
+ *
+ * Use this function to free the array returned by
+ * \ref get_string_config_array() or by
+ * \ref get_raw_string_config_array().
+ *
+ * @param[in] str_config Array of string values.
+ */
+void free_string_config_array(char **str_config);
+
+/**
+ * @brief Free array of long values.
+ *
+ * Use this function to free the array returned by
+ * \ref get_long_config_array().
+ *
+ * @param[in] array Array of long values.
+ */
+void free_long_config_array(long *array);
+/**
+ * @brief Free array of floating pointer values.
+ *
+ * Use this function to free the array returned by
+ * \ref get_double_config_array().
+ *
+ * @param[in] array Array of floating pointer values.
+ */
+void free_double_config_array(double *array);
+
+#endif
#endif
diff --git a/ini/ini_defines.h b/ini/ini_defines.h
index efa9c98..bead998 100644
--- a/ini/ini_defines.h
+++ b/ini/ini_defines.h
@@ -46,8 +46,8 @@
#define FAILED_TO_PROC_V _("Internal Error. Failed to process list of validation errors.\n")
#define ERROR_HEADER_V _("Validation errors and warnings in file: %s\n")
-#define LINE_FORMAT _("%s (%d) on line %d: %s\n")
-
+#define LINE_FORMAT _("%s (%d) on line %d: %s")
+#define MAX_ERROR_LINE 120
/* Codes that parsing function can return */
#define RET_PAIR 0
@@ -59,6 +59,7 @@
#define RET_ERROR 6
#define INI_ERROR "errors"
+#define INI_METADATA "meta"
#define INI_ERROR_NAME "errname"
#define INI_CONFIG_NAME "INI"
@@ -73,10 +74,26 @@
#define CONVERSION_BUFFER 80
/* Size of the block for a value */
-#define INI_VALUE_BLOCK 100
-
-/* This constant belongs here. Move from ini_config - TBD */
-/* #define COL_CLASS_INI_BASE 20000 */
+#define INI_VALUE_BLOCK 100
+
+/* Default boundary */
+#define INI_WRAP_BOUNDARY 80
+
+/* This constant belongs here. */
+#define COL_CLASS_INI_BASE 20000
+/**
+ * @brief A one level collection of parse errors.
+ *
+ * Collection stores \ref parse_error structures.
+ */
+#define COL_CLASS_INI_PERROR COL_CLASS_INI_BASE + 2
+
+/**
+ * @brief Collection of metadata.
+ *
+ * Collection that stores metadata.
+ */
+#define COL_CLASS_INI_META COL_CLASS_INI_BASE + 4
/* Different error string functions can be passed as callbacks */
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c
new file mode 100644
index 0000000..117608c
--- /dev/null
+++ b/ini/ini_fileobj.c
@@ -0,0 +1,271 @@
+/*
+ INI LIBRARY
+
+ File context related functions
+
+ Copyright (C) Dmitri Pal <dpal@redhat.com> 2010
+
+ INI Library is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ INI Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with INI Library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "config.h"
+#include "trace.h"
+#include "ini_defines.h"
+#include "ini_configobj.h"
+#include "ini_config_priv.h"
+#include "collection.h"
+#include "path_utils.h"
+#include "collection_tools.h"
+
+
+/* Close file context and destroy the object */
+void ini_config_file_close(struct ini_cfgfile *file_ctx)
+{
+ TRACE_FLOW_ENTRY();
+
+ if(file_ctx) {
+ free(file_ctx->filename);
+ col_destroy_collection(file_ctx->error_list);
+ col_destroy_collection(file_ctx->metadata);
+ fclose(file_ctx->file);
+ free(file_ctx);
+ }
+
+ TRACE_FLOW_EXIT();
+}
+
+/* Create a file object for parsing a config file */
+int ini_config_file_open(const char *filename,
+ int error_level,
+ uint32_t collision_flags,
+ uint32_t metadata_flags,
+ struct ini_cfgfile **file_ctx)
+{
+ int error = EOK;
+ struct ini_cfgfile *new_ctx = NULL;
+
+ TRACE_FLOW_ENTRY();
+
+ if ((!filename) || (!file_ctx)) {
+ TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
+ return EINVAL;
+ }
+
+ /* Allocate structure */
+ errno = 0;
+ new_ctx = malloc(sizeof(struct ini_cfgfile));
+ if (!new_ctx) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Failed to allocate file ctx.", error);
+ return error;
+ }
+
+ /* Construct the full file path */
+ errno = 0;
+ new_ctx->filename = malloc(PATH_MAX + 1);
+ if (!(new_ctx->filename)) {
+ error = errno;
+ ini_config_file_close(new_ctx);
+ TRACE_ERROR_NUMBER("Failed to allocate memory for file path.", error);
+ return error;
+ }
+
+ /* Construct path */
+ error = make_normalized_absolute_path(new_ctx->filename,
+ PATH_MAX,
+ filename);
+ if(error) {
+ TRACE_ERROR_NUMBER("Failed to resolve path", error);
+ ini_config_file_close(new_ctx);
+ return error;
+ }
+
+ /* Open file */
+ TRACE_INFO_STRING("File", new_ctx->filename);
+ errno = 0;
+ new_ctx->file = NULL;
+ new_ctx->file = fopen(new_ctx->filename, "r");
+ if (!(new_ctx->file)) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Failed to open file", error);
+ ini_config_file_close(new_ctx);
+ return error;
+ }
+
+ /* Store flags */
+ new_ctx->error_level = error_level;
+ new_ctx->collision_flags = collision_flags;
+ new_ctx->metadata_flags = metadata_flags;
+ new_ctx->count = 0;
+
+ /* Create internal collections */
+ error = col_create_collection(&(new_ctx->error_list),
+ INI_ERROR,
+ COL_CLASS_INI_PERROR);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create error list", error);
+ ini_config_file_close(new_ctx);
+ return error;
+ }
+
+ error = col_create_collection(&(new_ctx->metadata),
+ INI_METADATA,
+ COL_CLASS_INI_META);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
+ ini_config_file_close(new_ctx);
+ return error;
+ }
+
+ *file_ctx = new_ctx;
+ TRACE_FLOW_EXIT();
+ return error;
+}
+
+
+/* How many errors do we have in the list ? */
+unsigned ini_config_error_count(struct ini_cfgfile *file_ctx)
+{
+ unsigned count = 0;
+
+ TRACE_FLOW_ENTRY();
+
+ count = file_ctx->count;
+
+ TRACE_FLOW_EXIT();
+ return count;
+
+}
+
+/* Free error strings */
+void ini_config_free_errors(char **errors)
+{
+ TRACE_FLOW_ENTRY();
+
+ col_free_property_list(errors);
+
+ TRACE_FLOW_EXIT();
+}
+
+/* Get the list of error strings */
+int ini_config_get_errors(struct ini_cfgfile *file_ctx,
+ char ***errors)
+{
+ char **errlist = NULL;
+ struct collection_iterator *iterator = NULL;
+ int error;
+ struct collection_item *item = NULL;
+ struct ini_parse_error *pe;
+ unsigned int count = 0;
+ char *line;
+
+ TRACE_FLOW_ENTRY();
+
+ /* If we have something to print print it */
+ if ((!errors) || (!file_ctx)) {
+ TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
+ return EINVAL;
+ }
+
+
+ errno = 0;
+ errlist = calloc(file_ctx->count + 1, sizeof(char *));
+ if (!errlist) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Failed to allocate memory for errors.", error);
+ return error;
+ }
+
+ /* Bind iterator */
+ error = col_bind_iterator(&iterator,
+ file_ctx->error_list,
+ COL_TRAVERSE_DEFAULT);
+ if (error) {
+ TRACE_ERROR_NUMBER("Faile to bind iterator:", error);
+ ini_config_free_errors(errlist);
+ return error;
+ }
+
+ while(1) {
+ /* Loop through a collection */
+ error = col_iterate_collection(iterator, &item);
+ if (error) {
+ TRACE_ERROR_NUMBER("Error iterating collection", error);
+ col_unbind_iterator(iterator);
+ ini_config_free_errors(errlist);
+ return error;
+ }
+
+ /* Are we done ? */
+ if (item == NULL) break;
+
+ /* Process collection header */
+ if (col_get_item_type(item) == COL_TYPE_COLLECTION) {
+ continue;
+ }
+ else {
+ /* Put error into provided format */
+ pe = (struct ini_parse_error *)(col_get_item_data(item));
+
+ /* Would be nice to have asprintf function...
+ * ...but for now we know that all the errors
+ * are pretty short and will fir into the predefined
+ * error length buffer.
+ */
+ errno = 0;
+ line = malloc(MAX_ERROR_LINE + 1);
+ if (!line) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Failed to get memory for error.", error);
+ col_unbind_iterator(iterator);
+ ini_config_free_errors(errlist);
+ return error;
+ }
+
+ snprintf(line, MAX_ERROR_LINE, LINE_FORMAT,
+ col_get_item_property(item, NULL),
+ pe->error,
+ pe->line,
+ parsing_error_str(pe->error));
+
+ errlist[count] = line;
+ count++;
+ }
+
+ }
+
+ /* Do not forget to unbind iterator - otherwise there will be a leak */
+ col_unbind_iterator(iterator);
+
+ *errors = errlist;
+
+ TRACE_FLOW_EXIT();
+ return error;
+}
+
+/* Get the fully resolved file name */
+const char *ini_config_get_filename(struct ini_cfgfile *file_ctx)
+{
+ const char *ret;
+ TRACE_FLOW_ENTRY();
+
+ ret = file_ctx->filename;
+
+ TRACE_FLOW_EXIT();
+ return ret;
+}
diff --git a/ini/ini_parse.c b/ini/ini_parse.c
index 843acf2..253b78b 100644
--- a/ini/ini_parse.c
+++ b/ini/ini_parse.c
@@ -42,7 +42,6 @@ struct parser_obj {
FILE *file;
struct collection_item *top;
struct collection_item *el;
- struct collection_item **el_acceptor;
const char *filename;
int error_level;
/* Wrapping boundary */
@@ -109,7 +108,7 @@ int parser_create(FILE *file,
const char *config_filename,
struct collection_item *ini_config,
int error_level,
- struct collection_item **error_list,
+ struct collection_item *error_list,
uint32_t boundary,
struct parser_obj **po)
{
@@ -144,7 +143,7 @@ int parser_create(FILE *file,
/* Save external data */
new_po->file = file;
new_po->top = ini_config;
- new_po->el_acceptor = error_list;
+ new_po->el = error_list;
new_po->filename = config_filename;
new_po->error_level = error_level;
new_po->boundary = boundary;
@@ -161,7 +160,6 @@ int parser_create(FILE *file,
new_po->raw_lines = NULL;
new_po->raw_lengths = NULL;
new_po->ret = EOK;
- new_po->el = NULL;
/* Create a queue */
new_po->queue = NULL;
@@ -827,46 +825,20 @@ static int parser_error(struct parser_obj *po)
uint32_t action;
int idx = 0;
const char *errtxt[] = { ERROR_TXT, WARNING_TXT };
- struct parse_error pe;
+ struct ini_parse_error pe;
TRACE_FLOW_ENTRY();
- /* Create collection for errors */
- if ((po->el_acceptor) && (!(po->el))) {
- error = col_create_collection(&(po->el), INI_ERROR, COL_CLASS_INI_PERROR);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to create error collection", error);
- return error;
- }
- }
-
- /* Try to add to the error list only if it is present */
- if (po->el) {
-
- /* If this is the first error add file name as the first item */
- if (po->ret == EOK) {
- error = col_add_str_property(po->el,
- NULL,
- INI_ERROR_NAME,
- po->filename,
- 0);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to and name to collection", error);
- return error;
- }
- }
-
- pe.line = po->linenum;
- /* Clear the warning bit */
- pe.error = po->last_error & ~INI_WARNING;
- if (po->last_error & INI_WARNING) idx = 1;
- error = col_add_binary_property(po->el, NULL,
- errtxt[idx], &pe, sizeof(pe));
- if (error) {
- TRACE_ERROR_NUMBER("Failed to add error to collection",
- error);
- return error;
- }
+ pe.line = po->linenum;
+ /* Clear the warning bit */
+ pe.error = po->last_error & ~INI_WARNING;
+ if (po->last_error & INI_WARNING) idx = 1;
+ error = col_add_binary_property(po->el, NULL,
+ errtxt[idx], &pe, sizeof(pe));
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to add error to collection",
+ error);
+ return error;
}
/* Exit if there was an error parsing file */
@@ -963,10 +935,6 @@ int parser_run(struct parser_obj *po)
if (action == PARSE_DONE) {
TRACE_INFO_NUMBER("We are done", error);
error = po->ret;
- if ((po->el_acceptor) && (po->el)) {
- *(po->el_acceptor) = po->el;
- po->el = NULL;
- }
break;
}
@@ -983,12 +951,8 @@ int parser_run(struct parser_obj *po)
}
/* Top level wrapper around the parser */
-int ini_config_parse(FILE *file,
- const char *config_filename,
- struct configobj *ini_config,
- int error_level,
- struct collection_item **error_list,
- uint32_t boundary)
+int ini_config_parse(struct ini_cfgfile *file_ctx,
+ struct ini_cfgobj *ini_config)
{
int error = EOK;
struct parser_obj *po;
@@ -1000,12 +964,12 @@ int ini_config_parse(FILE *file,
return EINVAL;
}
- error = parser_create(file,
- config_filename,
+ error = parser_create(file_ctx->file,
+ file_ctx->filename,
ini_config->cfg,
- error_level,
- error_list,
- boundary,
+ file_ctx->error_level,
+ file_ctx->error_list,
+ ini_config->boundary,
&po);
if (error) {
TRACE_ERROR_NUMBER("Failed to perform an action", error);
@@ -1013,11 +977,18 @@ int ini_config_parse(FILE *file,
}
error = parser_run(po);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to parse file", error);
+ col_get_collection_count(file_ctx->error_list, &(file_ctx->count));
+ if(file_ctx->count) (file_ctx->count)--;
+ parser_destroy(po);
+ return error;
+ }
parser_destroy(po);
- TRACE_INFO_NUMBER("Parsing returned:", error);
+
+ TRACE_INFO_NUMBER("Count returned:", error);
TRACE_FLOW_EXIT();
return error;
-
}
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c
index 963579b..f55b3c2 100644
--- a/ini/ini_parse_ut.c
+++ b/ini/ini_parse_ut.c
@@ -24,7 +24,6 @@
#include <errno.h>
#include <stdlib.h>
#include "ini_defines.h"
-#include "ini_config.h"
#include "ini_configobj.h"
#include "simplebuffer.h"
#include "path_utils.h"
@@ -45,10 +44,11 @@ typedef int (*test_fn)(void);
int test_one_file(const char *filename)
{
int error = EOK;
+ struct ini_cfgfile *file_ctx = NULL;
FILE *ff = NULL;
char new_file[100];
- struct configobj *ini_config = NULL;
- struct collection_item *error_list = NULL;
+ struct ini_cfgobj *ini_config = NULL;
+ char **error_list = NULL;
struct simplebuffer *sbobj = NULL;
uint32_t left = 0;
char filename_base[96];
@@ -57,33 +57,38 @@ int test_one_file(const char *filename)
/* Create config collection */
error = ini_config_create(&ini_config);
- if (error != EOK) {
+ if (error) {
printf("Failed to create collection. Error %d.\n", error);
return error;
}
- errno = 0;
- ff = fopen(filename,"r");
- if(!ff) {
- error = errno;
+ error = ini_config_file_open(filename,
+ INI_STOP_ON_NONE,
+ 0, /* TBD */
+ 0, /* TBD */
+ &file_ctx);
+ if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
ini_config_destroy(ini_config);
return error;
}
- error = ini_config_parse(ff,
- filename,
- ini_config,
- INI_STOP_ON_NONE,
- &error_list,
- 80);
- fclose(ff);
- if (error != EOK) {
+ error = ini_config_parse(file_ctx,
+ ini_config);
+ if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n", error));
- INIOUT(print_file_parsing_errors(stdout, error_list));
- col_destroy_collection(error_list);
+
+ if (ini_config_error_count(file_ctx)) {
+ INIOUT(printf("Errors detected while parsing: %s\n",
+ ini_config_get_filename(file_ctx)));
+ ini_config_get_errors(file_ctx, &error_list);
+ INIOUT(ini_print_errors(stdout, error_list));
+ }
+ /* We do not return here intentionally */
}
+ ini_config_file_close(file_ctx);
+
error = simplebuffer_alloc(&sbobj);
if (error) {
TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
@@ -93,7 +98,7 @@ int test_one_file(const char *filename)
error = ini_config_serialize(ini_config, sbobj);
if (error != EOK) {
- printf("Failed to parse configuration. Error %d.\n", error);
+ printf("Failed to serialize configuration. Error %d.\n", error);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
return error;
diff --git a/ini/ini_print.c b/ini/ini_print.c
index 60771d3..f12b27e 100644
--- a/ini/ini_print.c
+++ b/ini/ini_print.c
@@ -388,3 +388,25 @@ void print_config_parsing_errors(FILE *file,
TRACE_FLOW_STRING("print_config_parsing_errors", "Exit");
}
+
+
+/* Function to print errors from the list */
+void ini_print_errors(FILE *file, char **error_list)
+{
+ unsigned count = 0;
+
+ TRACE_FLOW_ENTRY();
+
+ if (!error_list) {
+ TRACE_FLOW_STRING("List is empty.", "");
+ return;
+ }
+
+ while (error_list[count]) {
+ fprintf(file, "%s\n", error_list[count]);
+ count++;
+ }
+
+ TRACE_FLOW_EXIT();
+ return;
+}
diff --git a/ini/ini_serialize.c b/ini/ini_serialize.c
index 9738be9..177979a 100644
--- a/ini/ini_serialize.c
+++ b/ini/ini_serialize.c
@@ -63,7 +63,7 @@ static int ini_serialize_cb(const char *property,
}
/* Traverse the collection and build the serialization object */
-int ini_config_serialize(struct configobj *ini_config,
+int ini_config_serialize(struct ini_cfgobj *ini_config,
struct simplebuffer *sbobj)
{
int error = EOK;