[collectd] [PATCH] configfile.c: Include more than one files in lexicographical order.

Sebastian Harl sh at tokkee.org
Thu Mar 20 13:22:15 CET 2008


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 at tokkee.org>
---
 src/collectd.conf.pod |    5 ++++
 src/configfile.c      |   54 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 7afe3f1..00f56e7 100644
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -63,6 +63,11 @@ use statements like the following:
 
   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
diff --git a/src/configfile.c b/src/configfile.c
index 63b926a..e4f26d2 100644
--- a/src/configfile.c
+++ b/src/configfile.c
@@ -18,6 +18,7 @@
  *
  * Authors:
  *   Florian octo Forster <octo at verplant.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
  **/
 
 #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 */
 
+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;
-	char name[1024];
+	char **filenames = NULL;
+	int filenames_num = 0;
 	int status;
+	int i;
 
 	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)
 	{
-		oconfig_item_t *temp;
+		char   name[1024];
+		char **tmp;
 
 		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);
-			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);
 		}
+		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) {
+			int j;
+			for (j = i; j < filenames_num; ++j)
+				free (filenames[j]);
+			free (filenames);
 			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);
+
+		free (name);
 	}
 
+	free(filenames);
 	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));
 
+	/* 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;
-- 
1.5.4.3.325.g6d216

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mailman.verplant.org/pipermail/collectd/attachments/20080320/1a30ae87/attachment.pgp 


More information about the collectd mailing list