diff options
-rw-r--r-- | common/config-parser.c | 76 | ||||
-rw-r--r-- | tools/rrdbot-create.c | 94 |
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) { |