summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/config-parser.c76
-rw-r--r--tools/rrdbot-create.c94
2 files changed, 151 insertions, 19 deletions
diff --git a/common/config-parser.c b/common/config-parser.c
index 23f57a4..905e019 100644
--- a/common/config-parser.c
+++ b/common/config-parser.c
@@ -226,39 +226,58 @@ finally:
return ret;
}
-int
-cfg_parse_dir(const char* dirname, void* data)
+static int
+parse_dir_internal(const char* subdir, void* data)
{
- char olddir[MAXPATHLEN];
+ char path[MAXPATHLEN];
struct dirent* dire;
- char *memory;
+ char* memory;
DIR* dir;
+ int r;
- ASSERT(dirname != NULL);
-
- if(!getcwd(olddir, MAXPATHLEN))
- olddir[0] = 0;
-
- if(chdir(dirname) == -1)
- errmsg(NULL, data, "couldn't list config directory: %s", dirname);
-
- dir = opendir(".");
+ /* Open specified or current directory */
+ dir = opendir(subdir ? subdir : ".");
if(!dir)
{
- errmsg(NULL, data, "couldn't list config directory: %s", dirname);
+ errmsg(NULL, data, "couldn't list config directory: %s",
+ subdir ? subdir : ".");
return -1;
}
while((dire = readdir(dir)) != NULL)
{
+ /* Build a file path to this entry */
+ if(subdir)
+ {
+ strlcpy(path, subdir, MAXPATHLEN);
+ strlcat(path, "/", MAXPATHLEN);
+ strlcat(path, dire->d_name, MAXPATHLEN);
+ }
+ else
+ strlcpy(path, dire->d_name, MAXPATHLEN);
+
+ /* Descend into each sub directory */
+ if(dire->d_type == DT_DIR)
+ {
+ /* No hidden or dot directories */
+ if(dire->d_name[0] == '.')
+ continue;
+
+ r = parse_dir_internal(path, data);
+ if(r < 0)
+ return r;
+
+ continue;
+ }
+
if(dire->d_type != DT_REG && dire->d_type != DT_LNK)
continue;
/* Build a happy path name */
- cfg_parse_file(dire->d_name, data, &memory);
+ cfg_parse_file(path, data, &memory);
/* We call it with blanks after files */
- if(cfg_value(dire->d_name, NULL, NULL, NULL, data) == -1)
+ if(cfg_value(path, NULL, NULL, NULL, data) == -1)
break;
/* Keep the memory around */
@@ -270,3 +289,28 @@ cfg_parse_dir(const char* dirname, void* data)
return 0;
}
+
+int
+cfg_parse_dir(const char* dirname, void* data)
+{
+ char olddir[MAXPATHLEN];
+ int ret;
+
+ ASSERT(dirname != NULL);
+
+ if(!getcwd(olddir, MAXPATHLEN))
+ olddir[0] = 0;
+
+ if(chdir(dirname) == -1)
+ {
+ errmsg(NULL, data, "couldn't list config directory: %s", dirname);
+ return -1;
+ }
+
+ ret = parse_dir_internal(NULL, data);
+
+ if(olddir[0])
+ chdir(olddir);
+
+ return ret;
+}
diff --git a/tools/rrdbot-create.c b/tools/rrdbot-create.c
index 86f5b27..c7a7350 100644
--- a/tools/rrdbot-create.c
+++ b/tools/rrdbot-create.c
@@ -41,7 +41,7 @@
#include <unistd.h>
#include <stdarg.h>
#include <err.h>
-
+#include <sys/stat.h>
#include <rrd.h>
#include "config-parser.h"
@@ -105,7 +105,92 @@ verb(const char* fmt, ...)
* CREATE
*/
-void
+static int
+mkdir_p(char* path)
+{
+ struct stat sb;
+ int first, last, retval = 0;
+ char* p = path;
+
+ /* Skip leading '/'. */
+ while(p[0] == '/')
+ ++p;
+
+ for(first = 1, last = 0; !last ; ++p)
+ {
+ if(p[0] == '\0')
+ last = 1;
+ else if (p[0] != '/')
+ continue;
+ *p = '\0';
+ if(!last && p[1] == '\0')
+ last = 1;
+
+ /* Modified by the umask */
+ if(mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) < 0)
+ {
+ if(errno == EEXIST || errno == EISDIR)
+ {
+ if(stat(path, &sb) < 0)
+ {
+ retval = 1;
+ break;
+ }
+ else if(!S_ISDIR(sb.st_mode))
+ {
+ if (last)
+ errno = EEXIST;
+ else
+ errno = ENOTDIR;
+ retval = 1;
+ break;
+ }
+ }
+ else
+ {
+ retval = 1;
+ break;
+ }
+ }
+ if (!last)
+ *p = '/';
+ }
+
+ return (retval);
+}
+
+static int
+create_dir_for_file(const char* path)
+{
+ char *p = strrchr(path, '/');
+ char *dir;
+ int r;
+
+ /* No subdirectories, not needed */
+ if (!p)
+ return 0;
+
+ dir = calloc((p - path) + 1, 1);
+ if(!dir)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ memcpy (dir, path, (p - path));
+ r = mkdir_p(dir);
+ free(dir);
+
+ if(r < 0)
+ {
+ warnx("couldn't create directory for rrd file: %s", dir);
+ return r;
+ }
+
+ return r;
+}
+
+static void
create_file(create_ctx* ctx, const char* rrd)
{
create_arg* arg;
@@ -113,6 +198,9 @@ create_file(create_ctx* ctx, const char* rrd)
int argc, r;
const char** argv;
+ if(create_dir_for_file(rrd))
+ return;
+
for(arg = ctx->args; arg; arg = arg->next)
num++;
@@ -263,7 +351,7 @@ cfg_value(const char* filename, const char* header, const char* name,
check_create_file(ctx);
/* Do cleanup */
- ctx->confname = NULL;
+ ctx->confname = 0;
while(ctx->args)
{