summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ini/Makefile.am7
-rw-r--r--ini/configure.ac2
-rw-r--r--ini/ini_config.c534
-rw-r--r--ini/ini_config.h390
-rw-r--r--ini/ini_config_ut.c113
-rw-r--r--ini/ini_metadata.c104
-rw-r--r--ini/ini_metadata.h42
7 files changed, 915 insertions, 277 deletions
diff --git a/ini/Makefile.am b/ini/Makefile.am
index af81a9f..7620526 100644
--- a/ini/Makefile.am
+++ b/ini/Makefile.am
@@ -33,12 +33,15 @@ dist_include_HEADERS = \
# Build library
lib_LTLIBRARIES = libini_config.la
libini_config_la_SOURCES = \
- ini_config.c
+ ini_config.c \
+ ini_metadata.c \
+ ini_metadata.h
+
libini_config_la_LIBADD = \
-L$(topbuilddir)/collection \
-lcollection
libini_config_la_LDFLAGS = \
- -version-info 1:0:0
+ -version-info 2:0:0
# Build unit test
check_PROGRAMS = ini_config_ut
diff --git a/ini/configure.ac b/ini/configure.ac
index a8c751f..aa2033c 100644
--- a/ini/configure.ac
+++ b/ini/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([ini_config],[0.4.0],[sssd-devel@lists.fedorahosted.org])
+AC_INIT([ini_config],[0.5.0],[sssd-devel@lists.fedorahosted.org])
AC_CONFIG_SRCDIR([ini_config.c])
AC_CONFIG_AUX_DIR([build])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
diff --git a/ini/ini_config.c b/ini/ini_config.c
index e87419a..9015590 100644
--- a/ini/ini_config.c
+++ b/ini/ini_config.c
@@ -28,6 +28,7 @@
#include <stdlib.h>
#include <locale.h>
#include <fcntl.h>
+#include <unistd.h>
#include "config.h"
/* For error text */
#include <libintl.h>
@@ -37,6 +38,7 @@
#include "collection_tools.h"
#include "trace.h"
#include "ini_config.h"
+#include "ini_metadata.h"
#define NAME_OVERHEAD 10
@@ -79,20 +81,40 @@
#define INI_ERROR "errors"
#define INI_ERROR_NAME "errname"
-
/* Internal sizes. MAX_KEY is defined in config.h */
#define MAX_VALUE PATH_MAX
#define BUFFER_SIZE MAX_KEY + MAX_VALUE + 3
-/* Internally used functions */
-static int config_with_lines(const char *application,
- FILE *config_file,
- const char *config_source,
- struct collection_item **ini_config,
- int error_level,
- struct collection_item **error_list,
- struct collection_item **lines);
+/*============================================================*/
+/* The following classes moved here from the public header
+ * They are reserved for future use.
+ *
+ * NOTE: before exposing these constants again in the common header
+ * check that the class IDs did not get reused over time by
+ * other classes.
+ */
+/** @brief Collection of grammar errors.
+ *
+ * Reserved for future use.
+ */
+#define COL_CLASS_INI_GERROR COL_CLASS_INI_BASE + 5
+/** @brief Collection of validation errors.
+ *
+ * Reserved for future use.
+ */
+#define COL_CLASS_INI_VERROR COL_CLASS_INI_BASE + 6
+
+#ifdef HAVE_VALIDATION
+
+/** @brief Collection of lines from the INI file.
+ *
+ * Reserved for future use
+ */
+#define COL_CLASS_INI_LINES COL_CLASS_INI_BASE + 7
+
+#endif /* HAVE_VALIDATION */
+/*============================================================*/
/* Different error string functions can be passed as callbacks */
@@ -122,7 +144,23 @@ const char *parsing_error_str(int parsing_error)
* This function is currently not used.
* It is planned to be used by the INI
* file grammar parser.
+ *
+ * The following doxygen description is moved here.
+ * When the function gets exposed move it into
+ * the header file.
*/
+/** @brief Function to return a grammar error in template.
+ *
+ * EXPERIMENTAL. Reserved for future use.
+ *
+ * This error is returned when the template
+ * is translated into the grammar object.
+ *
+ * @param[in] parsing_error Error code for the grammar error.
+ *
+ * @return Error string.
+ */
+
const char *grammar_error_str(int grammar_error)
{
const char *placeholder= _("Unknown grammar error.");
@@ -147,6 +185,22 @@ const char *grammar_error_str(int grammar_error)
* This function is currently not used.
* It is planned to be used by the INI
* file grammar validator.
+ *
+ * The following doxygen description is moved here.
+ * When the function gets exposed move it into
+ * the header file.
+ */
+/** @brief Function to return a validation error.
+ *
+ * EXPERIMENTAL. Reserved for future use.
+ *
+ * This is the error that it is returned when
+ * the INI file is validated against the
+ * grammar object.
+ *
+ * @param[in] parsing_error Error code for the validation error.
+ *
+ * @return Error string.
*/
const char *validation_error_str(int validation_error)
{
@@ -186,7 +240,7 @@ static int ini_to_collection(FILE *file,
struct collection_item *ini_config,
int error_level,
struct collection_item **error_list,
- struct collection_item **lines)
+ struct collection_item *lines)
{
int error;
int status;
@@ -204,25 +258,18 @@ static int ini_to_collection(FILE *file,
TRACE_FLOW_STRING("ini_to_collection", "Entry");
- if (file == NULL) {
- TRACE_ERROR_NUMBER("No file handle", EINVAL);
- return EINVAL;
- }
-
/* Open the collection of errors */
if (error_list != NULL) {
*error_list = NULL;
error = col_create_collection(error_list, INI_ERROR, COL_CLASS_INI_PERROR);
if (error) {
TRACE_ERROR_NUMBER("Failed to create error collection", error);
- fclose(file);
return error;
}
/* Add file name as the first item */
error = col_add_str_property(*error_list, NULL, INI_ERROR_NAME, config_filename, 0);
if (error) {
TRACE_ERROR_NUMBER("Failed to and name to collection", error);
- fclose(file);
col_destroy_collection(*error_list);
return error;
}
@@ -239,16 +286,18 @@ static int ini_to_collection(FILE *file,
switch (status) {
case RET_PAIR:
+
+#ifdef HAVE_VALIDATION
+
/* Add line to the collection of lines.
* It is pretty safe in this case to just type cast the value to
* int32_t since it is unrealistic that ini file will ever have
* so many lines.
*/
if (lines) {
- error = col_add_int_property(*lines, NULL, key, (int32_t)line);
+ error = col_add_int_property(lines, NULL, key, (int32_t)line);
if (error) {
TRACE_ERROR_NUMBER("Failed to add line to line collection", error);
- fclose(file);
col_destroy_collection(current_section);
if (created) {
col_destroy_collection(*error_list);
@@ -258,6 +307,8 @@ static int ini_to_collection(FILE *file,
}
}
+#endif /* HAVE_VALIDATION */
+
/* Do we have a section at the top of the file ? */
if (section_count == 0) {
/* Check if collection already exists */
@@ -273,7 +324,6 @@ static int ini_to_collection(FILE *file,
current_section,
COL_ADD_MODE_REFERENCE))) {
TRACE_ERROR_NUMBER("Failed to create collection", error);
- fclose(file);
col_destroy_collection(current_section);
if (created) {
col_destroy_collection(*error_list);
@@ -297,7 +347,6 @@ static int ini_to_collection(FILE *file,
length);
if (error != EOK) {
TRACE_ERROR_NUMBER("Failed to add pair to collection", error);
- fclose(file);
col_destroy_collection(current_section);
if (created) {
col_destroy_collection(*error_list);
@@ -308,6 +357,9 @@ static int ini_to_collection(FILE *file,
break;
case RET_SECTION:
+
+#ifdef HAVE_VALIDATION
+
/* Add line to the collection of lines */
if (lines) {
/* For easier search make line numbers for the sections negative.
@@ -316,10 +368,9 @@ static int ini_to_collection(FILE *file,
* int32_t since it is unrealistic that ini file will ever have
* so many lines.
*/
- error = col_add_int_property(*lines, NULL, key, (int32_t)(-1 * line));
+ error = col_add_int_property(lines, NULL, key, (int32_t)(-1 * line));
if (error) {
TRACE_ERROR_NUMBER("Failed to add line to line collection", error);
- fclose(file);
col_destroy_collection(current_section);
if (created) {
col_destroy_collection(*error_list);
@@ -329,6 +380,8 @@ static int ini_to_collection(FILE *file,
}
}
+#endif /* HAVE_VALIDATION */
+
/* Read a new section */
col_destroy_collection(current_section);
current_section = NULL;
@@ -343,7 +396,6 @@ static int ini_to_collection(FILE *file,
current_section,
COL_ADD_MODE_REFERENCE))) {
TRACE_ERROR_NUMBER("Failed to add collection", error);
- fclose(file);
col_destroy_collection(current_section);
if (created) {
col_destroy_collection(*error_list);
@@ -370,7 +422,6 @@ static int ini_to_collection(FILE *file,
ERROR_TXT, &pe, sizeof(pe));
if (error) {
TRACE_ERROR_NUMBER("Failed to add error to collection", error);
- fclose(file);
col_destroy_collection(current_section);
if (created) {
col_destroy_collection(*error_list);
@@ -382,7 +433,6 @@ static int ini_to_collection(FILE *file,
if (error_level != INI_STOP_ON_NONE) {
TRACE_ERROR_STRING("Invalid format of the file", "");
col_destroy_collection(current_section);
- fclose(file);
return EIO;
}
break;
@@ -395,7 +445,6 @@ static int ini_to_collection(FILE *file,
WARNING_TXT, &pe, sizeof(pe));
if (error) {
TRACE_ERROR_NUMBER("Failed to add warning to collection", error);
- fclose(file);
col_destroy_collection(current_section);
if (created) {
col_destroy_collection(*error_list);
@@ -407,7 +456,6 @@ static int ini_to_collection(FILE *file,
if (error_level == INI_STOP_ON_ANY) {
TRACE_ERROR_STRING("Invalid format of the file", "");
if (created) col_destroy_collection(current_section);
- fclose(file);
return EIO;
}
TRACE_ERROR_STRING("Invalid string", "");
@@ -416,8 +464,11 @@ static int ini_to_collection(FILE *file,
ext_err = -1;
}
- /* Close file */
- fclose(file);
+ /* Note: File is not closed on this level any more.
+ * It opened on the level above, checked and closed there.
+ * It is not the responsibility of this function to close
+ * file any more.
+ */
COL_DEBUG_COLLECTION(ini_config);
@@ -447,7 +498,23 @@ void free_ini_config_errors(struct collection_item *error_set)
TRACE_FLOW_STRING("free_ini_config_errors", "Exit");
}
-/* Function to free configuration lines list */
+#ifdef HAVE_VALIDATION
+
+/* Function to free configuration lines list.
+ *
+ * The following doxygen description is moved here.
+ * When the function gets exposed move it into
+ * the header file.
+ */
+/**
+ * @brief Function to free lines object.
+ *
+ * EXPERIMENTAL. Reserved for future use.
+ *
+ * @param[in] lines Lines object.
+ *
+ */
+
void free_ini_config_lines(struct collection_item *lines)
{
TRACE_FLOW_STRING("free_ini_config_lines", "Entry");
@@ -455,6 +522,8 @@ void free_ini_config_lines(struct collection_item *lines)
TRACE_FLOW_STRING("free_ini_config_lines", "Exit");
}
+#endif /* HAVE_VALIDATION */
+
/* Read configuration information from a file */
int config_from_file(const char *application,
@@ -466,12 +535,13 @@ int config_from_file(const char *application,
int error;
TRACE_FLOW_STRING("config_from_file", "Entry");
- error = config_from_file_with_lines(application,
- config_filename,
- ini_config,
- error_level,
- error_list,
- NULL);
+ error = config_from_file_with_metadata(application,
+ config_filename,
+ ini_config,
+ error_level,
+ error_list,
+ 0,
+ NULL);
TRACE_FLOW_NUMBER("config_from_file. Returns", error);
return error;
}
@@ -487,97 +557,43 @@ int config_from_fd(const char *application,
int error;
TRACE_FLOW_STRING("config_from_fd", "Entry");
- error = config_from_fd_with_lines(application, fd, config_source,
- ini_config, error_level,
- error_list, NULL);
+ error = config_from_fd_with_metadata(application,
+ fd,
+ config_source,
+ ini_config,
+ error_level,
+ error_list,
+ 0,
+ NULL);
TRACE_FLOW_NUMBER("config_from_fd. Returns", error);
return error;
}
-/* Function to read the ini file and have a collection
- * of which item appers on which line
- */
-int config_from_file_with_lines(const char *application,
- const char *config_filename,
- struct collection_item **ini_config,
- int error_level,
- struct collection_item **error_list,
- struct collection_item **lines)
-{
- int error = EOK;
- FILE *config_file = NULL;
- TRACE_FLOW_STRING("config_from_file_with_lines", "Entry");
-
- config_file = fopen(config_filename, "r");
- if(!config_file) {
- error = errno;
- TRACE_ERROR_NUMBER("Failed to open file", error);
- return error;
- }
-
- error = config_with_lines(application, config_file,
- config_filename, ini_config,
- error_level, error_list,
- lines);
- TRACE_FLOW_NUMBER("config_from_file_with_lines. Returns", error);
- return error;
-}
-
-/* Function to read the ini file and have a collection
- * of which item appers on which line
- */
-int config_from_fd_with_lines(const char *application,
- int fd,
- const char *config_source,
- struct collection_item **ini_config,
- int error_level,
- struct collection_item **error_list,
- struct collection_item **lines)
-{
- int error = EOK;
- FILE *config_file;
-
- TRACE_FLOW_STRING("config_from_fd_with_lines", "Entry");
-
- config_file = fdopen(fd, "r");
- if (!config_file) {
- error = errno;
- TRACE_ERROR_NUMBER("Failed to dup file", error);
- return error;
- }
-
- error = config_with_lines(application, config_file,
- config_source, ini_config,
- error_level, error_list,
- lines);
- TRACE_FLOW_NUMBER("config_from_fd_with_lines. Returns", error);
-
- return error;
-}
/* Low level function that prepares the collection
* and calls parser.
*/
-static int config_with_lines(const char *application,
- FILE *config_file,
- const char *config_source,
- struct collection_item **ini_config,
- int error_level,
- struct collection_item **error_list,
- struct collection_item **lines)
+static int config_with_metadata(const char *application,
+ FILE *config_file,
+ const char *config_source,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_list,
+ uint32_t metaflags,
+ struct collection_item *metadata)
{
int error;
int created = 0;
+ struct collection_item *lines = NULL;
+
+#ifdef HAVE_VALIDATION
int created_lines = 0;
+#endif
TRACE_FLOW_STRING("config_from_file", "Entry");
- if ((ini_config == NULL) ||
- (application == NULL)) {
- TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
- return EINVAL;
- }
+ /* Now we check arguments in the calling functions. */
/* Create collection if needed */
if (*ini_config == NULL) {
@@ -591,40 +607,32 @@ static int config_with_lines(const char *application,
created = 1;
}
/* Is the collection of the right class? */
- else if (col_is_of_class(*ini_config, COL_CLASS_INI_CONFIG)) {
+ else if (((col_is_of_class(*ini_config, COL_CLASS_INI_CONFIG))== 0) &&
+ ((col_is_of_class(*ini_config, COL_CLASS_INI_META))== 0)) {
TRACE_ERROR_NUMBER("Wrong collection type", EINVAL);
return EINVAL;
}
-
- /* Create collection if needed */
- if (lines) {
-
- /* Make sure that the lines collection is empty */
- if (*lines) {
- TRACE_ERROR_NUMBER("Collection of lines is not empty", EINVAL);
- if (created) {
- col_destroy_collection(*ini_config);
- *ini_config = NULL;
- }
- return EINVAL;
- }
-
- error = col_create_collection(lines,
- application,
- COL_CLASS_INI_LINES);
- if (error != EOK) {
- TRACE_ERROR_NUMBER("Failed to create collection", error);
- if (created) {
- col_destroy_collection(*ini_config);
- *ini_config = NULL;
- }
- return error;
+#ifdef HAVE_VALIDATION
+ /* This code is preserved for future use */
+ error = col_create_collection(lines,
+ application,
+ COL_CLASS_INI_LINES);
+ if (error != EOK) {
+ TRACE_ERROR_NUMBER("Failed to create collection", error);
+ if (created) {
+ col_destroy_collection(*ini_config);
+ *ini_config = NULL;
}
- created_lines = 1;
+ return error;
}
+ created_lines = 1;
+#else
+ /* Until we implement validation do not read the lines. */
+ lines = NULL;
+#endif /* HAVE_VALIDATION */
- /* Do the actual work */
+ /* Do the actual work - for now do not read lines.*/
error = ini_to_collection(config_file, config_source,
*ini_config, error_level,
error_list, lines);
@@ -633,57 +641,146 @@ static int config_with_lines(const char *application,
col_destroy_collection(*ini_config);
*ini_config = NULL;
}
- /* Also create collection of lines if we created it */
- if (error && created_lines) {
- col_destroy_collection(*lines);
- *lines = NULL;
- }
+
+ /* FIXME - put lines collection into the metadata */
TRACE_FLOW_NUMBER("config_from_file. Returns", error);
return error;
}
-/* Special wrapper around the inernal parser
- * to open the file first.
- * Used in conf_for_app function.
+/* Function to read the ini file from fd
+ * with meta data.
*/
-static int ini_to_col_from_file(const char *config_filename,
- struct collection_item *ini_config,
- int error_level,
- struct collection_item **error_list,
- struct collection_item **lines)
+int config_from_fd_with_metadata(const char *application,
+ int ext_fd,
+ const char *config_filename,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_list,
+ uint32_t metaflags,
+ struct collection_item **metadata)
{
int error = EOK;
+ int file_error = EOK;
+ int save_error = 0;
+ int fd = -1;
FILE *config_file = NULL;
- TRACE_FLOW_STRING("ini_to_col_from_file", "Entry");
+ TRACE_FLOW_STRING("config_from_fd_with_metadata", "Entry");
+
+ /* We need to check arguments before we can move on,
+ * and start allocating memory.
+ */
+ if ((ini_config == NULL) ||
+ (application == NULL)) {
+ TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
+ return EINVAL;
+ }
+
+ /* Prepare meta data */
+ error = prepare_metadata(metaflags, metadata, &save_error);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to prepare metadata", error);
+ return error;
+ }
+
+ errno = 0;
+
+ if (ext_fd == -1) {
+ /* No file descriptor so use name */
+ config_file = fopen(config_filename, "r");
+ }
+ else {
+ /* Create a copy of the descriptor so that we can close it if needed */
+ fd = dup(ext_fd);
+ if (fd != -1) config_file = fdopen(fd, "r");
+ }
+ file_error = errno;
+
+ if (save_error) {
+ /* Record the result of the open file operation in metadata */
+ error = col_add_int_property(*metadata,
+ INI_META_SEC_ERROR,
+ INI_META_KEY_READ_ERROR,
+ file_error);
+ if (error) {
+ /* Something is really wrong if we failed here */
+ TRACE_ERROR_NUMBER("Failed to save file open error", error);
+ if (config_file) fclose(config_file);
+ return error;
+ }
+ }
- config_file = fopen(config_filename, "r");
if(!config_file) {
- error = errno;
- TRACE_ERROR_NUMBER("ini_to_col_from_file. Returns", error);
- return ENOENT;
+ TRACE_ERROR_NUMBER("Failed to open file", file_error);
+ return file_error;
}
- error = ini_to_collection(config_file,
- config_filename,
- ini_config,
- error_level,
- error_list,
- lines);
- TRACE_FLOW_NUMBER("ini_to_col_from_file. Returns", error);
+ /* Collect meta data before actually parsing the file */
+ error = collect_metadata(metaflags, metadata, config_file);
+ if(error) {
+ TRACE_ERROR_NUMBER("Failed to collect metadata", error);
+ return error;
+ }
+
+ if (!(metaflags & INI_META_ACTION_NOPARSE)) {
+ /* Parse data if needed */
+ error = config_with_metadata(application,
+ config_file,
+ config_filename,
+ ini_config,
+ error_level,
+ error_list,
+ metaflags,
+ *metadata);
+ }
+
+ /* We opened the file we close it */
+ fclose(config_file);
+
+ TRACE_FLOW_NUMBER("config_from_fd_with_metadata. Returns", error);
+ return error;
+}
+
+/* Function to read the ini file with metadata
+ * using file name.
+ */
+int config_from_file_with_metadata(const char *application,
+ const char *config_filename,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_list,
+ uint32_t metaflags,
+ struct collection_item **metadata)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("config_from_file_with_metadata", "Entry");
+
+ error = config_from_fd_with_metadata(application,
+ -1,
+ config_filename,
+ ini_config,
+ error_level,
+ error_list,
+ metaflags,
+ metadata);
+
+ TRACE_FLOW_STRING("config_from_file_with_metadata", "Exit");
return error;
}
/* Read default config file and then overwrite it with a specific one
* from the directory */
-int config_for_app(const char *application,
- const char *config_file,
- const char *config_dir,
- struct collection_item **ini_config,
- int error_level,
- struct collection_item **error_set)
+int config_for_app_with_metadata(const char *application,
+ const char *config_file,
+ const char *config_dir,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_set,
+ uint32_t metaflags,
+ struct collection_item **meta_default,
+ struct collection_item **meta_appini)
{
int error = EOK;
char *file_name;
@@ -695,7 +792,7 @@ int config_for_app(const char *application,
int tried = 0;
int noents = 0;
- TRACE_FLOW_STRING("config_to_collection", "Entry");
+ TRACE_FLOW_STRING("config_for_app", "Entry");
if (ini_config == NULL) {
TRACE_ERROR_NUMBER("Invalid parameter", EINVAL);
@@ -745,7 +842,8 @@ int config_for_app(const char *application,
created = 1;
}
/* Is the collection of the right class? */
- else if (col_is_of_class(*ini_config, COL_CLASS_INI_CONFIG)) {
+ else if ((col_is_of_class(*ini_config, COL_CLASS_INI_CONFIG) == 0) &&
+ (col_is_of_class(*ini_config, COL_CLASS_INI_META) == 0)) {
TRACE_ERROR_NUMBER("Wrong collection type", EINVAL);
return EINVAL;
}
@@ -753,8 +851,14 @@ int config_for_app(const char *application,
/* Read master file */
if (config_file != NULL) {
TRACE_INFO_STRING("Reading master file:", config_file);
- error = ini_to_col_from_file(config_file, *ini_config,
- error_level, pass_common, NULL);
+ /* Get configuration information from the file */
+ error = config_from_file_with_metadata(application,
+ config_file,
+ ini_config,
+ error_level,
+ pass_common,
+ metaflags,
+ meta_default);
tried++;
/* ENOENT and EOK are Ok */
if (error) {
@@ -812,8 +916,13 @@ int config_for_app(const char *application,
sprintf(file_name, "%s%s%s.conf", config_dir, SLASH, application);
TRACE_INFO_STRING("Opening file:", file_name);
/* Read specific file */
- error = ini_to_col_from_file(file_name, *ini_config,
- error_level, pass_specific, NULL);
+ error = config_from_file_with_metadata(application,
+ file_name,
+ ini_config,
+ error_level,
+ pass_specific,
+ metaflags,
+ meta_appini);
tried++;
free(file_name);
/* ENOENT and EOK are Ok */
@@ -874,6 +983,36 @@ int config_for_app(const char *application,
return EOK;
}
+
+/* Function to return configuration data
+ * for the application without meta data.
+ */
+int config_for_app(const char *application,
+ const char *config_file,
+ const char *config_dir,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_set)
+{
+ int error = EOK;
+ TRACE_FLOW_STRING("config_for_app", "Entry");
+
+ error = config_for_app_with_metadata(application,
+ config_file,
+ config_dir,
+ ini_config,
+ error_level,
+ error_set,
+ 0,
+ NULL,
+ NULL);
+
+ TRACE_FLOW_NUMBER("config_for_app. Returning", error);
+ return error;
+}
+
+
+
/* Reads a line from the file */
int read_line(FILE *file,
char *buf,
@@ -1127,7 +1266,22 @@ void print_file_parsing_errors(FILE *file,
}
-/* Print errors and warnings that were detected while processing grammar */
+/* Print errors and warnings that were detected while processing grammar.
+ *
+ * The following doxygen description is moved here.
+ * When the function gets exposed move it into
+ * the header file.
+ */
+/**
+ * @brief Print errors and warnings that were detected while
+ * checking grammar of the template.
+ *
+ * EXPERIMENTAL. Reserved for future use.
+ *
+ * @param[in] file File descriptor.
+ * @param[in] error_list List of the parsing errors.
+ *
+ */
void print_grammar_errors(FILE *file,
struct collection_item *error_list)
{
@@ -1141,7 +1295,22 @@ void print_grammar_errors(FILE *file,
grammar_error_str);
}
-/* Print errors and warnings that were detected while validating INI file. */
+/* Print errors and warnings that were detected while validating INI file.
+ *
+ * The following doxygen description is moved here.
+ * When the function gets exposed move it into
+ * the header file.
+ */
+/**
+ * @brief Print errors and warnings that were detected while
+ * checking INI file against the grammar object.
+ *
+ * EXPERIMENTAL. Reserved for future use.
+ *
+ * @param[in] file File descriptor.
+ * @param[in] error_list List of the parsing errors.
+ *
+ */
void print_validation_errors(FILE *file,
struct collection_item *error_list)
{
@@ -1243,7 +1412,8 @@ int get_config_item(const char *section,
}
/* Is the collection of a right type */
- if (!col_is_of_class(ini_config, COL_CLASS_INI_CONFIG)) {
+ if ((col_is_of_class(ini_config, COL_CLASS_INI_CONFIG) == 0) &&
+ (col_is_of_class(ini_config, COL_CLASS_INI_META) == 0)) {
TRACE_ERROR_NUMBER("Wrong collection type", EINVAL);
return EINVAL;
}
@@ -2054,7 +2224,8 @@ char **get_section_list(struct collection_item *ini_config, int *size, int *erro
TRACE_FLOW_STRING("get_section_list","Entry");
/* Do we have the item ? */
if ((ini_config == NULL) ||
- !col_is_of_class(ini_config, COL_CLASS_INI_CONFIG)) {
+ ((col_is_of_class(ini_config, COL_CLASS_INI_CONFIG) == 0) &&
+ (col_is_of_class(ini_config, COL_CLASS_INI_META) == 0))) {
TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
if (error) *error = EINVAL;
return NULL;
@@ -2079,7 +2250,8 @@ char **get_attribute_list(struct collection_item *ini_config, const char *sectio
TRACE_FLOW_STRING("get_attribute_list","Entry");
/* Do we have the item ? */
if ((ini_config == NULL) ||
- !col_is_of_class(ini_config, COL_CLASS_INI_CONFIG) ||
+ ((col_is_of_class(ini_config, COL_CLASS_INI_CONFIG) == 0) &&
+ (col_is_of_class(ini_config, COL_CLASS_INI_META) == 0)) ||
(section == NULL)) {
TRACE_ERROR_NUMBER("Invalid argument.", EINVAL);
if (error) *error = EINVAL;
diff --git a/ini/ini_config.h b/ini/ini_config.h
index da8227b..bd2bdd9 100644
--- a/ini/ini_config.h
+++ b/ini/ini_config.h
@@ -180,22 +180,13 @@
* of such sets.
*/
#define COL_CLASS_INI_PESET COL_CLASS_INI_BASE + 3
-/** @brief Collection of grammar errors.
- *
- * Reserved for future use.
- */
-#define COL_CLASS_INI_GERROR COL_CLASS_INI_BASE + 4
-/** @brief Collection of validation errors.
- *
- * Reserved for future use.
- */
-#define COL_CLASS_INI_VERROR COL_CLASS_INI_BASE + 5
-/** @brief Collection of lines from the INI file.
+
+/**
+ * @brief Collection of metadata.
*
- * Reserved for future use
+ * Collection that stores metadata.
*/
-#define COL_CLASS_INI_LINES COL_CLASS_INI_BASE + 6
-
+#define COL_CLASS_INI_META COL_CLASS_INI_BASE + 4
/**
* @}
*/
@@ -295,44 +286,185 @@ struct parse_error {
*/
/**
- * @defgroup functions Functions
+ * @defgroup metadata Meta data
+ *
+ * Metadata is a collection of a similar structure as any ini file.
+ * The difference is that there are some predefined sections
+ * and attributes inside these sections.
+ * Using meta flags one can specify what section he is interested
+ * in including into the meta data. If a flag for a corresponding
+ * meta data section is specified the data for this section will
+ * be included into the meta data collection. The caller can then
+ * use meta data collection to get items from it and then get
+ * a specific value using a corresponding conversion function.
+ *
+ * Think about the meta data as an INI file that looks like this:
+ *
+ * <b>
+ * [ACCESS]
+ * - uid = <i>\<ini file owner uid\></i>
+ * - gid = <i>\<ini file group gid\></i>
+ * - perm = <i>\<permissions word\></i>
+ * - name = <i>\<file name\></i>
+ * - created = <i>\<time stamp\></i>
+ * - modified = <i>\<time stamp\></i>
+ * - ...
+ *
+ * [ERROR]
+ * - read_error = <i><file open error if any\></i>
+ * - ...
+ *
+ * [<i>TBD</i>]
+ * - ...
+ *
+ * </b>
+ *
+ * The names of the keys and sections provide an example
+ * of how the meta data is structured. Look information
+ * about specific sections and available keys in this manual
+ * to get the exact set of currently supported sections
+ * and keys.
+ *
* @{
*/
-/** @brief Function to return a parsing error as a string.
+/**
+ * @brief Collect only meta data.
*
- * @param[in] parsing_error Error code for the parsing error.
+ * Special flag that indicates that only meta data
+ * needs to be collected. No parsing should be performed.
*
- * @return Error string.
*/
-const char *parsing_error_str(int parsing_error);
+#define INI_META_ACTION_NOPARSE 0x10000000
-/** @brief Function to return a grammar error in template.
+/**
+ * @defgroup metasection Meta data section names
*
- * EXPERIMENTAL. Reserved for future use.
+ * @{
+ */
+
+/**
+ * @brief Meta data section that stores file access information
+ * and ownership.
+ */
+#define INI_META_SEC_ACCESS "ACCESS"
+
+/**
+ * @brief Meta data "access" section flag to include access section
+ * into the output.
+ */
+#define INI_META_SEC_ACCESS_FLAG 0x00000001
+
+
+/**
+ * @defgroup metaaccesskeys Key names available in the "ACCESS" section
*
- * This error is returned when the template
- * is translated into the grammar object.
+ * @{
*
- * @param[in] parsing_error Error code for the grammar error.
+ */
+
+/**
+ * @brief The value for this key will store user ID of the INI file owner.
+ *
+ */
+#define INI_META_KEY_UID "uid"
+
+/**
+ * @brief The value for this key will store group ID of the INI file owner.
+ *
+ */
+#define INI_META_KEY_GID "gid"
+
+/**
+ * @brief The value for this key will store INI file access permissions.
+ *
+ */
+#define INI_META_KEY_PERM "perm"
+
+/**
+ * @brief The value for this key will store INI file creation time stamp.
+ *
+ */
+#define INI_META_KEY_CREATED "created"
+
+/**
+ * @brief The value for this key will store INI file modification time stamp.
+ *
+ */
+#define INI_META_KEY_MODIFIED "modified"
+
+/**
+ * @brief The value for this key will store INI file full name.
*
- * @return Error string.
*/
-const char *grammar_error_str(int parsing_error);
+#define INI_META_KEY_NAME "name"
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Meta data section that stores error related information.
+ */
+#define INI_META_SEC_ERROR "ERROR"
+
+/**
+ * @brief Meta data "error" section flag to include access section
+ * into the output.
+ */
+#define INI_META_SEC_ERROR_FLAG 0x00000002
+
-/** @brief Function to return a validation error.
+/**
+ * @defgroup metaerrorkeys Key names available in the "ERROR" section
*
- * EXPERIMENTAL. Reserved for future use.
+ * @{
*
- * This is the error that it is returned when
- * the INI file is validated against the
- * grammar object.
+ */
+
+/**
+ * @brief The value for this key will store read error when file was opened.
*
- * @param[in] parsing_error Error code for the validation error.
+ * If file was opened by caller first but this section was requested
+ * the value will be zero.
+ */
+#define INI_META_KEY_READ_ERROR "read_error"
+
+/**
+ * @brief The value for this key will store read error message if any.
+ *
+ * If file was opened by caller first but this section was requested
+ * the key will no be present. Also the key will no exist if no error
+ * occured.
+ */
+#define INI_META_KEY_READ_ERRMSG "err_msg"
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup functions Functions
+ * @{
+ */
+
+/** @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 *validation_error_str(int parsing_error);
+const char *parsing_error_str(int parsing_error);
+
/**
* @brief Read configuration information from a file.
@@ -397,36 +529,112 @@ int config_from_fd(const char *application,
struct collection_item **error_list);
+
/**
* @brief Read configuration information from a file with
- * extra collection of line numbers.
+ * additional meta data.
+ *
+ * Meta data consists of addition information about
+ * the file for example when it was created
+ * or who is the owner. For the detailed description
+ * of the meta data content and structure see
+ * \ref metadata "meta data" section.
+ *
+ * If the metadata argument is not NULL
+ * the calling function MUST always free meta data since it can
+ * be allocated even if the function returned error.
+ *
+ * @param[in] application Name of the application,
+ * will be used as name of
+ * the collection.
+ * @param[in] config_filename Name of the config file,
+ * if NULL the configuration
+ * collection will be empty.
+ * @param[out] ini_config If *ini_config is NULL
+ * a new ini object will be
+ * allocated, otherwise
+ * the one that is pointed to
+ * will be updated.
+ * @param[in] error_level Break for errors, warnings
+ * or best effort (don't break).
+ * @param[out] error_list List of errors for the file
+ * detected during parsing.
+ * @param[in] metaflags A bit mask of flags that define
+ * what kind of metadata should
+ * be collected.
+ * @param[out] metadata Collection of metadata
+ * values. See \ref metadata "meta data"
+ * section for more details.
+ * Can be NULL.
+ *
+ * @return 0 - Success.
+ * @return EINVAL - Invalid parameter.
+ * @return Any error returned by fopen().
*
- * EXPERIMENTAL. Reserved for future use.
*
*/
-int config_from_file_with_lines(
+int config_from_file_with_metadata(
const char *application,
const char *config_filename,
struct collection_item **ini_config,
int error_level,
struct collection_item **error_list,
- struct collection_item **lines);
+ uint32_t metaflags,
+ struct collection_item **metadata);
+
/**
- * @brief Read configuration information from a file descriptor with
- * extra collection of line numbers.
+ * @brief Read configuration information from a file descriptor
+ * with additional meta data.
*
- * EXPERIMENTAL. Reserved for future use.
+ * Meta data consists of addition information about
+ * the file for example when it was created
+ * or who is the owner. For the detailed description
+ * of the meta data content and structure see
+ * \ref metadata "meta data" section.
+ *
+ * If the metadata argument is not NULL
+ * the calling function MUST always free meta data since it can
+ * be allocated even if the function returned error.
+ *
+ * @param[in] application Name of the application,
+ * will be used as name of
+ * the collection.
+ * @param[in] fd Previously opened file
+ * descriptor for the config file.
+ * @param[in] config_source Name of the file being parsed,
+ * for use when printing the error
+ * list.
+ * @param[out] ini_config If *ini_config is NULL
+ * a new ini object will be
+ * allocated, otherwise
+ * the one that is pointed to
+ * will be updated.
+ * @param[in] error_level Break for errors, warnings
+ * or best effort (don't break).
+ * @param[out] error_list List of errors for the file
+ * detected during parsing.
+ * @param[in] metaflags A bit mask of flags that define
+ * what kind of metadata should
+ * be collected.
+ * @param[out] metadata Collection of metadata
+ * values. See \ref metadata "meta data"
+ * section for more details.
+ * Can be NULL.
+ *
+ * @return 0 - Success.
+ * @return EINVAL - Invalid parameter.
*
*/
-int config_from_fd_with_lines(
+int config_from_fd_with_metadata(
const char *application,
int fd,
const char *config_source,
struct collection_item **ini_config,
int error_level,
struct collection_item **error_list,
- struct collection_item **lines);
+ uint32_t metaflags,
+ struct collection_item **metadata);
/**
@@ -443,7 +651,7 @@ int config_from_fd_with_lines(
* the configuration files for
* different applications reside.
* Function will look for file
- * with the name name constructed by
+ * with the name constructed by
* appending ".ini" to the end of
* the "application" argument.
* @param[out] ini_config A new configuration object.
@@ -464,6 +672,64 @@ int config_for_app(const char *application,
struct collection_item **error_set);
/**
+ * @brief Read default configuration file and then
+ * overwrite it with a specific one from the directory.
+ *
+ * If requested collect meta data for both.
+ *
+ * If the metadata argument is not NULL
+ * the calling function MUST always free meta data since it can
+ * be allocated even if the function returned error.
+ *
+ * @param[in] application Name of the application,
+ * will be used as name of
+ * the collection.
+ * @param[in] config_file Name of the configuration file,
+ * with default settings for all
+ * appplications.
+ * @param[in] config_dir Name of the directory where
+ * the configuration files for
+ * different applications reside.
+ * Function will look for file
+ * with the name constructed by
+ * appending ".ini" to the end of
+ * the "application" argument.
+ * @param[out] ini_config A new configuration object.
+ * @param[in] error_level Break for errors, warnings
+ * or best effort (don't break).
+ * @param[out] error_set Collection of error lists.
+ * One list per file.
+ * @param[in] metaflags A bit mask of flags that define
+ * what kind of metadata should
+ * be collected.
+ * @param[out] meta_default Collection of metadata
+ * values for the default common
+ * config file for all applications.
+ * See \ref metadata "meta data"
+ * section for more details.
+ * Can be NULL.
+ * @param[out] meta_appini Collection of metadata
+ * values for the application
+ * specific config file.
+ * See \ref metadata "meta data"
+ * section for more details.
+ * Can be NULL.
+ *
+ * @return 0 - Success.
+ * @return EINVAL - Invalid parameter.
+ * @return Any error returned by fopen().
+ */
+int config_for_app_with_metadata(
+ const char *application,
+ const char *config_file,
+ const char *config_dir,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_set,
+ uint32_t metaflags,
+ struct collection_item **meta_default,
+ struct collection_item **meta_appini);
+/**
* @brief Function to free configuration object.
*
* @param[in] ini_config Configuration object.
@@ -479,16 +745,14 @@ void free_ini_config(struct collection_item *ini_config);
*/
void free_ini_config_errors(struct collection_item *error_set);
+
/**
- * @brief Function to free lines object.
- *
- * EXPERIMENTAL. Reserved for future use.
+ * @brief Function to free metadata.
*
- * @param[in] lines Lines object.
+ * @param[in] error_set Configuration meta data object.
*
*/
-void free_ini_config_lines(struct collection_item *lines);
-
+void free_ini_config_metadata(struct collection_item *metadata);
/**
@@ -501,34 +765,6 @@ void free_ini_config_lines(struct collection_item *lines);
void print_file_parsing_errors(FILE *file,
struct collection_item *error_list);
-/**
- * @brief Print errors and warnings that were detected while
- * checking grammar of the template.
- *
- * EXPERIMENTAL. Reserved for future use.
- *
- * @param[in] file File descriptor.
- * @param[in] error_list List of the parsing errors.
- *
- */
-void print_grammar_errors(FILE *file,
- struct collection_item *error_list);
-
-/**
- * @brief Print errors and warnings that were detected while
- * checking INI file against the grammar object.
- *
- * EXPERIMENTAL. Reserved for future use.
- *
- * @param[in] file File descriptor.
- * @param[in] error_list List of the parsing errors.
- *
- */
-void print_validation_errors(FILE *file,
- struct collection_item *error_list);
-
-
-
/**
* @brief Print errors and warnings that were detected
diff --git a/ini/ini_config_ut.c b/ini/ini_config_ut.c
index 1c82a05..dde1c52 100644
--- a/ini/ini_config_ut.c
+++ b/ini/ini_config_ut.c
@@ -87,7 +87,8 @@ int single_file(void)
int error;
struct collection_item *ini_config = NULL;
struct collection_item *error_set = NULL;
- struct collection_item *lines = NULL;
+ struct collection_item *metadata = NULL;
+ uint32_t flags;
error = config_from_file("test", "./not_exist_ini.conf",
&ini_config, INI_STOP_ON_NONE, &error_set);
@@ -123,18 +124,54 @@ int single_file(void)
ini_config = NULL;
error_set = NULL;
- COLOUT(printf("TEST WITH LINES\n"));
+ COLOUT(printf("TEST WITH METADATA NO PARSE\n"));
+ flags = INI_META_SEC_ACCESS_FLAG |
+ INI_META_SEC_ERROR_FLAG |
+ INI_META_ACTION_NOPARSE;
- error = config_from_file_with_lines("test", "./ini.conf",
- &ini_config, INI_STOP_ON_NONE,
- &error_set, &lines);
+ error = config_from_file_with_metadata("test", "./ini.conf",
+ &ini_config, INI_STOP_ON_NONE,
+ NULL,
+ flags,
+ &metadata);
if (error) {
printf("Attempt to read configuration returned error: %d\n",error);
+ printf("\n\nMetadata\n");
+ col_debug_collection(metadata, COL_TRAVERSE_DEFAULT);
+ free_ini_config_metadata(metadata);
return error;
}
+ if (ini_config) {
+ printf("Expected no config but got some.\n");
+ col_debug_collection(ini_config, COL_TRAVERSE_DEFAULT);
+ free_ini_config(ini_config);
+ printf("\n\nMetadata\n");
+ col_debug_collection(metadata, COL_TRAVERSE_DEFAULT);
+ free_ini_config_metadata(metadata);
+ return EINVAL;
+ }
+
+ COLOUT(printf("\n\nMeta data\n"));
+ COLOUT(col_debug_collection(metadata, COL_TRAVERSE_DEFAULT));
+ free_ini_config_metadata(metadata);
+
+ COLOUT(printf("\n\n----------------------\n"));
+
+ error = config_from_file_with_metadata("test", "./ini.conf",
+ &ini_config, INI_STOP_ON_NONE,
+ &error_set,
+ 0,
+ NULL);
+ if (error) {
+ printf("Attempt to read configuration returned error: %d\n",error);
+ print_file_parsing_errors(stdout, error_set);
+ free_ini_config_errors(error_set);
+ return error;
+ }
+
+ COLOUT(printf("\n\n----------------------\n"));
COLOUT(col_debug_collection(ini_config, COL_TRAVERSE_DEFAULT));
- COLOUT(col_debug_collection(lines, COL_TRAVERSE_DEFAULT));
COLOUT(printf("\n\n----------------------\n"));
/* Output parsing errors (if any) */
@@ -144,7 +181,6 @@ int single_file(void)
free_ini_config(ini_config);
free_ini_config_errors(error_set);
- free_ini_config_lines(lines);
return 0;
}
@@ -154,7 +190,8 @@ int single_fd(void)
int error;
struct collection_item *ini_config = NULL;
struct collection_item *error_set = NULL;
- struct collection_item *lines = NULL;
+ struct collection_item *metadata = NULL;
+ uint32_t flags;
int fd = open("./ini.conf", O_RDONLY);
if (fd < 0) {
@@ -187,7 +224,7 @@ int single_fd(void)
ini_config = NULL;
error_set = NULL;
- COLOUT(printf("TEST WITH LINES\n"));
+ COLOUT(printf("TEST WITH FILE FD & META DATA\n"));
fd = open("./ini.conf", O_RDONLY);
if (fd < 0) {
@@ -195,18 +232,63 @@ int single_fd(void)
printf("Attempt to read configuration returned error: %d\n", error);
return error;
}
- error = config_from_fd_with_lines("test", fd,
- "./ini.conf",
- &ini_config,
- INI_STOP_ON_NONE,
- &error_set, &lines);
+
+ flags = INI_META_SEC_ACCESS_FLAG |
+ INI_META_SEC_ERROR_FLAG |
+ INI_META_ACTION_NOPARSE;
+
+ error = config_from_fd_with_metadata("test", fd,
+ "./ini.conf",
+ &ini_config,
+ INI_STOP_ON_NONE,
+ &error_set,
+ flags,
+ &metadata);
+ if (error) {
+ printf("Attempt to read configuration returned error: %d\n",error);
+ printf("\n\nErrors\n");
+ print_file_parsing_errors(stdout, error_set);
+ free_ini_config_errors(error_set);
+ printf("\n\nMetadata\n");
+ col_debug_collection(metadata, COL_TRAVERSE_DEFAULT);
+ free_ini_config_metadata(metadata);
+ return error;
+ }
+
+ if (ini_config) {
+ printf("Expected no config but got some.\n");
+ col_debug_collection(ini_config, COL_TRAVERSE_DEFAULT);
+ free_ini_config(ini_config);
+ return EINVAL;
+ }
+
+ /* FIXME get elements of the meta data and check them */
+
+
+ COLOUT(printf("\n\nMeta data\n"));
+ COLOUT(col_debug_collection(metadata, COL_TRAVERSE_DEFAULT));
+ free_ini_config_metadata(metadata);
+
+
+ error = config_from_fd_with_metadata("test", fd,
+ "./ini.conf",
+ &ini_config,
+ INI_STOP_ON_NONE,
+ &error_set,
+ 0,
+ NULL);
+
+ close(fd);
+
if (error) {
printf("Attempt to read configuration returned error: %d\n",error);
+ printf("\n\nErrors\n");
+ print_file_parsing_errors(stdout, error_set);
+ free_ini_config_errors(error_set);
return error;
}
COLOUT(col_debug_collection(ini_config, COL_TRAVERSE_DEFAULT));
- COLOUT(col_debug_collection(lines, COL_TRAVERSE_DEFAULT));
COLOUT(printf("\n\n----------------------\n"));
/* Output parsing errors (if any) */
@@ -216,7 +298,6 @@ int single_fd(void)
free_ini_config(ini_config);
free_ini_config_errors(error_set);
- free_ini_config_lines(lines);
return 0;
}
diff --git a/ini/ini_metadata.c b/ini/ini_metadata.c
new file mode 100644
index 0000000..630de69
--- /dev/null
+++ b/ini/ini_metadata.c
@@ -0,0 +1,104 @@
+/*
+ INI LIBRARY
+
+ Functions to process metadata.
+
+ 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 "config.h"
+#include "collection.h"
+#include "collection_tools.h"
+#include "trace.h"
+#include "ini_config.h"
+#include "ini_metadata.h"
+
+#define INI_METADATA "meta"
+
+/* Prepare metadata */
+int prepare_metadata(uint32_t metaflags,
+ struct collection_item **metadata,
+ int *save_error)
+{
+ int error = EOK;
+ struct collection_item *metasec = NULL;
+
+ TRACE_FLOW_STRING("prepare_metadata", "Entry");
+
+ /* Are we supposed to collect or process meta data ? */
+ if (!metadata) {
+ TRACE_FLOW_STRING("No meta data", "Exit");
+ return EOK;
+ }
+
+ /* Allocate metadata */
+ error = col_create_collection(metadata,
+ INI_METADATA,
+ COL_CLASS_INI_META);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create meta data", error);
+ return error;
+ }
+
+ /* Check and create section for file error if needed */
+ if (metaflags & INI_META_SEC_ERROR_FLAG) {
+ /* Create ERROR collection */
+ if ((error = col_create_collection(&metasec,
+ INI_META_SEC_ERROR,
+ COL_CLASS_INI_SECTION)) ||
+ (error = col_add_collection_to_collection(
+ *metadata,
+ NULL,
+ NULL,
+ metasec,
+ COL_ADD_MODE_REFERENCE))) {
+ TRACE_ERROR_NUMBER("Failed to create error section", error);
+ col_destroy_collection(metasec);
+ col_destroy_collection(*metadata);
+ return error;
+ }
+ /* If we are here we would have to save file open error */
+ *save_error = 1;
+ col_destroy_collection(metasec);
+ }
+
+ TRACE_FLOW_STRING("prepare_metadata", "Exit");
+ return error;
+}
+
+
+
+/* Collect metadata for the file */
+int collect_metadata(uint32_t metaflags,
+ struct collection_item **metadata,
+ FILE *config_file)
+{
+ int error = EOK;
+
+ TRACE_FLOW_STRING("collect_metadata", "Entry");
+
+ TRACE_FLOW_STRING("collect_metadata", "Exit");
+ return error;
+}
+
+/* Function to free metadata */
+void free_ini_config_metadata(struct collection_item *metadata)
+{
+ TRACE_FLOW_STRING("free_ini_config_metadata", "Entry");
+ col_destroy_collection(metadata);
+ TRACE_FLOW_STRING("free_ini_config_metadata", "Exit");
+}
diff --git a/ini/ini_metadata.h b/ini/ini_metadata.h
new file mode 100644
index 0000000..2839453
--- /dev/null
+++ b/ini/ini_metadata.h
@@ -0,0 +1,42 @@
+/*
+ INI LIBRARY
+
+ Header file for the meta data related functions.
+
+ Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
+
+ 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/>.
+*/
+
+#ifndef INI_METADATA_H
+#define INI_METADATA_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include "collection.h"
+
+
+/* Prepare metadata */
+int prepare_metadata(uint32_t metaflags,
+ struct collection_item **metadata,
+ int *save_error);
+
+/* Collect metadata for the file */
+int collect_metadata(uint32_t metaflags,
+ struct collection_item **metadata,
+ FILE *config_file);
+
+
+
+#endif