>From c443d984a19df8fbbdb7337563ea4ec0ea2d693d Mon Sep 17 00:00:00 2001
From: Dmitri Pal <dpal@dpal.csb>
Date: Sun, 7 Sep 2014 22:55:02 +0200
Subject: [PATCH 09/10] [INI] Make the merge function build

---
 Makefile.am           |   15 +++++-
 ini/ini_configobj.h   |  115 +++++++++++++++++++++++++++++++++++++++++++++++++
 ini/libini_config.sym |    1 +
 3 files changed, 128 insertions(+), 3 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 32fcfae..7f38e50 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -255,6 +255,7 @@ libini_config_la_SOURCES = \
     ini/ini_get_valueobj.c \
     ini/ini_get_array_valueobj.c \
     ini/ini_list_valueobj.c \
+    ini/ini_augment.c \
     trace/trace.h
 libini_config_la_DEPENDENCIES = ini/libini_config.sym
 libini_config_la_LIBADD = \
@@ -286,19 +287,23 @@ dist_noinst_DATA += \
     ini/ini.d/real32be.conf \
     ini/ini.d/real32le.conf \
     ini/ini.d/symbols.conf \
-    ini/ini.d/new_line.conf
+    ini/ini.d/new_line.conf \
+    ini/ini.d/merge.validator
 
 check_PROGRAMS += \
     ini_config_ut \
     ini_comment_ut \
     ini_valueobj_ut \
-    ini_parse_ut
+    ini_parse_ut \
+    ini_augment_ut
 
 TESTS += \
     ini_config_ut \
     ini_comment_ut \
     ini_valueobj_ut \
-    ini_parse_ut
+    ini_parse_ut \
+    ini_augment_ut
+
 
 ini_config_ut_SOURCES = ini/ini_config_ut.c
 ini_config_ut_LDADD = \
@@ -314,6 +319,9 @@ ini_valueobj_ut_LDADD = libini_config.la libbasicobjects.la
 ini_parse_ut_SOURCES = ini/ini_parse_ut.c
 ini_parse_ut_LDADD = libini_config.la libcollection.la libbasicobjects.la
 
+ini_augment_ut_SOURCES = ini/ini_augment_ut.c
+ini_augment_ut_LDADD = libini_config.la libcollection.la libbasicobjects.la
+
 ini_config-docs:
 if HAVE_DOXYGEN
 	cd ini; \
@@ -324,6 +332,7 @@ clean-local-ini_config:
 	rm -f ./*.out
 	rm -f test.ini
 	rm -f ./foo.conf ./bom* #From ini_parse_ut
+	rm -f ./merge.validator.in #From ini_augment_ut
 
 ##############################################################################
 # Additional rules
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h
index 4ef98dc..620b545 100644
--- a/ini/ini_configobj.h
+++ b/ini/ini_configobj.h
@@ -374,6 +374,46 @@ enum INI_GET {
  * @}
  */
 
+
+/**
+ * @defgroup augment Constants and structures related to augmentation.
+ *
+ * @{
+ */
+
+/** Structure to pass access check parameters to augmentation function.
+ *
+ * flags            Define what to check.
+ *                  One can check file
+ *                  permissions with mask,
+ *                  uid, and gid of the file.
+ * uid              Expected uid of the file.
+ * gid              Expected gid of the file.
+ * mode             Expected mode of the file.
+ * mask             Mask to use in the mode check.
+ *                  Mask is always adjusted to
+ *                  include at least S_IRWXU,
+ *                  S_IRWXG and S_IRWXO
+ */
+struct access_check {
+    uint32_t flags;
+    uid_t uid;
+    gid_t gid;
+    mode_t mode;
+    mode_t mask;
+};
+
+/** Enumeration of augmentation modes. */
+enum augmode {
+    INI_AUG_ANY   = 0, /**< Allow any augmentation. */
+    INI_AUG_ADD   = 1, /**< Allow only new sections. */
+    INI_AUG_OVER  = 2  /**< Allow section updates. */
+};
+
+/**
+ * @}
+ */
+
 /**
  * @brief Name of the default section.
  *
@@ -780,6 +820,81 @@ int ini_config_merge(struct ini_cfgobj *first,
                      uint32_t collision_flags,
                      struct ini_cfgobj **result);
 
+
+/**
+ * @brief Augment configuration
+ *
+ * Function merges the main configuration file 
+ * with the configuration file snippets 
+ * read from a specified directory.
+ *
+ * @param[in]  base_cfg         A configuration object
+ *                              that will be augmented.
+ * @param[in]  path             Path to a directory where
+ *                              configuration snippets
+ *                              will be read from.
+ * @param[in]  patterns         List of regular expressions
+ *                              that the name of a snippet file
+ *                              has to match to be considered
+ *                              for merge.
+ * @param[in]  sections         List of regular expressions
+ *                              that the section names in the snippet
+ *                              file need to match. If file contains
+ *                              sections that do not match any patterns
+ *                              the file is skipped and error is recorded.
+ * @param[in]  check_perm       Pointer to structure that
+ *                              holds criteria for the 
+ *                              access check.
+ * @param[in]  error_level      Flags that control actions
+ *                              in case of parsing error in a snippet file.
+ * @param[in]  collision_flags  These flags control how the potential
+ *                              collisions between keys and sections
+ *                              within the snippet file will be handled.
+ *                              For more information
+ *                              see collision flag definitions.
+ * @param[in]  parse_flags      Flags that control parsing process,
+ *                              for example how to handle spaces at
+ *                              the beginning of the line.
+ * @param[in]  merge_flags      Flags that control handling
+ *                              of the duplicate sections or keys
+ *                              during merging of the snippets.
+ *                              They are different from the collision flags
+ *                              because duplicate sections and keys inside
+ *                              are snippets most likely will be handled as
+ *                              'last value wins' while during merge
+ *                              the attempt to overwrite
+ *                              a specific section might be treated as
+ *                              an error.
+ * @param[out] result_cfg       A new configuration object,
+ *                              the result of the merge.
+ * @param[out] error_list       List of strings that
+ *                              contains all encountered
+ *                              errors.
+ *                              It can be NULL, in this case list of errors
+ *                              is not populated.
+ * @param[out] success_list     List of strings that
+ *                              contains file names of snippets that were
+ *                              successfully merged.
+ *                              It can be NULL, in this case list of files
+ *                              is not populated.
+ *
+ * @return 0 - Success.
+ * @return EINVAL - Invalid parameter.
+ * @return ENOMEM - No memory.
+ */
+int ini_config_augment(struct ini_cfgobj *base_cfg,
+                       const char *path,
+                       const char **patterns,
+                       const char **sections,
+                       struct access_check *check_perm,
+                       int error_level,
+                       uint32_t collision_flags,
+                       uint32_t parse_flags,
+                       uint32_t merge_flags,
+                       struct ini_cfgobj **result_cfg,
+                       struct ref_array **error_list,
+                       struct ref_array **success_list);
+
 /**
  * @brief Set the folding boundary
  *
diff --git a/ini/libini_config.sym b/ini/libini_config.sym
index 3ca15bb..33d2246 100644
--- a/ini/libini_config.sym
+++ b/ini/libini_config.sym
@@ -62,6 +62,7 @@ global:
     ini_config_parse;
     ini_config_copy;
     ini_config_merge;
+    ini_config_augment;
     ini_config_set_wrap;
     ini_config_serialize;
     ini_get_section_list;
-- 
1.7.1

