configfile.c: Include more than one files in lexicographical order.
authorSebastian Harl <sh@tokkee.org>
Thu, 20 Mar 2008 12:22:15 +0000 (13:22 +0100)
committerFlorian Forster <octo@huhu.verplant.org>
Sat, 22 Mar 2008 08:34:26 +0000 (09:34 +0100)
Using qsort() and strcmp() the list of files (after reading the contents
of a directory or expanding globs) is sorted before inclusion. As the
order of options in the config file matters this is more convenient.

Signed-off-by: Sebastian Harl <sh@tokkee.org>
Signed-off-by: Florian Forster <octo@huhu.verplant.org>
src/collectd.conf.pod
src/configfile.c

index 383dda6..aa4421d 100644 (file)
@@ -63,6 +63,11 @@ use statements like the following:
 
   Include "/etc/collectd.d/*.conf"
 
 
   Include "/etc/collectd.d/*.conf"
 
+If more than one files are included by a single B<Include> option, the files
+will be included in lexicographical order (as defined by the C<strcmp>
+function). Thus, you can e.E<nbsp>g. use numbered prefixes to specify the
+order in which the files are loaded.
+
 To prevent loops and shooting yourself in the foot in interesting ways the
 nesting is limited to a depth of 8E<nbsp>levels, which should be sufficient for
 most uses. Since symlinks are followed it is still possible to crash the daemon
 To prevent loops and shooting yourself in the foot in interesting ways the
 nesting is limited to a depth of 8E<nbsp>levels, which should be sufficient for
 most uses. Since symlinks are followed it is still possible to crash the daemon
index 63b926a..4a9789a 100644 (file)
@@ -18,6 +18,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
  **/
 
 #include "collectd.h"
  **/
 
 #include "collectd.h"
@@ -505,13 +506,20 @@ static oconfig_item_t *cf_read_file (const char *file, int depth)
        return (root);
 } /* oconfig_item_t *cf_read_file */
 
        return (root);
 } /* oconfig_item_t *cf_read_file */
 
+static int cf_compare_string (const void *p1, const void *p2)
+{
+       return strcmp (*(const char **) p1, *(const char **) p2);
+}
+
 static oconfig_item_t *cf_read_dir (const char *dir, int depth)
 {
        oconfig_item_t *root = NULL;
        DIR *dh;
        struct dirent *de;
 static oconfig_item_t *cf_read_dir (const char *dir, int depth)
 {
        oconfig_item_t *root = NULL;
        DIR *dh;
        struct dirent *de;
-       char name[1024];
+       char **filenames = NULL;
+       int filenames_num = 0;
        int status;
        int status;
+       int i;
 
        assert (depth < CF_MAX_DEPTH);
 
 
        assert (depth < CF_MAX_DEPTH);
 
@@ -534,7 +542,8 @@ static oconfig_item_t *cf_read_dir (const char *dir, int depth)
 
        while ((de = readdir (dh)) != NULL)
        {
 
        while ((de = readdir (dh)) != NULL)
        {
-               oconfig_item_t *temp;
+               char   name[1024];
+               char **tmp;
 
                if ((de->d_name[0] == '.') || (de->d_name[0] == '\0'))
                        continue;
 
                if ((de->d_name[0] == '.') || (de->d_name[0] == '\0'))
                        continue;
@@ -546,12 +555,43 @@ static oconfig_item_t *cf_read_dir (const char *dir, int depth)
                        ERROR ("configfile: Not including `%s/%s' because its"
                                        " name is too long.",
                                        dir, de->d_name);
                        ERROR ("configfile: Not including `%s/%s' because its"
                                        " name is too long.",
                                        dir, de->d_name);
-                       oconfig_free (root);
+                       for (i = 0; i < filenames_num; ++i)
+                               free (filenames[i]);
+                       free (filenames);
+                       free (root);
+                       return (NULL);
+               }
+
+               ++filenames_num;
+               tmp = (char **) realloc (filenames,
+                               filenames_num * sizeof (*filenames));
+               if (tmp == NULL) {
+                       ERROR ("configfile: realloc failed.");
+                       for (i = 0; i < filenames_num - 1; ++i)
+                               free (filenames[i]);
+                       free (filenames);
+                       free (root);
                        return (NULL);
                }
                        return (NULL);
                }
+               filenames = tmp;
+
+               filenames[filenames_num - 1] = sstrdup (name);
+       }
+
+       qsort ((void *) filenames, filenames_num, sizeof (*filenames),
+                       cf_compare_string);
+
+       for (i = 0; i < filenames_num; ++i)
+       {
+               oconfig_item_t *temp;
+               char *name = filenames[i];
 
                temp = cf_read_generic (name, depth);
                if (temp == NULL) {
 
                temp = cf_read_generic (name, depth);
                if (temp == NULL) {
+                       int j;
+                       for (j = i; j < filenames_num; ++j)
+                               free (filenames[j]);
+                       free (filenames);
                        oconfig_free (root);
                        return (NULL);
                }
                        oconfig_free (root);
                        return (NULL);
                }
@@ -559,8 +599,11 @@ static oconfig_item_t *cf_read_dir (const char *dir, int depth)
                cf_ci_append_children (root, temp);
                sfree (temp->children);
                sfree (temp);
                cf_ci_append_children (root, temp);
                sfree (temp->children);
                sfree (temp);
+
+               free (name);
        }
 
        }
 
+       free(filenames);
        return (root);
 } /* oconfig_item_t *cf_read_dir */
 
        return (root);
 } /* oconfig_item_t *cf_read_dir */
 
@@ -606,6 +649,11 @@ static oconfig_item_t *cf_read_generic (const char *path, int depth)
        }
        memset (root, '\0', sizeof (oconfig_item_t));
 
        }
        memset (root, '\0', sizeof (oconfig_item_t));
 
+       /* wordexp() might return a sorted list already. That's not
+        * documented though, so let's make sure we get what we want. */
+       qsort ((void *) we.we_wordv, we.we_wordc, sizeof (*we.we_wordv),
+                       cf_compare_string);
+
        for (i = 0; i < we.we_wordc; i++)
        {
                oconfig_item_t *temp;
        for (i = 0; i < we.we_wordc; i++)
        {
                oconfig_item_t *temp;