X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fconfigfile.c;h=8b526f2e958902a5dcbb22a674b0c0caa267f44f;hb=3c316743f0dccb70e49a10ed44951dd4b289d9f0;hp=36b6dadcc846a98f20a0cb854341bacd6ea5c4ae;hpb=23f2ac0835c5cf2760bd1b687e868fd033c7639c;p=collectd.git diff --git a/src/configfile.c b/src/configfile.c index 36b6dadc..8b526f2e 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -18,6 +18,7 @@ * * Authors: * Florian octo Forster + * Sebastian tokkee Harl **/ #include "collectd.h" @@ -327,7 +328,7 @@ static int dispatch_block_plugin (oconfig_item_t *ci) if (ci->children[i].children == NULL) dispatch_value_plugin (name, ci->children + i); else - {DEBUG ("No nested config blocks allow for this plugin.");} + {DEBUG ("No nested config blocks allowed for this plugin.");} } return (0); @@ -353,18 +354,6 @@ static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src, assert (offset >= 0); assert (dst->children_num > offset); - /* Resize the memory containing the children to be big enough to hold - * all children. */ - temp = (oconfig_item_t *) realloc (dst->children, - sizeof (oconfig_item_t) - * (dst->children_num + src->children_num - 1)); - if (temp == NULL) - { - ERROR ("configfile: realloc failed."); - return (-1); - } - dst->children = temp; - /* Free the memory used by the replaced child. Usually that's the * `Include "blah"' statement. */ temp = dst->children + offset; @@ -378,9 +367,34 @@ static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src, sfree (temp->values); temp = NULL; - /* If there are children behind the include statement, move them to the - * end of the list, so that the new children have room before them. */ - if ((dst->children_num - (offset + 1)) > 0) + /* If (src->children_num == 0) the array size is decreased. If offset + * is _not_ the last element, (offset < (src->children_num - 1)), then + * we need to move the trailing elements before resizing the array. */ + if ((src->children_num == 0) && (offset < (src->children_num - 1))) + { + int nmemb = src->children_num - (offset + 1); + memmove (src->children + offset, src->children + offset + 1, + sizeof (oconfig_item_t) * nmemb); + } + + /* Resize the memory containing the children to be big enough to hold + * all children. */ + temp = (oconfig_item_t *) realloc (dst->children, + sizeof (oconfig_item_t) + * (dst->children_num + src->children_num - 1)); + if (temp == NULL) + { + ERROR ("configfile: realloc failed."); + return (-1); + } + dst->children = temp; + + /* If there are children behind the include statement, and they have + * not yet been moved because (src->children_num == 0), then move them + * to the end of the list, so that the new children have room before + * them. */ + if ((src->children_num > 0) + && ((dst->children_num - (offset + 1)) > 0)) { int nmemb = dst->children_num - (offset + 1); int old_offset = offset + 1; @@ -410,6 +424,9 @@ static int cf_ci_append_children (oconfig_item_t *dst, oconfig_item_t *src) { oconfig_item_t *temp; + if ((src == NULL) || (src->children_num == 0)) + return (0); + temp = (oconfig_item_t *) realloc (dst->children, sizeof (oconfig_item_t) * (dst->children_num + src->children_num)); @@ -489,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); @@ -518,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; @@ -530,18 +555,55 @@ 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); - continue; + 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) - continue; + if (temp == NULL) { + int j; + for (j = i; j < filenames_num; ++j) + free (filenames[j]); + free (filenames); + oconfig_free (root); + return (NULL); + } cf_ci_append_children (root, temp); sfree (temp->children); sfree (temp); + + free (name); } + free(filenames); return (root); } /* oconfig_item_t *cf_read_dir */ @@ -587,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; @@ -601,6 +668,7 @@ static oconfig_item_t *cf_read_generic (const char *path, int depth) ERROR ("configfile: stat (%s) failed: %s", path_ptr, sstrerror (errno, errbuf, sizeof (errbuf))); + oconfig_free (root); return (NULL); } @@ -615,6 +683,11 @@ static oconfig_item_t *cf_read_generic (const char *path, int depth) continue; } + if (temp == NULL) { + oconfig_free (root); + return (NULL); + } + cf_ci_append_children (root, temp); sfree (temp->children); sfree (temp); @@ -815,7 +888,11 @@ int cf_read (char *filename) dispatch_block (conf->children + i); } + oconfig_free (conf); + + /* Read the default types.db if no `TypesDB' option was given. */ if (cf_default_typesdb) - read_types_list (PLUGINDIR"/types.db"); /* FIXME: Configure path */ + read_types_list (PLUGINDIR"/types.db"); + return (0); } /* int cf_read */