On 04/19/2013 09:00 PM, Jakub Hrozek wrote:
On Fri, Apr 19, 2013 at 04:05:49PM +0200, Ondrej Kos wrote:

I know that the transaction logic in this function predates this patch,
but I think we should fix it when we are changing the code anyway. Can
you take a look at how we use the "in_transaction" booleans elsewhere
for sysdb transaction and put the same logic here?

Then you would always be able to just goto done and have the cleanup
done on one place.

fixed, thanks for pointing out


You're leaking tmp_ctx here and on several other places. The advice
above would fix this problem.


fixed

+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("No stat data though stat collection was requested.\n"));

I don't understand this error message, can you reword it?



+    ret = sss_ini_get_mtime(timestr, init_data);

This function really should have a size_t parameter, an API cannot
make any assumptions about the size of an input buffer, sorry.

fixed


      if (ret <= 0 || ret >= 21) {

you can use sizeof(timestr) here in the odd case timestr actually
changed.

quoting the reference:
Return Value
The number of characters that would have been written if n had been sufficiently large, not counting the terminating null character.
If an encoding error occurs, a negative number is returned.
Notice that only when this returned value is non-negative and less than n, the string has been completely written.
(where N is the sizeof parameter)

so I'd rather leave it this way, seems more defensive

-    /* Purge existing database */
-    ret = confdb_purge(cdb);
-    if (ret != EOK) {
-        DEBUG(0, ("Could not purge existing configuration\n"));
-        close(fd);
+    } else {
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to get lastUpdate attribute.\n"));
          goto done;

goto done is currently wrong here, it would attempt to cancel a
transaction that hasn't started yet.

fixed


[snip]

+    version = sss_ini_get_int_config_value(init_data, 1, -1, &ret);
      if (ret != EOK) {
-        DEBUG(0, ("Config file version could not be determined\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Config file version could not be determined\n"));

All previous error handlers called sss_ini_close_file() and
sss_ini_config_destroy() is being called from now on. Is that correct?

this was no longer destroying the file descriptor, but the loaded configuration object, since I now restructured the error handling, it's no longer there.

+PKG_CHECK_MODULES(INI_CONFIG, [
+    ini_config >= 1.0.0], [
+
+        HAVE_LIBINI_CONFIG_V1=1

This assignment seems redundant to me. AC_DEFINE_UNQUOTED accepts an
identifier as the first parameter.

you're right, fixed

+#include <stdio.h>
+#include <errno.h>
+#include <talloc.h>
+
+#include "config.h"
+#include "util/util.h"
+#include "util/sss_ini.h"
+#include "confdb/confdb_setup.h"
+#include "confdb/confdb_private.h"
+
+#ifdef HAVE_LIBINI_CONFIG_V1
+#include "ini_configobj.h"
+#endif
+#include "ini_config.h"
+
+#ifdef HAVE_LIBINI_CONFIG_V0
+#include "collection.h"
+#include "collection_tools.h"
+#endif

We should be paranoid here and have an #else that would contain an
#error directive. It is OK to add this just once, I guess, the
compiler would error out.


I don't think it's necessary, but fixed.

+/* Initialize data structure */
+
+struct sss_ini_initdata* sss_ini_initdata_init(TALLOC_CTX *tmp_ctx)

Memory context that allocates output directly should not be named
tmp_ctx but mem_ctx probably.

fixed

+/* Get mtime */
+
+int sss_ini_get_mtime(char *timestr, struct sss_ini_initdata *init_data)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    return snprintf(timestr, 21, "%llu",
                               ^^^^^^^
             This function should either have a big fat comment saying that
             timestr is at least 21 bytes large, or (better) accept also
             a size_t parameter that specifies the actual size.

fixed with size_t function parameter
+    /* Parse file */
+    ret = ini_config_parse(init_data->file,
+                           INI_STOP_ON_ANY,
+                           0, /* <- check that you really want this */

What does this comment mean?

I forgot to remove the comment and replace the value with macro INI_MV1S_OVERWRITE, it's flag for handling collisions, in this case, duplicate is overwritten.

+/* Free ini config (v0) */
+
+void sss_ini_free_ini_config(struct sss_ini_initdata *init_data)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    return;
+#elif HAVE_LIBINI_CONFIG_V0
+    free_ini_config(init_data->sssd_config);
+#endif
+}
+
+
+
+/* Destroy ini config (v1) */
+
+void sss_ini_config_destroy(struct sss_ini_initdata *init_data)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    ini_config_destroy(init_data->sssd_config);
+#elif HAVE_LIBINI_CONFIG_V0
+    return;
+#endif
+}
+

I don't get why these functions are separate, sounds like you should
merge them to me?

in the previous code flow the config-free occured in different parts of code, because the structure data was needed further between versions.

This new wrapper interface looks much better to me, but in general when
designing such quasi-object interfaces that operate on a structure, the
structure should always be the first (with the exception of talloc context)
parameter and especially any output parameters should always come last.

sss_confdb_create_ldif() got it right.

+/* Get mtime */
+int sss_ini_get_mtime(char *timestr, struct sss_ini_initdata *init_data);

Functionally the code seems to be working well.


new patch attached.

Ondra


--
Ondrej Kos
Associate Software Engineer
Identity Management
Red Hat Czech
From 4ad8a96eb33891124d6e33e9f4d898d05679b2b6 Mon Sep 17 00:00:00 2001
From: Ondrej Kos <o...@redhat.com>
Date: Thu, 28 Mar 2013 15:35:03 +0100
Subject: [PATCH] DB: Switch to new libini_config API

https://fedorahosted.org/sssd/ticket/1786

Since we need to support the old interface as well, the configure scritp
is modified and correct ini interface is chosen.
---
 Makefile.am                         |   2 +
 src/confdb/confdb_setup.c           | 349 ++++++++++-----------------
 src/external/libini_config.m4       |  24 +-
 src/monitor/monitor.c               |   2 -
 src/responder/nss/nsssrv_netgroup.c |   2 +-
 src/responder/nss/nsssrv_services.c |   1 -
 src/util/sss_ini.c                  | 466 ++++++++++++++++++++++++++++++++++++
 src/util/sss_ini.h                  |  81 +++++++
 8 files changed, 688 insertions(+), 239 deletions(-)
 create mode 100644 src/util/sss_ini.c
 create mode 100644 src/util/sss_ini.h

diff --git a/Makefile.am b/Makefile.am
index 09056b5d9fec1d23213132940d11c312bcbfc23d..0b70f963701a63f51473ffb94c5eb6bc7fb55867 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -391,6 +391,7 @@ dist_noinst_HEADERS = \
     src/util/sss_selinux.h \
     src/util/sss_utf8.h \
     src/util/sss_ssh.h \
+    src/util/sss_ini.h \
     src/util/refcount.h \
     src/util/find_uid.h \
     src/util/user_info_msg.h \
@@ -552,6 +553,7 @@ libsss_util_la_SOURCES = \
     src/util/domain_info_utils.c \
     src/util/util_lock.c \
     src/util/util_errors.c \
+    src/util/sss_ini.c \
     src/util/io.c
 libsss_util_la_LIBADD = \
     $(SSSD_LIBS) \
diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c
index 6c68461faf1e14270a03dc979c4b9c21c0374af2..57bd848ce13104dc9b398b51f009dead6fd263bb 100644
--- a/src/confdb/confdb_setup.c
+++ b/src/confdb/confdb_setup.c
@@ -26,9 +26,7 @@
 #include "confdb.h"
 #include "confdb_private.h"
 #include "confdb_setup.h"
-#include "collection.h"
-#include "collection_tools.h"
-#include "ini_config.h"
+#include "util/sss_ini.h"
 
 
 int confdb_test(struct confdb_ctx *cdb)
@@ -126,280 +124,159 @@ int confdb_create_base(struct confdb_ctx *cdb)
     return EOK;
 }
 
-static int confdb_create_ldif(TALLOC_CTX *mem_ctx,
-                              struct collection_item *sssd_config,
-                              const char **config_ldif)
-{
-    int ret, i, j;
-    char *ldif;
-    char *tmp_ldif;
-    char **sections;
-    int section_count;
-    char *dn;
-    char *tmp_dn;
-    char *sec_dn;
-    char **attrs;
-    int attr_count;
-    char *ldif_attr;
-    struct collection_item *attr;
-    TALLOC_CTX *tmp_ctx;
-    size_t dn_size;
-    size_t ldif_len;
-    size_t attr_len;
-
-    ldif_len = strlen(CONFDB_INTERNAL_LDIF);
-    ldif = talloc_array(mem_ctx, char, ldif_len+1);
-    if (!ldif) return ENOMEM;
-
-    tmp_ctx = talloc_new(ldif);
-    if (!tmp_ctx) {
-        ret = ENOMEM;
-        goto error;
-    }
-
-    memcpy(ldif, CONFDB_INTERNAL_LDIF, ldif_len);
-
-    /* Read in the collection and convert it to an LDIF */
-    /* Get the list of sections */
-    sections = get_section_list(sssd_config, &section_count, &ret);
-    if (ret != EOK) {
-        goto error;
-    }
-
-    for(i = 0; i < section_count; i++) {
-        const char *rdn = NULL;
-        DEBUG(6,("Processing config section [%s]\n", sections[i]));
-        ret = parse_section(tmp_ctx, sections[i], &sec_dn, &rdn);
-        if (ret != EOK) {
-            goto error;
-        }
-
-        dn = talloc_asprintf(tmp_ctx,
-                             "dn: %s,cn=config\n"
-                             "cn: %s\n",
-                             sec_dn, rdn);
-        if(!dn) {
-            ret = ENOMEM;
-            free_section_list(sections);
-            goto error;
-        }
-        dn_size = strlen(dn);
-
-        /* Get all of the attributes and their values as LDIF */
-        attrs = get_attribute_list(sssd_config, sections[i],
-                                   &attr_count, &ret);
-        if (ret != EOK) {
-            free_section_list(sections);
-            goto error;
-        }
-
-        for(j = 0; j < attr_count; j++) {
-            DEBUG(6, ("Processing attribute [%s]\n", attrs[j]));
-            ret = get_config_item(sections[i], attrs[j], sssd_config,
-                                   &attr);
-            if (ret != EOK) goto error;
-
-            const char *value = get_const_string_config_value(attr, &ret);
-            if (ret != EOK) goto error;
-            if (value && value[0] == '\0') {
-                DEBUG(1, ("Attribute '%s' has empty value, ignoring\n", attrs[j]));
-                continue;
-            }
-
-            ldif_attr = talloc_asprintf(tmp_ctx,
-                                        "%s: %s\n", attrs[j], value);
-            DEBUG(9, ("%s", ldif_attr));
-
-            attr_len = strlen(ldif_attr);
-
-            tmp_dn = talloc_realloc(tmp_ctx, dn, char,
-                                    dn_size+attr_len+1);
-            if(!tmp_dn) {
-                ret = ENOMEM;
-                free_attribute_list(attrs);
-                free_section_list(sections);
-                goto error;
-            }
-            dn = tmp_dn;
-            memcpy(dn+dn_size, ldif_attr, attr_len+1);
-            dn_size += attr_len;
-        }
-
-        dn_size ++;
-        tmp_dn = talloc_realloc(tmp_ctx, dn, char,
-                                dn_size+1);
-        if(!tmp_dn) {
-            ret = ENOMEM;
-            free_attribute_list(attrs);
-            free_section_list(sections);
-            goto error;
-        }
-        dn = tmp_dn;
-        dn[dn_size-1] = '\n';
-        dn[dn_size] = '\0';
-
-        DEBUG(9, ("Section dn\n%s", dn));
-
-        tmp_ldif = talloc_realloc(mem_ctx, ldif, char,
-                                  ldif_len+dn_size+1);
-        if(!tmp_ldif) {
-            ret = ENOMEM;
-            free_attribute_list(attrs);
-            free_section_list(sections);
-            goto error;
-        }
-        ldif = tmp_ldif;
-        memcpy(ldif+ldif_len, dn, dn_size);
-        ldif_len += dn_size;
-
-        free_attribute_list(attrs);
-        talloc_free(dn);
-    }
-
-    ldif[ldif_len] = '\0';
-
-    free_section_list(sections);
-
-    *config_ldif = (const char *)ldif;
-    talloc_free(tmp_ctx);
-    return EOK;
-
-error:
-    talloc_free(ldif);
-    return ret;
-}
-
 int confdb_init_db(const char *config_file, struct confdb_ctx *cdb)
 {
+    TALLOC_CTX *tmp_ctx;
     int ret;
-    int fd = -1;
-    struct collection_item *sssd_config = NULL;
-    struct collection_item *error_list = NULL;
-    struct collection_item *item = NULL;
+    int sret = EOK;
+    int version;
+    char timestr[21];
+    char *lasttimestr;
+    bool in_transaction = false;
     const char *config_ldif;
-    struct ldb_ldif *ldif;
-    TALLOC_CTX *tmp_ctx;
-    char *lasttimestr, timestr[21];
     const char *vals[2] = { timestr, NULL };
-    struct stat cstat;
-    int version;
+    struct ldb_ldif *ldif;
+    struct sss_ini_initdata *init_data;
+
 
     tmp_ctx = talloc_new(cdb);
-    if (tmp_ctx == NULL) return ENOMEM;
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory.\n"));
+        return ENOMEM;
+    }
 
-    ret = check_and_open_readonly(config_file, &fd, 0, 0, (S_IRUSR|S_IWUSR),
-                                  CHECK_REG);
+    init_data = sss_ini_initdata_init(tmp_ctx);
+    if (!init_data) {
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory.\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    /* Open config file */
+    ret = sss_ini_config_file_open(init_data, config_file);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to open configuration file.\n"));
+        ret = EIO;
+        goto done;
+    }
+
+    ret = sss_ini_config_access_check(init_data);
     if (ret != EOK) {
-        DEBUG(1, ("Permission check on config file failed.\n"));
-        talloc_zfree(tmp_ctx);
-        return EPERM;
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("Permission check on config file failed.\n"));
+        ret = EPERM;
+        goto done;
     }
 
     /* Determine if the conf file has changed since we last updated
      * the confdb
      */
-    ret = fstat(fd, &cstat);
-    if (ret != 0) {
-        DEBUG(0, ("Unable to stat config file [%s]! (%d [%s])\n",
-                  config_file, errno, strerror(errno)));
-        close(fd);
-        talloc_zfree(tmp_ctx);
-        return errno;
+    ret = sss_ini_get_stat(init_data);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Status check on config file failed.\n"));
+        ret = errno;
+        goto done;
     }
-    ret = snprintf(timestr, 21, "%llu", (long long unsigned)cstat.st_mtime);
+
+    errno = 0;
+
+    ret = sss_ini_get_mtime(init_data, sizeof(timestr), timestr);
     if (ret <= 0 || ret >= 21) {
-        DEBUG(0, ("Failed to convert time_t to string ??\n"));
-        close(fd);
-        talloc_zfree(tmp_ctx);
-        return errno ? errno: EFAULT;
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Failed to convert time_t to string ??\n"));
+        ret = errno ? errno : EFAULT;
     }
+    ret = confdb_get_string(cdb, tmp_ctx, "config", "lastUpdate",
+                            NULL, &lasttimestr);
+    if (ret == EOK) {
 
-    /* check if we need to re-init the db */
-    ret = confdb_get_string(cdb, tmp_ctx, "config", "lastUpdate", NULL, &lasttimestr);
-    if (ret == EOK && lasttimestr != NULL) {
-
-        /* now check if we lastUpdate and last file modification change differ*/
-        if (strcmp(lasttimestr, timestr) == 0) {
+        /* check if we lastUpdate and last file modification change differ*/
+        if ((lasttimestr != NULL) && (strcmp(lasttimestr, timestr) == 0)) {
             /* not changed, get out, nothing more to do */
-            close(fd);
-            talloc_zfree(tmp_ctx);
-            return EOK;
+            ret = EOK;
+            goto done;
         }
-    }
-
-    /* Set up a transaction to replace the configuration */
-    ret = ldb_transaction_start(cdb->ldb);
-    if (ret != LDB_SUCCESS) {
-        DEBUG(0, ("Failed to start a transaction for updating the configuration\n"));
-        talloc_zfree(tmp_ctx);
-        close(fd);
-        return sysdb_error_to_errno(ret);
-    }
-
-    /* Purge existing database */
-    ret = confdb_purge(cdb);
-    if (ret != EOK) {
-        DEBUG(0, ("Could not purge existing configuration\n"));
-        close(fd);
+    } else {
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to get lastUpdate attribute.\n"));
         goto done;
     }
 
-    /* Read the configuration into a collection */
-    ret = config_from_fd("sssd", fd, config_file, &sssd_config,
-                         INI_STOP_ON_ANY, &error_list);
-    close(fd);
+    ret = sss_ini_get_config(init_data, config_file);
     if (ret != EOK) {
-        DEBUG(0, ("Parse error reading configuration file [%s]\n",
-                  config_file));
-        print_file_parsing_errors(stderr, error_list);
-        free_ini_config_errors(error_list);
-        free_ini_config(sssd_config);
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to load configuration\n"));
         goto done;
     }
 
     /* Make sure that the config file version matches the confdb version */
-    ret = get_config_item("sssd", "config_file_version",
-                          sssd_config, &item);
+    ret = sss_ini_get_cfgobj(init_data, "sssd", "config_file_version");
     if (ret != EOK) {
-        DEBUG(0, ("Internal error determining config_file_version\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Internal error determining config_file_version\n"));
         goto done;
     }
-    if (item == NULL) {
+
+    ret = sss_ini_check_config_obj(init_data);
+    if (ret != EOK) {
         /* No known version. Assumed to be version 1 */
-        DEBUG(0, ("Config file is an old version. "
-                  "Please run configuration upgrade script.\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Config file is an old version. "
+               "Please run configuration upgrade script.\n"));
         ret = EINVAL;
         goto done;
     }
-    version = get_int_config_value(item, 1, -1, &ret);
+
+    version = sss_ini_get_int_config_value(init_data, 1, -1, &ret);
     if (ret != EOK) {
-        DEBUG(0, ("Config file version could not be determined\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Config file version could not be determined\n"));
         goto done;
     } else if (version < CONFDB_VERSION_INT) {
-        DEBUG(0, ("Config file is an old version. "
-                  "Please run configuration upgrade script.\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Config file is an old version. "
+                 "Please run configuration upgrade script.\n"));
         ret = EINVAL;
         goto done;
     } else if (version > CONFDB_VERSION_INT) {
-        DEBUG(0, ("Config file version is newer than confdb\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Config file version is newer than confdb\n"));
         ret = EINVAL;
         goto done;
     }
 
-    ret = confdb_create_ldif(tmp_ctx, sssd_config, &config_ldif);
-    free_ini_config(sssd_config);
+    /* Set up a transaction to replace the configuration */
+    ret = ldb_transaction_start(cdb->ldb);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Failed to start a transaction for "
+               "updating the configuration\n"));
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+    in_transaction = true;
+
+    /* Purge existing database */
+    ret = confdb_purge(cdb);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+              ("Could not purge existing configuration\n"));
+        goto done;
+    }
+
+    ret = sss_confdb_create_ldif(tmp_ctx, init_data, &config_ldif);
     if (ret != EOK) {
-        DEBUG(0, ("Could not create LDIF for confdb\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE, ("Could not create LDIF for confdb\n"));
         goto done;
     }
 
-    DEBUG(7, ("LDIF file to import: \n%s", config_ldif));
+    DEBUG(SSSDBG_TRACE_LIBS, ("LDIF file to import: \n%s", config_ldif));
 
     while ((ldif = ldb_ldif_read_string(cdb->ldb, &config_ldif))) {
         ret = ldb_add(cdb->ldb, ldif->msg);
         if (ret != LDB_SUCCESS) {
-            DEBUG(0, ("Failed to initialize DB (%d,[%s]), aborting!\n",
-                      ret, ldb_errstring(cdb->ldb)));
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                    ("Failed to initialize DB (%d,[%s]), aborting!\n",
+                     ret, ldb_errstring(cdb->ldb)));
             ret = EIO;
             goto done;
         }
@@ -411,15 +288,31 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb)
 
     ret = confdb_add_param(cdb, true, "config", "lastUpdate", vals);
     if (ret != EOK) {
-        DEBUG(1, ("Failed to set last update time on db!\n"));
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Failed to set last update time on db!\n"));
+        goto done;
     }
 
+    ret = ldb_transaction_commit(cdb->ldb);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
+        goto done;
+    }
+    in_transaction = false;
+
     ret = EOK;
 
 done:
-    ret == EOK ?
-            ldb_transaction_commit(cdb->ldb) :
-            ldb_transaction_cancel(cdb->ldb);
+    if (in_transaction) {
+        sret = ldb_transaction_cancel(cdb->ldb);
+        if (sret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to cancel transaction\n"));
+        }
+    }
+
+    sss_ini_config_destroy(init_data);
+    sss_ini_close_file(init_data);
+
     talloc_zfree(tmp_ctx);
     return ret;
 }
diff --git a/src/external/libini_config.m4 b/src/external/libini_config.m4
index f41f31917d1cf12dda49ec2e1f2411e39dbcc759..93a4bd94ae79cf2164e4bc87a4f8048c881ecab4 100644
--- a/src/external/libini_config.m4
+++ b/src/external/libini_config.m4
@@ -1,10 +1,20 @@
+PKG_CHECK_MODULES(INI_CONFIG, [
+    ini_config >= 1.0.0], [
+
+        AC_DEFINE_UNQUOTED(HAVE_LIBINI_CONFIG_V1, 1, [libini_config version greater than 1.0.0])
+    ], [
+        AC_MSG_WARN([libini_config-devel >= 1.0.0 not available, trying older version])
+        PKG_CHECK_MODULES(INI_CONFIG, [
+            ini_config >= 0.6.1], [
+
+                AC_DEFINE_UNQUOTED(HAVE_LIBINI_CONFIG_V0, 1, [libini_config version lesser than 1.0.0])
+            ], [
+                AC_MSG_ERROR([Please install libini_config-devel])
+            ]
+        )
+    ]
+)
+
 AC_SUBST(INI_CONFIG_OBJ)
 AC_SUBST(INI_CONFIG_CFLAGS)
 AC_SUBST(INI_CONFIG_LIBS)
-
-PKG_CHECK_MODULES(INI_CONFIG,
-    ini_config >= 0.6.1,
-    ,
-    AC_MSG_ERROR("Please install libini_config-devel")
-    )
-
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 4e81f55970de40bcb21d1f473027348d9420306a..bd22a951d3b48d0ea367e36f628b07e2783d469a 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -44,8 +44,6 @@
 #include "tevent.h"
 #include "confdb/confdb.h"
 #include "confdb/confdb_setup.h"
-#include "collection.h"
-#include "ini_config.h"
 #include "db/sysdb.h"
 #include "monitor/monitor.h"
 #include "dbus/dbus.h"
diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c
index 30459beaa9f9b98aab5d29c81fbc9a195e071bff..36792365fb545a230426ff324e101e7b4e3f8ea6 100644
--- a/src/responder/nss/nsssrv_netgroup.c
+++ b/src/responder/nss/nsssrv_netgroup.c
@@ -22,7 +22,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <collection.h>
+
 #include "util/util.h"
 #include "responder/nss/nsssrv.h"
 #include "responder/nss/nsssrv_private.h"
diff --git a/src/responder/nss/nsssrv_services.c b/src/responder/nss/nsssrv_services.c
index 7b76cad86e28a7f091833295659836289e351099..c99074235b3b93ab1492b89138d3f59beb633ba2 100644
--- a/src/responder/nss/nsssrv_services.c
+++ b/src/responder/nss/nsssrv_services.c
@@ -21,7 +21,6 @@
 */
 
 
-#include <collection.h>
 #include <arpa/inet.h>
 #include "util/util.h"
 #include "responder/nss/nsssrv.h"
diff --git a/src/util/sss_ini.c b/src/util/sss_ini.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f9529694ab1c2ee4474b3617294c5be732f9192
--- /dev/null
+++ b/src/util/sss_ini.c
@@ -0,0 +1,466 @@
+/*
+    SSSD
+
+    sss_ini.c
+
+    Authors:
+        Ondrej Kos <o...@redhat.com>
+
+    Copyright (C) 2013 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <talloc.h>
+
+#include "config.h"
+#include "util/util.h"
+#include "util/sss_ini.h"
+#include "confdb/confdb_setup.h"
+#include "confdb/confdb_private.h"
+
+#ifdef HAVE_LIBINI_CONFIG_V1
+#include "ini_configobj.h"
+#endif
+#include "ini_config.h"
+
+#ifdef HAVE_LIBINI_CONFIG_V0
+#include "collection.h"
+#include "collection_tools.h"
+#endif
+
+
+
+#ifdef HAVE_LIBINI_CONFIG_V1
+
+struct sss_ini_initdata {
+    char **error_list;
+    struct ini_cfgobj *sssd_config;
+    struct value_obj *obj;
+    const struct stat *cstat;
+    struct ini_cfgfile *file;
+};
+
+#define sss_ini_get_sec_list                   ini_get_section_list
+#define sss_ini_get_attr_list                  ini_get_attribute_list
+#define sss_ini_get_const_string_config_value  ini_get_const_string_config_value
+#define sss_ini_get_config_obj                 ini_get_config_valueobj
+
+
+
+#elif HAVE_LIBINI_CONFIG_V0
+
+struct sss_ini_initdata {
+    struct collection_item *error_list;
+    struct collection_item *sssd_config;
+    struct collection_item *obj;
+    struct stat cstat;
+    int file;
+};
+
+#define sss_ini_get_sec_list                   get_section_list
+#define sss_ini_get_attr_list                  get_attribute_list
+#define sss_ini_get_const_string_config_value  get_const_string_config_value
+#define sss_ini_get_config_obj(secs,attrs,cfg,flag,attr) \
+    get_config_item(secs,attrs,cfg,attr)
+
+#endif
+
+
+/* Initialize data structure */
+
+struct sss_ini_initdata* sss_ini_initdata_init(TALLOC_CTX *mem_ctx)
+{
+    return talloc_zero(mem_ctx, struct sss_ini_initdata);
+}
+
+
+
+/* Close file descriptor */
+
+void sss_ini_close_file(struct sss_ini_initdata *init_data)
+{
+    if (init_data == NULL) return;
+#ifdef HAVE_LIBINI_CONFIG_V1
+    if (init_data->file != NULL) {
+        ini_config_file_destroy(init_data->file);
+        init_data->file = NULL;
+    }
+#elif HAVE_LIBINI_CONFIG_V0
+    if (init_data->file != -1) {
+        close(init_data->file);
+        init_data->file = -1;
+    }
+#endif
+}
+
+
+
+/* Open configuration file */
+
+int sss_ini_config_file_open(struct sss_ini_initdata *init_data,
+                             const char *config_file)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    return ini_config_file_open(config_file,
+                                INI_META_STATS,
+                                &init_data->file);
+#elif HAVE_LIBINI_CONFIG_V0
+    return check_and_open_readonly(config_file, &init_data->file, 0, 0,
+                                   (S_IRUSR|S_IWUSR), CHECK_REG);
+#endif
+}
+
+
+
+/* Check configuration file permissions */
+
+int sss_ini_config_access_check(struct sss_ini_initdata *init_data)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    return ini_config_access_check(init_data->file,
+                                   INI_ACCESS_CHECK_MODE |
+                                   INI_ACCESS_CHECK_UID |
+                                   INI_ACCESS_CHECK_GID,
+                                   0, /* owned by root */
+                                   0, /* owned by root */
+                                   (S_IRUSR|S_IWUSR), /* rw------- */
+                                   0); /* check all there parts */
+#elif HAVE_LIBINI_CONFIG_V0
+    return EOK;
+#endif
+}
+
+
+
+/* Get cstat */
+
+int sss_ini_get_stat(struct sss_ini_initdata *init_data)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    init_data->cstat = ini_config_get_stat(file_desc);
+
+    if (!init_data->cstat) return EIO;
+
+    return EOK;
+#elif HAVE_LIBINI_CONFIG_V0
+
+    return fstat(init_data->file, &init_data->cstat);
+#endif
+}
+
+
+
+/* Get mtime */
+
+int sss_ini_get_mtime(struct sss_ini_initdata *init_data,
+                      size_t timestr_len,
+                      char *timestr)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    return snprintf(timestr, timestr_len, "%llu",
+                    (long long unsigned)init_data->cstat->st_mtime);
+#elif HAVE_LIBINI_CONFIG_V0
+    return snprintf(timestr, timestr_len, "%llu",
+                    (long long unsigned)init_data->cstat.st_mtime);
+#endif
+}
+
+
+
+/* Load configuration */
+
+int sss_ini_get_config(struct sss_ini_initdata *init_data,
+                       const char *config_file)
+{
+    int ret;
+#ifdef HAVE_LIBINI_CONFIG_V1
+
+    /* Create config object */
+    ret = ini_config_create(&(init_data->sssd_config));
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Failed to create config object. Error %d.\n", ret));
+        return ret;
+    }
+
+    /* Parse file */
+    ret = ini_config_parse(init_data->file,
+                           INI_STOP_ON_ANY,
+                           INI_MV1S_OVERWRITE,
+                           0,
+                           init_data->sssd_config);
+
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Failed to parse configuration. Error %d.\n", ret));
+
+        if (ini_config_error_count(init_data->sssd_config)) {
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                    ("Errors detected while parsing: %s\n",
+                     ini_config_get_filename(init_data->file));
+
+            ini_config_get_errors(init_data->sssd_config,
+                                  &init_data->error_list);
+            ini_config_print_errors(debug_file, init_data->error_list));
+            ini_config_free_errors(init_data->error_list);
+        }
+        ini_config_destroy(init_data->sssd_config);
+        return ret;
+    }
+
+    return ret;
+
+#elif HAVE_LIBINI_CONFIG_V0
+
+    /* Read the configuration into a collection */
+    ret = config_from_fd("sssd",
+                         init_data->file,
+                         config_file,
+                         &init_data->sssd_config,
+                         INI_STOP_ON_ANY,
+                         &init_data->error_list);
+    close(init_data->file);
+
+    if (ret != EOK) {
+        DEBUG(SSSDBG_FATAL_FAILURE,
+                ("Parse error reading configuration file [%s]\n",
+                 config_file));
+
+        print_file_parsing_errors(stderr, init_data->error_list);
+
+        free_ini_config_errors(init_data->error_list);
+        free_ini_config(init_data->sssd_config);
+
+        return ret;
+    }
+
+    return EOK;
+
+#endif
+}
+
+
+
+/* Get configuration object */
+
+int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data,
+                       const char *section, const char *name)
+{
+    return sss_ini_get_config_obj(section,name, init_data->sssd_config,
+                                  INI_GET_FIRST_VALUE, &init_data->obj);
+}
+
+
+
+/* Check configuration object */
+
+int sss_ini_check_config_obj(struct sss_ini_initdata *init_data)
+{
+    if (init_data->obj == NULL) {
+        return ENOENT;
+    } else {
+        return EOK;
+    }
+}
+
+
+
+/* Get integer value */
+
+int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data,
+                                 int strict, int def, int *error)
+{
+#ifdef HAVE_LIBINI_CONFIG_V1
+    return ini_get_int_config_value(init_data->obj, strict, def, error);
+#elif HAVE_LIBINI_CONFIG_V0
+    return get_int_config_value(init_data->obj, strict, def, error);
+#endif
+}
+
+
+
+/* Destroy ini config (v1) */
+
+void sss_ini_config_destroy(struct sss_ini_initdata *init_data)
+{
+    if (init_data == NULL) return;
+#ifdef HAVE_LIBINI_CONFIG_V1
+    if (init_data->sssd_config != NULL) {
+        ini_config_destroy(init_data->sssd_config);
+        init_data->sssd_config = NULL;
+    }
+#elif HAVE_LIBINI_CONFIG_V0
+    free_ini_config(init_data->sssd_config);
+#endif
+}
+
+
+
+/* Create LDIF */
+
+int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx,
+                           struct sss_ini_initdata *init_data,
+                           const char **config_ldif)
+{
+    int ret, i, j;
+    char *ldif;
+    char *tmp_ldif;
+    char **sections;
+    int section_count;
+    char *dn;
+    char *tmp_dn;
+    char *sec_dn;
+    char **attrs;
+    int attr_count;
+    char *ldif_attr;
+    TALLOC_CTX *tmp_ctx;
+    size_t dn_size;
+    size_t ldif_len;
+    size_t attr_len;
+#ifdef HAVE_LIBINI_CONFIG_V1
+    struct value_obj *obj = NULL;
+#elif HAVE_LIBINI_CONFIG_V0
+    struct collection_item *obj = NULL;
+#endif
+
+    ldif_len = strlen(CONFDB_INTERNAL_LDIF);
+    ldif = talloc_array(mem_ctx, char, ldif_len+1);
+    if (!ldif) return ENOMEM;
+
+    tmp_ctx = talloc_new(ldif);
+    if (!tmp_ctx) {
+        ret = ENOMEM;
+        goto error;
+    }
+
+    memcpy(ldif, CONFDB_INTERNAL_LDIF, ldif_len);
+
+    /* Read in the collection and convert it to an LDIF */
+    /* Get the list of sections */
+    sections = sss_ini_get_sec_list(init_data->sssd_config,
+                                    &section_count, &ret);
+    if (ret != EOK) {
+        goto error;
+    }
+
+    for(i = 0; i < section_count; i++) {
+        const char *rdn = NULL;
+        DEBUG(SSSDBG_TRACE_FUNC,
+                ("Processing config section [%s]\n", sections[i]));
+        ret = parse_section(tmp_ctx, sections[i], &sec_dn, &rdn);
+        if (ret != EOK) {
+            goto error;
+        }
+
+        dn = talloc_asprintf(tmp_ctx,
+                             "dn: %s,cn=config\n"
+                             "cn: %s\n",
+                             sec_dn, rdn);
+        if(!dn) {
+            ret = ENOMEM;
+            free_section_list(sections);
+            goto error;
+        }
+        dn_size = strlen(dn);
+
+        /* Get all of the attributes and their values as LDIF */
+        attrs = sss_ini_get_attr_list(init_data->sssd_config, sections[i],
+                                   &attr_count, &ret);
+        if (ret != EOK) {
+            free_section_list(sections);
+            goto error;
+        }
+
+        for(j = 0; j < attr_count; j++) {
+            DEBUG(SSSDBG_TRACE_FUNC,
+                    ("Processing attribute [%s]\n", attrs[j]));
+            ret = sss_ini_get_config_obj(sections[i], attrs[j],
+                                         init_data->sssd_config,
+                                         INI_GET_FIRST_VALUE, &obj);
+            if (ret != EOK) goto error;
+
+            const char *value = sss_ini_get_const_string_config_value(obj, &ret);
+            if (ret != EOK) goto error;
+            if (value && value[0] == '\0') {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                        ("Attribute '%s' has empty value, ignoring\n",
+                         attrs[j]));
+                continue;
+            }
+
+            ldif_attr = talloc_asprintf(tmp_ctx,
+                                        "%s: %s\n", attrs[j], value);
+            DEBUG(SSSDBG_TRACE_ALL, ("%s", ldif_attr));
+
+            attr_len = strlen(ldif_attr);
+
+            tmp_dn = talloc_realloc(tmp_ctx, dn, char,
+                                    dn_size+attr_len+1);
+            if(!tmp_dn) {
+                ret = ENOMEM;
+                free_attribute_list(attrs);
+                free_section_list(sections);
+                goto error;
+            }
+            dn = tmp_dn;
+            memcpy(dn+dn_size, ldif_attr, attr_len+1);
+            dn_size += attr_len;
+        }
+
+        dn_size ++;
+        tmp_dn = talloc_realloc(tmp_ctx, dn, char,
+                                dn_size+1);
+        if(!tmp_dn) {
+            ret = ENOMEM;
+            free_attribute_list(attrs);
+            free_section_list(sections);
+            goto error;
+        }
+        dn = tmp_dn;
+        dn[dn_size-1] = '\n';
+        dn[dn_size] = '\0';
+
+        DEBUG(SSSDBG_TRACE_ALL, ("Section dn\n%s", dn));
+
+        tmp_ldif = talloc_realloc(mem_ctx, ldif, char,
+                                  ldif_len+dn_size+1);
+        if(!tmp_ldif) {
+            ret = ENOMEM;
+            free_attribute_list(attrs);
+            free_section_list(sections);
+            goto error;
+        }
+        ldif = tmp_ldif;
+        memcpy(ldif+ldif_len, dn, dn_size);
+        ldif_len += dn_size;
+
+        free_attribute_list(attrs);
+        talloc_free(dn);
+    }
+
+    ldif[ldif_len] = '\0';
+
+    free_section_list(sections);
+
+    *config_ldif = (const char *)ldif;
+    talloc_free(tmp_ctx);
+    return EOK;
+
+error:
+    talloc_free(ldif);
+    return ret;
+}
diff --git a/src/util/sss_ini.h b/src/util/sss_ini.h
new file mode 100644
index 0000000000000000000000000000000000000000..3beaca15ba87ad12a016a3295371a56239165683
--- /dev/null
+++ b/src/util/sss_ini.h
@@ -0,0 +1,81 @@
+/*
+    SSSD
+
+    sss_ini.c
+
+    Authors:
+        Ondrej Kos <o...@redhat.com>
+
+    Copyright (C) 2013 Red Hat
+
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+#ifndef __SSS_INI_H__
+#define __SSS_INI_H__
+
+/* Structure declarations */
+
+/* INI data structure */
+struct sss_ini_initdata;
+
+
+/* Function declarations */
+
+/* Initialize data structure */
+struct sss_ini_initdata* sss_ini_initdata_init(TALLOC_CTX *tmp_ctx);
+
+/* Close file descriptor */
+void sss_ini_close_file(struct sss_ini_initdata *init_data);
+
+/* Open config file */
+int sss_ini_config_file_open(struct sss_ini_initdata *init_data,
+                             const char *config_file);
+
+/* Check file permissions */
+int sss_ini_config_access_check(struct sss_ini_initdata *init_data);
+
+/* Cstat */
+int sss_ini_get_stat(struct sss_ini_initdata *init_data);
+
+/* Get mtime */
+int sss_ini_get_mtime(struct sss_ini_initdata *init_data,
+                      size_t timestr_len,
+                      char *timestr);
+
+/* Load configuration */
+int sss_ini_get_config(struct sss_ini_initdata *init_data,
+                       const char *config_file);
+/* Get configuration object */
+int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data,
+                       const char *section, const char *name);
+
+/* Check configuration object */
+int sss_ini_check_config_obj(struct sss_ini_initdata *init_data);
+
+/* Get int value */
+int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data,
+                                 int strict, int def, int *error);
+
+/* Destroy ini config */
+void sss_ini_config_destroy(struct sss_ini_initdata *init_data);
+
+/* Create LDIF */
+int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx,
+                           struct sss_ini_initdata *init_data,
+                           const char **config_ldif);
+
+#endif /* __SSS_INI_H__ */
-- 
1.8.1.4

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to