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)          { | 
